require 'glue/builder/xml' module Nitro module FormHelper # A specialized Builder for dynamically building of forms. # Provides extra support for forms backed by managed objects # (entities). #-- # TODO: allow multiple objects per form. # TODO: use more generalized controls. #++ class FormXmlBuilder < ::Glue::XmlBuilder def initialize buffer = '', options = {} super @obj = options[:object] end # Render a control+label for the given property of the form # object. def property sym, options = {} if prop = @obj.class.properties[sym] control = Form::Control.fetch(@obj, prop, options).render print element(prop, control) else raise "Undefined property '#{sym}' for class '#{@obj.class}'." end end # Render controls+labels for all relations of the form object. def all_properties options = {} for prop in @obj.class.properties.values property prop.symbol, options end end alias_method :properties, :all_properties #-- # IMPLEMENT ME #++ def relation sym, options = {} end #-- # IMPLEMENT ME #++ def all_relations options = {} end # Renders a control to select a file for upload. def select_file name, options = {} print %|| end private # Emit a label. Override this method to customize the # rendering for your application needs. def label prop %{} end # Emit a form element. Override this method to customize the # rendering for your application needs. def element prop, html %{

#{label(prop)}
#{html}

} end end # A sophisticated form generation helper method. # # === Options # # * :object, :entity, :class = The object that acts as model # for this form. If you pass a class an empty object is # instantiated. # # === Example # # #{form(:object => @owner, :action => :save_profile) do |f| # f.property :name, :editable => false # f.property :password # f.br # f.submit 'Update' # end} def form options = {}, &block obj = (options[:object] ||= options[:entity] || options[:class]) # If the passed obj is a Class instantiate an empty object # of this class. if obj.is_a? Class obj = options[:object] = obj.allocate end # Convert virtual :multipart method to method="post", # enctype="multipart/form-data" if options[:method] == :multipart options[:method] = :post options[:enctype] = 'multipart/form-data' end b = FormXmlBuilder.new('', options) b << '' b.hidden(:name => 'oid', :value => obj.oid) if obj and obj.saved? yield b b << '' return b end end end # * George Moschovitis