问题描述
我试图通过提供一个共同的基础模型,从继承来概括我的一些机型包含了一些相互named_scope声明,并且激活了搜索控制器端简单的查询过滤器的方法。这似乎是,当我在控制台中运行工作,但失败时控制器:
I'm trying to generalize some of my models by providing a common base model to inherit from that contains some mutual named_scope declarations and a filter method that activates that search for simpler querying on the controller side. This appears to be working when I run it in the console, but fails when in the controller:
# in the base model
class GenericModel < ActiveRecord::Base
named_scope :by_name, lambda { |name|
( name.blank? ) ? {} : { :conditions => [ "#{self.table_name}.name like ?", "%#{name}%" ] }
}
def filter(params)
res = []
res = self.by_name( (params[:name] or '') ) if params[:name]
return res
end
end
class MyModel < GenericModel
set_table_name 'my_models'
end
# works in in console!
>> params = { :name => 'jimmy' }
>> MyModel.filter(params)
=> [ <#MyModel ...>, ... ]
nil
# fails in controller
@model = MyModel.filter(params)
# ActiveRecord::StatementInvalid (Mysql::Error Unknown column 'generic_models.name' in where clause...)
显然,父类的named_scope被调用时,在轨,但能正常工作在轨控制台。任何想法如何补呢?谢谢。
Apparently the parent class' named_scope is being called when in rails, but works fine in rails console. Any ideas how to mend this? thanks.
推荐答案
这是一个有点列车残骸,因为方式的ActiveRecord试图跨preT你在说什么。从一般的ActiveRecord :: Base的派生第一类是用来定义基表的名称是,而被定义为使用单表继承(STI),默认的子类。您正在解决此通过使用 set_table_name
但是,这是常有的情况下,虽然有可能违背Rails中粮,事情往往会导致混乱。
That's a bit of a train-wreck because of the way ActiveRecord is trying to interpret what you're saying. Generally the first class derived from ActiveRecord::Base is used to define what the base table name is, and sub-classes of that are defined to use Single Table Inheritance (STI) by default. You're working around this by using set_table_name
but, as is often the case, while it's possible to go against the grain in Rails, things often get messy.
您应该可以有很多更清洁使用混入这样做所建议的Beerlington。
You should be able to do this a lot more cleanly using a mixin as suggested by Beerlington.
module ByNameExtension
def self.extended(base)
# This method is called when a class extends with this module
base.send(:scope, :by_name, lambda { |name|
name.blank? ? nil : where("#{self.table_name}.name LIKE ?", "%#{name}%")
})
end
def filter(params)
params[:name].present? ? self.by_name(params[:name]) : [ ]
end
end
class MyModel < ActiveRecord::Base
# Load in class-level methods from module ByNameExtension
extend ByNameExtension
end
您应该能够保持载到该模块的扩展。如果您想进一步打扫一下,编写定义如 scoped_by_name
A方法的ActiveRecord :: Base的触发此行为的初始化:
You should be able to keep your extensions contained to that module. If you want to clean this up even further, write an initializer that defines a method like scoped_by_name
for ActiveRecord::Base that triggers this behavior:
class ActiveRecord::Base
def scoped_by_name
extend ByNameExtension
end
end
然后你可以标记需要这一切类:
Then you can tag all classes that require this:
class MyModel < ActiveRecord::Base
scoped_by_name
end
这篇关于Rails的named_scope继承?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!