如何正确重写ActiveRecord的where方法?

Rob*_*bin 6 ruby activerecord ruby-on-rails

我已经成功地覆盖了该where方法。我想要实现的行为是,如果hstore访问 my ,它会where以这样的方式重写查询,即这些hstore项目被视为单独的列。这是我的where方法:

def where(opts = :chain, *rest)
  if opts == :chain
    WhereChain.new(spawn)
  elsif opts.blank?
    return self
  elsif opts.is_a?(Hash)
    translated_attributes(opts).each do |attribute|
      return spawn.where!("'#{opts[attribute]}' = any(avals(#{attribute}))", rest)
    end
  else
    super(opts, rest)
  end
end
Run Code Online (Sandbox Code Playgroud)

为此,我写了这个minitest,效果很好!

def test_where_query_with_translated_value
  PageWithFallbacks.create!(:title_raw => {'en' => 'English title', 'de' => 'Deutscher Titel'})
  exp = PageWithFallbacks.create!(:title_raw => {'en' => 'Another English title', 'de' => 'Noch ein Deutscher Titel'})
  res = PageWithFallbacks.where(title: 'Another English title').first
  assert_equal(exp.id, res.id)
end
Run Code Online (Sandbox Code Playgroud)

现在我为这些find_by()方法编写了另一个测试:

def test_find_by_query_with_translated_value
  PageWithFallbacks.create!(:title_raw => {'en' => 'English title', 'de' => 'Deutscher Titel'})
  exp = PageWithFallbacks.create!(:title_raw => {'en' => 'Another English title', 'de' => 'Noch ein Deutscher Titel'})
  res = PageWithFallbacks.find_by(title: 'Another English title')
  assert_equal(exp.id, res.id)
end
Run Code Online (Sandbox Code Playgroud)

不幸的是这不起作用。正如“我们”已经发现的那样,find_by()ActiveRecord 有两种不同的实现。 Find_by()调用核心中的实现,该实现创建 aActiveRecord::StatementCache::Substitute并将其交给我的where方法。我不知道该如何处理这个问题?我该如何修改声明?

顺便说一句,这有助于我实现Awesome_hstore_translate