If I have a model scheme like this: Company 1---* Customer 1---* Car 1---* Workcard Or in Rails language: class Company < ActiveRecord::Base has_many :customers end class Customer < ActiveRecord::Base belongs_to :company has_many :cars end class Car < ActiveRecord::Base belongs_to :customer has_many :workcards end class Workcard < ActiveRecord::Base belongs_to :car end I can easily extend the associations in Company with class Company < ActiveRecord::Base has_many :customers has_manu :cars, :through => :customers end But what if I also want a direct associations to Workcard? Like this? class Company < ActiveRecord::Base has_many :customers has_manu :cars, :through => :customers has_manu :workcards, :through => :cars end When I do this (assuming, that I''ve filled the DB with relevant data) company = Company.find(1) company.customers => Works fine company.cars => Works fine company.workcards => Gives the following error: ActiveRecord::StatementInvalid: Mysql::Error: #42S22Unknown column ''cars.company_id'' in ''where clause'': SELECT workcards.* FROM workcards INNER JOIN cars ON workcards.car_id = cars.id WHERE ((cars.company_id 1)) So ActiveRecord assumes, that the Car model should have a direct association to Company instead of going through the other "has_many through" association between Company and Cars. How do I go around and implement this? Should I default to making a finder method class Company < ActiveRecord::Base has_many :customers has_manu :cars, :through => :customers def workcards # Loop through all cars, find related workcards, and return them merged ... end end Or is there a better approach? - Carsten -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Carsten Gehling wrote:> class Company < ActiveRecord::Base > has_many :customers > has_many :cars, :through => :customers > has_many :workcards, :through => :cars > end > > doesnt work!yeah. I haven''t tried this for a while, but it certainly didn''t used to be possible, although I imagine someone could probably code a rails patch to add this functionality. My solution would be something like; class Company < ActiveRecord::Base has_many :customers has_many :cars, :through => :customers def workcards(force_reload=false) self.cars(force_reload).map{|car| car.workcards(force_reload)} end end and make sure that if I need to do this en-masse, instead of; Company.find(:all, :include => :workcards) you''d have to go, Company.find(:all, :include => {:cars => :workcards}) but yeah... I''m gonna play around with this... must be a reason noone''s ever patched rails to allow multi-level :throughs -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Matthew Rudy Jacobs wrote:> def workcards(force_reload=false) > self.cars(force_reload).map{|car| car.workcards(force_reload)} > endNice solution. I''ll probably never need to do the find(:all) on companies and at the same time load workcards. One thing though: On associated cars I would be able to do this: company.cars.find(:all, :conditions => {:model => ''Seat''}) but I cannot do company.workcards.find(:all, :conditions => {:status => ''open''}) I can do a work-around (I did already and decided I could always refactor when the geniuses at ruby-forum had had their say). I just wanted to find out, if I was severly missing a point here.> must be a reason noone''s ever patched rails to allow multi-level > :throughsI''ve spent more than an hour googling for any sources about this. It almost seems, that noone has ever had the need to do this before. One could argue that, while my db-design is fully 3NF I should proably add company_id as a foreignkey on the workcard model due to performance considerations. - Carsten -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Carsten Gehling wrote:> > On associated cars I would be able to do this: > > company.cars.find(:all, :conditions => {:model => ''Seat''}) > > but I cannot do > > company.workcards.find(:all, :conditions => {:status => ''open''}) > > - CarstenDo you really need a fake proxy for company.workcards? How about just def find_workcards(*args) car_ids = self.cars.map(&:id) Workcard.send(:with_scope, :find => {:conditions => {:car_id => car_ids}}) do Workcard.find(*args) end end But... if you really want to this may work. class Company has_many :cars, :through => :customers def workcard(force_reload=false) return @workcard_proxy if @workcard_proxy && !force_reload @workcard_proxy = WorkcardProxy.new(self) end class WorkcardProxy delegate :each, :[], :length, :size, :to => :all def initialize(company) @company = company end def cars @cars = @company.cars end def all(force_reload=false) return @all if @all && !force_reload @all = find(:all) end def scope(&block) car_ids = self.cars.map(&:id) Workcard.send(:with_scope, :find => {:conditions => {:car_id => car_ids}}) do return(yield(&block)) end end def find(*args) scope do return Workcard.find(*args) end end def count(*args) scope do return Workcard.count(*args) end end end end big me up on WWR; http://workingwithrails.com/person/12394-matthew-rudy-jacobs Matthew Rudy -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Matthew Rudy Jacobs wrote:> big me up on WWR; > http://workingwithrails.com/person/12394-matthew-rudy-jacobsWow.... I will. But I think I have to wait for tomorrow to fully understand your code fully. It''s 23.36 here in Denmark, and I am on my third glass of wine. So my brain bailed out on your example. :-) But thanks for these very thorough examples. I don''t really know yet, if I need a proxy, since your find_workcard method does the trick. My question actually stemmed from looking at my E/R diagram and thinking relation complexities and performance-issues. That set me on the track of looking for "The Rails Way" on nested associations (beyond the first level done by :through) On another note: Why is it not possible to do "belongs_to :through..." ? I know that it''s easy to do workcard.car.customer.company.<some-attribute>, but I read about "Preventing train wrecks" in "Advanced Rails Recipes". It gives a solution on the method scope (with delegation), but not an entire association "up through the hierarchy". - Carsten -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Sorry if I am blabbering now - it''s probably the wine. :-) - Carsten -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Carsten Gehling wrote:> On another note: Why is it not possible to do "belongs_to :through..." ? > > - CarstenI dunno, I guess just because it seems like a wild use case that you''d want to build 2nd level associations that way. say; house belongs to street belongs to town belongs to state belongs to country country.houses.create seems reasonable (ish). but house.create_country seems crazy. can''t see how you''d use it as anything other than a shortcut for multiple delegates. -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---