0

Rails newbie here. I am having trouble with ensuring the presence of at least one "has_many :through" relationship in my users model.

I have:

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

  #validates :company_users, presence: true
end

class Company < ApplicationRecord
  has_many :company_users, dependent: :destroy
  has_many :users, through: :company_users   
end

class CompanyUser < ApplicationRecord
  belongs_to :user
  belongs_to :company
end

I got the commented validates line from the excellent answers at:

However when I implement this line, then doing the following in rails console:

c = Company.create
c.users.create!(email: "test@example.com")

gives

`raise_validation_error': Validation failed: Company users can't be blank (ActiveRecord::RecordInvalid)

From my newbie perspective, it seems like the HMT entry isn't created until after the user is created, which creates a validation error preventing the user in the first place! It's probably a very simple error, but how do I get the above behaviour to work with that validation in place?

I have tried setting inverse_of in a couple place, without any success.

And before it's mentioned, I'm purposefully using HMT instead of HABTM because I have additional attributes on the company_users model that will be set.

Nick Gobin
  • 131
  • 13

1 Answers1

1

One option would be to change the validation to

validates :companies, presence: true

and then create the user with

User.create(companies: [Company.create])

Edit:

Adding inverse_of to the CompanyUser model should also work. The validation would be left as validate :company_users, presence: true:

class CompanyUser
  belongs_to :user, inverse_of: :company_users
  belongs_to :company
end
ramblex
  • 3,042
  • 21
  • 20
  • This seems like it's not idiomatically correct and a bit of an awkward way of creating users? In any case, I don't understand how User.create(companies: [Company.create]) works. When I try calling ```User.create(email: "test@example.com", companies: c)``` as in the example above I get an ```method_missing': undefined method `each' for # – Nick Gobin Jan 21 '23 at 23:12
  • @NickGobin It should also be possible to add inverse_of to the CompanyUser model (answer edited). `User.create(email: 'test@example.com', companies: [c])` seems to have a clear intention to me i.e. it's creating a user who belongs to the given companies. An array needs to be passed in since a user can belong to many companies. – ramblex Jan 21 '23 at 23:42
  • Yes! Adding inverse_of did it! I had actually tried that earlier without success, but this time I restarted the rails server in between. Not 100% sure if that was the only thing I did different to make it work this time, but it is definitely working now. I need to read more on inverse_of, as it still confuses me a bit. In any case, thank you!! – Nick Gobin Jan 22 '23 at 00:53