使用Ruby和MySQL进行多字搜索

Edu*_*rdo 2 ruby mysql search activerecord

我正在尝试使用Ruby,ActiveRecord和MySQL在引号数据库中完成多字搜索.我的方式如下所示,它正在运作,但我想知道是否有更好的方法.

# receives a string, splits it in a array of words, create the 'conditions'
# query, and send it to ActiveRecord
def search
    query = params[:query].strip.split if params[:query]
    like = "quote LIKE "
    conditions = ""
    query.each do |word|
        conditions += (like + "'%#{word}%'")
        conditions += " AND " unless query.last == word
    end
    @quotes = Quote.all(:conditions => conditions)
end
Run Code Online (Sandbox Code Playgroud)

我想知道是否有更好的方法来组成这个'条件'字符串.我也尝试使用字符串插值,例如,使用*运算符,但最终需要更多的字符串处理.提前致谢

Sim*_*tti 9

首先,我强烈建议您将Model的逻辑移到模型中.不是在Controller中创建搜索逻辑,而是在Quote模式中创建一个#search方法.

class Quote
  def self.search(query)
    ...
  end
end
Run Code Online (Sandbox Code Playgroud)

你的控制器变成了

# receives a string, splits it in a array of words, create the 'conditions'
# query, and send it to ActiveRecord
def search
  @quotes = Quote.search(params[:query])
end
Run Code Online (Sandbox Code Playgroud)

现在,回到原来的问题.您现有的搜索逻辑会犯一个非常糟糕的错误:它直接插入值,将代码打开到SQL注入.假设您使用Rails 3,您可以利用新的#where语法.

class Quote
  def self.search(query)
    words = query.to_s.strip.split
    words.inject(scoped) do |combined_scope, word|
      combined_scope.where("quote LIKE ?", "%#{word}%")
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

这是一个高级主题.我想了解combined_scope+的inject作用,我建议你阅读文章The Skinny on Scopes.

  • 我建议将`to_s.downcase.strip.split.uniq`折叠成小写并删除重复的单词. (2认同)