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