开发者

Upgrade to Rails 3, has_many association extensions no longer working with scopes

I am upgrading a rails 2.3 app to rails 3.0.3

I have the following association extensions and scopes on my Product model

 has_many :related_products, :through => :product_related_products do
    [:alternative, :complement, :bigger_pack, :higher_quantity, :lower_quality].each do |meth|
    define_method(meth) {
       find :all, :conditions => ["product_related_products.#{meth} = ?", true] }
    end
 end

scope :visible, where(:hidden => false)

the concept taken from: http://guides.rubyonrails.org/association_basics.html#association-extensions

When I call the association in a chain

 @product.related_products.visible.alternative

It works fine in rails 2.3, I get the following error in Rails 3:

 undefined method `alternative' for #<ActiveRecord::Relation:0x1047ef978>

 activerecord (3.0.3) lib/active_record/relation.rb:371:in `method_missing'
 app/views/products/show.html.haml:18:in `_app_views_products_show_html_haml___1131941434_2185376080_0'

I assume its something to do with the new relation that is created but im not sure how to proceed, the rails guide still suggests this method is ok.

//edit after changes suggested by François:

Class definitions are as follows:

class Product < ActiveRecord::Base
  has_many :product_related_products
  has_many :related_products, :through => :product_related_products
end

class ProductRelatedPro开发者_StackOverflowduct < ActiveRecord::Base
  belongs_to :product
  belongs_to :related_product, :class_name => "Product"

  scope :with_attribute, lambda {|attr| where(attr, true)}

end


@product.related_products.with_attribute(:alternative) raises: 

NoMethodError Exception: undefined method `with_attribute' for #<Class:0x108fbd8b8>


Define your scopes in the related class:

class RelatedProduct < ActiveRecord::Base

  scope :visible, where(:hidden, false)

  %w(alternative complement bigger_pack higher_quantity lower_quality).each do |attribute|
    scope attribute, where(attribute, true)
  end

end

@product.related_products.visible.bigger_pack

Alternatively, create a single method that expects the attribute you're searching for:

class RelatedProduct < ActiveRecord::Base
  scope :with_attribute, lambda {|attr| where(attr, true)}
end

@product.related_products.visible.with_attribute(:bigger_pack)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜