1

User、、Activityと呼ばれるモデルTaskがあり、次のことができます

> 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この2つを試してみると、配列が得られます。

> 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明示的に委任され、その他のメソッドはmethod_missingmergeを介して実行されます。

たとえば、次の場合:

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 に答える