2016-08-31 36 views
1

我旁邊車型的Rails 5.錯誤結果的範圍鏈接

user.rb

class User < ApplicationRecord 
    has_many :user_tags, dependent: :destroy 
    has_many :tags, through: :user_tags 
    has_many :children, foreign_key: 'parent_id', dependent: :destroy 

tag.rb

class Tag < ApplicationRecord 
    has_many :user_tags, dependent: :destroy 
    has_many :users, through: :user_tags 

user_tag.rb

class UserTag < ApplicationRecord 
    belongs_to :tag 
    belongs_to :user 

child.rb

class Child < ApplicationRecord 
    belongs_to :parent, class_name: 'User' 

在模型的用戶,我有幾個範圍。

選擇用戶,提供一切必要的標籤關聯:

scope :search_by_tags, -> (ids) { 
    joins(:tags).where(tags: {id: ids}).having('COUNT(tags.id) >= ?', ids.count).group('users.id') 
} 

其中,產生下一個SQL請求

SELECT "users".* FROM "users" INNER JOIN "user_tags" ON "user_tags"."user_id" = "users"."id" INNER JOIN "tags" ON "tags"."id" = "user_tags"."tag_id" WHERE "tags"."id" IN (17, 37, 70, 8, 11, 3, 91, 64) GROUP BY users.id HAVING (COUNT(tags.id) >= 8) 

其他範圍中選擇用戶,帶着孩子在特定年齡相關

scope :children_in_ages, -> (age_ranges) { 
    joins(:children).where(children_ages_query(age_ranges)) 
     .where.not(children: {gender: -1}).group('users.id') 
} 

def self.children_ages_query(age_ranges) 
    child_table = Child.arel_table 
    range_conditions = age_ranges.map { |r| child_table[:birth_date].in(r) } 
    range_conditions.inject(range_conditions.shift, &:and).to_sql 
end 

其中age_ranges是日期數組。這個範圍產生下一個SQL查詢:

SELECT "users".* FROM "users" INNER JOIN "children" ON "children"."parent_id" = "users"."id" WHERE ("children"."birth_date" BETWEEN '2016-02-29 08:35:00.322919' AND '2016-08-31 08:35:00.327283') AND ("children"."gender" != $1) GROUP BY users.id 

另外,範圍正在正確的,但是當我合併範圍,我有錯誤的結果。

User.children_in_ages(a).search_by_tags(ids) 
    User Load (85.2ms) SELECT "users".* FROM "users" INNER JOIN "children" ON "children"."parent_id" = "users"."id" INNER JOIN "user_tags" ON "user_tags"."user_id" = "users"."id" INNER JOIN "tags" ON "tags"."id" = "user_tags"."tag_id" WHERE ("children"."birth_date" BETWEEN '2016-02-29 08:35:00.322919' AND '2016-08-31 08:35:00.327283') AND ("children"."gender" != $1) AND "tags"."id" IN (17, 37, 70, 8, 11, 3, 91, 64) GROUP BY users.id HAVING (COUNT(tags.id) >= 8) 

任何想法什麼可能是錯的?

+0

你並不是真正的「合併」範圍,你在其他搜索之上進行「搜索」,並通過分析輸出sql,我可以告訴它它工作得很好。預期的結果是什麼 - 你想要在一個響應中結合兩個查詢聯合? – shlajin

+0

@shlajin例如,'search_by_tags'返回帶有ids [1,2,3]的用戶數組,'children_in_ages'返回帶有ids [2,3,4]的用戶數組。預期的結果應該是具有ID [2,3]的用戶的數組。所以,是的,我需要兩個查詢的聯合 – Derk153

+0

我很難理解你想用'having('COUNT(tags.id)> =?',ids.count)實現什麼,但是我不能。 'search_by_tags'方法的目的是什麼?這不僅僅是「顯示與指定標籤相關聯的用戶」。 – shlajin

回答

0

我找到了解決方案,我的問題。

正確的方式來選擇具有特定標籤的用戶:

型號/ user.rb

scope :search_by_tags, -> (ids) { where(id: UserTag.users_with_tags(ids)) unless ids.blank? } 

型號/ user_tag.rb

scope :users_with_tags, -> (ids) { 
    select(:user_id).where(tag: ids).having('COUNT(user_id) >= ?', ids.count).group('user_id') 
} 

這樣,鏈接與其他示波器正常工作