views:

239

answers:

2

we use

(1..10).each do |i|
  p i
end

so that a value is "yield" to i in a block...

but what about

<% form_for @story do |f| %>
  <%= f.text_field :name %>
<% end %>

there is no loop at all... why do we need to make it look like a loop? Can't we do it without making it look like a loop? (write in another way)?

Also, must be use a Story instance here? Can't we just use :story and achieve the same result? The @story instance is just newly created and has no data at all -- does it actually help creating the form? Can't :story suffice already? thanks.

Update:

is the idea similar to: (just pseudo code)

with_model_give_form (@story) do |f|
  f.begin_form
  f.text_field :name
  f.end_form
end

so i think the block method will save the begin_form and end_form because it automatically add the begin and end before and after calling the block. is that the main benefit?

A: 

A "yield" does not always imply a loop - it's more of a "block" concept, it just happens to manifest itself in more of a iteration / loop context. The more you think about yield being a loop construct the more you pigeon hole yourself and prevent yourself from truly learning the awesomeness of blocks.

As for :story, yeah, it is kind of lame. You would think that Rails would just constantize it and infer its model from there. You could also just also Story.new in your view, versus doing that in your controller, but yeah, it's the same thing.

Cody Caughlan
is it something like in my Update?
動靜能量
+6  A: 

I think you have misunderstood the way Ruby works in this case.

It is true that you put everything in a block, but it has nothing to do with a loop.

What you actually do in

(1..10).each do |i|
  p i
end

is creating the block {|i| p(i); } and sending it to the function Range.each()

It is the same thing with the form_for. What you actually do is creating the block {|f| puts( f.text_field(:name)); } and passing it to the form_for function. (now it doesn't use puts, but some string concatenation, but you get the idea).

So it's basically not a loop, but a lambda function that will be called several times when called in a loop.

Here is some more information about blocks

Update: Regarding your update. In a way, yes, that is the main benefit. It is not completely true, but you get the idea. The purpose for that block (and a lot other) are to make the code easier to read and understand. And also to speed up the development.

Dividing code into blocks have always been sought for, just look at the concept of functions, classes and other statements.

for instance, the form_for is mostly for speeding up the development. Yes, it creates the start and end tags, but that is not all.

<% form_for @story do |f| %>
  <%= f.text_field :name -%>
<% end %>

Could actually be written something like:

<form action="<%= polymorphic_edit_path(@story) -%>" 
      id="<%= @story.class_name.underscore -%>">
   <%= text_field :story, :name -%>
</form>

of course, it wouldn't exactly be like that, this is a lot simplified and the form_for function can do a lot more than that, but at least you should get the picture.

Jimmy Stenke
i added something in the question... is it something like the Update part?
動靜能量