如何将 `matches()` 与数据库函数一起使用?

How to use `matches()` with a database function?

我有一个这样的 ActiveRecord 作用域:

scope :matching, ->(query) {
  where Post.arel_table[:title].matches "%#{query}%"
}

这很好用。然后我将其更改为忽略 title:

中的额外空格
scope :matching, ->(query) {
  where "regexp_replace(title, '\s+', ' ', 'g') ILIKE ?", "%#{query}%"
}

这可行,但我不得不从 matches()(在 Ruby 级别)下降到 ILIKE(在 SQL 级别)。

是否可以将 regexp_replace(...)matches() 一起使用?例如:

scope :matching, ->(query) {
  where handwaving("regexp_replace(title, '\s+', ' ', 'g')").matches "%#{query}%"
}

(我尝试使用 Arel::Nodes::NamedFunction 但无法正常工作。)

是的,您可以按如下方式构建 Arel::Nodes::NamedFunction

condition = Arel::Nodes::NamedFunction.new(
   'regex_replace', 
   [Post.arel_attribute(:title),
    Arel.sql("'\s+'"),
    Arel.sql("' '"), 
    Arel.sql("'g'")]
).matches("%#{query}%")

然后

scope :matching, ->(query) {
  # above condition code
  where(condition)
}

这将导致以下 (query = 'testing')

SELECT 
  posts.*
FROM 
  posts
WHERE 
  regex_replace(posts.title, '\s+',' ','g') ILIKE '%testing%'