I am attempting to track mutual likes where a user likes a user that likes them. To check if the like is mutual, I call an method after the like is created. If that liker has been a likee than it is considered mutual.
The problem however, is that I run into some odd errors that I believe are related to how the foreign keys have been set up. I have set up a has many association in Rails but any time I attempt to access it, I get a PG::InFailedSqlTransaction: ERROR:  current transaction is aborted, commands ignored until end of transaction block
       : RELEASE SAVEPOINT active_record_1 error.
User:
class User < ApplicationRecord
  has_many :likes
end
Like:
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
I've tried changing the hook to be around save, etc. but that doesn't work either.
Also, I cannot even call Like.first else I get the same error. 
I've tried printing out liker.likes.where(likee: liker) and i get PG::UndefinedColumn: ERROR:  column likes.user_id does not exist which I think is the problem. 
I can however, access the liker like this: self.likee inside of the hook but I cannot call self.likee.likes without it returning #<Like::ActiveRecord_Associations_CollectionProxy:0x3fd91ca5ca78>
Schema:
  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
Tests:
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
 ...
Is this caused because I'm attempting to lookup a record that is being saved?
liker.likes.where(likee: liker) returns only a relation. You have to execute your query like this liker.likes.where(likee: liker).exists? 
has_many :likes within your User model expects a column user_id within your table likes. With the code given I would think you have to change it to 
class User < ApplicationRecord
  has_many :other_likes, foreign_key: :liker_id 
  has_many :likes, foreign_key: :likee_id 
end
belongs_to :connection is a bad name in my point of view. ActiveRecord::Base has a class method with the same name. 
Maybe you will run into issues with such an association name some day.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With