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]
"名前付きスコープが無効です" をご覧になることをお勧めします
著者は、Arelがどれほど強力かを説明しています:)
私はそれが役立つことを願っています。
一部のコメントが述べているように、違いは個人的な好みの問題です。
ただし、Arelのスコープを上位層(コントローラーまたはモデルに直接アクセスするもの)に公開しないようにすることを個人的にお勧めします。
関連付けの拡張機能はどうですか?
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
スコープの代わりに、クラスメソッドを定義したところです。
def self.age0 do
where("blah")
end
私は次のようなものを使用します:
class Invoice < ActiveRecord::Base
scope :aged_0, lambda{ where("created_at IS NULL OR created_at < ?", Date.today + 30.days).joins(:owner) }
end
mergeメソッドを使用して、異なるモデルのスコープをマージできます。詳細については、こちらでマージを検索してください railscast
ユーザーの注文を取得しようとしているだけなら、なぜ関係を使用しないのですか?
現在のユーザーがコントローラーのcurrent_userメソッドからアクセスできると仮定すると:
@my_orders = current_user.orders
これにより、ユーザーの特定の注文のみが表示されます。 joins
を使用して、任意にネストされた結合を行ってより深いリソースを取得することもできます。
current_user.orders.joins(:level1 => { :level2 => :level3 }).where('level3s.id' => X)