【问题标题】:Setting up Foreign Keys in Rails with Postgres使用 Postgres 在 Rails 中设置外键
【发布时间】:2016-10-08 05:00:04
【问题描述】:

我正在尝试跟踪用户喜欢喜欢他们的用户的共同喜欢。为了检查like是否是相互的,我在创建like之后调用一个方法。如果那个喜欢的人是一个喜欢的人,那么它被认为是相互的。

然而,问题是我遇到了一些奇怪的错误,我认为这些错误与外键的设置方式有关。我在 Rails 中设置了一个 has many 关联,但每当我尝试访问它时,都会收到 PG::InFailedSqlTransaction: ERROR: current transaction is aborted, commands ignored until end of transaction block : RELEASE SAVEPOINT active_record_1 错误。

用户:

class User < ApplicationRecord
  has_many :likes
end

点赞:

class Like < ApplicationRecord
  belongs_to :likee, class_name: 'User', foreign_key: 'likee_id'
  belongs_to :liker, class_name: 'User', foreign_key: 'liker_id'
  belongs_to :connection, optional: true

  after_save :mutual_like?

  private

  def mutual_like?

    if liker.likes.where(likee: liker)
      # fails
    end
  end
end

我尝试将钩子更改为保存等,但这也不起作用。

另外,我什至不能打电话给Like.first,否则我会得到同样的错误。

我尝试打印出liker.likes.where(likee: liker) 并得到PG::UndefinedColumn: ERROR: column likes.user_id does not exist,我认为这是问题所在。

但是,我可以像这样访问喜欢的对象:self.likee 在钩子内部,但如果不返回#&lt;Like::ActiveRecord_Associations_CollectionProxy:0x3fd91ca5ca78&gt;,我就无法调用self.likee.likes

架构:

  create_table "likes", force: :cascade do |t|
    t.integer  "liker_id",      null: false
    t.integer  "likee_id",      null: false
    t.integer  "connection_id"
    t.datetime "created_at",    null: false
    t.datetime "updated_at",    null: false
    t.index ["likee_id"], name: "index_likes_on_likee_id", using: :btree
    t.index ["liker_id"], name: "index_likes_on_liker_id", using: :btree
  end





create_table "users", force: :cascade do |t|
    t.string   "email"
    t.string   "username"
    t.string   "password_digest"
    t.boolean  "admin",                default: false
    t.index ["email"], name: "index_users_on_email", using: :btree
    t.index ["username"], name: "index_users_on_username", using: :btree
  end

测试:

RSpec.describe Like, type: :model do
  let(:liker) { Fabricate(:user) }
  let(:likee) { Fabricate(:user) }
  let(:like) { Fabricate(:like, liker: liker, likee: likee) }
  let(:pending_like) { Fabricate.build(:like, liker: liker, likee: likee)}

  context 'relations' do
    it { should belong_to :likee }
    it { should belong_to :liker }

    describe 'liking another user' do

      it '#liker references first user' do
        expect(like.likee).to eq likee
      end

      it '#likee references second user' do
        expect(like.liker).to eq liker
      end

    end
  end
  ...

RSpec.describe User, type: :model do
  context 'relations' do
    it { should have_many :likes }
  end
 ...

这是因为我正在尝试查找正在保存的记录吗?

【问题讨论】:

  • 您能否为这两个表发布架构的相关部分。
  • 我发布了用户和点赞表的相关信息
  • liker.user.likes 工作吗?
  • 没有NoMethodError: undefined method user'`。奇怪的是我有测试来验证正在传递的关系
  • 如果我这样做 self.likee.likes 我得到 #&lt;Like::ActiveRecord_Associations_CollectionProxy:0x3feaa56865bc&gt; 不能转换为普通模型实例/数组

标签: ruby-on-rails ruby


【解决方案1】:

liker.likes.where(likee: liker) 只返回一个关系。您必须像这样执行查询liker.likes.where(likee: liker).exists?

has_many :likes 在您的 User 模型中需要一个列 user_id 在您的表 likes 中。根据给出的代码,我认为您必须将其更改为

class User < ApplicationRecord
  has_many :other_likes, foreign_key: :liker_id 
  has_many :likes, foreign_key: :likee_id 
end

belongs_to :connection 在我看来是个坏名字。 ActiveRecord::Base 有一个同名的类方法。 也许有一天你会遇到这样一个关联名称的问题。

【讨论】:

  • 我认为这是正确的 - 我现在正在建立关系。就这样我明白了,问题是我的关系的用户端没有引用正确的列?谢谢,关于 connection 在内部使用,我不知道。
  • 是的,您的用户端没有引用正确的列。 liker.likes.where(likee: liker) 的问题是次要的。当您不附加 .exists? 时,您的 if 语句在任何情况下都是 true
猜你喜欢
  • 1970-01-01
  • 2011-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多