2016-04-09 16 views
1

Kullanıcılar ve Oturumlar bir has_and_belongs_to_many derneğine dahil edildi.Birleştirilmiş bir tablodan sonuçları filtreleyen bir ActiveRecord sorgusunu nasıl yazarım?

Aşağıdaki koşullara uyan Kullanıcıların benzersiz listesini nasıl edinebilirim?

  • user.coach == true
  • user.available == true

Ve bu kullanıcı herhangi bir etkin Oturumda bir koç ise o zaman bir kullanıcı EKLEMEMELİSİNİZ:

  • session.coach_id == user.id
  • session.call_ends_at == nil

Bunu ActiveRecord Sorgu dili ile yazmanın bir yolu var mı? Saf bir SQL ifadesi yazmam gerekiyor mu? Bir çeşit melez mi? Sen ne yapardın?

Ayrıca burada yararlı olabilecek tanımlanmış kapsamlarım var.

  • User.available_coaches (kapsam)
  • Session.in_progress (kapsam)

Kullanıcı modeli

class User < ActiveRecord::Base 
    has_many :client_sessions, class_name: 'Session', foreign_key: :client_id 
    has_many :coach_sessions, class_name: 'Session', foreign_key: :coach_id 

    scope :coaches, -> { where(coach: true) } 
    scope :available_coaches, -> { coaches.where(available: true) } 

Oturum modeli

class Session < ActiveRecord::Base 
    belongs_to :client, class_name: 'User' 
    belongs_to :coach, class_name: 'User' 

    scope :in_progress, -> { where.not(coach: nil).where(call_ends_at: nil) } 
: Ama bunları nasıl ekleneceğini emin değilim

SQL'de exists ile bunu yapacağını

create_table "sessions", force: :cascade do |t| 
    t.integer "client_id" 
    t.integer "coach_id" 
    t.boolean "canceled",   default: false 
    t.datetime "coach_accepted_at" 
    t.datetime "call_begins_at" 
    t.datetime "call_ends_at" 
    t.datetime "created_at",      null: false 
    t.datetime "updated_at",      null: false 
end 

add_index "sessions", ["client_id"], name: "index_sessions_on_client_id", using: :btree 
add_index "sessions", ["coach_id"], name: "index_sessions_on_coach_id", using: :btree 

create_table "users", force: :cascade do |t| 
    t.string "first_name" 
    t.string "last_name" 
    t.boolean "coach",    default: false 
    t.boolean "available",   default: false 
    t.datetime "created_at",      null: false 
    t.datetime "updated_at",      null: false 
end 
+1

'User.joins (: oturumları) .where (koç: true, available: true) .where.not (oturumları: {coach_id: user.id, call_ends_at: nil})' - bunun sizin için çalışıp çalışmadığını kontrol edin, Ben test etmedim. – dp7

+0

Teşekkürler! Süper yakındı ve çözmeme yardımcı oldu. User.joins (: coach_sessions) .yer (koç: gerçek, mevcut: doğru) .where.not (oturumları: {call_ends_at: nil}) uniq' –

+0

Hmm ... Aslında bunu yapmaz. Hiçbir oturumları olmayan kullanıcıları bulmam gerekiyor: call_ends_at: nil'. Bu, herhangi bir 'call_ends_at' değerinin sıfırlanmaya ayarlanmamış oturumları olan kullanıcıları döndürür. bu mantıklı mı? –

cevap

1

Şema: olduğundan hiçbir .uniq için gerek yoktur sessions katılmak olduğunu

User.where(coach: true, available: true). 
    where("not exists (select 1 from sessions " + 
    "where sessions.coach_id = users.id and sessions.call_ends_at is null)") 

Not.

İlgili konular