2017-01-22 8 views
0

を参照するときに、私は2つのモデルがあります:RailsのN + 1回、同じモデルに

class User < ActiveRecord::Base 

end 

class Message < ActiveRecord::Base 
    has_one :sender, :class_name => 'User' 
    has_one :recipient, :class_name => 'User' 
end 

を、私は私が持っているユーザーはmessages_controller.rbにして受け取ったすべてのメッセージを取得したい:

def messages_to_user 
    messages = Message.where(recipient_id: current_user.id) 

    respond_with messages 
    end 

このサービスは動作しますが、ログに私は古典的なN + 1つの問題を見ることができます:

Started GET "/messages_to_user" for 127.0.0.1 at 2017-01-22 15:35:01 +0200 
Processing by MessageController#user as */* 
    User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 2]] 
    Message Load (0.0ms) SELECT "messages".* FROM "messages" WHERE "messages"."recipient_id" = ? [["recipient_id", 2]] 
[active_model_serializers] User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]] 
[active_model_serializers] Rendered ActiveModel::Serializer::CollectionSerializer with ActiveModelSerializers::Adapter::Attributes (42.01ms) 
Completed 200 OK in 217ms (Views: 63.0ms | ActiveRecord: 3.0ms) 

は、だから私はを追加することによって、それを解決しようとしました:

def messages_to_user 
    messages = Message.includes(:recipient).where(recipient_id: current_user.id) 

    respond_with messages 
    end 

しかし、その後、私は次のエラーを取得する:それは固定することができますどのように

SQLite3::SQLException: no such column: users.message_id: SELECT "users".* FROM "users" WHERE "users"."message_id" IN ('1', '2', '3', '4', '5', '6', '7', '8', '9') 

私は、ユーザとユーザ内のメッセージセットではなく、メッセージの集合を返したいと思います。しかし、N + 1問題なく

EDIT

2つのモデル間の接続は、メッセージテーブルを介して行われ、ここでの移行(フィールドの送信者、受信者が)あるので、私はusersusers.message_idを必要といけません。さらに、どのユーザも複数のメッセージを送受信することができますが、私の実装はそれを反映していませんか?どのようにそれを行う必要がありますか?ここ

は、メッセージの移行です:

class CreateMessages < ActiveRecord::Migration 
    def change 
    create_table :messasges do |t| 
     t.string :title 
     t.references :sender, index: true, foreign_key: true 
     t.references :recipient, index: true, foreign_key: true 
     t.string :content 
     t.timestamps null: false 
    end 
    end 
end 
+0

を試してみて、エラーメッセージは非常に明確である、上の欠落している 'message_id'列がありますusersテーブル – Iceman

+0

@Iceman私の編集、thatnksをご覧ください。 – yossico

+0

私は、この列がユーザーの表にはありませんが、sincユーザーはメッセージの列を置くことができない多くのメッセージを持つことができるというエラーメッセージが表示されていることがわかります。正しい方法は、メッセージテーブルにuser_itを追加することです。その後buを再実行して、どのようにn + 1を防ぐことができますか? – yossico

答えて

1

はまあ、あなたが必要な列を追加する必要が

messages = Message.includes(:recipient).references(:recipient).where(recipient_id: current_user.id) 
関連する問題