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