简体   繁体   中英

Rails: Has many through associations — find with AND condition, not OR condition

I have the following query method in my ActiveRecord model:

def self.tagged_with( string )
    array = string.split(',').map{ |s| s.lstrip }
    select('distinct photos.*').joins(:tags).where('tags.name' => array )
end

So, this finds all records that have tags taken from a comma separated list and converted into an array.

Currently this matches records with ANY matching tags -- how can I make it work where it matches ALL tags.

IE: if currently if I input: "blue, red" then I get all records tagged with blue OR red.

I want to match all records tagged with blue AND red.

Suggestions?

-- EDIT --

My models are like so:

class Photo < ActiveRecord::Base
  ...
  has_many :taggings, :dependent => :destroy
  has_many :tags, :through => :taggings
  ...
  def self.tagged_with( string )
    array = string.split(',').map{ |s| s.lstrip }
    select('distinct photos.*').joins(:tags).where('tags.name' => array )
  end
  ...
end

class Tag < ActiveRecord::Base
  has_many :taggings, :dependent => :destroy
  has_many :photos, :through => :taggings
end

class Tagging < ActiveRecord::Base
  belongs_to :photo
  belongs_to :tag
end

A tag has two attributes: ID and Name (string).

This should work:

def self.tagged_with( string )
  array = string.split(',').map{ |s| s.lstrip }
  select('distinct photos.*').
    joins(:tags).
    where('tags.name' => array).
    group("photos.id").
    having("count(*) = #{array.size}")
end

Above will match photos that have tags red and blue at least . So that means if a photo has red, blue and green tags, that photo would match too.

You could change your select statement to the following:

select('distinct photos.*').joins(:tags).where('tags.name = ?',  array.join(' OR '))

Which will properly create the OR string in the where clause.

ian.

LOL the solution for this is not a simple task--I thought through it from a SQL standpoint and it was UGLY. I figured somebody else has to have tried this so I did some searching and found this post that should help you:

HABTM finds with "AND" joins, NOT "OR"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM