Class: Forme::Form

Inherits:
Object
  • Object
show all
Defined in:
lib/forme/form.rb

Overview

The Form class is the main entry point to the library.

Using the form, input, tag, and inputs methods, one can return HTML form tag string (or fragments of an HTML form tag).

Direct Known Subclasses

Sequel::Plugins::Forme::Form

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(obj = nil, opts = {}) ⇒ Form

Creates a Form object. Arguments:

obj

Sets the obj for the form. If a hash, is merged with the opts argument to set the opts.

opts

A hash of options for the form



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/forme/form.rb', line 85

def initialize(obj=nil, opts={})
  @opts = opts.merge(obj.is_a?(Hash) ? obj : {:obj=>obj})
  @opts[:namespace] = Array(@opts[:namespace])

  if obj && obj.respond_to?(:forme_config)
    obj.forme_config(self)
  end

  config = CONFIGURATIONS[@opts[:config]||Forme.default_config]
  copy_inputs_wrapper_from_wrapper(@opts)

  TRANSFORMER_TYPES.each do |t|
    case @opts[t]
    when Symbol
      @opts[t] = Forme.transformer(t, @opts[t], @opts)
    when nil
      unless @opts.has_key?(t)
        @opts[t] = Forme.transformer(t, config, @opts)
      end
    end
  end

  @serializer = @opts[:serializer]
  @input_defaults = @opts[:input_defaults] || {}
  @to_s = String.new
end

Instance Attribute Details

#form_tag_attributesObject (readonly)

The attributes used for the form tag for this form.



16
17
18
# File 'lib/forme/form.rb', line 16

def form_tag_attributes
  @form_tag_attributes
end

#input_defaultsObject (readonly)

Set the default options for inputs by type. This should be a hash with input type keys and values that are hashes of input options.



13
14
15
# File 'lib/forme/form.rb', line 13

def input_defaults
  @input_defaults
end

#optsObject (readonly)

A hash of options for the form.



9
10
11
# File 'lib/forme/form.rb', line 9

def opts
  @opts
end

#serializerObject (readonly)

The serializer determines how Tag objects are transformed into strings. Must respond to call or be a registered symbol.



20
21
22
# File 'lib/forme/form.rb', line 20

def serializer
  @serializer
end

#to_sObject (readonly)

The contents of the form as a string. This should not be mutated by external code.



24
25
26
# File 'lib/forme/form.rb', line 24

def to_s
  @to_s
end

Class Method Details

.form(obj = nil, attr = {}, opts = {}, &block) ⇒ Object

Create a Form instance and yield it to the block. Returns an HTML string for the form tag.

Argument Handling:

No args

Creates a Form object with no options and not associated to an obj, and with no attributes in the opening tag.

1 hash arg

Treated as opening form tag attributes, creating a Form object with no options.

1 non-hash arg

Treated as the Form‘s obj, with empty options and no attributes in the opening tag.

2 hash args

First hash is opening attributes, second hash is Form options.

1 non-hash arg, 1-2 hash args

First argument is Form‘s obj, second is opening attributes, third if provided is Form’s options.



76
77
78
79
# File 'lib/forme/form.rb', line 76

def self.form(obj=nil, attr={}, opts={}, &block)
  f, attr, block = form_args(obj, attr, opts, &block)
  f.form(attr, &block)
end

.form_args(obj, attr, opts, &block) ⇒ Object

Parse the args given to #form and return Form instance, form tag attributes, and block for form.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/forme/form.rb', line 38

def self.form_args(obj, attr, opts, &block)
  f = if obj.is_a?(Hash)
    raise Error, "Can't provide 3 hash arguments to form" unless opts.empty?
    opts = attr
    attr = obj
    new(opts)
  else
    new(obj, opts)
  end

  ins = opts[:inputs]
  button = opts[:button]
  if ins || button
    block = proc do |form|
      form.inputs(ins, opts) if ins
      yield form if block_given?
      form.button(button) if button
    end
  end

  [f, attr, block]
end

.new(obj = nil, opts = {}) ⇒ Object

Use appropriate Form subclass for object based on the current class, if the object responds to forme_form_class.



28
29
30
31
32
33
34
# File 'lib/forme/form.rb', line 28

def self.new(obj=nil, opts={})
  if obj && obj.respond_to?(:forme_form_class) && !opts[:_forme_form_class_set]
    obj.forme_form_class(self).new(obj, opts.merge(:_forme_form_class_set=>true))
  else
    super
  end
end

Instance Method Details

#<<(tag) ⇒ Object

Add the Input/Tag instance to the HTML buffer.



300
301
302
# File 'lib/forme/form.rb', line 300

def <<(tag)
  @to_s << tag.to_s
end

#_input(*a) ⇒ Object

Return a new Input associated with the receiver with the given arguments, doing no other processing.



181
182
183
# File 'lib/forme/form.rb', line 181

def _input(*a)
  Input.new(self, *a)
end

#_tag(*a, &block) ⇒ Object

Create a Tag associated to the receiver with the given arguments and block, doing no other processing.



256
257
258
# File 'lib/forme/form.rb', line 256

def _tag(*a, &block)
  Tag.new(self, *a, &block)
end

#button(opts = {}) ⇒ Object

Creates a :submit Input with the given opts. Returns the generated HTML for the input.



294
295
296
297
# File 'lib/forme/form.rb', line 294

def button(opts={})
  opts = {:value=>opts} if opts.is_a?(String)
  content_added{self << _input(:submit, opts)}
end

#closeObject

Returns a string representing the closing of the form tag, for serializers that support closing tags.



250
251
252
# File 'lib/forme/form.rb', line 250

def close
  serializer.serialize_close(_tag(:form)) if serializer.respond_to?(:serialize_close)
end

#each_obj(objs, namespace = nil) ⇒ Object

Calls the block for each object in objs, using with_obj with the given namespace and an index namespace (starting at 0).



306
307
308
309
310
311
312
# File 'lib/forme/form.rb', line 306

def each_obj(objs, namespace=nil)
  objs.each_with_index do |obj, i|
    with_obj(obj, Array(namespace) + [i]) do
      yield obj, i
    end
  end
end

#form(attr = {}) ⇒ Object

Create a form tag with the given attributes. Returns an HTML string for the generated form tag.



114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/forme/form.rb', line 114

def form(attr={})
  if obj && !attr[:method] && !attr['method'] && obj.respond_to?(:forme_default_request_method)
    attr = Hash[attr]
    attr['method'] = obj.forme_default_request_method
  end
  @form_tag_attributes = attr

  tag(:form, attr) do
    before_form_yield
    yield self if block_given?
    after_form_yield
  end
end

#input(field, opts = {}) ⇒ Object

Creates an Input with the given field and opts associated with the receiver. Returns the HTML generated by the given input.

If the form is associated with an obj, or the :obj key exists in the opts argument, treats the field as a call to the obj. If obj responds to forme_input, that method is called with the field and a copy of opts. Otherwise, the field is used as a method call on the obj and a text input is created with the result.

If no obj is associated with the receiver, field represents an input type (e.g. :text, :textarea, :select), and an input is created directly with the field and opts.



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/forme/form.rb', line 146

def input(field, opts={})
  content_added do
    if opts.has_key?(:obj)
      opts = opts.dup
      obj = opts.delete(:obj)
    else
      obj = self.obj
    end

    input = if obj
      if obj.respond_to?(:forme_input)
        obj.forme_input(self, field, opts.dup)
      else
        opts = opts.dup
        opts[:key] = field unless opts.has_key?(:key)
        type = opts.delete(:type) || :text
        unless opts.has_key?(:value) || type == :file
          opts[:value] = if obj.is_a?(Hash)
            obj[field]
          else
            obj.send(field)
          end
        end
        _input(type, opts)
      end
    else
      _input(field, opts)
    end

    self << input
  end
end

#inputs(inputs = [], opts = {}) ⇒ Object

Creates a tag using the inputs_wrapper (a fieldset by default), calls input on each element of inputs, and yields if given a block. You can use array arguments if you want inputs to be created with specific options:

f.inputs([:field1, :field2])
f.inputs([[:field1, {:name=>'foo'}], :field2])

The given opts are passed to the inputs_wrapper, and the default inputs_wrapper supports a :legend option that is used to set the legend for the fieldset.

opts can also include transformer options itself (e.g. :wrapper), which override the form’s current transformer options for the duration of the block. The exception is the :inputs_wrapper transformer option, which affects the wrapper to use for this inputs call. You can use the :nested_inputs_wrapper option to set the default :inputs_wrapper option for the duration of the block.

Returns the HTML generated by the inputs added to the form.

This can also be called with a single hash argument to just use an options hash:

f.inputs(:legend=>'Foo') do
  # ...
end

or even without any arguments:

f.inputs do
  # ...
end


216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/forme/form.rb', line 216

def inputs(inputs=[], opts={})
  content_added do
    if inputs.is_a?(Hash)
      opts = inputs.merge(opts)
      inputs = []
    end

    form_opts = {}
    form_opts[:inputs_wrapper] = opts[:nested_inputs_wrapper] if opts[:nested_inputs_wrapper]
    TRANSFORMER_TYPES.each do |t|
      if opts.has_key?(t) && t != :inputs_wrapper
        form_opts[t] = opts[t]
      end
    end

    Forme.transform(:inputs_wrapper, opts, @opts, self, opts) do
      with_opts(form_opts) do
        inputs.each do |i|
          input(*i)
        end
        yield if block_given?
      end
    end
  end
end

#namespacesObject

The namespaces if any for the receiver’s inputs. This can be used to automatically setup namespaced class and id attributes.



269
270
271
# File 'lib/forme/form.rb', line 269

def namespaces
  @opts[:namespace]
end

#objObject

The object associated with this form, if any. If the Form has an associated obj, then calls to input are assumed to be accessing fields of the object instead to directly representing input types.



263
264
265
# File 'lib/forme/form.rb', line 263

def obj
  @opts[:obj]
end

#open(attr) ⇒ Object

Returns a string representing the opening of the form tag for serializers that support opening tags.



244
245
246
# File 'lib/forme/form.rb', line 244

def open(attr)
  serializer.serialize_open(_tag(:form, attr)) if serializer.respond_to?(:serialize_open)
end

#post?Boolean

Whether the method for this form is POST. Only callable after calling #form.

Returns:

  • (Boolean)


130
131
132
# File 'lib/forme/form.rb', line 130

def post?
  (form_tag_attributes[:method] || form_tag_attributes['method']).to_s.upcase == 'POST'
end

#raw(s) ⇒ Object

Return a new string that will not be HTML escaped by the default serializer.



315
316
317
# File 'lib/forme/form.rb', line 315

def raw(s)
  Forme.raw(s)
end

#tag(*a, &block) ⇒ Object

Creates a Tag associated to the receiver with the given arguments. If a block is given, yield to the block inside the generated tag. Returns the HTML added to the form by the addition of this tag.



276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/forme/form.rb', line 276

def tag(*a, &block)
  content_added do
    tag = _tag(*a)
    if block
      self << serialize_open(tag)
      if children = tag.children
        children.each{|child| self << child}
      end
      yield self
      self << serialize_close(tag)
    else
      self << tag
    end
  end
end

#with_obj(obj, namespace = nil) ⇒ Object

Temporarily override the given object and namespace for the form. Any given namespaces are appended to the form’s current namespace.



321
322
323
324
325
# File 'lib/forme/form.rb', line 321

def with_obj(obj, namespace=nil)
  with_opts(:obj=>obj, :namespace=>@opts[:namespace]+Array(namespace)) do
    yield obj
  end
end

#with_opts(opts) ⇒ Object

Temporarily override the opts for the form for the duration of the block. This merges the given opts with the form’s current opts, restoring the previous opts before returning.



330
331
332
333
334
335
336
337
338
339
# File 'lib/forme/form.rb', line 330

def with_opts(opts)
  orig_opts = @opts
  @opts = orig_opts.merge(opts)
  copy_inputs_wrapper_from_wrapper(opts, @opts)
  yield
ensure
  # :nocov:
  @opts = orig_opts if orig_opts
  # :nocov:
end