質問

カスタム検索条件を設定する必要があるモデルがいくつかあります。たとえば、Contact モデルがある場合、Contact.find が呼び出されるたびに、返される連絡先を、使用中のアカウントにのみ属するものに制限したいと考えます。

Google 経由でこれを見つけました (少しカスタマイズしました)。

def self.find(*args)
  with_scope(:find => { :conditions =>  "account_id = #{$account.id}" }) do
    super(*args)
  end
end

これは、account_id があいまいな場合を除いて、うまく機能します。そのため、次のように調整しました。

def self.find(*args)
  with_scope(:find => { :conditions =>  "#{self.to_s.downcase.pluralize}.account_id = #{$account.id}" }) do
    super(*args)
  end
end

これもうまく機能しますが、DRY にしておきたいと思います。現在、この種の機能を使用したいいくつかの異なるモデルがあります。これを行うための最良の方法は何ですか?

回答するときは、メタプログラミング Ruby を理解するのに役立つコードを含めてください。

(Rails v2.1を使用しています)

役に立ちましたか?

解決

使用している Rails のバージョンは教えてもらえません [編集 - Rails 2.1 上にあるため、次のアドバイスは完全に機能します] が、 find own をオーバーロードする代わりに次の形式を使用することをお勧めします。

account.contacts.find(...) 

これにより、user 句が含まれるスコープで検索が自動的にラップされます (account_id があるので、近い場所にアカウントがあると思われます)

スコープに関する次のリソースを確認することをお勧めします

他のヒント

ジャンのアドバイスは的確だ。モデルが次のようになっていると仮定します。

class Contact < ActiveRecord::Base
  belongs_to :account
end

class Account < ActiveRecord::Base
  has_many :contacts
end

を使用する必要があります contacts 現在のアカウントを関連付けて、確実に取得できるものだけを確保します Contact そのアカウントをスコープとするレコードは次のようになります。

@account.contacts

連絡先クエリにさらに条件を追加したい場合は、find を使用して条件を指定できます。

@account.contacts.find(:conditions => { :activated => true })

また、アクティブ化されたユーザーを常にクエリしている場合は、それを名前付きスコープにリファクタリングできます。

class Contact < ActiveRecord::Base
  belongs_to :account
  named_scope :activated, :conditions => { :activated => true }
end

これを次のように使用します。

@account.contacts.activated

問題に対する具体的な答えを得るには、上記のメソッドをモジュールに移動して、問題のモデルに含めることをお勧めします。そうすればいいでしょう

class Contact
  include NarrowFind
  ...
end

PS.account_id の SQL エスケープに注意してください。おそらく、 :conditions=>[".... =?", $account_id] 構文。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top