This module extends all Forme::Form
instances that use a Sequel::Model
instance as the form’s obj
.
Public Instance methods
Use the post method by default for Sequel
forms, unless overridden with the :method attribute.
# File lib/sequel/plugins/forme.rb 22 def form(attr={}, &block) 23 attr[:class] = ::Forme.merge_classes(attr[:class], "forme", obj.forme_namespace) 24 super(attr, &block) 25 end
Call humanize on a string version of the argument if String#humanize exists. Otherwise, do some monkeying with the string manually.
# File lib/sequel/plugins/forme.rb 30 def humanize(s) 31 s = s.to_s 32 s.respond_to?(:humanize) ? s.humanize : s.gsub(/_id$/, "").gsub(/_/, " ").capitalize 33 end
Handle nested association usage. The association
should be a name of the association for the form’s obj
. Inside the block, calls to the input
and inputs
methods for the receiver treat the associated object as the recevier’s obj
, using name and id attributes that work with the Sequel
nested_attributes
plugin. Returns the HTML generated by the subform.
The following options are currently supported:
:inputs |
Automatically call |
:inputs_opts |
When using the :grid option, this allows you to specify options to pass to the table InputsWrapper. |
:legend |
Overrides the default :legend used (which is based on the association name). You can also use a proc as the value, which will called with each associated object (and the position in the associated object already for *_to_many associations), and should return the legend string to use for that object. |
:grid |
Sets up a table with one row per associated object, and one column per field. |
:labels |
When using the :grid option, override the labels that would be created via the :inputs option. If you are not providing an :inputs option or are using a block with additional inputs, you should specify this option. |
:skip_primary_key |
Skip adding a hidden primary key field for existing objects. |
# File lib/sequel/plugins/forme.rb 61 def subform(association, opts={}, &block) 62 content_added do 63 nested_obj = opts.has_key?(:obj) ? opts[:obj] : obj.send(association) 64 ref = obj.class.association_reflection(association) 65 multiple = ref.returns_array? 66 grid = opts[:grid] 67 ns = "#{association}_attributes" 68 69 send(multiple ? :each_obj : :with_obj, nested_obj, ns) do |no, i| 70 input(ref.associated_class.primary_key, :type=>:hidden, :label=>nil, :wrapper=>nil) unless no.new? || opts[:skip_primary_key] 71 end 72 73 contents = proc do 74 send(multiple ? :each_obj : :with_obj, nested_obj, ns) do |no, i| 75 options = opts.dup 76 if grid 77 options.delete(:legend) 78 else 79 if options.has_key?(:legend) 80 if options[:legend].respond_to?(:call) 81 options[:legend] = multiple ? options[:legend].call(no, i) : options[:legend].call(no) 82 end 83 else 84 if multiple 85 options[:legend] = humanize("#{obj.model.send(:singularize, association)} ##{i+1}") 86 else 87 options[:legend] = humanize(association) 88 end 89 end 90 end 91 options[:subform] = true 92 93 inputs(options[:inputs]||[], options, &block) 94 end 95 end 96 97 if grid 98 labels = opts.fetch(:labels){opts[:inputs].map{|l,| humanize(l)} if opts[:inputs]} 99 legend = opts.fetch(:legend){humanize(association)} 100 inputs_opts = opts[:inputs_opts] || {} 101 inputs(inputs_opts.merge(:inputs_wrapper=>:table, :nested_inputs_wrapper=>:tr, :wrapper=>:td, :labeler=>nil, :labels=>labels, :legend=>legend), &contents) 102 else 103 contents.call 104 end 105 end 106 end