2010-03-04 52 views
1

採取了一些Ruby代碼會有人能夠打破的東西在儘可能方法,參數塊的解釋等,這是很常見的Rails代碼,看看這些語句組成的紅寶石細節我試圖瞭解Ruby解釋如何讀取這些代碼:分崩離析從Rails的

respond_to do |format| 
    format.xml { render :layout => false } 
end 

在據我瞭解,respond_to代碼是要帶一個參數給它,塊的方法。所以我猜它是這樣寫的:

def respond_to(&block) 
    block.call 
end 

..或類似的東西?

在塊本身中,格式是對象respond_to傳入塊,xml是請求被設置爲的內容,此時如果請求請求XML類型數據並且繼續前進,則它本身調用塊;調用一個渲染方法,傳遞一個基於關鍵字的參數:layout => false?

有人會清理我對上述工作原理的理解。這種類型的代碼遍佈於Rails,在使用它之前我想先了解它。

回答

1

這對於在紅寶石內部DSL的典型實現模式:你產生一個目的是,然後本身可以接受新的方法調用和塊,因此引導接口塊。 (其實,這是在Java中很常見,太,它是用來獲取有意義的代碼完成內部DSL)

這裏有一個例子:

def respond_to 
    yield FormatProxy.new(@responders ||= {}) 
end 

class FormatProxy 
    def initialize(responders) 
    @responders = responders 
    end 

    def method_missing(msg, *args, &block) 
    @responders[msg] = [args, block] 
    end 
end 

現在你有格式的可執行塊的映射代碼存儲在@responders及更高版本和在不同的地方,無論何時,徘徊無論而且不論你願意,你可以把它叫做:

respond_to do |f| 
    f.myformat { puts 'My cool format' } 
    f.myotherformat { puts 'The other' } 
end 

@responders[:myformat].last.call # => My cool format 
@responders[:myotherformat].last.call # => The other 

正如我在上面所暗示的,如果不是簡單地使用method_missing啞代理對象,你是使用一個其中有最重要的方法預定義的(xmlhtmljsonrss,​​等),足夠聰明的IDE甚至可以給你有意義的代碼完成。

注:我完全不知道這是否是它是如何在Rails的實現,但但它的實施,這大概是這一些變化。

0

如果你有這樣那樣的問題或不知道如何工作,找出來最好的辦法就是去源(在Ruby是非常可讀的)。

對於這個特定的問題,你可以去mime_respond.rb。 187線ATM。

註釋說明:

# Here's the same action, with web-service support baked in: 
# 
# def index 
#  @people = Person.find(:all) 
# 
#  respond_to do |format| 
#  format.html 
#  format.xml { render :xml => @people.to_xml } 
#  end 
# end 
# 
# What that says is, "if the client wants HTML in response to this action, just respond as we 
# would have before, but if the client wants XML, return them the list of people in XML format." 
# (Rails determines the desired response format from the HTTP Accept header submitted by the client.) 

此外respond_to需要阻止或MIME類型與迴應。

我真的會推薦看看那裏的代碼。
評論非常全面。

0
def respond_to(&block) 
    block.call 
end 

這是帶一個參數的方法的定義。 &告訴解釋器,當我們要調用方法時,參數也可以在do ... end表格respond_to do puts 1 end中給出。該參數也可以是響應於一個呼叫梅託德(像一個Proc或λ)的任何物體:
a = lambda{ puts 1 }; respond_to(a)

respond_to do |format| 
    format.xml { render :layout => false } 
end 

這將調用respond_to方法與一個參數,即do ... end塊。在這第二respond_to方法的實現這個塊被稱爲類似如下:

def respond_to(&block) 
    block.call(@format) # or yield @format 
end 

所以爲了符合1個參數電話,我們的代碼塊也必須接受1個參數,這在do ... end' syntax is given between the bars |格式|`

1

你已經基本掌握了它,並且源代碼足夠易讀,可以弄清楚發生了什麼。當你想要潛水這樣的事情時,只需要幾個步驟。

1.找出Rails的位置。

$ gem environment 

RubyGems Environment: 
    - RUBYGEMS VERSION: 1.3.5 
    - RUBY VERSION: 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin9.8.0] 
    - INSTALLATION DIRECTORY: /opt/ruby-enterprise-1.8.7-2009.10/lib/ruby/gems/1.8 
    ... 

2.找出代碼在Rails中的位置。

$ cd /opt/ruby-enterprise-1.8.7-2009.10/lib/ruby/gems/1.8/gems # installation directory from above + "/gems" 

$ ack "def respond_to" 

... 
actionpack-2.3.5/lib/action_controller/mime_responds.rb 
102:  def respond_to(*types, &block) 
... 

3.跳水。

$ vim actionpack-2.3.5/lib/action_controller/mime_responds.rb 
+0

或者只是控制單擊NetBeans中的方法。 – clyfe 2010-03-04 22:08:38

+0

幾年來我還沒有使用過NetBeans,因爲編輯推動了我的瘋狂,但這聽起來像是一個有用的功能。 – jdl 2010-03-04 22:13:31

+0

如果您想深入瞭解Rails的源代碼,Rails 3絕對是非常棒的:更清晰,更模塊化,更簡單,更直接,所有依賴關係都清晰可辨。 – 2010-03-04 23:12:12