В Rails что такое form_for?Кажется волшебным - PullRequest
2 голосов
/ 08 декабря 2010

Прежде всего, я понимаю, что должен был попытаться полностью понять Ruby, прежде чем прыгнуть в Rails. Тем не менее, ничто в Ruby не казалось слишком сложным, чтобы быстро понять (до этого!), Поэтому я решил начать, пока я еще с энтузиазмом изучал. __

В любом случае, вот сверхконденсированный пример form_for:

<%= form_for(@post) do |f| %>
    <div class="field">
        <%= f.label :name %><br />
        <%= f.text_field :name %>
    </div>
<% end %>

Я понимаю, что методы в Ruby не нужно вызывать с круглыми скобками. Однако form_for вызывается с круглыми скобками, и все же каким-то образом кажется, что блок do |f| передается ему!

Возвращает ли form_for метод, который принимает блок, а затем , что метод немедленно вызывается (без скобок), передавая блок do |f|? Что здесь происходит?

Ответы [ 4 ]

3 голосов
/ 08 декабря 2010

Ruby использует много того, что называется «синтаксическим сахаром», поскольку он немного более гибок в интерпретации определенных операций, чем другие языки.

например:

model.property = "something"

на самом деле является вызовом функции:

model.property=("something")

ваш form_for пример похожий случай. Блоки тихо передаются в функции Ruby в качестве параметра.

my_block = Proc.new { some code }
my_function(param1, param2, &my_block)

эквивалентно

my_function param1, param2 do
  some code
end

и в функции def для my_function вы можете написать:

def my_function(param1, param2, &block)

и вы можете получить доступ к блоку через параметр, а также yield.

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

2 голосов
/ 08 декабря 2010

Здесь происходит просто то, что метод form_for вызывается с обоими параметрами и блоком в одном вызове.

Вот базовый пример того, как метод принимает и параметр, и блок, чтобы проиллюстрироватьпринцип:

def hello(name)
  puts "Hello, #{name}!"
  yield if block_given?
  puts "Goodbye, #{name}!"
end

Этот метод можно вызывать с одним параметром или с параметром и блоком:

> hello("John")
Hello, John!
Goodbye, John!

> hello("John") do
*   puts "Inside the block"
* end
Hello, John!
Inside the block
Goodbye, John!

По вопросу в вашем комментарии:

Почему в скобках указывается только первый параметр?После обнаружения открытых + закрытых скобок после form_for, как Ruby узнает, что ему следует «подождать» перед вызовом метода?

Если я правильно понимаю ваш вопрос, вы спрашиваете, почему вокруг круглых скобок@post в вызове form_for, а не вокруг всего блока.Это синтаксис для передачи блока методу в Ruby - если блок следует сразу после метода и его обычных параметров, блок передается методу вместе с параметрами.

Вот некоторые изНаиболее распространенные способы вызова метода в Ruby:

# Calling a method without a block
mymethod(param1, param2)

# Same as above, but leaving out parentheses
mymethod param1, param2

# Calling a method with a block that takes no arguments
# (this works without parentheses too)
mymethod(param1, param2) { do_stuff_in_block() }

# or
# (this works without parentheses too)
mymethod(param1, param2) do
  do_stuff_in_block()
end

# Calling a method with a block that takes arguments
# (this works without parentheses too)
mymethod(param1, param2) do |arg1, arg2|
  do_stuff_in_block(arg1, arg2)
end

# or
# (this works without parentheses too)
mymethod(param1, param2) { |arg1, arg2| do_stuff_in_block(arg1, arg2) }

Посмотрите на Блоки и итераторы в программировании на Ruby для получения дополнительной информации о том, как вызывать методы с блоками и какнапишите свои собственные методы, которые принимают блоки.

1 голос
/ 08 декабря 2010

Методы в ruby ​​могут быть переданы аргументы (например, @post) и блок (например, все вещи внутри do ... end).

Если вы посмотрите, как form_for определено в рельсах , вы увидите:

def form_for(record, options = {}, &proc)
  # a lot of funky magical rails stuff ...
end

Все в блоке do захвачено в proc. Предыдущий & в определении метода указывает, что proc является блоком и может быть выполнен. Где-то вдоль линии рельсы выполнят proc.

Блоки - большая часть волшебной удивительности Рубина. Проверьте эту удивительную бесплатную рубиновую электронную книгу для получения дополнительной информации о блоках. Блоки - это своего рода «замыкание», а у ruby ​​различные варианты замыканий, которые ведут себя немного по-разному (другое распространенное закрытие - lambda). Если вы хотите глубже понять, как работают замыкания в Ruby, прочитайте этот замечательный учебник .

1 голос
/ 08 декабря 2010

Есть 2 отдельных вопроса, но сначала я отвечу на более неотложный:

form_for @product do |f|
  # stuff here
end

и

form_for(@product) do |f|
  # stuff here
end

Это одно и то же.form_for - это метод, который принимает block в качестве параметра среди других параметров.

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