ruby on rails - has_many :through with class_name and foreign_key -
i'm working straightforward has_many through: situation can make class_name/foreign_key parameters work in 1 direction not other. perhaps can me out. (p.s. i'm using rails 4 if makes diff):
english: user manages many listings through listingmanager, , listing managed many users through listingmanager. listing manager has data fields, not germane question, edited them out in below code
here's simple part works:
class user < activerecord::base has_many :listing_managers has_many :listings, through: :listing_managers end class listing < activerecord::base has_many :listing_managers has_many :managers, through: :listing_managers, class_name: "user", foreign_key: "manager_id" end class listingmanager < activerecord::base belongs_to :listing belongs_to :manager, class_name:"user" attr_accessible :listing_id, :manager_id end as can guess above listingmanager table looks like:
create_table "listing_managers", force: true |t| t.integer "listing_id" t.integer "manager_id" end so non-simple here listingmanager uses manager_id rather user_id
anyway, above works. can call user.listings listings associated user, , can call listing.managers managers associated listing.
however (and here's question), decided wasn't terribly meaningful user.listings since user can "own" rather "manage" listings, wanted user.managed_listings tweaked user.rb change has_many :listings, through: :listing_managers has_many :managed_listings, through: :listing_managers, class_name: "listing", foreign_key: "listing_id"
this exact analogy code in listing.rb above, thought should work right off. instead rspec test of barfs saying activerecord::hasmanythroughsourceassociationnotfounderror: not find source association(s) :managed_listing or :managed_listings in model listingmanager. try 'has_many :managed_listings, :through => :listing_managers, :source => <name>'. 1 of :listing or :manager?
the test being:
it "manages many managed_listings" user = factorygirl.build(:user) l1 = factorygirl.build(:listing) l2 = factorygirl.build(:listing) user.managed_listings << l1 user.managed_listings << l2 expect( @user.managed_listings.size ).to eq 2 end now, i'm convinced know nothing. yes, guess alias, i'm bothered same technique used in listing.rb doesn't seem work in user.rb. can explain?
update: updated code reflect @gregates suggestions, i'm still running problem: wrote additional test fails (and confirmed "hand"-tesing in rails console). when 1 writes test this:
it "manages many managed_listings" l1 = factorygirl.create(:listing) @user = user.last listingmanager.destroy_all @before_count = listingmanager.count expect( @before_count ).to eq 0 lm = factorygirl.create(:listing_manager, manager_id: @user.id, listing_id: l1.id) expect( @user.managed_listings.count ).to eq 1 end the above fails. rails generates error pg::undefinedcolumn: error: column listing_managers.user_id not exist (it should looking 'listing_managers.manager_id'). think there's still error on user side of association. in user.rb's has_many :managed_listings, through: :listing_managers, source: :listing, how user know use manager_id listing(s) ?
the issue here in
has_many :managers, through: :listing_managers activerecord can infer name of association on join model (:listing_managers) because has same name has_many :through association you're defining. is, both listings , listing_mangers have many managers.
but that's not case in other association. there, listing_manager has_many :listings, user has_many :managed_listings. activerecord unable infer name of association on listingmanager should use.
this :source option (see http://guides.rubyonrails.org/association_basics.html#has-many-association-reference). correct declaration be:
has_many :managed_listings, through: :listing_managers, source: :listing
(p.s. don't need :foreign_key or :class_name options on other has_many :through. you'd use define direct associations, , need on has_many :through point correct association on :through model.)
Comments
Post a Comment