Accessing from both ends of has many through relationship

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?

On 3 August 2012 15:57, Martyn W. [email protected] wrote:

class Part < ActiveRecord::Base
  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 %>

What happens when you do this? You have specified a simple WorkTicket
belongs_to :material so there is nothing complex about this.

Forcing me to use:

<%= work_ticket.part.material.number %>

Am I expecting the wrong behaviour, or am I using the wrong relationship
pattern?

It appears you have two routes for getting to material, that is bad as
there is redundant information somewhere and there is a danger of the
two routes getting mismatched.

Colin

For <%= work_ticket.material.number %>

I get undefined method `number’ for nil:NilClass

Please remember to quote the previous message so that it is easier to
follow the thread, remember this is a mailing list not a forum (though
you may be accessing it through a forum like interface).

On 3 August 2012 17:02, Martyn W. [email protected] wrote:

For <%= work_ticket.material.number %>

I get undefined method `number’ for nil:NilClass

Try displaying work_ticket.material_id, I think you will find that it
is not set.

Colin

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.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs