web-dev-qa-db-ja.com

Rails 3?

Rails 3プロジェクト。Rails 3でArelが登場し、1つのスコープを再利用して別のスコープを構築できるようになりました。関係を定義するときにスコープを使用します(例: "has_many")。

許可列があるレコードがあります。レコード(リレーションシップを介してアクセスされるレコードも)がフィルター処理されるように、アクセス許可列を考慮するdefault_scopeを構築したいと思います。

現在、Rails 3、default_scope(私が見つけたパッチを含む)は、procを渡す有効な手段を提供していません(遅延変数バインディングに必要です)。定義することは可能ですか?名前付きスコープを渡すことができるhas_many?

名前付きスコープを再利用するという考えは次のようになります。

Orders.scope :my_orders, lambda{where(:user_id => User.current_user.id)}
has_many :orders, :scope => Orders.my_orders

または、関係の名前付きスコープを暗黙的にコーディングすると、次のようになります。

has_many :orders, :scope => lambda{where(:user_id => User.current_user.id)}

私は単に遅延バインディングでdefault_scopeを適用しようとしています。 Arelアプローチ(存在する場合)を使用したいと思いますが、実行可能なオプションを使用します。

現在のユーザーを参照しているため、次のような最後の瞬間に評価されない条件に頼ることはできません。

has_many :orders, :conditions => ["user_id = ?", User.current_user.id]
59
Mario

"名前付きスコープが無効です" をご覧になることをお勧めします

著者は、Arelがどれほど強力かを説明しています:)

私はそれが役立つことを願っています。

編集#1 2014年3月

一部のコメントが述べているように、違いは個人的な好みの問題です。

ただし、Arelのスコープを上位層(コントローラーまたはモデルに直接アクセスするもの)に公開しないようにすることを個人的にお勧めします。

  1. スコープを作成し、モデルのメソッドを介してスコープを公開します。このメソッドは、コントローラーに公開するメソッドです。
  2. モデルをコントローラーに決して公開しないのであれば(その上に何らかの種類のサービスレイヤーがあります)、大丈夫です。腐敗防止レイヤーサービスであり、スコープの実装方法をあまり気にせずにモデルのスコープにアクセスできます。
21
Franck Verrot

関連付けの拡張機能はどうですか?

class Item < ActiveRecord::Base
  has_many :orders do
    def for_user(user_id)
      where(user_id: user_id)
    end
  end
end

Item.first.orders.for_user(current_user)

更新:クラスのメソッドまたはスコープとは対照的に、関連付けの拡張の利点を指摘したいのは、関連付けプロキシの内部にアクセスできることです。

proxy_association.ownerは、関連付けが含まれるオブジェクトを返します。 proxy_association.reflectionは、関連付けを記述するリフレクションオブジェクトを返します。 proxy_association.targetは、belongs_toまたはhas_oneの関連オブジェクト、またはhas_manyまたはhas_and_belongs_to_manyの関連オブジェクトのコレクションを返します。

詳細はこちら: http://guides.rubyonrails.org/association_basics.html#association-extensions

20
Peter P.

スコープの代わりに、クラスメソッドを定義したところです。

def self.age0 do
  where("blah")
end
15
Kevin

私は次のようなものを使用します:

class Invoice < ActiveRecord::Base
  scope :aged_0,  lambda{ where("created_at IS NULL OR created_at < ?", Date.today + 30.days).joins(:owner) }
end 
10
craig

mergeメソッドを使用して、異なるモデルのスコープをマージできます。詳細については、こちらでマージを検索してください railscast

9
ramigg

ユーザーの注文を取得しようとしているだけなら、なぜ関係を使用しないのですか?

現在のユーザーがコントローラーのcurrent_userメソッドからアクセスできると仮定すると:

@my_orders = current_user.orders

これにより、ユーザーの特定の注文のみが表示されます。 joinsを使用して、任意にネストされた結合を行ってより深いリソースを取得することもできます。

current_user.orders.joins(:level1 => { :level2 => :level3 }).where('level3s.id' => X)
3
adamlamar