Разбивает на части некоторый код Ruby, взятый из Rails - PullRequest
1 голос
/ 05 марта 2010

Может ли кто-нибудь разобрать специфику Ruby, из которой состоит каждое из этих утверждений, в части методов, параметров, интерпретаций блоков и т. Д. Это очень часто встречается в коде Rails, и я пытаюсь понять, как интерпретатор Ruby читает этот код:

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

Насколько я понимаю, response_to - это метод, который принимает один параметр - блок. Я предполагаю, что написано что-то вроде:

def respond_to(&block)
    block.call
end

.. или что-то подобное?

в самом блоке, формат - это объект response_to, который передается в блок, а xml - это то, на что установлен запрос, и в этот момент он вызывает блок сам по себе, если запрос запрашивает данные типа XML, выполняется и вызывает метод рендеринга, передав ему аргумент на основе ключевого слова: layout => false?

Кто-нибудь очистит мое понимание того, как они работают выше? Этот тип кода распространяется на Rails, и я хотел бы понять его, прежде чем использовать его подробнее.

Ответы [ 4 ]

1 голос
/ 05 марта 2010

Вы в основном получили его, и исходный код достаточно читабелен, чтобы понять, что происходит. Если вы хотите выполнить исходное погружение примерно так, вам понадобится всего несколько шагов.

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
1 голос
/ 05 марта 2010

Это типичный шаблон реализации для внутренних DSL в Ruby: вы передаете объект блоку, который затем сам принимает новые вызовы и блоки методов и, таким образом, направляет интерфейс. (На самом деле, это довольно распространено и в 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, вы должны использовать тот, который имеет самые важные методы (xml, html, json, rss , atom и т. Д.) Предопределенная, достаточно интеллектуальная IDE может даже дать вам значимое завершение кода.

Примечание: я абсолютно не знаю, так ли это реализовано в Rails, но как бы оно ни было реализовано, вероятно, это какой-то вариант.

0 голосов
/ 05 марта 2010
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 | | `

0 голосов
/ 05 марта 2010

Если у вас есть такие вопросы или вы не знаете, как все работает, лучший способ узнать это - обратиться к источнику (который в Ruby очень читабелен).

По этому конкретному вопросу вы можете перейти на mime_respond.rb . Линия 187 банкоматов.

Комментарий объясняет:

# 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-типы для ответа.

Я действительно рекомендовал бы взглянуть на код там.
Комментарии очень полны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...