2017-01-22 28 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個模型之間的連接是通過郵件表完成的,這裏是遷移(字段發件人,收件人),所以我不需要的users.message_idusers 。此外,任何用戶都可以發送/接收多條消息,也許我的實現不反映?應該怎麼做?

這裏是消息遷移:

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'列上用戶表。 – Iceman

+0

@Iceman請看我的編輯,thatnks。 – yossico

+0

我可以看到,錯誤消息說,這個列在用戶表中丟失,但sinc用戶可以有很多消息,我不能把message_it列放在那裏。正確的方法是在消息表中添加user_it,然後再次如何防止n + 1? – yossico

回答

1

嘗試

messages = Message.includes(:recipient).references(:recipient).where(recipient_id: current_user.id) 
相關問題