2012-02-22 8 views
0
(@products + @collections + @users + @questions).map do |r| 
    @results << { 
    :label => ["Product", "Collection", "User"].include?(r.class.name) ? r.name : r.question, 
    :category => r.class.name, 
    :href => eval("#{r.class.name.downcase}_path(r)") 
    } 
end 

へのもう一つの方法は、私は現在探しています。方法は、ヘルパーに変換した文字列にevalを使用しないことがあれば、出力ヘルパーの代わりにeval

注:このコードは現在コントローラに存在します。私はここに、コンテキストの完全わからないので、私はこれが動作する100%自信がないんだけど、これはメソッドであれば

:href => self.send("#{r.class.name.downcase}_path".to_sym, r) 

:2.3.11

答えて

1

使用polymorphic_path

@results = (@products + @collections + @users + @questions).map do |r| 
    { 
    :label => ["Product", "Collection", "User"].include?(r.class.name) ? r.name : r.question, 
    :category => r.class.name, 
    :href => polymorphic_path(r) 
    } 
end 
1

レールあなたはこのような何かを試すことができますあなたが参照しようとしている場合は、自己がそれの最も可能性の高いターゲットです。

+0

+1それも動作します。 –

1

benchmarks shown hereでメソッドを動的に呼び出す3つの方法があります。 I'lは、以下の記事を要約:Rubyで動的メソッドを呼び出す

一つの方法は、オブジェクトにメッセージを送信することである。

p s.send(:length) #=> 6 
p s.send(:include?,"hi") #=> true 

第二の方法は、メソッドオブジェクトをインスタンス化し、それを呼び出しています。

eval "s.length" #=> 6 
eval "s.include? 'hi'" #=>true 

アコード:

method_object = s.method(:length) 
p method_object.call #=> 6 
method_object = s.method(:include?) 
p method_object.call('hi') #=> true 

そして、第三の方法は、evalメソッドを使用することですベンチマーク結果にはSLOWESTが評価されるので、代わりに sendを使用します。

####################################### 
##### The results 
####################################### 
#Rehearsal ---------------------------------------- 
#call 0.050000 0.020000 0.070000 ( 0.077915) 
#send 0.080000 0.000000 0.080000 ( 0.086071) 
#eval 0.360000 0.040000 0.400000 ( 0.405647) 
#------------------------------- total: 0.550000sec 

#   user  system  total  real 
#call 0.050000 0.020000 0.070000 ( 0.072041) 
#send 0.070000 0.000000 0.070000 ( 0.077674) 
#eval 0.370000 0.020000 0.390000 ( 0.399442) 
+0

+1ベンチマークが大好き! –

0

あなたがルックアップテーブルを使用できます。

class_procs = { 
    Product => { 
     :path => lambda { |r| product_path(r) }, 
     :label => lambda { |r| r.name } 
    }, 
    Collection => { 
     :path => lambda { |r| collection_path(r) }, 
     :label => lambda { |r| r.name } 
    } 
    User => { 
     :path => lambda { |r| user_path(r) }, 
     :label => lambda { |r| r.name } 
    }, 
    Question => { 
     :path => lambda { |r| question_path(r) }, 
     :label => lambda { |r| r.question } 
    } 
} 

(@products + @collections + @users + @questions).map do |r| 
    procs = class_procs[r.class] 
    @results << { 
     :label => procs[:label].call(r), 
     :category => r.class.name, 
     :href  => procs[:path].call(r) 
    } 
end 

をし、ニーズが複雑になりますならば、あなたは簡単になってから内側のハッシュを維持するために、個々のクラスにクラスごとのハッシュを変換することができ大きすぎると複雑です。

1

に触れたか、明示的に他の回答に記載されているが、私は、これは、より良い仕事をしていませんと思いますされているそのうちのいくつかは、あなたが別のやるべきことがいくつかあります:

@results = (@products + @collections + @users + @questions).map do |r| 
    { 
    :label => r.try(:question) || r.name, 
    :category => r.class.model_name.human, 
    :href => send(:"#{r.class.model_name.underscore}_path", r) 
    } 
end 
  1. あなたはドン」の手動で結果配列を作成する必要があります。既にmapを使用しています。結果を@resultsに割り当ててください。
  2. 質問や名前を投稿する必要があるかどうかを判断する手作業をすべて行う必要はありません。これらのモデルにはすべてto_labelメソッドを渡すことができますが、これはかなり簡単ですが、質問にはtryという名前と2進数を使用した名前がないことを前提にしています。
  3. 単語のモデル名はかなり簡単にタイトルを表示するように変換されますが、BedSheetのようなクラスになると、「ベッドシート」として表示されます。始めるのも正しいでしょう。
  4. もう1つの問題は、クラス名をpath/urlヘルパーメソッドに変換していることです。bed_sheet_pathではなく、bedsheet_pathです。
  5. sendeval以上に使用すると、他の回答で説明したとおりです。to_symを明示的に使用する必要はありませんが、Rubyでは二重引用符を使用してシンボルを完全に作成することがサポートされているためです。 Railsの2.xは同じだった場合

もう一つの簡単なメモは、私は知らないが、レール3に、あなたは、ほとんどのHTMLヘルパーので、モデルのインスタンスにリンクするパスヘルパーを使用する必要はありませんメソッドは自動的に変換されます(例:link_to 'A Product', @product)。

Voila。

+0

+1それは動作し、非常に良い説明 –

関連する問題