User と UserSkill という 2 つのアクティブ レコード クラスがあります。UserSkill には、以下に示すように、スクイール シフターがあります。
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
私の問題は、基本的に、関係が適用されると、次の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))
これは私が望むものではありません:
実際、skill_id が 10 の user_skill を持つユーザーと、skill_id が 11 で値が 2 より大きい user_skill を持つユーザーが必要です。
ActiveRecords は条件を「連鎖」しているように見えますが、UserSkill は同時に 10 と 11 の ID を持つことができないため、常に空の関係になってしまいます!
同じ user_skill 行ではなく、最初の条件と 2 番目の条件を順番に満たす user_skills を持つユーザーを取得できるように、最初の条件と 2 番目の条件をどうにかして区別したいと思いますが、達成方法がわかりません。それ!
エイリアスを使用するのがよいと思いますが、squeel または ActiveRecord 構文を使用して参照したい user_skill ごとに異なるエイリアスを指定するにはどうすればよいですか?
私の質問はこれと非常に似ていると思いますが、ループを使用しているため、提案されたソリューションを使用できないと思います!
編集: squeel github でもこれを見つけましたが、特定のユース ケースに適用する方法がわかりません:同じリレーションで複数の結合の結合をエイリアスする方法が必要です
最終編集:
私は動作する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