Rails:组合多个表搜索条件

时间:2016-07-28 07:06:22

标签: ruby-on-rails search

def self.search(search)
  Post.where("caption LIKE ?", "%#{search}%") 
  Post.joins(:tags).where('tags.name LIKE ?', "%#{search}%" )
end

在这里,我试图将条件与OR语句结合起来,即我希望能够搜索帖子标题和标签名称。我如何将它们加入一条线?谢谢!

PostsController

def index
  if params[:search]
    @posts = Post.search(params[:search]).order("created_at DESC").paginate(page: params[:page], per_page: 10)
  else
    @posts = Post.all.recent.paginate(page: params[:page], per_page: 10)
  end
  respond_to do |format|
    format.html
    format.js
  end
end

post.rb

has_many :taggings
has_many :tags, through: :taggings

tag.rb

has_many :taggings
has_many :posts, through: :taggings

tagging.rb

belongs_to :post
belongs_to :tag

4 个答案:

答案 0 :(得分:2)

您必须加入两个表并编写搜索条件。确保使用LEFT JOIN,因为JOIN永远不会给你一个没有任何标签的帖子。 所以,不要这样做:

# This produces an SQL query with JOIN (not LEFT JOIN).
# Posts without tags will never be found.
Post.joins(:tags).where(...)

相反,请使用Post.includes(:tags) whith references子句:

# you have to use 'references' clause here to produce a normal LEFT JOIN query instead of eager loading associations
Post.includes(:tags).where("posts.caption LIKE :search OR tags.name LIKE :search", search: "%#{search}%" ).references(:tags)

或者您可以使用joins手动编写查询条件:

Post.joins('LEFT OUTER JOIN taggings ON taggings.post_id = posts.id LEFT OUTER JOIN tags ON taggings.tag_id = tags.id')
.where("posts.caption LIKE :search OR tags.name LIKE :search", search: "%#{search}%").uniq

如果您使用的是Rails 5,则会有一个新方法left_outer_joins也会这样做:

Post.left_outer_joins(:tags).where("posts.caption LIKE :search OR tags.name LIKE :search", search: "%#{search}%")

答案 1 :(得分:0)

Post.joins(:tags).where("posts.caption LIKE :search OR tags.name LIKE :search", search: "%#{search}%" )

答案 2 :(得分:0)

试试这个:

Post.joins(:tags).where("caption LIKE ? OR tags.name LIKE ?", "%#{search}%", "%#{search}%")

答案 3 :(得分:0)

对于高级过滤,我使用范围。您可以使用查询创建两个范围,并在控制器中调用它们。

型号:

scope :search1, -> (search) {where("caption LIKE :search", "%#{search}%")}
scope :search2, -> (search) {joins(:tags).where('tags.name LIKE :search', "%#{search}%" )}

控制器:

@posts = Post.where(nil)
@posts = @posts.search1(params[:search]) if params[:search].present?
@posts = @posts.search2(params[:search]) if params[:search].present?
@posts = @posts.recent.paginate(page: params[:page], per_page: 10)

有关范围的更多信息,请访问:http://www.justinweiss.com/articles/search-and-filter-rails-models-without-bloating-your-controller/

他的帖子帮助了我很多,我建议你阅读它:)