2016-07-17 25 views
8

tatmin katılır:ActiveRecord koşulu Böyle bir veritabanı modeli olan tüm ilişkilerini

İstediğim sorgu o zaten oy henüz belirli bir kullanıcı için tüm posts olan
Post 
    has_many :votes 
    belongs_to :user 
User 
    has_many :posts 
    has_many :votes 
Vote 
    belongs_to :post 
    belongs_to :user 

.

böyle denedim: 1 sadece bir örnektir kullanıcı kimliği olan

Post.left_outer_joins(:votes).where.not(votes: { user_id: 1 }) 

.

Sorun, bu sorgunun user_id'un 1 olmadığı en az bir oyu olan tüm posts getirdiği görünüyor.
Ancak birden fazla kullanıcı bu yayınlar için oy kullanacağı için, birden fazla oylama olduğunda, tüm kullanıcılar şu anda tüm Mesajları alacak. joins doğru yaklaşım ise

Bilmiyorum ama İngilizce benim Sorgu olacaktır:

bana oyların hiçbiri 1

mi bir user_id olan tüm Mesajını ver Daha önce oy vermediği bir kullanıcı için sadece posts'u almak mümkün mü?

DÜZENLEME:

yukarıdaki üç tablo Benim veritabanı şeması:

Oy:

CREATE TABLE "votes" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
     "post_id" integer, 
     "user_id" integer, 
     "created_at" datetime NOT NULL, 
     "updated_at" datetime NOT NULL, 
     "vote_type" integer DEFAULT 0); 
CREATE INDEX "index_votes_on_post_id" ON "votes" ("post_id"); 
CREATE INDEX "index_votes_on_user_id" ON "votes" ("user_id"); 

Mesajlar:

CREATE TABLE "posts" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
     "photo_gcs_key" varchar, "photo_gcs_bucket" varchar, 
     "user_id" integer, "campaign_id" integer, 
     "created_at" datetime NOT NULL, 
     "updated_at" datetime NOT NULL); 
CREATE INDEX "index_images_on_user_id" ON "images" ("user_id"); 
CREATE INDEX "index_images_on_campaign_id" ON "images" ("campaign_id"); 

kullanıcılar:

CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
     "uid" varchar, "display_name" varchar, "email" varchar, 
     "photo_url" varchar, "photo_gcs_key" varchar, 
     "photo_gcs_bucket" varchar, "user_name" varchar, 
     "created_at" datetime NOT NULL, 
     "updated_at" datetime NOT NULL); 
Eğer kullanıcı tarafından oluşturulan mesajları görmezden umurumda değil eğer
+0

Yukarıdaki üç tablonun şemasını gönderebilir misiniz? – 1000111

+0

@ 1000111 Ne demek istiyorsun? İlk birkaç satır, tablolar arasındaki ilişkileri göstermektedir. Başka neye ihtiyacın var? – Ybrin

+0

bu sorgunun çıktısını yapıştır: 'show tablosu oluştur ' – 1000111

cevap

8

Yani, bu

gibi bir şey kullanıcı, ilk o zaman olarak olanları oy kullandığı mesajlar öğrenin olmalıdır.

Post.where.not(id: Vote.where(user_id: user_id).select(:post_id)) 
1

Açıkladığınız gibi bir örnek oluşturuyorum. Bir kullanıcı, id '1' ve beş mesaj, '1' - '5' oluşturdum. Sonra '2' ve '4' mesajlarını beğenirim. Diğer cevaptaki sözdizimi çalışmadı, not hakkında şikayet etti. Aşağıdakiler kullanıcı tarafından beğenilmeyen mesajları (1, 3, 5) seçmek için çalışır '1'

irb(main):062:0> Post.where(Sequel.~(id: Vote.select(:post_id).where(user_id: 1))) 
=> #<Sequel::MySQL::Dataset: "SELECT * FROM `posts` WHERE (`id` NOT IN (SELECT `post_id` FROM `votes` WHERE (`user_id` = 1)))"> 

irb(main):063:0> Post.where(Sequel.~(id: Vote.select(:post_id).where(user_id: 1))).all 
=> [#<Post @values={:id=>1, :photo_gcs_key=>nil, :photo_gcs_bucket=>nil, :user_id=>1, :campaign_id=>nil, :created_at=>2016-08-12 17:23:53 -0700, :updated_at=>2016-08-12 17:23:53 -0700}>, #<Post @values={:id=>3, :photo_gcs_key=>nil, :photo_gcs_bucket=>nil, :user_id=>1, :campaign_id=>nil, :created_at=>2016-08-12 17:23:56 -0700, :updated_at=>2016-08-12 17:23:56 -0700}>, #<Post @values={:id=>5, :photo_gcs_key=>nil, :photo_gcs_bucket=>nil, :user_id=>1, :campaign_id=>nil, :created_at=>2016-08-12 17:23:57 -0700, :updated_at=>2016-08-12 17:23:57 -0700}>] 
+0

Oops, cevabım bir ActiveRecord kurulumu değil, bir Ruby Sequel model kurulumu. – Tony

İlgili konular