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)
精彩评论