0

Why does the CompaniesController not create a record CompanyUser with current_user.companies.build(company_params)? How can I create CompanyUser record at the time of creation of the Company record?

Models:

User

class User < ApplicationRecord
  has_many :company_users, dependent: :destroy
  has_many :companies, through: :company_users
end

Company

class Company < ApplicationRecord
  include Userstampable::Stampable

  has_many :company_users, dependent: :destroy
  has_many :users, through: :company_users

  accepts_nested_attributes_for :company_users, reject_if: :all_blank

  validates :name, presence: true, length: { maximum: 100 }
  validates :description, length: { maximum: 1000 }
end

CompanyUser

class CompanyUser < ApplicationRecord
  include Userstampable::Stampable

  belongs_to :company
  belongs_to :user

  validates :company_id, presence: true
  validates :user_id, presence: true
end

CompaniesController

class CompaniesController < ApplicationController
  def create
    @company = current_user.companies.build(company_params)

    respond_to do |format|
      if @company.save
        format.html { redirect_to @company, notice: 'Company was successfully created.' }
        format.json { render :show, status: :created, location: @company }
      else
        format.html { render :new }
        format.json { render json: @company.errors, status: :unprocessable_entity }
      end
    end
  end

  private

    # Never trust parameters from the scary internet, only allow the white list through.
    def company_params
      params.require(:company).permit(:name, :description)
    end
end

Migrate

class CreateCompanyUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :company_users do |t|
      t.integer :role, default: 0
      t.belongs_to :company, null: false, foreign_key: true
      t.belongs_to :user, null: false, foreign_key: true

      t.timestamps null: false, include_deleted_at: true
      t.userstamps index: true, include_deleter_id: true

      t.index [:company_id, :user_id], unique: true
    end
  end
end
max
  • 96,212
  • 14
  • 104
  • 165
Nikolay Lipovtsev
  • 657
  • 1
  • 6
  • 15
  • Does this answer your question? - https://stackoverflow.com/a/9346642 – Nitish Parkar Jul 31 '20 at 08:19
  • current_user.companies.build(company_params) should be create a Company with CompanyUser record? – Nikolay Lipovtsev Jul 31 '20 at 17:01
  • In Rails 5+ `belongs_to` associations are non optional by default. Those two validations in CompanyUser are completely superfluous and may be the route of the problem. Also how are you actually testing this? – max Jul 31 '20 at 18:27
  • @max I'm creating a company in view. If I remove two validations, CompanyUser record will still not be created. – Nikolay Lipovtsev Jul 31 '20 at 19:11

1 Answers1

1

You need to set the :inverse_of option on the belongs_to associations in CompanyUser model and remove the presence validations on :company_id and :user_id in ComapanyUser to make this work. The ComapanyUser model should look like this:

class CompanyUser < ApplicationRecord
  include Userstampable::Stampable

  belongs_to :company, inverse_of: :company_users
  belongs_to :user, inverse_of: :company_users
end

Check the description of the :through option in ActiveRecord association docs. It mentions that you need :inverse_of to create join model records.

If you are going to modify the association (rather than just read from it), then it is a good idea to set the :inverse_of option on the source association on the join model. This allows associated records to be built which will automatically create the appropriate join model records when they are saved. (See the 'Association Join Models' section above.)

Nitish Parkar
  • 2,838
  • 1
  • 19
  • 22