In my app I have User
and Language
models.
User can have multiple languages and a language can have multiple users.
class Language < ApplicationRecord
has_and_belongs_to_many :users
end
class User < ApplicationRecord
has_and_belongs_to_many :languages
end
I want to create a form that will allow user to add a new language to the profile.
Since both User
and Language
models already exist, I'm wondering how to create a form that will not create any new model, but just create a relation between existing models.
CodePudding user response:
Both the has_many and HABTM macros create _ids
and _ids=
setters and getters that make it trivial to associate different records:
<%= form_with(model: @user) do |form| %>
<div class="field">
<%= form.label :language_ids, "Languages" %>
<%= form.collection_select(:language_ids, Language.all, :id, :name, multiple: true) %>
# or if you prefer checkboxes
<%= form.collection_checkboxes(:language_ids, Language.all, :id, :name) %>
</div>
# ...
<% end %>
The form collection helpers are smart enough to iterate accross the collection and will select/check depending on if an assocation already exists.
You whitelist an array parameter by passing a hash key to permit
with an empty array as its value:
class UsersController < ApplicationController
def create
@user = User.new(user_params)
# ...
end
private
def user_params
params.require(:user)
.permit(
:foo, :bar, :baz,
langauge_ids: []
)
end
end
I would also seriously consider if you want to use has_and_belongs_to_many
in the first place. Since there is no model you can't access any additional columns on the join table like for example how proficient a user is or if its their primary language. There is also no straight forward way to query the join table directly. has_many through:
is a actually better solution in most cases.