Home > front end >  Form to create relationship between objects
Form to create relationship between objects

Time:11-11

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.

  • Related