2010-07-26 56 views

回答

65

send將消息發送到一個對象實例和其在類層次結構的祖先直到一些方法進行反應(因爲它的名字的第一個參數相匹配)。

實事求是地講,這些線路是等價的:

1.send '+', 2 
1.+(2) 
1 + 2 

注意send繞過可視性檢查,這樣就可以調用私有方法,太(單元測試非常有用)。


如果真的發送之前沒有變化,這意味着全球的對象用於:

send :to_s # "main" 
send :class # Object 
+0

哦,我明白了,所以如果有人想在數據庫中存儲諸如1.month之類的東西,而不是靜態地說出天數,可以使用send。 – 2010-07-26 20:00:04

+2

確實,您可以使用它來調用計算名稱的方法,而不是靜態的。 (儘管如此,你不應該允許無限制的用戶輸入,以避免調用私有方法......但是,你可以給它們一個唯一的前綴:send'user_method _'+ methodname,* args) – giraff 2010-07-26 20:06:40

+0

好的用例可能是你想要的要測試受保護的類方法,您可以將它稱爲類入內測試文件.. – 2017-06-28 02:40:26

69

send是一個ruby(無導軌)方法,允許通過名稱調用另一個方法。

從技術文檔

class Klass 
    def hello(*args) 
     "Hello " + args.join(' ') 
    end 
    end 
    k = Klass.new 
    k.send :hello, "gentle", "readers" #=> "Hello gentle readers" 

http://corelib.rubyonrails.org/classes/Object.html#M001077

+3

很好的答案,比詳細的接受答案更清晰。 – 2015-06-16 21:53:37

33

一個最有用的功能,我認爲與方法。發送的是,它可以動態調用on方法。這可以爲您節省很多打字。 .send方法最流行的用法之一是動態分配屬性。例如:

class Car 
    attr_accessor :make, :model, :year 
end 

定期屬性分配一個需要

c = Car.new 
c.make="Honda" 
c.model="CRV" 
c.year="2014" 

或者使用方法。發送:

c.send("make=", "Honda") 
c.send("model=", "CRV") 
c.send("year=","2014") 

但都可以用下面的代替:

假設您的Rails應用程序需要從用戶輸入中爲您的汽車類指定屬性,喲ü可以做

c = Car.new() 
params.each do |key, value| 
    c.send("#{key}=", value) 
end 
+0

感謝您的好鏈接 – 2015-07-07 12:10:10

+3

以這種方式使用.send會增加不必要的複雜性,並且可以更輕鬆地在代碼中無意中引入錯誤。例如,在上面的代碼中,如果向參數散列添加一個新條目(例如'cylinders'),代碼將會失敗並顯示未定義的方法錯誤。 – 2015-08-05 12:06:24

+1

respond_to?可以用來防止這種錯誤,如果需要的話。 – 2015-10-04 19:14:51

8

另一個例子,類似安東尼桑傑·賈的https://stackoverflow.com/a/26193804/1897857

是,如果你需要在對象上讀取屬性。

例如,如果您有一個字符串數組,如果您嘗試遍歷它們並在您的對象上調用它們,它將無法工作。

atts = ['name', 'description'] 
@project = Project.first 
atts.each do |a| 
    puts @project.a 
end 
# => NoMethodError: undefined method `a' 

但是,您可以send字符串對象:

atts = ['name', 'description'] 
@project = Project.first 
atts.each do |a| 
    puts @project.send(a) 
end 
# => Vandalay Project 
# => A very important project 
+0

感謝您的簡單和簡單的解釋! – 2017-09-17 16:30:09

+0

謝謝!這正是我所追求的答案。想知道這是常用的嗎?我在遺留代碼中遇到了類似的東西,我不確定我應該堅持下去。@ Mike Vallano – 2017-10-23 03:51:01

+0

@ b-liu我見過它被有經驗的開發人員用於新代碼中。當使用'define_method'時,它也會很有幫助:https://apidock.com/ruby/Module/define_method。 – 2017-11-02 11:18:01

0

另一個用例的觀點:

<%= link_to 
    send("first_part_of_path_{some_dynamic_parameters}_end_path", 
    attr1, attr2), .... 
    %> 

允許。你寫可伸縮視圖誰與所有種類的對象 與:

render 'your_view_path', object: "my_object"