같은 테이블에 여러 개의 조인이있는 경우 ActiveRecord가 별칭 테이블 이름을 설정하는 상황이 있습니다. 이러한 조인에 범위가 포함되어있는 상황 ('병합'사용)에 갇혀 있습니다.동일한 테이블을 조건과 함께 두 번 결합하십시오.
모델 TABLE_NAME :
users
두 번째 모델 TABLE_NAME :
posts
가입 테이블 이름 :
access_levels
게시물
나는 대다 관계를 가지고 access_levels를 통해 많은 사용자가 있고 그 반대도 마찬가지입니다.두
, 사용자 모델과 포스트 모델 공유 같은 관계 :has_many :access_levels, -> { merge(AccessLevel.valid) }
ACCESSLEVEL 모델의 내부 범위는 다음과 같습니다
# v1
scope :valid, -> {
where("(valid_from IS NULL OR valid_from < :now) AND (valid_until IS NULL OR valid_until > :now)", :now => Time.zone.now)
}
# v2
# scope :valid, -> {
# where("(#{table_name}.valid_from IS NULL OR #{table_name}.valid_from < :now) AND (#{table_name}.valid_until IS NULL OR #{table_name}.valid_until > :now)", :now => Time.zone.now)
# }
내가 전화를하고 싶습니다 이 같은 sth :
Post.joins(:access_levels).joins(:users).where (...)
활성 Record는 두 번째 조인 ('access_levels_users')의 별칭을 만듭니다. 이 테이블 이름을 AccessLevel 모델의 '유효한'범위 내부에서 참조하려고합니다.
V1은 분명히 PG::AmbiguousColumn
-Error를 생성합니다. V2를 사용하면 두 조건 앞에 access_levels.
접두어가 붙습니다. 이는 의미 상 잘못되었습니다.
# inside of a policy
scope = Post.
joins(:access_levels).
where("access_levels.level" => 1, "access_levels.user_id" => current_user.id)
# inside of my controller
scope.joins(:users).select([
Post.arel_table[Arel.star],
"hstore(array_agg(users.id::text), array_agg(users.email::text)) user_names"
]).distinct.group("posts.id")
생성 된 쿼리 (위에서 valid
범위 (V2)을 사용)과 같다 간체 :
SELECT "posts".*, hstore(array_agg(users.id::text), array_agg(users.email::text)) user_names
FROM "posts"
INNER JOIN "access_levels" ON "access_levels"."post_id" = "posts"."id" AND (("access_levels"."valid_from" IS NULL OR "access_levels"."valid_from" < '2014-07-24 05:38:09.274104') AND ("access_levels"."valid_until" IS NULL OR "access_levels"."valid_until" > '2014-07-24 05:38:09.274132'))
INNER JOIN "users" ON "users"."id" = "access_levels"."user_id"
INNER JOIN "access_levels" "access_levels_posts" ON "access_levels_posts"."post_id" = "posts"."id" AND (("access_levels"."valid_from" IS NULL OR "access_levels"."valid_from" < '2014-07-24 05:38:09.274675') AND ("access_levels"."valid_until" IS NULL OR "access_levels"."valid_until" > '2014-07-24 05:38:09.274688'))
WHERE "posts"."deleted_at" IS NULL AND "access_levels"."level" = 4 AND "access_levels"."user_id" = 1 GROUP BY posts.id
액티브이 방법은 적절한 별명 설정
이것은 I 쿼리를 생성하는 방법이다 access_levels 테이블의 두 x 째 조인에 대한 'access_levels_posts'. 문제는 병합 된 valid
-scope가 'access_levels_posts'대신 'access_levels'로 열 앞에 붙는 것입니다. 또한 범위를 생성하기 위해 arel을 사용하려고했습니다.
# v3
scope :valid, -> {
where arel_table[:valid_from].eq(nil).or(arel_table[:valid_from].lt(Time.zone.now)).and(
arel_table[:valid_until].eq(nil).or(arel_table[:valid_until].gt(Time.zone.now))
)
}
결과 쿼리는 동일하게 유지됩니다.
귀하의 질문에 약간 혼란 스럽지만 나는 당신이 무엇을하고 싶은지 알고 있습니다. 'valid '범위를'join (: user) .where ("(valid_from IS NULL 또는 valid_from <: now) AND (valid_until IS NULL 또는 valid_until> : 지금)", now : Time.zone.now) .where로 변경하십시오 (사용자 : {active : true, 또는 : something})' – jvnill