2015-07-07 11 views
9

Ben User s diğer kullanıcıları onaylayabileceği bir flört tarzı uygulama yapıyorum. Bu ilişkileri izlemek için Approval modelini kullanıyorum. Her bir Approval, bir user_id ve bir approved_id - onaylanmış User'un Kullanıcı kimliğine sahiptir. Ayrıca bir User başka bir reddetti belirten bir tarih saat rejected_at vardır. DatingApp programlama: Onaylar olmayan kullanıcılar bulmak için ActiveRecord ilişkilendirmesi veya tek yönlü onaylar var

hak Kullanıcı onaylar anlam (Ya

  • No Approval münasebetini sadece current_user.id olarak approved_id ile
  • Approval ilişki vardır kendisi için Kullanıcılar için sorgulamak gerekir current_user hak Kullanıcıları sunmak current_user ancak başka bir ilişki yok
  • olmayan nil özniteliği approved_id, User veya user_id, current_user'dur.

Uygun Kullanıcılar bulmak için bir ActiveRecord sorgusunu nasıl kullanabilirim? Anladığım kadarıyla Approval numaralı telefondan joins yapabilirim ama User s arasında Approval no'lu bir ilişkinin varlığını da açıklamak istiyorum! Ben sadece 2 ayrı sorgu yapmak için daha mantıklı olabileceğini düşünüyorum ama ben bir araya getirmek mümkün olup olmadığını bilmek istiyorum ..

+0

Üçünü ya da üçünü tatmin eden bir sorgu mu arıyorsunuz? – Pavan

+0

Tüm 3 bult birinci ve ikinci bir XOR var. # 1 ve # 2'nin OR yan tümcesiyle mümkün olduğuna inanıyorum – quantumpotato

cevap

6

İstediğiniz davranış users satırları içeren LEFT OUTER JOIN olup olmadığını veya approvals'da eşleşen herhangi bir satır var. Bu şekilde, User hedefiniz hakkında Approval no'lu yayınlayan bir User veya reddeden filtreleyebileceğiniz bir tane olsun.

The query

hiçbir approvals
  • ON users.id = approvals.user_id çiftleri approvals ile users onlar
  • ON ... AND approvals.approved_id = 1 oluşturulan olsa bile,

    • users LEFT OUTER JOIN approvals tüm users dikkate alır

      adet olarak
      -- Looking for users who either have no opinion or have approved user 1 
      SELECT * 
      FROM users 
      LEFT OUTER JOIN approvals 
          ON users.id = approvals.user_id 
          AND approvals.approved_id = 1 -- Filter for only approvals of user 1 
      WHERE users.id != 1 -- Ignore user 1 
          AND (
          approvals.approved_id IS NULL -- Approving user has no opinion of user 1 
          OR approvals.rejected_at IS NULL -- Approving user has not rejected user 1 
      ) 
      ; 
      

      gibi görünecektir Sadece approvalsUser 1

    • WHERE users.id != 1 için sadece diğer
    • WHERE ... approvals.approved_id IS NULLusers değilUser 1 ilişkin herhangi approvals oluşturduk userso alır düşünmektedir düşünmektedir.
    • WHERE ... approvals.rejected_at IS NULLusersoUser 1 için bir Approval yarattı sürer ve bir ret
    değildi

    ActiveRecord özellikle oldukça biz bu tercüme zaman bir şey yapmaz, ama işe yarıyor:

    class User < ActiveRecord::Base 
        def eligible_partners 
        User.joins(# Join like we did before 
         <<-SQL 
         LEFT OUTER JOIN approvals 
         ON users.id = approvals.user_id 
         AND approvals.approved_id = #{self.id} 
         SQL 
        ).where.not(id: id) # Ignore ourselves 
        .where(# Filter for no approvals or a positive approval 
         <<-SQL 
         approvals.approved_id IS NULL 
         OR approvals.rejected_at IS NULL 
         SQL 
        ) 
        end 
    end 
    

    Daha okunabilir bir şey istiyorsanız, belirli bir kişiyi reddeden her User kimliğini toplayabilir ve ardından diğer tümnumaralarını alabilirsiniz.s. Bir yandan, iki sorgu; Diğer taraftan, masalarınız büyük olduğunda, JOIN'dan daha ucuz olabilir ve daha kolay anlaşılır.

    def other_eligible_partners 
        rejecter_ids = Approval 
         .where(approved_id: id) # About ourselves 
         .where.not(rejected_at: nil) # Rejected us 
         .pluck(:user_id) 
        User.where.not(id: rejecter_ids + [id]) # People who didn't reject us 
        end 
    
  • İlgili konular