【发布时间】:2017-06-13 19:59:01
【问题描述】:
我在 Rails 协会遇到了不寻常的情况,并创建了简单的示例来证明这一点。 假设我们有 4 个模型: 1) 列表.rb
class List < ApplicationRecord;end
2) 显示.rb
class Show < List;end
3)joined_table.rb
class JoinedTable < ApplicationRecord
belongs_to :listable, polymorphic: true
belongs_to :work
end
4) 工作.rb
class Work < ApplicationRecord
has_many :joined_tables, dependent: :destroy
has_many :lists, through: :joined_tables, source: :listable, source_type: 'List'
has_many :shows, through: :joined_tables, source: :listable, source_type: 'Show'
end
因此我们有了下一个 schema.rb
create_table "joined_tables", force: :cascade do |t|
t.integer "listable_id"
t.string "listable_type"
t.integer "work_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "lists", force: :cascade do |t|
t.string "type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "works", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
现在当你得到所有信息后,谁能解释我为什么要尝试
Work.first.shows
它生成
Show Load (0.2ms) SELECT "lists".* FROM "lists" INNER JOIN "joined_tables" ON "lists"."id" = "joined_tables"."listable_id" WHERE "lists"."type" IN ('Show') AND "joined_tables"."work_id" = ? AND "joined_tables"."listable_type" = ? [["work_id", 1], ["listable_type", "Show"]]
这看起来像是一个正确的请求,但是当我尝试这样做时
Work.first.lists
它生成
List Load (0.1ms) SELECT "lists".* FROM "lists" INNER JOIN "joined_tables" ON "lists"."id" = "joined_tables"."listable_id" WHERE "joined_tables"."work_id" = ? AND "joined_tables"."listable_type" = ? [["work_id", 1], ["listable_type", "List"]]
这是不一样的,并且缺少检查列表。类型。
我知道这是一种糟糕的架构,并且可能应该在 Work 中使用关联范围,而将 JoinedTable 中的多态性放在一边,但这只是我在项目中遇到的问题。我也很想听听替代解决方案,但最重要的是我想知道为什么 rails 会生成不同的查询。
附:在示例中,我使用的是 rails 5 和 SQLite。但在使用 rails 4 和 postgres 的实际项目中,情况更糟。如果我先做 Work.first.shows 然后 Work.first.lists 它会生成
List Load (0.4ms) SELECT "lists".* FROM "lists" INNER JOIN "list_works" ON "lists"."id" = "list_works"."listable_id" WHERE "list_works"."work_id" = $1 AND "list_works"."listable_type" IN ('List', 'Show') [["work_id", 50]]
但如果我立即执行 Work.first.lists 它会生成
List Load (0.8ms) SELECT "lists".* FROM "lists" INNER JOIN "list_works" ON "lists"."id" = "list_works"."listable_id" WHERE "list_works"."work_id" = $1 AND "list_works"."listable_type" = 'List' [["work_id", 50]]
感谢您的帮助!
【问题讨论】:
标签: ruby-on-rails ruby ruby-on-rails-4 activerecord rails-activerecord