Reputation: 7624
I have models for a business and for a user. A business may have multiple managers, but only one of those managers can be an owner. I have tried to model as follows:
class Business < ApplicationRecord
has_many :managements
has_many :managers, through: :managements, source: :user, autosave: true
has_one :ownership, -> { where owner: true },
class_name: 'Management',
autosave: true
has_one :owner, through: :ownership, source: :user, autosave: true
end
class Management < ApplicationRecord
belongs_to :user
belongs_to :business
end
class User < ApplicationRecord
has_many :managements
has_many :businesses, through: :managements
end
This all seems to work fine until I try to save the business:
business.owner = owner
#<User id: nil, email: "[email protected]", password_digest: "$2a$04$aXswT85yAiyQ/3Pa2QAMB.4eDs9JPikpFfb8fJtwsUg...", confirmation_token: nil, confirmed_at: nil, confirmation_sent_at: nil, created_at: nil, updated_at: nil>
business.ownership
#<Management id: nil, user_id: nil, business_id: nil, owner: true, created_at: nil, updated_at: nil>
(byebug) business.owner
#<User id: nil, email: "[email protected]", password_digest: "$2a$04$aXswT85yAiyQ/3Pa2QAMB.4eDs9JPikpFfb8fJtwsUg...", confirmation_token: nil, confirmed_at: nil, confirmation_sent_at: nil, created_at: nil, updated_at: nil>
(byebug) business.valid?
false
(byebug) business.errors
#<ActiveModel::Errors:0x007f9ef5ca5148 @base=#<Business id: nil, longitude: #<BigDecimal:7f9ef2c23e48,'0.101E3',9(27)>, latitude: #<BigDecimal:7f9ef2c23d58,'-0.23E2',9(27)>, address: "line 1, line2, town, county", postcode: "B1 1NL", business_name: "Business 1", deleted_at: nil, created_at: nil, updated_at: nil>, @messages={:"ownership.business"=>["must exist"]}, @details={:"ownership.business"=>[{:error=>:blank}]}>
I don't understand what the ownership.business
relationship is? What can I do to make this work?
I am using rails 5.0.6.
Upvotes: 0
Views: 102
Reputation: 2624
Try to append inverse_of: :business
to the has_one :ownership
has_one :ownership, -> { where(owner: true) },
class_name: 'Management',
autosave: true,
inverse_of: :business
From the documentation, it seems like the :inverse_of
option is a method for avoiding SQL queries, not generating them. It's a hint to ActiveRecord
to use already loaded data instead of fetching it again through a relationship.
I think :inverse_of
is most useful when you are working with associations that have not yet been persisted.
:inverse_of
arguments, ownership.business
would return nil, because it triggers an sql query and the data isn't stored yet.:inverse_of
arguments, the data is retrieved from memory.Upvotes: 1