2016-06-17 10 views
0

私は最近、Rails 5に更新されたレールアプリを持っています。このような(簡略化された)データモデルがあります:AppsUsers複数のTeamMemberであり、各Teamは複数のAppを有することもできる。私のAppのインデックスビュー/コントローラでは、自分が作成したすべてのユーザーのアプリケーションを一覧表示したいと思います。UsersMemberであるTeamに属するすべてのアプリケーションをリストしたいと思います。Rails 5、リファクタリング、複数条件の最適なクエリ

私の現在の実装よりも、もっと良いやり方があると感じています(おそらく、Rails 5の新機能です)。これは私の現在の実装がどのように見えるかです:

ので
apps = [] 
# First get all the team apps where the user is a member, but haven't created the app. 
current_or_guest_user.teams.each do |team| 
    team.apps.each do |app| 
    unless app.user.eql?(current_or_guest_user) 
     apps << app 
    end 
    end 
end 
# ... then get all the apps that the user have created. 
current_or_guest_user.apps.each do |app| 
    unless apps.include?(app) 
    apps << app 
    end 
end 
# Return the apps. 
@apps = apps 

を、私がやっている何をすべきか、よりクリーンで最適な方法は何ですか?それはどうやって見えるの?

編集

これはどのように見えるか、私のアクティブモデルの団体である:Railsの5方法#orhttps://github.com/rails/rails/pull/16052)を使用することができれば、私は疑問に思う

# App.rb 
belongs_to :user 
belongs_to :team 

# User.rb 
has_many :apps, dependent: :destroy 
has_many :teams 
has_many :teams, through: :members 

# Team.rb 
has_many :apps, dependent: :destroy 

編集2

この使用例では、次のようになります。

current_user.apps.or([...]]) 
# [...] = In not exactly sure what to put here in that case. 
+0

モデルの関連付けを適切な形式で貼り付けることはできますか? – oreoluwa

+0

@oreoluwa私は今協会を追加しました。 – Anders

+1

私は、より最適化されたアプローチが 'Arel'になると思っています。私はRails 5がまだこれ以上の良い方法を持っているとは思っていません。しかし、別の方法は、メソッドを委譲することですが、まだ最適化されていない可能性があります。 – oreoluwa

答えて

3

は、私は次のコードは、このより簡潔に達成すべきだと思う:

# using a shorter variable name 
user = current_or_guest_user 

# does the same thing as your first loop over teams 
set1 = user.teams.includes(:apps).where("apps.user_id = ?", user.id).map(&:apps) 

# does the same thing as the second loop 
# (no need to check for duplicates here) 
set2 = user.apps 

# combine the two queries without adding duplicates 
return set1 | set2 

謝罪これがアウトボックスを動作しない場合、私はそれをテストしていません。

ここでカップルの概念:

  • includesは団体を通じてレコードを "プリロード" されます。これは、個々のSQLクエリを実行する代わりに、すべての関連レコードを単一のクエリで取得します。
  • where("apps.user_id = ?", user.id)は、関連付けられたレコードのuser_idに基づいてクエリをフィルタリングします。 ?は、ここではuser.idに置き換えられた変数です。
+0

ありがとう、それを試してみよう!新しいRails 5 '#or'メソッドをこのユースケースでも使用する可能性があると思いますか? https://github.com/rails/rails/pull/16052 – Anders

+0

なぜそうは見えないのですか? –

+0

私は 'or'メソッドを知らなかった。私は[active_record_union](https://github.com/brianhempel/active_record_union)の宝石を使用しています –

関連する問題