1

我有名为User,的模型ActivityTask并且我可以执行以下操作

> puts Activity.joins(:task).to_sql
SELECT "activities".* FROM "activities" INNER JOIN "tasks" ON "tasks"."id" = "activities"."task_id" ORDER BY date DESC

> puts User.first.shared_tasks.to_sql
SELECT "tasks".* FROM "tasks" INNER JOIN "user_tasks" ON "tasks"."id" = "user_tasks"."task_id" WHERE "user_tasks"."user_id" = 1

但是当我尝试merge这两个时,我得到一个数组:

> puts Activity.joins(:task).merge(User.first.shared_tasks).to_sql
NoMethodError: undefined method `to_sql' for []:Array

为什么不返回关系?我需要在其上放置一个 where 子句。

更新:

经过进一步检查,它似乎User.first.shared_tasks正在立即被评估为一系列任务。order我可以通过添加调用来获得我想要的行为:

> puts Activity.joins(:task).merge(User.first.shared_tasks.order()).to_sql
SELECT "activities".* FROM "activities" INNER JOIN "tasks" ON "tasks"."id" = "activities"."task_id" INNER JOIN "user_tasks" ON "tasks"."id" = "user_tasks"."task_id" WHERE "user_tasks"."user_id" = 1 ORDER BY date DESC

除了添加一个空之外,还有更好的方法来防止该关系被评估order吗?

4

3 回答 3

2

每当您在关系对象上调用它不响应的方法时,它都会将该方法委托给其他类型的对象。在 的情况下merge,它将被转换为一个数组。这是通过ActiveRecord::Delegation 模块完成的。一些方法,例如each式委托,而另一些方法,例如merge通过method_missing完成。

例如,如果您这样做:

Activity.joins(:task).each { |activity| puts activity }

关系委托.each给一个数组(枚举器),本质上是进行转换。

于 2012-05-16T12:30:09.837 回答
1

好吧,我还没有弄清楚为什么User.first.shared_tasks会立即被评估,但我已经想出了一个解决方法。我可以打电话scoped

> User.first.shared_tasks.class
=> Array

> User.first.shared_tasks.scoped.class
=> ActiveRecord::Relation

现在,当我尝试进行合并时:

Activity.joins(:task).merge(User.first.shared_tasks.scoped)

它使用ActiveRecord::Relation#merge而不是Array#merge

于 2012-05-19T14:50:52.923 回答
0

对于关系,你可以试试这个

puts (Activity.joins(:task) & User.first.shared_tasks).to_sql

合并有助于创建范围并返回结果对象数组。

于 2012-05-16T11:58:34.623 回答