没有这样的列users.user_id,试图为用户实现友谊关系

时间:2016-02-23 17:45:36

标签: ruby-on-rails ruby activerecord rspec rails-activerecord

我解决了这个问题,请参阅下面的答案,了解完整功能的关系,模型和架构。

在测试我的友谊模型时,我遇到了错误:

ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: users.user_id: SELECT 1 AS one FROM "users" INNER JOIN "friendships" ON "users"."id" = "friendships"."friend_id" WHERE "friendships"."user_id" = ? AND "users"."user_id" IN (SELECT "friendships"."id" FROM "friendships" WHERE "friendships"."status" = ?) AND "users"."id" = ? LIMIT 1

在创建友谊后尝试在rspec测试中访问用户pending_friends时。我有以下代码来定义友谊:

class Friendship < ActiveRecord::Base
  belongs_to :user
  belongs_to :friend, :class_name => "User"

  enum status: [:pending, :accepted]
  scope :accepted, -> { where(status: :accepted) }
  scope :pending, -> { where(status: :pending) }
  validates :user, uniqueness: { scope: :friend, message: "This user is already your friend" }

  def decline
    self.destroy
  end

  def accept
    self.update status: :accepted
  end

end

下面的代码定义了pending_friends在我的用户模型中应该是什么:

has_many :friendships
has_many :pending_friends, -> { where(friendships: Friendship.pending) }, 
                      through: :friendships, class_name: "User", source: :friend

我不确定为什么它会尝试访问users.user_id ...如果有人知道如何解决这个问题,我们将非常感谢任何帮助,我一直在深入研究联接的工作原理但我似乎无法找到任何有用的东西。

仅供参考:这就是我创造友谊的方式:

friendship1 = Friendship.build(user: current_user, friend: other_user)
friendship2 = Friendship.build(user: other_user, friend: current_user)

(然后进行保存和错误检查)

这是我的友谊迁移:

class CreateFriendships < ActiveRecord::Migration
  def change
    create_table :friendships do |t|
      t.integer :status, :null => false, :default => 0
      t.integer :user_id
      t.integer :friend_id

      t.timestamps null: false
      end
   end
end

2 个答案:

答案 0 :(得分:1)

让我们深入探讨这个问题。 注意:在关键字上缩进SQL可以更容易地发现正在发生的事情:

SELECT  1 AS one
FROM "users"
INNER JOIN "friendships" ON "users"."id" = "friendships"."friend_id"
WHERE "friendships"."user_id" = ? AND 
      "users"."user_id" IN (
         SELECT "friendships"."id"
         FROM "friendships"
         WHERE "friendships"."status" = ?) AND 
      "users"."id" = ?
LIMIT 1

所以......问题显然是这句话:"users"."user_id" IN 用户没有user_id,用户有id

友谊有user_id。所以...有些东西导致你的SQL认为你应该通过user_id获取用户,而不应该以这种方式取出友谊。

has_many :pending_friends, -> { where(friendships: Friendship.pending) }, 
                  through: :friendships, class_name: "User", source: :friend

显然是产生此权利的代码?

如何将挂起的部分从pending-friends部分拆分出来,看看它们是否分开工作:

has_many :friendships
has_many :pending_friendships, -> { friendships.merge(Friendship.pending) }

看看那部分是否有效?如果没有让它工作(它更简单) (注意:我没有测试过这段代码,你可能需要以不同的方式做这个部分...尝试一下)

然后你可以添加:

has_many :pending_friends, through: :pending_friendships, class_name: "User", source: :friend

答案 1 :(得分:0)

这就是为我做的,感谢max关于如何格式化procs的提示

友谊迁移

class CreateFriendships < ActiveRecord::Migration
  def change
    create_table :friendships do |t|
      t.integer :status, :null => false, :default => 0
      t.integer :user_id
      t.integer :friend_id

      t.timestamps null: false
    end
  end
end

用户模型中的友谊关系

has_many :friendships, :foreign_key => :user_id, dependent: :destroy
has_many :inverse_friendships, :foreign_key => :friend_id, dependent: :destroy,
                    class_name: :Friendship

has_many :pending_incoming_friendships,  
                    -> { where(friendships: { status: 0 }) },
                    :class_name => :Friendship,
                    :foreign_key => :friend_id, :dependent => :destroy

has_many :pending_outgoing_friendships,
                      -> { where(friendships: { status: 0 }) },
                    :class_name => :Friendship,
                    :foreign_key => :user_id, :dependent => :destroy

然后我只检查状态:1获得已接受的友谊!不确定为什么检查符号或使用Friendship.accepted或Friendship.pending范围无法正常工作。看起来这个值最初被设置为&#34; pending&#34;,一个字符串,但是在我调用我的accept函数后,它明确地将它设置为一个符号,然后它就是一个符号。我选择使用整数,因为它们只有2个,并且看起来更安全,具有明显的不可预测性。