2011-12-20 7 views
0

私はアプリにbazillionコントローラを持っていて、メンテナンスを少なくするためにメタプログラミングを使用することに不安がありました。これは動作しますが、それはevalの形式で危険でスパイクです:Evalの代替

def plural_action(method_name) 
    class_name = self.class.to_s.gsub(%r{^(\w*)Controller}) {|s| $1 } 
    @title = "#{method_name.to_s.titlecase} of #{class_name}" 
    eval "@q = #{class_name.singularize}.where(:client_id => current_user.client_id).search(params[:q])" 
    eval "@#{class_name.downcase} = @q.result(:distinct => true).paginate(:page => params[:page])" 
    eval "session[:query] = @#{class_name.downcase}.map(&:id)" 
    eval "respond_with(@#{class_name.downcase})" 
    end 

私はevalのを使用せずにこれを行うことができますか?私はinstance_variable_set、sendとconst_getを試しましたが、これまでのところ運がありません。

ここに、私が評価する方法の例があります。

def index 
    @title = "Index of Books" 
    @q = Book.where(:client_id => current_user.client_id).search(params[:q]) 
    @books = @q.result(:distinct => true).paginate(:page => params[:page]) 
    session[:query] = @books.map(&:id) 
    respond_with(@books) 
    end 
+0

[decent_exposure](https://github.com/voxdolo/decent_exposure)の宝石は、問題を完全に解決することはありませんが、そこに行く途中にあるかもしれません。 –

答えて

3

定数に文字列(そのクラス型は一例です)、それが表すターン壮大方法constantizeあります。このことを念頭に置いて、私はあなたのようにあなたの方法を書き換えることができると思う:

def plural_action(method_name) 
    class_name = self.class.to_s.gsub(%r{^(\w*)Controller}) {|s| $1 } 
    @title = "#{method_name.to_s.titlecase} of #{class_name}" 
    @q = class_name.singularize.constantize.where(:client_id => current_user.client_id).search(params[:q]) 
    self.instance_variable_set("@#{class_name.downcase}", @q.result(:distinct => true).paginate(:page => params[:page])) 
    session[:query] = self.instance_variable_get("@#{class_name.downcase}").map(&:id) 
    respond_with(self.instance_variable_get("@#{class_name.downcase}")) 
end 
+0

おっと、それは便利です。しかし、インスタンス変数も設定できる必要があります。私は希望の結果で私の質問を編集します。ありがとう! – snowangel

+0

@snowangel - 'instance_variable_set'のように見えますか?私は自分の答えを編集しますが、あなたはそれを試したと言いますか? – Chowlett

+0

さて、私はそれを試しましたが、おそらくそれは間違っていたので、あなたの考えは信じられないほど役に立つでしょう。 – snowangel

0
def plural_action(method_name) 
    class_name = self.class.to_s.gsub(%r{^(\w*)Controller}) {|s| $1 } 
    @title = "#{method_name.to_s.titlecase} of #{class_name}" 
    @q = class_name.singularize.constantize.where(:client_id => current_user.client_id).search(params[:q]) 
    instance_variable_set class_name.downcase, @q.result(:distinct => true).paginate(:page => params[:page]) 
    session[:query] = @q_result.map(&:id) 
    respond_with(@q_result) 
end 
+0

これは、 "本はインスタンス変数名として許可されていません"というエラーを投げました。 Chowlettのバージョンはうまくいった。しかし、多くの返信のおかげで! – snowangel

0

あなたはあなたのために、このすべてを行うinherited_resource宝石を使用して考えていましたか?

+0

サウンドは駄目ですが、私のheroku slugのサイズは、宝石の依存関係のためにすでに77MBです。私は可能な限りどこにでも追加しようとしています! – snowangel

+0

私はHerokuが100MBの限界を再評価しなければならないと思う。私の基本的なRails 3.1アプリも50MB近くです。私はむしろHerokuが私の宝石を取り除くよりもこれを修正するだろう。 – Amala

+0

私は同意します。私は最近、それについてのサポートチケットを掲示しました - 私が戻ってきたらここにコメントを追加します。 – snowangel