class ResourcefulViews cattr_accessor :form_helpers_suffix, :link_helpers_suffix def initialize # :nodoc: @module ||= Module.new yield self end # generate a string of space-separated standardized CSS classnames def self.resourceful_classnames(primary_classname, *secondary_classnames) classnames = [] classnames << primary_classname secondary_classnames.each do |classname| classnames << classname classnames << [classname, primary_classname].join('_') # a little help for IE end classnames.join(' ') end # Build resourceful helpers for a plural resource and install them into ActionView::Base def build_and_install_helpers_for_resource(resource) # :nodoc: build_index_helper(resource) build_search_helper(resource) build_show_helper(resource) build_new_helper(resource) build_edit_helper(resource) build_destroy_helper(resource) build_list_helpers(resource) build_create_helper(resource) build_update_helper(resource) install_helpers end # Build resourceful helpers for a singular resource and install them into ActionView::Base def build_and_install_helpers_for_singular_resource(resource) # :nodoc: build_show_helper(resource) build_new_helper(resource) build_edit_helper(resource) build_destroy_helper(resource) build_create_helper(resource) build_update_helper(resource) install_helpers end protected # Build the 'index_[resource]' helper # # === Examples # # <% index_tables %> # # renders: # # Index # # <% index_table_legs(@table, :id => 'back_button', :label => 'Back') %> # # renders: # # Back # def build_index_helper(resource) helper_name = "index_#{resource.name_prefix}#{resource.plural}#{@@link_helpers_suffix}" return if already_defined?(helper_name) @module.module_eval <<-end_eval def #{helper_name}(*args) opts = args.extract_options! label = opts.delete(:label) || 'Index' custom_classes = opts.delete(:class) || '' opts[:class] = ResourcefulViews.resourceful_classnames('#{resource.plural}', 'index', *custom_classes.split) args << opts.delete(:parameters) if opts[:parameters] link_to(label, #{resource.name_prefix}#{resource.plural}_path(*args), opts) end end_eval end # Build the 'search_[resource]' helper # # === Examples # # <% search_tables %> # # renders: # #
# # <%= search_tables(:label => 'Find', :parameters => {:order => 'material'}) %> # # renders: # # # # <% search_table_legs(table, :parameters => {:order => 'price'}) do %> # <%= select_tag 'filter', '', :id => false %> # <%= submit_button 'Search' %> # <% end %> # # renders: # # # def build_search_helper(resource) helper_name = "search_#{resource.name_prefix}#{resource.plural}#{@@form_helpers_suffix}" return if already_defined?(helper_name) @module.module_eval <<-end_eval def #{helper_name}(*args, &block) opts = args.extract_options! opts[:class] = ResourcefulViews.resourceful_classnames('#{resource.plural}', 'search', *(opts.delete(:class) || '').split) opts[:method] = :get parameters = opts.delete(:parameters) || {} if block_given? concat(form_tag(#{resource.name_prefix}#{resource.plural}_path(*args), opts), block.binding) parameters.collect{ |key, value| concat(hidden_field_tag(key.to_s, value, :id => nil), block.binding) } yield concat('', block.binding) else opts_for_button = opts.delete(:button) || {} opts_for_button.merge!(:type => 'submit') label = opts.delete(:label) || 'Search' opts[:action] = #{resource.name_prefix}#{resource.plural}_path(*args) content_tag('form', opts) do text_field_tag(:query, @query, :id => nil) + parameters.collect{ |key, value| hidden_field_tag(key.to_s, value, :id => nil) }.join + content_tag(:button, label, opts_for_button) end end end end_eval end # Build the 'show_[resource]' helper # # === Examples # # <% show_table_top(@table, @top) %> # # renders: # # Show # # <% show_table(@table, :label => @top.material) %> # # renders: # # Linoleum # def build_show_helper(resource) helper_name = "show_#{resource.name_prefix}#{resource.singular}#{@@link_helpers_suffix}" return if already_defined?(helper_name) @module.module_eval <<-end_eval def #{helper_name}(*args) opts = args.extract_options! label = opts.delete(:label) || 'Show' opts[:class] = ResourcefulViews.resourceful_classnames('#{resource.singular}', 'show', *(opts.delete(:class) || '').split) args << opts.delete(:parameters) if opts[:parameters] link_to(label, #{resource.name_prefix}#{resource.singular}_path(*args), opts) end end_eval end # Build the 'new_[resource]' helper # # === Examples # # <% new_table %> # # renders: # # New # # <% new_table_top(@table, :label => 'Add a top', :id => 'add_button') %> # # renders: # # Add a top # def build_new_helper(resource) helper_name = "new_#{resource.name_prefix}#{resource.singular}#{@@link_helpers_suffix}" return if already_defined?(helper_name) @module.module_eval <<-end_eval def #{helper_name}(*args, &block) opts = args.extract_options! opts[:class] = ResourcefulViews.resourceful_classnames('#{resource.singular}', 'new', *(opts.delete(:class) || '').split) parameters = opts.delete(:parameters) || {} parameters.merge!(opts.delete(:attributes).inject({}){|attributes, (key, value)| attributes['#{resource.singular}[' + key.to_s + ']'] = value; attributes}) if opts[:attributes] if block_given? opts[:method] = :get args_for_fields_for = ['#{resource.singular}'] concat(form_tag(new_#{resource.name_prefix}#{resource.singular}_path(*args), opts), block.binding) concat(parameters.collect{|key, value| hidden_field_tag(key.to_s, value, :id => nil)}.join, block.binding) unless parameters.empty? fields_for(*args_for_fields_for, &block) concat('', block.binding) else label = opts.delete(:label) || 'New' args << parameters unless parameters.empty? link_to(label, new_#{resource.name_prefix}#{resource.singular}_path(*args), opts) end end end_eval end # Build the 'edit_[resource]' helper # # === Examples # # <% edit_table_top(@table) %> # # renders: # # Edit # # <% edit_table_top(@table, :label => 'Change top') %> # # renders: # # Change top # def build_edit_helper(resource) helper_name = "edit_#{resource.name_prefix}#{resource.singular}#{@@link_helpers_suffix}" return if already_defined?(helper_name) @module.module_eval <<-end_eval def #{helper_name}(*args) opts = args.extract_options! label = opts.delete(:label) || 'Edit' opts[:class] = ResourcefulViews.resourceful_classnames('#{resource.singular}', 'edit', *(opts.delete(:class) || '').split) args << opts.delete(:parameters) if opts[:parameters] link_to(label, edit_#{resource.name_prefix}#{resource.singular}_path(*args), opts) end end_eval end # Build the 'destroy_[resource]' helper # # === Examples # # <% destroy_table_leg(@table, @leg) %> # # renders: # # # # <% destroy_table_leg(@table, @leg, :button => {:title => 'Click to remove'}) %> # # renders: # # # def build_destroy_helper(resource) helper_name = "destroy_#{resource.name_prefix}#{resource.singular}#{@@form_helpers_suffix}" return if already_defined?(helper_name) @module.module_eval <<-end_eval def #{helper_name}(*args) opts = args.extract_options! opts_for_button = opts.delete(:button) || {} opts_for_button.merge!(:type => 'submit') label = opts.delete(:label) || 'Delete' opts_for_button[:title] = opts.delete(:title) if opts[:title] opts[:class] = ResourcefulViews.resourceful_classnames('#{resource.singular}', 'destroy', *(opts.delete(:class) || '').split) opts[:method] = :post opts[:action] = #{resource.name_prefix}#{resource.singular}_path(*args) content_tag('form', opts) do hidden_field_tag(:_method, :delete, :id => nil) + token_tag.to_s + content_tag(:button, label, opts_for_button) end end end_eval end # Build the list helpers # # === Examples # # <% table_list do %> # ... # <%- end -%> # # renders: # #