2010-05-26 27 views
37

這是如何將一個字符串轉換爲軌道/ Ruby的一類:如何將字符串轉換爲類方法?

p = "Post" 
Kernel.const_get(p) 
eval(p) 
p.constantize 

但是,如果我從一個數組中檢索什麼方法/活動記錄的對象,如:

Post.description 

但可能是

Post.anything 

其中任何東西都是像anything = "description"這樣的字符串。

這很有幫助,因爲我想重構一個非常大的類,並減少代碼和重複行數。我怎樣才能使它工作?

+0

你意識到你只需要{const_get,EVAL,constantize}之一吧? – klochner 2010-05-26 17:03:11

+0

是的。我當然是了。因爲我剛剛測試了3. – kgpdeveloper 2010-05-26 23:12:48

回答

61
Post.send(anything) 
+0

完美的工作,謝謝。減少了很多代碼行數。 – kgpdeveloper 2010-05-26 23:24:53

+0

所以你可以接受答案。 – shingara 2010-05-27 08:08:01

+0

如果我的方法是這樣的:def test =(string){puts string}。我不認爲Post.send(「測試」,「嗨」)將工作正常.. – 2013-07-30 09:07:55

15

雖然EVAL可以爲這樣的事情一個有用的工具,而那些來自其他背景可能需要儘可能多一個可能開罐器使用它,它實際上是危險的,所以隨便用。 Eval意味着如果你不小心,任何事情都可能發生。

一個更安全的方法是這樣的:

on_class = "Post" 
on_class.constantize.send("method_name") 
on_class.constantize.send("method_name", arg1) 

對象#發送會打電話給你想要的任何方式。您可以發送一個符號或一個字符串,並提供該方法不是私有的或保護,應該工作。

+0

這已經執行任意方法。安全似乎不是這裏的主要因素。 – Chuck 2010-05-26 15:22:16

+0

任意方法與任意代碼有很大不同。我懷疑你的班上有「DROP ALL TABLES」方法。驗證給定的字符串是安全的還是不作爲方法名稱也是基本的,你可以有一個簡單的白名單來檢查,但是評估任意eval塊的危險是不可能的。 – tadman 2010-05-26 16:02:29

0

試試這個:

class Test 
def method_missing(id, *args) 
    puts "#{id} - get your method name" 
    puts "#{args} - get values" 
end 
end 

a = Test.new 
a.name('123') 

所以一般語法是a.<anything>(<any argument>)

12

由於這是Ruby on Rails問題,所以我稍微詳細說明一下。

在Rails 3,假設title是一個ActiveRecord對象的字段的名稱,再下面是同樣有效:

@post = Post.new 
method = "title" 

@post.send(method)    # => @post.title 
@post.send(method+'=',"New Name") # => @post.title = "New Name"