【发布时间】:2017-07-14 14:36:32
【问题描述】:
我有 3 节课。国家、城市和活动。一个国家有_许多城市,一个城市有_许多活动。
部分活动尚未准备就绪,因此这些活动处于审批状态。我想设置范围,所以没有批准活动的城市是无效的,没有有效城市的国家也是无效的。
class ApprovalStatus < ActiveRecord::Base
def self.approved_status_id
ApprovalStatus.find_or_create_by(name: 'Approved').id
end
class Activity < ActiveRecord::Base
# Named scopes
scope :that_is_approved, -> { where approval_status_id: ApprovalStatus.approved_status_id }
class City < ActiveRecord::Base
# Named scopes
scope :that_has_valid_activities, -> { joins(:activities).merge(Activity.that_is_approved).uniq }
class Country < ActiveRecord::Base
# Named scopes
scope :that_has_valid_cities, -> { joins(:cities).uniq }
# Associations
has_many :cities, -> { that_has_valid_activities }, dependent: :destroy
我希望范围和关联,因为我希望 Country.that_has_valid_cities 仅返回有效国家,并且当活动模型序列化程序获取城市时,仅在这些有效国家中显示有效城市。
在 Rails 控制台中: City.that_has_valid _activities 运行良好。
ApprovalStatus Load (13.4ms) SELECT "approval_statuses".* FROM "approval_statuses" WHERE "approval_statuses"."name" = $1 LIMIT 1 [["name", "Approved"]]
City Load (21.6ms) SELECT DISTINCT "cities".* FROM "cities" INNER JOIN "activities" ON "activities"."city_id" = "cities"."id" WHERE "activities"."approval_status_id" = $1 [["approval_status_id", 2]]
Country.that_has_valid_cities 中断。
ApprovalStatus Load (0.4ms) SELECT "approval_statuses".* FROM "approval_statuses" WHERE "approval_statuses"."name" = $1 LIMIT 1 [["name", "Approved"]]
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: missing FROM-clause entry for table "activities" LINE 1: ..." ON "cities"."country_id" = "countries"."id" AND "activitie...
^
: SELECT DISTINCT "countries".* FROM "countries" INNER JOIN "cities" ON "cities"."country_id" = "countries"."id" AND "activities"."approval_status_id" = $1
当我希望它执行第二次 INNER JOIN 时,它似乎正在尝试执行 AND。
class Country < ActiveRecord::Base
# Named scopes
scope :that_has_valid_cities, -> { joins(:cities).merge(City.that_has_valid_activities).uniq }
# Associations
has_many :cities, dependent: :destroy
工作并产生查询:
ApprovalStatus Load (0.6ms) SELECT "approval_statuses".* FROM "approval_statuses" WHERE "approval_statuses"."name" = $1 LIMIT 1 [["name", "Approved"]]
Country Load (1.2ms) SELECT DISTINCT "countries".* FROM "countries" INNER JOIN "cities" ON "cities"."country_id" = "countries"."id" LEFT OUTER JOIN "activities" ON "activities"."city_id" = "cities"."id" WHERE "activities"."approval_status_id" = $1 ORDER BY "countries"."id" ASC LIMIT 1 [["approval_status_id", 2]]
但是,返回的国家/地区仍会列出其无效城市,因为无效城市并未从有效国家/地区中过滤出来。
附:让我知道整个风格是否在这里关闭,因为我正在自己学习 Rails。
【问题讨论】:
-
您是否真的打算将
ApprovalStatus作为一个单独的模型,而不是在Activity模型中使用enum status: { approved: 1 }? -
当我开始这个项目时,这是一个现有的模型。不过我应该解决这个问题。
-
如果一个城市有2个活动:一个是有效活动,第二个是无效活动,那个城市是否仍然被认为是有效的(它将被包含在
that_has_valid_activities范围内)?还是仅在城市的两个(所有)活动都有效时才计算在内? -
该城市仍将被视为有效。我想要拥有 > 0 个有效活动的城市。
标签: ruby-on-rails postgresql join named-scopes