= Blocks Wiki[http://wiki.github.com/hunterae/blocks] Blocks is a replacement / complement to content_for with yield. It allows a user to specify a block capable of taking parameters that may be passed in when using that block. A user may also specify other blocks to be prepended or appended before or after a specific block is rendered. A template may also be specified to blocks that will provide the layout for a specific component and provide default implementations for its blocks. In this way, blocks is able to offer a very simple to use table generator ({table_for}[https://github.com/hunterae/blocks/wiki/table_for]) and list generator (list_for). == Installation In Rails 3, add this to your Gemfile. gem "blocks" In Rails 2, add this to your environment.rb file. (At this time, it is untested in Rails 2) config.gem "blocks" Alternatively, you can install it as a plugin. rails plugin install git://github.com/hunterae/blocks.git == Getting Started What makes blocks particularly powerful is that it represent a combination of the ruby definition of blocks and partials. A block may be defined inline utilizing syntax similar to that of content_for: <%= blocks.define :some_block_name, :some_parameter => 1, :some_parameter2 => 2 do |options| %> <%= options[:some_parameter] %> <%= options[:some_parameter2] %> <%= options[:some_parameter3] %> <% end %> or it may be written as a partial, existing in the controller view directory for whatever controller renders the view, or the globally configured blocks directory (views/blocks by default). The above block definition might then be written in the file views/blocks/_some_block_name.html.erb: <%= some_parameter if defined?(some_parameter)%> <%= some_parameter2 if defined?(some_parameter2) %> <%= some_parameter3 if defined?(some_parameter3) %> Notice that in the context of a partial, we have direct access to the parameters as local variables. However, since we're not utilizing "blocks.define" to create our block, we can't specify the default parameters :some_parameter and :some_parameter2 as we do in the first example. This has the potential to cause a runtime exception in the context of partials and we will need to assure that optional parameters are defined using "defined?". In the first example, we specified two parameters that are provided automatically to the block named "some_block_name". They are "some_parameter" and "some_parameter2". In addition, the definition of the block is assuming that the user will be passing in another parameter called "some_parameter3". However, all parameters are passed in in a hash (or local variables for partials), no error will occur if the user fails to specify "some_parameter3". Now, we may use the above block as follows: <%= blocks.use :some_block_name %> The system will first look for a block that's been defined inline by the name :some_block_name. If it cannot find one, it will try and render a partial with the same name within the current controller's view directory. Failing to find that, it will try and render a partial within the global blocks view directory (by default, views/blocks). If that partial also does not exist, it will give up and render nothing. (See [[Render Order]]) Here, we will see the output "1 2" for the first example (and "" for the second example). But if we pass in "some_parameter3", as follows: <%= blocks.use :some_block_name, :some_parameter3 => 3 %> Then we will see "1 2 3" for the first example (and "3" for the second example). Additionally, we can override any of the previous parameters when using a block simply by passing in the new value as a parameter: <%= blocks.use :some_block_name, :some_parameter2 => "overridden", :some_parameter3 => 3 %> In this case, we will see "1 overridden 3" for the first example (and "overridden 3" for the second example). Thus, we now have content_for but with parameters, and additional intelligence by utilizing partials. == table_for table_for is a useful example of how blocks may be utilized in an invaluable way. It is built entirely using the core blocks library. It is exposed as a helper method with the following prototype: table_for(records, options={}, &block) For example, if you have an Array of objects that respond to the following [:name, :email, :phonenumber] e.g. @records = [OpenStruct.new({:name => "The Name", :email => "The Email", :phonenumber => "A phone number"}), OpenStruct.new({:name => "The Second Name", :email => "The Second Email", :phonenumber => "A second phone number"})] And using table_for you can very easily specify intricate details about the table (Note: most of the options in this example are optional): <%= table_for @records, :table_html => {:id => "records"}, :header_html => {:style => "color:red"}, :row_html => {:class => lambda { |parameters| cycle('odd', 'even')}}, :column_html => {:style => "color:green"} do |table| %> <%= table.column :name, :column_html => {:style => "color:blue"}, :header_html => {:style => "color:orange"} %> <%= table.column :email %> <%= table.column :phonenumber, :column_html => {:style => "color:orange"}, :header_html => {:style => "color:blue"} %> <%= table.column :label => "???" do %> Some Random Column <% end %> <% end %> Will generate the following table:
Name | Phonenumber | ??? | |
---|---|---|---|
The Name | The Email | A phone number | Some Random Column |
The Second Name | The Second Email | A second phone number | Some Random Column |