I have a Profile
that can be published
. A profile
belongs_to :user
and has_many :ratings
.
A User has_one :profile
, and has_many :ratings
.
A Rating belongs_to :profile && belongs_to :user
.
These are the schemas for the above models:
Profile.rb
:
# == Schema Information
#
# Table name: profiles
#
# id :integer not null, primary key
# first_name :string
# last_name :string
# created_at :datetime not null
# updated_at :datetime not null
# user_id :integer
User.rb
:
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# email :string default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
# first_name :string
# last_name :string
Rating.rb
# == Schema Information
#
# Table name: ratings
#
# id :integer not null, primary key
# speed :integer default(0)
# passing :integer default(0)
# tackling :integer default(0)
# dribbling :integer default(0)
# profile_id :integer
# user_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
Note that coach = User.find(7)
.
When I do this query:
>p = Profile.published.where(id: coach.ratings.order(passing: :desc).pluck(:profile_id))
(0.4ms) SELECT "ratings"."profile_id" FROM "ratings" WHERE "ratings"."user_id" = $1 ORDER BY "ratings"."passing" DESC [["user_id", 7]]
Profile Load (1.1ms) SELECT "profiles".* FROM "profiles" WHERE "profiles"."status" = $1 AND "profiles"."id" IN (52, 14, 24, 29) [["status", 1]]
> p.ids
=> [24, 14, 52]
Note the order of the profile.ids
produced by p.ids
.
However, when I just run the inner query by itself, I get a different order:
> coach.ratings.order(passing: :desc).limit(3).pluck(:profile_id)
(0.8ms) SELECT "ratings"."profile_id" FROM "ratings" WHERE "ratings"."user_id" = $1 ORDER BY "ratings"."passing" DESC LIMIT $2 [["user_id", 7], ["LIMIT", 3]]
=> [52, 14, 24]
What is causing the discrepancy and why can't I get the first query to always produce the same results I expect from the latter query?
Edit 1
Note that even if I hardcode the order of the IDs in the first query, it still gives me back the results in the original order:
[19] pry(main)> cids = coach.ratings.order(passing: :desc).limit(3).pluck(:profile_id)
(0.7ms) SELECT "ratings"."profile_id" FROM "ratings" WHERE "ratings"."user_id" = $1 ORDER BY "ratings"."passing" DESC LIMIT $2 [["user_id", 7], ["LIMIT", 3]]
=> [52, 14, 24]
[21] pry(main)> q = Profile.published.where(id: cids)
Profile Load (0.7ms) SELECT "profiles".* FROM "profiles" WHERE "profiles"."status" = $1 AND "profiles"."id" IN (52, 14, 24) [["status", 1]]
[22] pry(main)> q.ids
=> [24, 14, 52]
Edit 2
When I try the following joins
query, it returns profiles
that violate the published
status (aka it returns profiles with status: :unpublished
when it shouldn't):
> a = Profile.joins(:ratings).where(status: :published, id: coach.ratings.pluck(:profile_id)).order('ratings.passing DESC')
(0.4ms) SELECT "ratings"."profile_id" FROM "ratings" WHERE "ratings"."user_id" = $1 [["user_id", 7]]
Profile Load (1.8ms) SELECT "profiles".* FROM "profiles" INNER JOIN "ratings" ON "ratings"."profile_id" = "profiles"."id" WHERE "profiles"."status" = $1 AND "profiles"."id" IN (24, 52, 29, 14) ORDER BY ratings.passing DESC [["status", 1]]
> o = Profile.find(29)
Profile Load (0.8ms) SELECT "profiles".* FROM "profiles" WHERE "profiles"."id" = $1 LIMIT $2 [["id", 29], ["LIMIT", 1]]
[59] pry(main)> o.status
=> "unpublished"
> a.ids
=> [52, 14, 24, 14, 24]
Edit 3
Error from server from above query:
PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
LINE 1: ... AND "profiles"."id" IN (24, 52, 29, 14) ORDER BY ratings.pa...
^
: SELECT DISTINCT "profiles".* FROM "profiles" INNER JOIN "ratings" ON "ratings"."profile_id" = "profiles"."id" WHERE "profiles"."status" = $1 AND "profiles"."id" IN (24, 52, 29, 14) ORDER BY ratings.passing DESC
Edit 3a
When I try to access @profiles
from the REPL of the error page, this is what I get:
>> @profiles
!! #<ActiveRecord::StatementInvalid: PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
LINE 1: ... AND "profiles"."id" IN (24, 52, 29, 14) ORDER BY ratings.pa...
^
: SELECT DISTINCT "profiles".* FROM "profiles" INNER JOIN "ratings" ON "ratings"."profile_id" = "profiles"."id" WHERE "profiles"."status" = $1 AND "profiles"."id" IN (24, 52, 29, 14) ORDER BY ratings.passing DESC>
>>