У меня есть два класса activerecords, User и UserSkill. UserSkill имеет squeel просеиватель, как показано ниже:ActiveRecords Присоединиться к условиям: как присоединиться к одной таблице с разными наборами условий с использованием squeel sifters?
class User < ActiveRecord::Base
has_many :user_skills
end
и
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
Я реализующий поиск в данный момент, и иметь это в контроллере:
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
моя проблема заключается в том, что в основном, когда применяется отношение, я заканчиваю следующим кодом:
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))
, который не то, что я хочу:
на самом деле, я хочу, чтобы пользователи, которые имеют user_skill с skill_id 10 и которые имеют также user_skill с skill_id 11 и значения выше, чем 2.
ActiveRecords, похоже, «цепочки» условий, и я всегда получаю пустое отношение, поскольку UserSkill не может иметь идентификатор 10 и 11 в одно и то же время!
Я хотел бы как-то различать первое и второе условие, чтобы получить пользователей с user_skills, которые удовлетворяют первому условию и второму условию в последовательности, а не для одной и той же строки user_skill, и я не конечно, как добиться этого!
Я думаю, что псевдонимы будут способом, но как я могу указать другой псевдоним для каждого из user_skill, с которым я хочу ссылаться, используя сиквел Squeel или ActiveRecord?
Я бы предположил, что мой вопрос очень похож на this one, однако, поскольку я использую цикл, я не думаю, что смогу использовать предлагаемое решение!
редактировать: Я также нашел это на squeel GitHub, но не знаете, как применить его к моему конкретному прецеденту: Need a way to alias joins for multiple joins on the same relation
Последнее редактирование:
Я написал решение в SQL, который работает , но, как вы можете видеть, что это очень некрасиво:
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
Большое спасибо питер для очень подробные ответы - как вы можете видеть из моего последнего редактирования, генерация псевдонимов для соединения с использованием индекса цикла, похоже, работает, но выглядит немного дерьмовым - я думаю, что это может быть намного чище, если я использую пересечение в том, как вы описали, где set1 и set2 - просеиватели squeel - я пойду на это и дам вам знать, как это происходит! – mulus