Permalink
Browse files

table_for should be working now, but still not finished

  • Loading branch information...
1 parent 1667cc1 commit 70a7432ea4da02b34c5c48ffd07a12ed01470486 Iain Hecker committed Nov 5, 2008
Showing with 115 additions and 31 deletions.
  1. +70 −10 README.textile
  2. +45 −21 lib/model_based_html.rb
View
@@ -1,28 +1,88 @@
h1. ModelBasedHtml
-This plugin enables the binding of other html elements to models, just like form_for.
+This plugin enables the binding of other html elements to models, comparible
+with form_for. This plugin works best with "Haml":http://haml.hamptoncatlin.com/,
+which I strongly recommend.
-An example says it all:
+h2. Definition Lists
+
+I'll start with an example, which explains the basic methods you can use:
<% definition_list_for @user do |dl| %>
- <%= dl.dt :login %>
- <%= dl.dd :login %>
+
+ <%= dl.dt_and_dd :login %>
+
<%= dl.dt :email %>
<%= dl.dd :email do |mail_address| %>
<%= mail_to mail_address %>
<% end %>
+
+ <%= dl.dt :signature %>
+ <%= dl.dd_h :signature %>
+
<% end %>
The dt method will automatically display the human_attribute_name of this
-attribute, the dd will automatically show the value of this attribute. You can
-pass a block to these methods to play with the value even more, like making it
-a link. Because these values may be harmful, a dd_h method is also available,
-sanitizing html automatically. You can limit it to one line, using dt_and_dd or dt_and_dd_h.
+attribute (and thus translate it), the dd will automatically show the value
+of this attribute. You can pass a block to these methods to play with the value
+even more, like making it a link. Because these values may be harmful, a dd_h
+method is also available, sanitizing html automatically. You can limit it to
+one line, using dt_and_dd or dt_and_dd_h.
+
+h2. Tables
+
+A similar option is available for tables.
+
+ <% table_for @users do |table| %>
+
+ <% table.thead do %>
+ <%= table.th :login %>
+ <%= table.th :email %>
+ <%= table.th :signature %>
+ <% end %>
+
+ <% table.tbody :sanitize => true %>
+
+ <% end %>
+
+By not specifying a block to table.tbody, it automatically loops all records.
+Setting :sanitize to true will automatically escape all html in the tds.
+If you do specify a block to tbody, you can define each cell, just as you would
+do with the definition list. It automatically loops.
-A table_for is also under development.
+ <% table_for @users do |table| %>
+
+ <% table.thead do %>
+ <%= table.th :login %>
+ <%= table.th :email %>
+ <%= table.th :signature %>
+ <% end %>
+
+ <% table.tbody do |user| %>
+ <% table.tr do %>
+ <%= table.td :login
+ <%= table.td :email do |email| %>
+ <%= mail_to(email) %>
+ <% end %>
+ <%= table.td_h :signature %>
+ <% end %>
+ <% end %>
+
+ <% end %>
+
+If the collection was empty, it doesn't render a table at all. You can still
+force a table to render, so you can fill it with your own data. Fill the :force
+option with the class you're using. A td with the proper colspan will be
+rendered with a translatable message.
+
+ <% table_for @users, :force => User do |table| %>
+ # etc...
+ <% end %>
-Please note that this plugin is still very much under development. Use at your own risk.
+h1. Nota bene
+This plugin is still in development and is in now way considered to be used in
+production. Please take care! If you'd like to contribute, please contact me!
Copyright (c) 2008 Iain Hecker, released under the MIT license
View
@@ -2,8 +2,8 @@ module ModelBasedHtml
module Helpers
- def table_for(collection, &block)
- ModelBasedHtml::Table.new(:table, collection, self, &block)
+ def table_for(collection, options = {}, &block)
+ ModelBasedHtml::Table.new(:table, collection, self, options, &block)
end
def definition_list_for(object, &block)
@@ -19,6 +19,7 @@ def initialize(type, object, template, &block)
default(type, object, template, &block)
end
+ # Sets all the defaults and stuff
def default(type, object, template, &block)
object = object.to_s.camelize.constantize.new if object.is_a?(Symbol)
@object = object
@@ -55,7 +56,9 @@ def name_tag(tag, method_or_value, options, &block)
private
def html_attrs_for_object(object)
- { :class => object_name(object), :id => "#{object_name(object)}_#{object.id}" }
+ id = object_name(object)
+ id = object.new_record? ? "new_#{id}" : "#{id}_#{object.id}"
+ { :class => object_name(object), :id => id }
end
def html_attrs_for_collection(collection)
@@ -93,22 +96,19 @@ def concat_or_yield(*args, &block)
def value(method_or_value)
return method_or_value unless method_or_value.is_a?(Symbol)
- real_object.send(method_or_value)
+ @object.send(method_or_value)
end
def name(method_or_value)
return method_or_value unless method_or_value.is_a?(Symbol)
- real_object.class.human_attribute_name(method_or_value.to_s)
- end
-
- def real_object
- @object.is_a?(Array) ? @object.first : @object
+ @object.class.human_attribute_name(method_or_value.to_s)
end
# Returns an empty string so it doesn't matter if you
# echo it in your views.
# <% dl.dd :name %> will be the same as <%= dl.dd :name %>
def concat(*args)
+ @template.concat("\n")
@template.concat(*args)
""
end
@@ -144,33 +144,57 @@ def dt_and_dd_h
class Table < ModelBasedHtml::Base
+ def initialize(type, collection, template, options = {}, &block)
+ # ModelBasedHtml::Table.new(:table, collection, self, &block)
+ @force = options.delete(:force)
+ if collection.empty?
+ if @force
+ object = @force.new
+ else
+ return ''
+ end
+ else
+ object = collection.first
+ end
+ @collection = collection
+ default(:table, object, template, &block)
+ end
+
def thead(options = {}, &block)
concat(start_tag(:thead, options))
+ @inside_thead = true
yield
+ @inside_thead = false
concat("</thead>")
end
def tbody(options = {}, &block)
sanitize = options.delete(:sanitize) or false
concat(start_tag(:tbody, options))
- collection = (@object.is_a?(Array) ? @object : [@object])
- if block_given?
- collection.each do |object|
- yield object
+ if @collection.empty? and @force
+ raise ArgumentError, "No columns defined, use thead and tr to do so." if @columns.nil? or @columns.empty?
+ tr(@object) do
+ td(I18n.t(:nothing), :colspan => @columns.size)
end
else
- raise ArgumentError, "No columns defined for automatic table making" if @columns.nil?
- collection.each do |o|
- @columns.each do |column|
+ if block_given?
+ @collection.each do |object|
+ @object = object
+ yield object
+ end
+ else
+ raise ArgumentError, "No columns defined for automatic table making" if @columns.nil? or @columns.empty?
+ @collection.each do |o|
tr(o) do
- th(o.class.human_attribute_name(column.to_s))
- sanitize ? td_h(o.send(column)) : td(o.send(column))
+ @columns.each do |column|
+ sanitize ? td_h(o.send(column)) : td(o.send(column))
+ end
end
end
end
end
- concat("</thead>")
+ concat("</tbody>")
end
def td(method_or_value = nil, options = {}, &block)
@@ -183,11 +207,11 @@ def td_h(method_or_value = nil, options = {}, &block)
def th(method_or_value = nil, options = {}, &block)
@columns ||= []
- @columns << method_or_value
+ @columns << method_or_value if @inside_thead
name_tag(:th, method_or_value, options, &block)
end
- def tr(object, &block)
+ def tr(object = @object, &block)
row = @template.cycle("odd", "even", :name => "table_#{@object.object_id}")
concat(start_tag(:tr, :class => row, :object_html => object))
yield

0 comments on commit 70a7432

Please sign in to comment.