2

I have two models: User and Company. A company can have many users and a user can have many companies. As you might suggest, this is the perfect place to use a join table. I'm actually using a full blown model to join User and Company so that I can specify the role that each user has. The table, companies_users, therefore has the following columns: user_id, company_id and company_role.

The situation I'm trying to negotiate is one in which I'm creating both a Company and a User and would like to specify the company_role while doing so.

My new method is as follows:

def new
    @user=User.new
    @company=@user.companies.build
end

This creates an entry in the companies_users join table but (obviously) does so in leaving the company_role blank.

How might I add this bit of info?

Thanks in advance!

neanderslob
  • 2,633
  • 6
  • 40
  • 82

2 Answers2

1

You can pass the attributes through the build / create methods:

#app/controllers/users_controller.rb
class UsersController < ApplicationController
    def new
       @user = User.new
       @user.company_users.build.build_company
    end

    def create
       @user = User.new user_params
       @user.save  
    end

    private

    def user_params
       params.require(:user).permit(company_users_attributes: [company_attributes:[:name]])
    end
end

#app/views/users/new.html.erb
<%= form_for @user do |f| %>
   <%= f.fields_for :company_users do |cu| %>
       <%= cu.text_field :company_role %>
       <%= cu.fields_for :company do |c| %>
          <%= c.text_field :name %>
       <% end %>
   <% end %>
   <%= f.submit %>
<% end %>

The above looks complicated, I'll explain in a second.

You need the following models:

#app/models/user.rb
class User < ActiveRecord::Base
   has_many :company_users
   has_many :companies, through: :company_users
   accepts_nested_attributes_for :company_users
end

#app/models/company_user.rb
class CompanyUser < ActiveRecord::Base
   belongs_to :company
   belongs_to :user
   accepts_nested_attributes_for :company
end

#app/models/company.rb
class Company < ActiveRecord::Base
   has_many :company_users
   has_many :users, through: :company_users
end

If you want to create a company and company_user, you'll have to pass params for both. Although it looks messy, all you're doing is passing each nested object to their respective models.

If you want to set the "role", you have to pass the attributes to company_users. If you want to also create a new company (rather than just assigning an existing one), you need to also pass the respective params for that too.

Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • Hi Rich, thanks for the response. I tried deploying your technique and am getting an error, similar to a question you've helped me with in the past (http://stackoverflow.com/q/34807228/2540204). After following your instructions, I am getting the error `Unpermitted parameter: companies_users`. Note that this isn't `companies_users_attributes`. Any ideas? – neanderslob Jan 28 '16 at 10:33
  • Want to go into chat? – Richard Peck Jan 28 '16 at 10:35
  • Sure, I just started one here: http://chat.stackoverflow.com/rooms/101868/room-for-neanderslob-and-rich-peck – neanderslob Jan 28 '16 at 10:37
  • Hi Rich, I applied the changes we discussed (adding in the strong parameters, putting `fields_for :companies` under `fields_for` the join table and renamed the model to follow convention). I am now getting the error `Unpermitted parameter: company`. I hate to ask again but any ideas? – neanderslob Jan 29 '16 at 10:21
  • Let's go to chat again – Richard Peck Jan 29 '16 at 10:22
0

You could explicitly reference the join table...

def new
    @user = User.new
    @company = Company.new
    @companies_user=@user.companies_user.build(company: @company, company_role: 'default role')
end
SteveTurczyn
  • 36,057
  • 6
  • 41
  • 53