'includes'方法似乎不适用于Rails 4中的'where'

时间:2016-01-18 23:11:29

标签: ruby-on-rails ruby-on-rails-4 activerecord

在我的模型中我有:

class Song < ActiveRecord::Base

  belongs_to :artist

  def self.default_scope
    includes :artist
  end

  def self.search query
    if query
      where "title LIKE :query OR artists.name LIKE :query", query: "%#{ query }%"
    else
      where nil
    end
  end

end

在我的控制器中:

def index
  @songs = Song.search(params[:search])
  respond_with(@songs)
end

当我搜索时,我收到以下错误:

Mysql2::Error: Unknown column 'artists.name' in 'where clause': SELECT  `songs`.* FROM `songs` WHERE (title LIKE '%my search%' OR artists.name LIKE '%my search%' OR albums.name LIKE '%my search%')

我做错了什么?我认为include方法会自动进行连接。

2 个答案:

答案 0 :(得分:6)

来自docs

  

像这样使用where只有在你传递哈希时才有效。对于   您需要使用references来强制连接表的SQL片段

你是正确的includes方法会自动进行连接,但当哈希被用作where的参数时

这将检测查询并加入comments

Article.includes(:comments).where(comments: { visible: true })

这需要明确的references

Article.includes(:comments).where("comments.visible = true").references(:comments)

不考虑default_scope是否是好事,您可以使用此代码运行代码:

def self.search(query)
  if query
    references(:artists).
      where("title LIKE :query OR artists.name LIKE :query", query: "%#{query}%")
  else
    where nil
  end
end

答案 1 :(得分:2)

includes不会生成join sql,因此您无法访问其他表列。事实上,这是一个非常棘手的方法,通常最好使用preloadjoins - 了解差异会对您的应用程序性能产生巨大影响。您需要在此处使用join

class Song < ActiveRecord::Base

  belongs_to :artist

  default_scope { joins :artist }

  def self.search query
    if query
      where "title LIKE :query OR artists.name LIKE :query", query: "%#{ query }%"
    else
      all
    end
  end
end

但是请注意,使用default_scope进行连接或包含并不是最干净的方式,最终会对你产生负面影响(从困难的角度来看)会受到性能损失。