ruby on rails - Retrieve default belongs_to record from a built has_many association in a before_create hook? -
i have 2 models, user
, stash
.
a user has many stashes, , default_stash. stash has 1 owner (user).
before user created want build stash , assign stash self.default_stash. per instructions here rails - best-practice: how create dependent has_one relations created stash relation, cannot 'create' belongs_to relation @ same time.
user.rb
has_many :stashes, foreign_key: :owner_id belongs_to :default_stash, class_name: 'stash', foreign_key: :owner_id before_create :build_default_stash def build_default_stash self.default_stash = stashes.build true end
stash.rb
belongs_to :owner, class_name: 'user'
at point stash can found in user.stashes
user.default_stash
remains nil, stashes.build
not return id in before_create block.
what need can achieved adding following user.rb
after_create :force_assign_default_stash def force_assign_default_stash update_attribute(:default_stash, stashes.first) end
but i'd prefer keep within before_create
block if possible, validations etc.
i agree describe should work, if you're building associated records in memory , expecting them save -- hooked -- activerecord particularly finicky how define them.
but can make work without changing thing in before_create
.
the usual problem need give ar hints relationships inverses of each other. has_many
, belongs_to
methods take :inverse_of
option. problem in case have 1 side of relationship (stash#owner
) inverse of 2 on other (user#stashes
, user#default_stash
), set inverse_of
stash#owner
?
the solution add has_one
stash (call owner_as_default
), balance things out. can add inverse_of
of definitions, each identifying inverse on other side. end result this:
class user < activerecord::base has_many :stashes, foreign_key: :owner_id, inverse_of: :owner belongs_to :default_stash, class_name: "stash", inverse_of: :owner_as_default ... end class stash < activerecord::base belongs_to :owner, class_name: "user", inverse_of: :stashes has_one :owner_as_default, class_name: "user", foreign_key: :default_stash_id, inverse_of: :default_stash end
(also, don't need foreign key on belongs_to.)
from there, before_create
should work you've written it.
yes, seems lot of redundant defining. can't activerecord figure out foreign keys , whatnot? feel i'm breaking walls making 1 side aware of it's inverse of. maybe in future version of rails ironed out.
Comments
Post a Comment