2009-07-30 15 views
0

このような何か:findを使用して定数を初期化しますか?

クラスカテゴリ

SOME_CATEGORY = find_by_name("some category") 

エンド

カテゴリー:: SOME_CATEGORY
は、問題なくしようとしたが、それは悪い考えであるかどうかを知りたいとの理由であれば任意..

ありがとう

答えて

6

モデルをキャッシュするたびにデータベースにヒットしたくない場合は、これを行うにはいくつかの方法がありますが、簡単な方法の1つはMemoizationです。これはRails 2.2で導入されました。

class Category < ActiveRecord::Base 
    class << self 
    extend ActiveSupport::Memoizable 
    def named(name) 
     find_by_name(name) 
    end 
    memoize :named 
    end 
end 

このように使用します。

Category.named("some category") # hits the database 
Category.named("some category") # doesn't hit the database 

キャッシュは、要求を超えて永続的に維持されます。最後のパラメータとしてtrueを渡すことでキャッシュをリセットできます。

Category.named("some category", true) # force hitting the database 
0

何をしますか? 行う?たぶん

class Category 
    def self.some_category 
    Category.find_by_name("some category") 
    end 
end 

だからあなたが呼び出すことができます。

Category.some_category 
=> <Category#2....> 
+0

これは、Category.some_categoryを実行するたびに新しいデータベース呼び出しを行いますが、元の質問の考え方はそうではありません。私はどちらかが悪いと言っていない、それは単なるメモです。 –

0

をそれはひどいアイデアではないのですが、それはどちらか本当に良いものではありません。 Railsのやり方とはまったく同じではありません。一つのこととして、あなたは醜い定数コードの多くで終わるでしょう。 ALL_CAPS_WORDSが多すぎます。あなたのRubyはC++のように見え始めます。ブリー。

もう一つは、柔軟性がありません。これらの定数のいずれかをすべてのカテゴリに適用しますか? 2か月後に新しいカテゴリを追加する場合は、Railsコードを更新して新しい定数を追加し、再デプロイしてサーバーを再起動することを忘れないでください。あなたは非常に簡単にカテゴリにアクセスし、DBクエリを繰り返さないことができるようにすることが重要な場合

、ここではそれらを自動的に検索し、最初のアクセスでのあなたのためのLichtambergのような静的メソッドを作成しますメタプログラミングのビットです:

代わりに、この方法では
def self.method_missing(category, *args) # The 'self' makes this a class method 
    @categories ||= {} 
    if (@categories[category] = find_by_name(category.to_s)) 
    class_eval "def self.#{category.to_s}; @categories[#{category}]; end" 
    return @categories[category] 
    end 
    super 
end 

、いつでもあなたの最初の呼び出しCategory.ham、それはfind_by_name("ham")の値を返すクラスメソッドを作成します - 再びどちらのクエリもmethod_missing()実行あなたはそれを呼び出す次回ように。これはかなり多くの方法です。OpenStructクラスが動作します。詳細を知りたい場合は、Pickaxeの本で調べてください。

(これらはすべてメモされているため、あなたのカテゴリオブジェクトに加えた変更はRailsアプリには反映されません。これは変更が行われない、または行われないことを前提にしていますそれが問題であれば@@categoriesをリセットするコードにいつもafter_updateコールバックを入れることができますが、その時点でこれは複雑になり始めます)

関連する問題