2016-07-01 12 views
1

現在、私はアクティブレコードの関連付けを行っていますが、もっと効率的な方法があるかどうかは疑問でした。基本的にはTaskというモデルがあります。タスクには作成者が1人あり、多くの人に割り当てることができます。ユーザーモデルは、ユーザーと呼ばれるDeviseモデルです。これは私の現在の設定ですが、作成したのか、割り当てられたのかにかかわらず、ユーザーのすべてのタスクをフェッチするために使用する必要があるクエリは嫌いです。ここに私のモデルです。私の現在のセットアップはページネーションにもひどいです。助言がありますか?割り当て済みおよび作成済みのアクティブレコードの関係

class Task < ActiveRecord::Base 
    has_and_belongs_to_many :users 
    belongs_to :creator, foreign_key: 'creator_id', class_name: 'User' 
end 

class User < ActiveRecord::Base 
    has_and_belongs_to_many :assigned_tasks, class_name: 'Task' 
    has_many :created_tasks, foreign_key: 'creator_id', class_name: 'Task' 

    def tasks 
    (assigned_tasks.includes(project: [:client]) + created_tasks.includes(project: [:client])).uniq 
    end 
end 

だからbasicsllyタスクを持つことがあります。

  • 一つクリエーター(ユーザー)に割り当てられ
  • 多くのユーザー

ソリューション

def tasks 
    Task.joins('LEFT JOIN tasks_users ON tasks_users.task_id = tasks.id').where('tasks_users.user_id = :user_id OR tasks.creator_id = :user_id', { user_id: id }).includes(project: [:client]) 
    end 
+0

ユーザーに所属して割り当てられているすべてのタスクをフェッチするために使用されている方法について、まったく気に入らないことについてもう少し詳しく知ることができますか?あなたはそれに関してどんな特別な問題を持っていますか?それは時間がかかりますか?作成するクエリが多すぎますか? – Kyril

+0

@Kyril大変申し訳ありませんが、基本的にはカミナリでこのページングを行いたい場合は難しくなります。その理由は、呼び出し元の2つのテーブル(ジョインと実際のタスクテーブル)と、 'status::open'はタスクの' enum'です。 –

+0

HABTM結合を取り除いて、実際のモデルを使用して、ユーザーをAsssignmentなどのタスク、has_many:tasks、through:assignmentsに参加させることがあります。 – Kris

答えて

0

簡単な方法は次のとおりです。私たちはLEFT JOINタスクとユーザー間の結合テーブルをINGのだ

class User 
    def associated_tasks 
    Task.joins(:user).joins("LEFT JOIN user_tasks ON user_tasks.task_id = tasks.id").where("users.id = :user_id OR user_tasks.user_id = :user_id", { user_id: id }).includes(project: [:client]) 
    end 
end 

注、私はuser_tasks、あなたが他の人の代わりにすることができるべきであると呼ばれます。

これを行う方法は他にもあります。私は時間があるとき、これらを含める答えを更新したいと思います。

+0

あなたの答えを下に向けて質問を更新しました。私は関連メソッドの中に入るように少し修正しました。なぜ作成されたタスクだけが返され、割り当てられたタスクではないのか? –

+0

いいえ、関係が既に作成されていると仮定しているので、 'has_many'の内部ではうまくいきません。 'scope:assigned_tasks、 - >(user){ここのメソッド}' – oreoluwa

0

代わりに、この方法でそれを複雑で、私は、ユーザー

+0

これを 'ActiveRecord'で試したくないと確信しています。これにより、すべてのレコードがフェッチされ、メモリ内の選択が開始されます。それは 'OP'で指定されたものよりも悪いでしょう。 – oreoluwa

+0

@ololuwaこれは私の落ち込みですが、フィルタリングするのが効率的で簡単なクエリは出ていないようです。 –

+0

これを助けるかもしれない質問を模擬しようとしていますが、Arelを使用しても構いません。 – oreoluwa

0

has_manyでタスクを見つけるために、タスクテーブルにそのような

class Task < ActiveRecord::Base 
    has_and_belongs_to_many :users 
end 

class User < ActiveRecord::Base 
    has_and_belongs_to_many :tasks 

    def user_created_tasks 
    tasks.select { |x| x.created_by == id } 
    end 
end 

か何かをCREATED_BY列を置くあなたが使用することができますwhere句を受け入れさらにスコープに関連:

class User < ActiveRecord::Base 
    has_and_belongs_to_many :assigned_tasks, class_name: 'Task' 
    has_many :created_tasks, foreign_key: 'creator_id', class_name: 'Task' 
    has_many :tasks, ->(user) { joins(:users).where('users.id = ? OR tasks.creator_id = ?', user.id, user.id) } 
end 

..andそして@user.tasksは、特定のユーザーが割り当てられ、作成されたすべてのタスクを提供しなければなりません。これを行うには

+0

これは' has_and_belongs_to_many:assigned_tasks'でも使われている結合テーブルでも使えますか?複数のユーザーにタスクを割り当てることができるので、user_idという列はタスクに存在しません –

+0

ああ、申し訳ありませんが、HABTMの関係は忘れています。私の答えを改訂する – Kyril

+0

私の質問は一番下のコードで更新されましたが、少し変更されました。何故何も返されないのか?オリジナルのコードもありませんでした。 –

関連する問題