【问题标题】:Rails named_scope inheritance?Rails named_scope 继承?
【发布时间】:2011-05-05 11:52:08
【问题描述】:

我试图通过提供一个通用的基础模型来概括我的一些模型,该基础模型包含一些相互的 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 控制台中可以正常工作。有什么想法可以解决这个问题吗?谢谢。

【问题讨论】:

  • 并不是说这可以解决您的问题,但是您应该为此使用模块混合而不是继承。继承适用于表示父类“类型”的子类。
  • 实际上,@Beerlington,这可能会解决 OP 的问题,:)

标签: ruby-on-rails inheritance activerecord named-scope


【解决方案1】:

由于 ActiveRecord 试图解释您所说的内容的方式,这有点像火车残骸。通常,从 ActiveRecord::Base 派生的第一个类用于定义基表名称,其子类默认使用单表继承 (STI)。您正在通过使用 set_table_name 来解决这个问题,但通常情况下,虽然在 Rails 中可能会违背常规,但事情往往会变得一团糟。

您应该能够按照 Beerlington 的建议使用 mixin 更干净地完成此操作。

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

您应该能够将扩展包含在该模块中。如果您想进一步清理它,请编写一个初始化程序,为触发此行为的 ActiveRecord::Base 定义类似 scoped_by_name 的方法:

class ActiveRecord::Base
  def scoped_by_name
    extend ByNameExtension
  end
end

然后你可以标记所有需要这个的类:

class MyModel < ActiveRecord::Base
  scoped_by_name
end

【讨论】:

  • 这看起来很棒。初始化器(ActiveRecord::Base)代码文件放在哪里?
  • 除非你制作了合适的 gem 或插件,否则config/initializers 通常是个好地方。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多