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