Ruby on rails 轨道N+;1当两次引用同一模型时
我有两种型号:Ruby on rails 轨道N+;1当两次引用同一模型时,ruby-on-rails,activerecord,controller,Ruby On Rails,Activerecord,Controller,我有两种型号: class User < ActiveRecord::Base end class Message < ActiveRecord::Base has_one :sender, :class_name => 'User' has_one :recipient, :class_name => 'User' end 这项服务有效,但在日志中我可以看到经典的N+1问题: Started GET "/messages_to_user" for 127.
class User < ActiveRecord::Base
end
class Message < ActiveRecord::Base
has_one :sender, :class_name => 'User'
has_one :recipient, :class_name => 'User'
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)
所以我试图通过添加includes
来解决这个问题:
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问题
编辑
这两个模型之间的连接是通过messages表完成的,这里是迁移(字段sender,recipient),因此我不需要用户中的用户.message\u 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
class CreateMessages
试试看
嗯,您必须添加所需的列,错误消息非常清楚,用户表上缺少message\u id
列。@Iceman请查看我的编辑,thatnks。我可以看到错误消息说users表中缺少此列,但sinc user可能有许多消息我无法将message\u it列放在那里。正确的方法是将用户添加到消息表中,但是我又如何防止n+1呢?看起来经典有很多:通过关联,但我希望在用户模型中也有一些东西。我假设用户应该是sender
或recepient
或两者都是。所以我需要为这些字段添加has\u many:through?
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
messages = Message.includes(:recipient).references(:recipient).where(recipient_id: current_user.id)