views:

32

answers:

3

I have 2 models Widget and Feature which have a has many through association using WidgetFeature model.

  class Widget < ActiveRecord::Base
    has_many :widget_features
    has_many :features, :through => :widget_features
  end

  class WidgetFeature < ActiveRecord::Base
    belongs_to :feature
    belongs_to :widget
    attr_accessible :children_features, :widget_id, :feature_id
  end

 class WidgetFeature < ActiveRecord::Base
   belongs_to :feature
   belongs_to :widget
   attr_accessible :children_features, :widget_id, :feature_id
 end

I have a widget_id.

So i do Widget.find_by_id(widget_id)

Now i want to find all the features for this widget where widget_features.children_features IS NULL.

I dont know how to do this, help me out.

A: 

Try

@widget = Widget.find_by_id(widget_id)
@features = @widget.features.conditions("widget_features.children_features IS nil")

EDITED

Ref this

has_many :features, :through => :widget_features, :conditions=>["widget_features.children_features is nil"]

AND then

@widget = Widget.find_by_id(widget_id)
@features = @widget.features
Salil
It doesn't work.I am getting an error undefined method `conditions' for #<Class:0x7fee245df970>which means that conditions is not a method.
Silver Spoon
@Jatin:- check my edited answer.
Salil
@Salil:-It still doesn't work and gives me an SQL error.Mysql::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'nil)))' at line 1: SELECT `features`.* FROM `features` INNER JOIN `widget_features` ON `features`.id = `widget_features`.feature_id WHERE ((`widget_features`.widget_id = 1) AND ((widget_features.children_features is nil)))
Silver Spoon
`is nil` should probably be `IS NULL`
Daniel Vandersluis
@Silver Spoon:- Change `is nil` to `IS NULL`
Salil
A: 
Feature.all(:joins => :widget_features, :conditions => ["widget_id = ? and children_features is null", some_id])
Omar Qureshi
for bonus points, use a named_scope
Omar Qureshi
A: 

I worked my way around named_scope and found an elegant solution. So, I am posting it here so that others stuck with the same problem can also get help. My solution gives you a way to access any column of the join model in the has many through association.

Here's the solution for my problem above:

class Widget < ActiveRecord::Base
  has_many :widget_features
  has_many :features, :through => :widget_features

  def leaf_features
    widget_features.leaf_features.map{|widget_feature|widget_feature.feature}
  end
end

class WidgetFeature < ActiveRecord::Base
  named_scope :leaf_features, :conditions => 'children_features IS NULL'
  belongs_to :feature
  belongs_to :widget
  attr_accessible :children_features, :widget_id, :feature_id
end

Now, Widget.find_by_id(widget_id).leaf_features will give you only those features where children_features column is NULL.

Silver Spoon