简体   繁体   中英

Rails activerecord find objects with specific children associations

I have a model User who can have many Features:

class User << ActiveRecord::Base
  has_many :features, dependent: :destroy
end

class Feature << ActiveRecord::Base
  belongs_to :user
  # columns id, user_id, name
end

I have 2 features I can put on a user called "feat1" and "feat2" The 2 features can combine for a total of 4 types of users:

  1. User has feat1 ONLY
  2. User has feat2 ONLY
  3. User has BOTH feat1 and feat2
  4. User has NEITHER feat1 and feat2

I want to create scopes on user to scope out the 4 types of users.

User.only_feat1
User.only_feat2
User.both_feats
User.no_feats

I've been playing around with .merge, .uniq, .joins, .includes, but can't seem to figure out the activerecord way.

So here's my solution. It involves a lot of raw SQL, but it gets the job done. The problem is if I join the same table (features) to my users table more then once, then the where clauses get overwritten and I can't do multiple joins.

So to combat this problem, I wrote a lot of raw sql which explicitly aliases the table on the join forcing the double join table.

scope :without_feature, ->(feat) { joins("LEFT OUTER JOIN features af ON users.id = af.user_id AND af.name = '#{feat}'").where(af: {id: nil}) }
scope :feat1, -> { joins("INNER JOIN features rs ON users.id = rs.user_id AND rs.name = 'feat1'") }
scope :feat2, -> { joins("INNER JOIN features rr ON users.id = rr.user_id AND rr.name = 'feat2'") }
scope :both_feats, -> { feat1.feat2 }
scope :only_feat1, -> { feat1.without_feature('feat2') }
scope :only_feat2, -> { feat2.without_feature('feat1') }

Hope this helps anyone else.

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