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)