Saturday, 7 March 2009

Ruby blocks

A block is a chunk of code. What is great in Ruby is the way they can be passed as an argument to a method. For example, that is what is happening here:
(0..10).each { |x|
p x
}

The (0..10) is a Range object, with a method, each. The method is passed the block (everything between the curly braces). Blocks can be defined with do and end, rather than curly braces (but note that the precedence is different).
(0..10).each do |x|
p x
end


Implicitly passing blocks
Here is an example of passing a block to a custom method, test. Note that test does not mention the block at all, so the block is considered to have been passed implicitly. Where the block is used is with the yield statement.
def test
p yield(5, 'house')
p yield(100, 'mansion')
end

test { |i, s|
puts "You are in the block #{i} #{s}"
"Returning #{i} #{s}"
}

# Output:

# You are in the block 5 house
# "Returning 5 house"
# You are in the block 100 mansion
# "Returning 100 mansion"

So what is going on? The test method is invoked, and passed a block of code. Inside the test method, Ruby iterates though each line until it reaches a yield statement, and when it does, it runs the code block passed to the method. The yield statement is kind of like a method call, in that you can pass it arguments (and it will insist on the right number of arguments), and it can return a value too. You can think of yield as an alias for your block, so in the above example, yield is sent a number and a string, and returns a new string.

Naturally the block will be run every time Ruby encounters a yield statement, which is twice in the above example.

Iterating with blocks
Okay, now it gets a bit hairy, and web pages that actually address this become correspondingly rare...

How do you get the method that is receiving a block to iterate over an Array or Hash? In this example, a method, test, is added to the class Array, then an Array object is ceated and test is invoked.
class Array
def test
total = 0
each { |x|
p yield(5 + x)
total += x
}
total
end
end

ma = [12, 34, 8]
p ma.test { |y|
p y
y - 5
}

# Output:

# 17
# 12
# 39
# 34
# 13
# 8
# 54

The first point to note is the each statement and its associated block. This is what allows us to iterate over the Array (or Hash). The each statement sets up a variable, x. This will take the value of each member of the array in turn, as normal. On the next line there is the yield statement. This invokes the block that was received, sending it the current value from the array, plus five.

The block is set up to accept a single value, and to call it y, which it then prints. It then returns this value minus five.

Back with the yield statement, and the test method prints the returned value. Then it adds the current value from the array, x, to the variable total. Once the loop finishes (all the array members have been done), total is used as a return value for the test method.

Back outside the test method, the returned value is printed.

Here are more useful examples for the Array class.

class Array
# Allows you to loop over an array, accessing
# both the index and the value
def each_pair
each_index { |i| yield i, fetch(i) }
end

# As the each method, but skips the first element
def each_not_first
each_index { |i| yield fetch(i) unless i == 0 }
end

# Returns a total over each element in the array
# where the value for an element is determined
# by the given block.
def total &prc
val = 0
each { |e| val += prc.call(e) }
val
end

# Returns an element that best fits the criteria
# given by the block.
# Note that I have used yield here, it seems to work
# better if you have more than one parameter;
# "warning: multiple values for a block parameter..."
def find_best &prc
best = first
each_not_first { |e| best = e if yield(best, e) }
best
end
end

# Example array
ary = [
{:name => 'one', :value => 56},
{:name => 'two', :value => 79},
{:name => 'three', :value => -5},
]

# This uses each_pair to print both the index,
# and the name of the item.
ary.each_pair { |index, item| "#{index}: #{item[:name]}" }

# This example uses total to add up the
# values of each element.
p ary.total { |e| e[:value] }

# This one uses find to get the element with the
# highest value.
p ary.find { |x, y| x[:value] < y[:value] }


Explicitly passing blocks
If you want to be able handle the block other than through yield, you need to pass it explicitly. All this involves is listing it in the arguments. Note that the block must be last in the list, and has to be preceded by an ampersand (but the ampersand should not be present when used later in your code). When you do this, the block is converted to a Proc object (which I discussed here; note that you cannot pass a Proc object in lieu of a block).

def test &prc
puts "The block is of the #{prc.class} class"
puts prc.call('This') unless prc.nil?
end

test { |s| "#{s} does nothing" }

test

# Output:

# The block is of the Proc class
# This does nothing
# The block is of the NilClass class

Apparently, this is significantly slower than using implicit passing. The block is invoked with call; arguments to that are passed to the block.

Note that you cannot set a default value for a block in the arguments of method, however, as shown above, if no block is given the variable will be set to nil.

Many languages have a 'with' statement (Visual BASIC and Pascal). This example adds that functionality to Ruby, and also compares explicit and implicit passing:
# Define a complicated data struction
data = { :ary => %w(one two three four) }

# Define a method, 'use', for all objects
# This version uses explicit passing
class Object
def use &prc
prc.call self
end
end

# This version uses implicit passing
class Object
def use
yield self
end
end

# invoke 'use' on a specific member of the data structure
data[:ary][2].use do |x|
# Do stuff with x, rather than data[:ary][2]
p "The number is #{x}"
end


See also:
http://blog.sidu.in/2007/11/ruby-blocks-gotchas.html
http://www.programimi.com/2007/10/11/ruby-on-rails-code-blocks-and-iteration/

Struggling with Ruby: Contents Page

Friday, 20 February 2009

Moving to Rails 2.2.2

Having just made the move from 2.1.2 to 2.2.2, I hought I wold share some of the issues I came across. There was a bug in 2.1.2 which meant that the image_tag method appended a dot to the end of the image filename, which has been resolved, so that is a good start.

Partials
The way you use partials has been updated in Rails 2.2. While the changes are certainly an improvement, modifying code is not fun (I had about 50 changes to make; thank goodness functional testing will catch your mistakes).

The basic change is that render_partial and render_partial_collection now accept a single hash, rather than a string indicating the file and the important variable, and can be accessed through the render method (thanks to mcclelland for pointing that out). The hash should have the file mapped to the :partial key, and any variables you want in your partial go in a hash mapped to the :locals key (so immediately we can see this is an improvement; you can pass as many of these as you want). These are accessed like local variables in your partial (but really as method calls, I assume). Class variables can be accessed in your partial just as they can in normal views.

To render a collection, just map it to :collection. You can also map any HTML code you want between the elements of your collection to the :spacer key. Rails works out that if :partial is present, it has to render a partial, and if :collection is present, it has to render that partial as a collection, so I would use render for everything (and personally, I would have removed or made private render_partial and render_partial_collection given that we all have to change our code anyway).

Let us see how it has changed. In this first example, a single variable is passed, which I have called :list (so I do not have to change the partial itself):
# Old version
<%= render_partial 'list', @events %>

# New version
<%= render :partial => 'list', :locals => { :list => @events } %>

Here is a table that uses two partials. The first, for the headings, requires no variables. The second is passed an array mapped to :collection:
# Old version
<table width="100%">
<%= render_partial 'table_headings', nil %>
<%= render_partial_collection 'table_row', @samples %>
</table>

# New version
<table width="100%">
<%= render :partial => 'table_headings' %>
<%= render :partial => 'table_row', :collection => @samples %>
</table>


Error pages
There are three error pages in the public directory, which Rails uses when something goes wrong in the production environment (rather than giving error details). I think these were passed through ERb previously. This is no longer the case.

Testing
When running tests, if the system encounters an error, it just gives up, instead of noting the error, and moving on to the next test. I strongly suspect this is a bug.

If a user tries to do something when logged in, but without the required role, he gets redirected to the root page. In the controller, I specify a controller and an action. Previously, I could specify that in the redirect too, but not now. It took some seaching to find that I needed this:
assert_redirected_to "http://test.host/"


Another change in that Rails now generates tests in a different form:
#Old format
def test_my_method
some_code
end

#New format
test "my method" do
some_code
end

The old format still works - no need to change all your old tests. Rather than creating a whole new set of methods, you are now invoking the test method... which then defines a new method by prepending test_ to the name, and then doing exactly the same as it did previously.

Tomcat problem
Having got everything working fine in the development environment, and all tests passing, I was confident to move to the production environmemt...
19-Feb-2009 14:40:58 org.apache.catalina.core.ApplicationContext log
SEVERE: unable to create shared application instance
org.jruby.rack.RackInitializationException: undefined method `cache_template_loading=' for ActionView::Base:Class
...
19-Feb-2009 11:23:00 org.apache.catalina.core.ApplicationContext log
SEVERE: Exception caught
java.lang.NullPointerException
at org.jruby.rack.DefaultRackDispatcher.process(DefaultRackDispatcher.java:32)
at org.jruby.rack.RackFilter.doFilter(RackFilter.java:51)

Oh dear. After much searching (and updating JRuby from 1.1.4 to 1.1.6), I found this forum thread. The solution was to remove the following line from config/environment/production.rb (may also be in config/environment.rb):
config.action_view.cache_template_loading = true


A has_one problem
An obscure bug I came across for the has_one/belongs_to relationship. When I attempted to access one model from the other, I got a NoMethodError exception, and a complaint that I was tryong to do nil.include?. My has_many/belongs_to relationships worked fine. The problem was related to setting the time zone. I have no idea how that can be, but I was not the only one:
http://www.nabble.com/Strange-error...-td21313953.html
http://www.railsformers.com/article/activerecord-timezone-settings-bug

Anyway, the solution is to delete or comment out the old time zone configuration in config/environment.rb, and put in a new one.
  #config.time_zone = 'UTC'
config.active_record.default_timezone = :utc


Additional: Rails 2.3.2 has been out for a while, and I have tried using that. The only noticeable difference was application.rb was renamed to application_controller.rb. Right up until I tried to deploy on Tomcat and it all stopped working. There is a word around here, but I have a suspicion this assumes you have created your project with a more recent version of Rails than I did. Anyway, it did not work for me, so I am back on 2.2.2.

Further addition: Going back to 2.2.2 caused my unit tests to fail mysteriously, with rake just giving up (though functionals and integration tests were fine, and each unit test on its own was fine). It turned out that new models I had added with 2.3.2 had an additional test in test/units/helpers, and this was upsetting the rake task (possibly because I had deleted the associated helper files).

Struggling with Ruby: Contents Page

Friday, 13 February 2009

The Ruby Proc

In Ruby a Proc (short for procedure) is a block of code, bound to a variable (closely related to a block, discussed here). As is always the way in Ruby, a Proc is an object, and so can be created with the new method, though, as discussed later, it is generally preferable to use the lambda method. Here are some examples (expanding on those in the Ruby documention):
# A Proc can have one, none or many arguments
times7 = Proc.new {|n| n * 7 }
statement = Proc.new { 'from statement' }
multiply3 = Proc.new {|x, y| x * y }

The code in the Proc object can be invoked by using the call method.
p times3.call(12)               #=> 36
p times5.call(5) #=> 25
p times7.call(8) #=> 56
p times3.call(times5.call(4)) #=> 60

p statement.call #=> "from statement"
p multiply.call(4, 3) #=> 12

You can pass around Proc objects like any other object:
def gen_times(factor)
return Proc.new {|n| n*factor }
end

class ProcTest
# Class variable is a Proc
@@times13 = Proc.new {|n| n * 13 }

# Method uses various Proc objects
def test
times11 = Proc.new {|n| n * 11 }
p times11.call(3)
p @@times13.call(7)
times2 = gen_times(2)
p times2.call(19)
end

# Method uses a Proc passed as an argument
def test_argument prc
p prc.call(4)
end
end

# ProcTest object instantiated, and methods called
pt = ProcTest.new
pt.test
pt.test_argument Proc.new {|x| x + 5}

Instead of using call, you can invoke the code using square brackets notation. The following are equivalent:
multiply.call(4, 3)
multiply[4, 3]


Proc.new vs lambda
If you call a Proc with too few arguments, Ruby will pad them out with the nil object, so multiply.call(14) above would invoke the Proc code with 14 and nil (which would generate an error in this case). Any extra arguments are simply discarded.

The Kernal has a method lambda (there is also a method proc, which reportedly does the same as Proc.new, but I found it identical to lambda) which will also give a Proc object, but in this case the Proc will raise an ArgumentError is the argument count is wrong.
count_nils_new = Proc.new {|x, y, z|
"#{x.nil?} #{y.nil?} #{z.nil?}"
}

count_nils_lambda = lambda {|x, y, z|
"#{x.nil?} #{y.nil?} #{z.nil?}"
}

# The 4 is quietly discarded
p count_nils_new.call(1, 2, 3, 4)

# The method is sent 1, 2, nil
p count_nils_new.call(1, 2)

# The method is sent nil, nil, nil
p count_nils_new.call

# This is fine
p count_nils_lambda.call(1, 2, 3)

# These will all generate an ArgumentError
p count_nils_lambda.call(1, 2, 3, 4)
p count_nils_lambda.call(1, 2)
p count_nils_lambda.call

Proc objects have an arity method that can be used to determine how many arguments the Proc is expecting.

Using return in a Proc
Using an explicit return in a Proc object created with Proc.new (but not lambda) will cause the calling method to return that value.
def with_return_and_new
prc = Proc.new { return 'This is printed' }
prc.call
'Never seen'
end

def no_return_with_new
prc = Proc.new { 'no_return_with_new' }
prc.call
'This is printed'
end

def with_return_and_lambda
prc = lambda { return 'with_return_and_lambda' }
prc.call
'This is printed'
end

p with_return_and_new
p no_return_with_new
p with_return_and_lambda

It seems that the Proc object is returning not just the value, but the return command too. In general, therefore, it is a bad idea to use an explicit return inside a Proc object defined with Proc.new (if only because the effect will be confusing to anyone with out a good understanding of Ruby peculiarities). This is discussed more here:
http://innig.net/software/ruby/closures-in-ruby.rb

API for the Proc object:
http://www.ruby-doc.org/core/classes/Proc.html

See also:
http://eli.thegreenplace.net/2006/04/18/understanding-ruby-blocks-procs-and-methods/
http://blog.sidu.in/2007/11/ruby-blocks-gotchas.html

Struggling with Ruby: Contents Page

Sunday, 8 February 2009

The Singleton in Ruby

When I first read about singletons in Ruby, I assumed this was a reference to the singleton pattern; perhaps the classic example of a pattern, and in my opinion not much use (actually Ruby has a Singleton module for doing just this). However, in Ruby the singleton is something else entirely.

The singleton is a method that is attached to a single instance of a class. Here is a simple example:
s1 = 'what'
s2 = 'where'
s3 = 'when'

def s1.hello
p "Hello world"
end

class << s2
def hello
p "Hello world"
end
end


s1.hello
s2.hello
begin
s3.hello
rescue NoMethodError
p $!
end

p s1.singleton_methods
# => ["hello"]
p s2.singleton_methods
# => ["hello"]
p s3.singleton_methods
# => []

Three strings are created. The first two have singleton methods added to them in slightly different ways. The singleton methods can be invoked on that specific instance, but not on any other object of that class. Finally, the singleton_methods method is invoked to show how these methods can be listed.

Technically, the object itself does not get a new method. Objects can only hold variables, not methods. Rather, the object has a metaclass, or virtual class, and this metaclass is where the new method is. This is what class << s2 is accessing.

Class methods
You can also add singleton methods to the class, where they become class methods. The logic here is that the class is itself an object, and these methods are being added to a single instance of the Class class. This code illustrates three ways to add a singleton to a class.
def String.goodbye1
p "Goodbye world (1)"
end

class String
def self.goodbye2
p "Goodbye world (2)"
end
end

class String
class << self
def goodbye3
p "Goodbye world (3)"
end
end
end

p String.singleton_methods
# => ["goodbye3", "goodbye2", "goodbye1"]

It is interesting to note that "String" is actually a constant that holds a Class object, and this is why it is capitalised.

Note: Some believe that class << self is bad; this suggests there may be more going on here.

The singleton_methods method returns all methods for the class that are not inherited from a superclass. Use singleton_methods false to exclude methods from modules.

See also:
http://ola-bini.blogspot.com/2006/09/ruby-singleton-class.html

http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html

Struggling with Ruby: Contents Page

Tuesday, 3 February 2009

Modules

A module is a collection of methods and constants, much like a method. However, a module cannot be instantiated. Instead, a module is added to an existing class or object to create a "mixin". Here is an example of a module, with both a method and a constant defined:
module TestModule
TEST_CONST = 1000

def hello
p "Hello"
end
end

The are two ways to add a module to your class, using the keywords include or extend:
class TestClass1
include TestModule
end

class TestClass2
extend TestModule
end

The include statement causes all the methods in the module to be added as instance methods, and also allows the constants to be accessed through the method. In contrast, the extend statement adds all the methods as class methods, and does nothing with the constants. Let us look at the constants first:
p TestModule::TEST_CONST
p TestClass1::TEST_CONST
begin
p TestClass2::TEST_CONST
rescue NameError
p $!
end

The class methods. TestClass2 had the module added using extend, so the method in the module is a class method:
begin
TestClass1.hello
rescue NoMethodError
p $!
end
TestClass2.hello

Finally the instance methods. TestClass1 had the module added using include, so the method in the module is an instance method. Note that you can add a module to an object at run time, but in that case the extend keyword is used:
# Create some instances
tc1 = TestClass1.new
tc2 = TestClass2.new
tc2too = TestClass2.new

# Methods accessible at the instance level
tc1.hello
begin
tc2.hello
rescue NoMethodError
p $!
end

# Module added at runtime
tc2.extend TestModule
tc2.hello
begin
tc2too.hello
rescue NoMethodError
p $!
end

I think the logic here is that extend is used for singletons; a single class or a single instance of the class.

Instantiation
Ruby will invoke the included or extended methods in your module, if they exist, when the module is included or extended respectively. These have to be defined as class methods - even though this is not a class. As far as I know, this is the only time you do tat for a module. Both methods should take a single parameter; the object or class to which the module is being added. An example:

module TestModule
def self.included base
p "I am being included by #{base}"
end

def self.extended base
p "I am being extended by #{base}"
end
end

class TestClass1
include TestModule
end

class TestClass2
extend TestModule
end

p 'Classes now defined'

tc2 = TestClass2.new
tc2.extend TestModule

# Output
#
# => "I am being included by TestClass1"
# => "I am being extended by TestClass2"
# => "Classes now defined"
# => "I am being extended by #<TestClass2:0x987a33>"

See also:
http://www.juixe.com/techknow/index.php/2006/06/15/mixins-in-ruby/

Struggling with Ruby: Contents Page

Saturday, 24 January 2009

The View Part 4 - Using Select in Forms

Last time around, I discussed forms, I am now going to focus on the select widget, as I found this particular mysterious at first. I am going to assume you have already read the page on forms.

Using f.select
The easiest way to use select is inside a FormBuilder block. While most FormBuilder code is in form_helper.rb, the select is in form_options_helper.

Suppose you have a column for integers in your database table (let us say "status", for example, in a table called "posts"). You want the user to be able to select an option from a drop-down list to set the value of the column. First, you need a set of options, and this is best defined in your model. This could be an array or a hash. If you use a hash, you can assign values to options yourself, but generally an array will be sufficient. I am going to use a hash, so in posts.rb, there will be this constant defined:
STATUS_OPTIONS = {'Read' => 1, 'Unread' => 2, 'Deleted' => 12}

Then, in the view, you just need a f.select. It might look something like this (with other fields removed for clarity):
<% form_for(@post) do |f| %>
<p>
Please select:
<%= f.select(:status, Post::STATUS_OPTIONS) %>
</p>
<p>
<%= f.submit "Update" %>
</p>
<% end %>

The f.select takes two parameters, the first being the name of the column (or any method as a symbol), the second is the array or hash. That is all you need to do. Rails will handle the saving and setting of the options for you.

Be aware that if you use an array, Rails will ignore the index. The value returned from the column method must be a value in the array, rather than a number for the index, and similarly what is set will be value, not the index. Personally, I found that annoying, so created a new method that would accept an array, and build a select element using the indices with the values.
# See actionpack/lib/action_view/helpers/form_options_helper.rb
module ActionView
module Helpers
class FormBuilder
def array_select(method, choices, options = {}, html_options = {})
h = {}
choices.each_index { |i| h.store(choices[i], i)}
@template.select(@object_name, method, h, objectify_options(options), @default_options.merge(html_options))
end
end
end
end


Using select_tag
The select_tag method is a bit poor, as it does not accept an array or hash, demanding instead a string with each entry surrounded by "<option>" and "</option>". Why it was not designed to accept an array and a value I cannot imagine. Instead, you have to use the options_for_select helper method, like this:
<%= select_tag("post[status]",
options_for_select(Post::STATUS_OPTIONS,
@post.status))
%>

However, there is also a select method that does the job.
<%= select(:post, :status, Post::STATUS_OPTIONS) %>

I imagine this was a later addition to Rails.

NOTE: I have read that select_tag should be used for GET commands, and select for POST (see here).

Submit on change to a select
Sometimes, you want the user to be able to select from a list, and to be taken straight to a new web page, without having to click on a button. This is pretty easy, with a bit of JavaScript. I set up a helper method to do that:
def submit_on_change
{:onchange => 'submit()'}
end

You can then add that method to your select or select_tag. Note that select takes two optional hashes, and you want to use the second, so I have put in an empty hash in that case.
<%= f.select :status, Post::STATUS_OPTIONS, {}, submit_on_change %>

<%= select_tag "post[status]",
options_for_select(Post::STATUS_OPTIONS,
@post.status),
submit_on_change %>


Another select example
Here is an example of using a select box to choose a web page. The web pages are set up in the model:
HELP_PAGES = {'Main' => 'index', 'Ruby Basics' => 'ruby', 'Ruby Classes' => 'classes'}

In the view, this code will set up the select (note that there is no submit button; be aware that any user with JavaScript disabled will not be able to navigate using this):
<% form_tag( {:action => :help, }, :method => :get) do %>
<%= select_tag "page", options_for_select(Post::HELP_PAGES),
submit_on_change %>
<% end %>

In the controller, the chosen page is handled:
def help
@page = params[:page]
# etc...
end


The collection_select method
Let us suppose you have one table associated with another, and want to be able to have the user select a record from one table for a record in the other. Let us go back to the archetypal blog application: Posts can be associated with a category (so a post belongs_to a category; a category has_many posts and the post table has a column called "category_id"). The user clicks on new post, writes his throughts, then can select from a list of categories from a drop-down list. How do we create such a thing?

This is what the collection_select method is for. As with select, there are two forms, one associated with a FormBuilder object, the other not.
<%= f.collection_select(:category_id,
Category.find(:all), :id, :name) %>
<%= collection_select(:post, :category_id,
Category.find(:all), :id, :name) %>

Note that the second form requires an extra parameter specifying the table we are modifying. The next parameter, :category_id in the example, is a method that is called to set the value; generally that will be the name of the column in the table you are modifying.

The next parameter is an array (kind of) of ActiveRecords; this is the list of options that will be available to the user. The next parameter, :id, is the method used by Rails to get values for each option of the select, while the next parameter determines the display name for the options. In effect, these two are the column names in the other table. To generate the list of options in the example, Rails iterates through the array of categories, and for each member it calls the "id" method to set the value, and the "name" method to set the text that is displayed.

As with select, there are two optional parameters for hashes of options.

As it turns out, you are not restricted to ActiveRecords. I tried it with this TestClass:
class TestClass
def initialize id, name
@id = id
@name = name
end
attr_reader :id, :name
end

Setting up an array:
  TEST_ARRAY = [
TestClass.new(12, 'First of all'),
TestClass.new(54, 'Middle'),
TestClass.new(32, 'Last and finally'),
]

And then using the collection_select like this:
<%= collection_select(:comment, :post_id,
Comment::TEST_ARRAY, :id, :name) %>

However, I have no idea why you would want to do that, rather than using a hash with select.

Selecting Dates
There are are set of methods to help you handle dates. If you are inside a FormBuilder block, just use date_select like this (Rails will even do this for you when you generate views):
<%= f.date_select :birthday %>
ActiveRecord will handle the rest. Outside FormBuilder you can use date_select or select_date (why not date_select_tag, which would be more consistent?). I found date_select easier to set up, but the values in the hash are not trivial to handle. I found some useful code here:

# Reconstruct a date object from date_select helper form params
def build_date_from_params(field_name, params)
Date.new(params["#{field_name.to_s}(1i)"].to_i,
params["#{field_name.to_s}(2i)"].to_i,
params["#{field_name.to_s}(3i)"].to_i)
end

date = build_date_from_params(:published_at, params[:article])


The API:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html
http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html
http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html

See also:
http://shiningthrough.co.uk/Select+helper+methods+in+Ruby+on+Rails

Struggling with Ruby: Contents Page

Friday, 23 January 2009

The View Part 3 - Using Forms

The basic component of a form for a view on Rails is the form_for method in ActionView::Helpers::FormHelper. This takes an object as an argument, and applies that object to the form components in a block. The variabe f is a FormBuilder object.
form_for(@post) do |f|
f.label :name
f.text_field :name
f.label :body
f.text_area :body
f.submit "Update"
end

Actually, it is not quite as simple as that, as you need to mix in the HTML, so in your view, the above becomes:
<% form_for(@post) do |f| %>
<p>
<%= f.label :name %>

<%= f.text_field :name %>
</p>
<p>
<%= f.label :body %>

<%= f.text_area :body %>
</p>
<p>
<%= f.submit "Update" %>
</p>
<% end %>

It is a good idea to put in <%= f.error_messages %> as the second line in your form (and indeed Rails will do this for you), as this will display error messages for you (for example, if the user's input fails validation).

There are a number of methods available for the FormHelper object that will place widgets on the web page. These ones are listed in the API:
check_box
file_field
hidden_field
label
password_field
radio_button
text_area
text_field

The check_box method should be associated with a Boolean field. The hidden_field is useful for data you do not want the user to have access to, but which has to saved with the rest of the fields (but if a field is missing from the form, the record will retain the previous value).



Using radio_button
Suppose you have a column for integers in your database table (let us say "status", for example, in a table called "posts"). You want the user to be able to select an option.

First, you need a set of options, and this is best defined in your model. I am going to use a hash, so in posts.rb, there will be this constant defined:
STATUS_OPTIONS = {'Read' => 1, 'Unread' => 2, 'Deleted' => 12}

Then, in the view, you just need something like this:
<% Post::STATUS_OPTIONS.each_pair do |k, v| %>
<%= k + f.radio_button("status", v) %>
<% end %>

Ruby will iterate through the hash, Post::STATUS_OPTIONS. For each element, it will create a radio button.

Buttons that do not submit
Sometimes you want a button that does not submit the form. You can still use the submit method, just set the :type to map to "button. Here is an example of how to create a button that will invoke a JavaScript function called calc.
<%= f.submit 'Calc', { :onclick => 'calc()', :type => "button", } %>


Other Forms
Sometimes you want to create a form that is not associated with a particular record, such as a search form. For this you use methods from the ActionView::Helpers::FormTagHelper module. The same sort of methods are available, but with _tag as a suffix.

Use form_tag to create the basic form. You can give it a URL segment, or the usual URL parameters. The form_tag method seems to default to POST, so for this show example, I had to specify the method as GET.
<% form_tag({:action => :show, :id => 1}, :method => :get) do %>
<%= submit_tag 'Show 1' %>
<% end %>

Or using the URL:
<% form_tag '/posts/update/1' do %>
<%= submit_tag 'Update 1' %>
<% end %>

Here is a more interesting example, doing the same as the first example (just for illustration - there is no good reason to not do it the other way), with radio buttons. Note that the method is now PUT for update. Also, the tag name is of the form post[status] (for the model called "post", and the field called "status"). When Rails receives the request, the value of status will be put in a hash called post, which will go inside the params hash. This is the standard Rails technique, and is what happens in the earlier example, behind the scenes. This means the controller does not need changing.
<% form_tag({:action => :update, :id => @post.id},
:method => :put) do %>
<p>
<%= label_tag 'Name' %>

<%= text_field_tag 'post[name]', @post.name %>
</p>
<p>
<%= label_tag 'Body' %>

<%= text_area_tag 'post[body]', @post.body %>
</p>
<% i = 0
Post::STATUS_OPTIONS.each_pair do |k, v| %>
<%= k + radio_button_tag('post[status]', v,
@post.status == v) %>
<% end %>
<%= submit_tag "Update" %>
<% end %>

Hopefully tomorrow I will post about select.

The API:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html
http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html

Struggling with Ruby: Contents Page