I have two activerecords classes, User and UserSkill. UserSkill has a squeel sifter, as shown below:
class User < ActiveRecord::Base
has_many :user_skills
end
and
class UserSkill < ActiveRecord::Base
belongs_to :user
belongs_to :skill
sifter :with_skill_id_and_value_of_at_least do |params|
if params[1].present?
skill_id.eq(params[0]) & value.gteq(params[1])
else
skill_id.eq(params[0])
end
end
end
I am implementing the search at the moment, and have this in the controller:
def search
users = User.skip_user(current_user)
if params[:user_skills].present?
params[:user_skills].each do |user_skill|
#user_skill is an array where [0] is the id, and [1] the minimum value.
#if [1] is empty, it will default to 0 in the sifter
users = users.joins(:user_skills).where do
{
user_skills: sift(:with_skill_id_and_value_of_at_least, user_skill)
}
end
end
end
end
my problem is that basically, when the relation is applied, I end up with the following sql:
SELECT "users".* FROM "users"
INNER JOIN "user_skills" ON "user_skills"."user_id" = "users"."id"
WHERE "user_skills"."skill_id" = 10
AND (("user_skills"."skill_id" = 11 AND "user_skills"."value" >= 2))
which is not what I want:
indeed, I want the users that have a user_skill with a skill_id of 10 AND that have also a user_skill with a skill_id of 11 and a value higher than 2.
ActiveRecords seems to "chain" the conditions, and I always end up with an empty relation as a UserSkill cannot have an id of 10 and 11 in the same time!
I would like to somehow differentiate between the first and the second condition so that I get the users with the user_skills that satisfy the first condition and the second condition in a sequence, and not for the same user_skill row, and am not sure how to achieve that!
I think aliases would be the way to go, but how can i specify a different alias for each of the user_skill I want to reference using squeel or ActiveRecord syntax?
I would imagine that my question is quite similar to this one, however since I'm using a loop I don't think I can use the proposed solution!
edit: I also found this on the squeel github, but not sure how to apply it to my particular use case: Need a way to alias joins for multiple joins on the same relation
LAST EDIT:
I've written a solution in sql that works, but as you can see it is very ugly:
params[:user_skills].each_with_index do |user_skill,index|
users = users.joins(",user_skills as u#{index}")
.where("u#{index}.skill_id= ? AND u#{index}.value >= ?"
,user_skill[0].to_i, user_skill[1].to_i)
end