自定义 ActiveRecord 查找器调用命名范围?

发布于 2024-08-20 05:59:25 字数 1585 浏览 4 评论 0原文

我有一个自定义查找器定义如下:

class ContainerGateIn << ActiveRecord::Base
  ...
  def self.search(text)
    result = if text
      text.split(' ').inject(self) do |result, criteria|
        case criteria
          when /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/
            result.search_by_date(criteria.to_date)
          else
            result.search_by_text(criteria)
        end
      end
    else
      self
    end
  end
  ...
end

其中 search_by_date 和 search_by_text 是命名范围,而 eager 是急切加载命名范围,定义为:

named_scope :eager, :include => [{:container_inventory => {:container => [:size_type, :grade]}}, :company, :truck, :hauler]

关联是通过 HMT 设置的(has_many :through):

class ContainerDepot << ActiveRecord::Base
  has_many :container_inventories
  has_many :container_gate_ins, :through => :container_inventories do
end

问题是查找器是否通过以下方式调用从 ContainerDepot 嵌套关联时,它会失败并显示 ActiveRecord::Statement::Invalid,表示该表已被指定多次。

ContainerDepot.first.container_gate_ins.eager.search(text)
=> ActiveRecord::StatementInvalid: PGError: ERROR:  table name "container_inventories" specified more than once

我可以通过将整个自定义查找器复制为关联扩展来纠正它:

class ContainerDepot << ActiveRecord::Base
  ...
  has_many :container_gate_ins, :through => :container_inventories do
    def search(text)
      ... custom finder code from ContainerGateIn ...
    end
  end
  ...
end

尽管它不是很干燥,并且引入了非常不必要且可能有问题的冗余,因为自定义查找器必须不时更改以适应额外的搜索逻辑。

关于如何做得更好有什么想法吗?

I have a custom finder defined below:

class ContainerGateIn << ActiveRecord::Base
  ...
  def self.search(text)
    result = if text
      text.split(' ').inject(self) do |result, criteria|
        case criteria
          when /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/
            result.search_by_date(criteria.to_date)
          else
            result.search_by_text(criteria)
        end
      end
    else
      self
    end
  end
  ...
end

Where search_by_date and search_by_text are named scopes, and eager is an eager-loading named scope defined as:

named_scope :eager, :include => [{:container_inventory => {:container => [:size_type, :grade]}}, :company, :truck, :hauler]

The association is setup via a HMT (has_many :through):

class ContainerDepot << ActiveRecord::Base
  has_many :container_inventories
  has_many :container_gate_ins, :through => :container_inventories do
end

The problem is if the finder is invoked via association nesting from ContainerDepot, it fails with an ActiveRecord::Statement::Invalid, saying that the table has been specified more than once.

ContainerDepot.first.container_gate_ins.eager.search(text)
=> ActiveRecord::StatementInvalid: PGError: ERROR:  table name "container_inventories" specified more than once

I could correct it by copying the whole custom finder as an association extension:

class ContainerDepot << ActiveRecord::Base
  ...
  has_many :container_gate_ins, :through => :container_inventories do
    def search(text)
      ... custom finder code from ContainerGateIn ...
    end
  end
  ...
end

It is not very DRY though and introduces a very unnecessary and potentially problematic redundancy, as the custom finder will have to be changed from time to time to accomodate additional search logic.

Any ideas on how this could be done better?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

待天淡蓝洁白时 2024-08-27 05:59:25

您可以将named_scope与lambda一起使用,从而允许您将参数传递给作用域方法:

named_scope :eager, lambda {|text| {:conditions=>{:name=>text}, :include => [{:container_inventory => {:container => [:size_type, :grade]}}, :company, :truck, :hauler]}}

这应该允许您仅使用一个命名范围来包含和过滤。

You can use named_scope with a lambda, allowing you to pass in parameters to the scoping method:

named_scope :eager, lambda {|text| {:conditions=>{:name=>text}, :include => [{:container_inventory => {:container => [:size_type, :grade]}}, :company, :truck, :hauler]}}

This should allow you to include and filter with only one named scope.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文