我有一个模型,Task
,Taskable
& Supply
。他们有这种关联关系。
class Task < AR::Base
has_one :taskable, inverse_of: :task, autosave: true
enum status: { :awaiting, :restarting, ... }
class Taskable < AR::Base
belongs_to :task, inverse_of: :taskable, autosave: true
has_many :supplies
class Supply < AR::Base
belongs_to :taskable
我需要查找耗材,这些耗材与具有某些枚举值的任务相关联。以下是我构建查询的方法:
Supply.where(
taskable: {
task: {
status: [ :awaiting, :starting ]
}
})
但是我遇到了一个例外:
PG::UndefinedTable: ERROR: missing FROM-clause entry for table "taskable"
LINE 1: ...upplies" WHERE "supplies"."component_id" = $1 AND "taskable"...
: SELECT "supplies".* FROM "supplies" WHERE "supplies"."component_id" = $1 AND "taskable"."task_id" = '---
:status:
- :awaiting
- :starting
' ORDER BY "supplies"."id" ASC LIMIT 1
(0.1ms) ROLLBACK
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: missing FROM-clause entry for table "taskable"
LINE 1: ...upplies" WHERE "supplies"."component_id" = $1 AND "taskable"... ^
: SELECT "supplies".* FROM "supplies" WHERE "supplies"."component_id" = $1 AND "taskable"."task_id" = '---
:status:
- :awaiting
- :starting
' ORDER BY "supplies"."id" ASC LIMIT 1
如何才能确切地查询我想要的内容?
已更新
db/schema.rb
create_table "tasks", force: :cascade do |t|
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "responsible_id", null: false
t.integer "status", null: false
end
create_table "taskables", force: :cascade do |t|
t.integer "task_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "supplies", force: :cascade do |t|
t.integer "taskable_id", null: false
t.datetime "expired_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
答案 0 :(得分:1)
您收到PG::UndefinedTable
错误,因为在查询关联的where-clauses时,您需要指定表名,而不是关联名。
这可能会给你一个更好的结果:
Supply.where(
taskables: {
tasks: {
status: [:awaiting, :starting]
}
}
)
您可能还必须包含或加入实际关联,具体取决于您是否只需要连接查询,还是希望预加载关联。使用.includes
进行预加载,使用.joins
进行加入查询。
Supply.includes(taskable: :task).where(...)
或
Supply.joins(taskable: :task).where(...)
编辑:感谢@Pavling提及.joins
和.includes
之间的区别。
答案 1 :(得分:1)
据我所知where
无法深入了解关系。
从我的角度看它应该是什么样的:
class Task < AR::Base
has_one :taskable, inverse_of: :task, autosave: true
enum status: { :awaiting, :restarting, ... }
class Taskable < AR::Base
belongs_to :task, inverse_of: :taskable, autosave: true
has_many :supplies
class Supply < AR::Base
belongs_to :taskable
has_many :supplies, through: :taskable
为了得到你想要的东西,你将能够使用:
Supply.joins(:tasks).where(tasks: {status: [:awaiting, :starting]})
还要注意where
子句中的状态值。如果您使用的是rails 4.1,则必须传递状态的数值。
<强>已更新强>
或者没有has_many :through
Supply.joins(taskable: :tasks).where(tasks: {status: [:awaiting, :starting]})