Rails 命名范围继承?
我试图通过提供一个通用的基本模型来概括我的一些模型,该模型包含一些相互的named_scope声明和一个过滤器方法,该方法激活在控制器端搜索更简单的查询。当我在控制台中运行它时,这似乎有效,但在控制器中运行时失败:
# 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...)
显然,在 Rails 中时正在调用父类的named_scope,但在 Rails 控制台中运行良好。有什么想法如何解决这个问题吗?谢谢。
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...)
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于 ActiveRecord 尝试解释您所说内容的方式,这有点像火车失事。通常,从 ActiveRecord::Base 派生的第一个类用于定义基表名称,其子类默认定义为使用单表继承 (STI)。您可以使用
set_table_name
来解决这个问题,但通常情况下,虽然可能违背 Rails 的原则,但事情往往会变得混乱。按照 Beerlington 的建议,您应该能够使用 mixin 更干净地完成此操作。
您应该能够将扩展包含在该模块中。如果您想进一步清理此问题,请编写一个初始化程序,为 ActiveRecord::Base 定义类似
scoped_by_name
的方法来触发此行为:然后您可以标记所有需要此操作的类:
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.You should be able to do this a lot more cleanly using a mixin as suggested by Beerlington.
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:Then you can tag all classes that require this: