Martyn W. wrote in post #1071177:
> I have a 'has many through' relationship in my models. I am trying to
> access objects from either side of this relationship, with mixed
> results.Here are my models:
>
> class Material < ActiveRecord::Base
> attr_accessible :description, :number
> has_many :parts
> has_many :work_tickets, :through => :parts
> end
>
> class Part < ActiveRecord::Base
> belongs_to :material
> attr_accessible :description, :number, :yield, :material_id
> has_many :work_tickets
> has_many :operations, :dependent => :destroy
> end
>
> class WorkTicket < ActiveRecord::Base
> belongs_to :part
> belongs_to :material
> attr_accessible :number, :yield, :opened, :closed, :part_id
> has_many :works, :dependent => :destroy
> end
>
> I can access the work_tickets from the material with:
>
> @work_tickets = @material.work_tickets
>
> But, cannot access material from work_ticket:
>
> <%= work_ticket.material.number %>
>
> Forcing me to use:
>
> <%= work_ticket.part.material.number %>
>
> Am I expecting the wrong behaviour, or am I using the wrong relationship
> pattern?
The error you get is correct as your relationships are mismatched.
Let's try to analyze:
> class Material < ActiveRecord::Base
> attr_accessible :description, :number
> has_many :parts
> has_many :work_tickets, :through => :parts
> end
that means when you do material.work_tickets, it will go to the parts
table and look for field matierial_id = self.id, then from those results
get the work_tickets_id and get the WorkTicket objects that match.
Sounds ok, but might not neccessarily return you the results you want.
The mySQL query will probably be something like
select work_tickets.* from work_tickets
inner join parts on parts.work_tickets_id = work_tickets.id
inner join materials on parts.material_id = [#id]
anyway, now for the other side:
> class WorkTicket < ActiveRecord::Base
> belongs_to :part
> belongs_to :material
> attr_accessible :number, :yield, :opened, :closed, :part_id
> has_many :works, :dependent => :destroy
> end
when you do work_ticket.material, rails will go to the Material model
and look for the other side of the relationship. Here it will fail,
because though you have has_many :work_tickets, this relationship goes
through the :parts table, and NOT directly to the WorkTicket model.
There can be no match.
There are a number of ways to fix this. Let's make sure we got the
relationships right.
There's a one-many from materials to tickets.
There's a one-many from materials to parts.
There's a one-many from parts to tickets.
No need for :through table
class Material < ActiveRecord::Base
attr_accessible :description, :number
has_many :parts
has_many :work_tickets
end
class Part < ActiveRecord::Base
belongs_to :material
attr_accessible :description, :number, :yield
has_many :work_tickets
has_many :operations, :dependent => :destroy
end
class WorkTicket < ActiveRecord::Base
belongs_to :part
belongs_to :material
attr_accessible :number, :yield, :opened, :closed
has_many :works, :dependent => :destroy
end
of course changing your models means your table columns will have to
match.
--
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 [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit https://groups.google.com/groups/opt_out.