Module: Sequel::Plugins::Forme::SequelForm

Defined in:
lib/sequel/plugins/forme.rb

Overview

This module extends all Forme::Form instances that use a Sequel::Model instance as the form’s obj.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#namespacesObject

The namespaces that should be added to the id and name attributes for the receiver’s inputs. Used as a stack by subform.



28
29
30
# File 'lib/sequel/plugins/forme.rb', line 28

def namespaces
  @namespaces
end

#nested_associationsObject

Stack of objects used by subform. The current obj is added to the top of the stack on a call to subform, the nested associated object is set as the current obj during the call to subform, and when subform returns, the top of the stack is set as the current obj.



23
24
25
# File 'lib/sequel/plugins/forme.rb', line 23

def nested_associations
  @nested_associations
end

Instance Method Details

#form(attr = {}, &block) ⇒ Object

Use the post method by default for Sequel forms, unless overridden with the :method attribute.



32
33
34
35
36
# File 'lib/sequel/plugins/forme.rb', line 32

def form(attr={}, &block)
  attr = {:method=>:post}.merge(attr)
  attr[:class] = ::Forme.merge_classes(attr[:class], "forme", obj.model.send(:underscore, obj.model.name))
  super(attr, &block)
end

#humanize(s) ⇒ Object

Call humanize on a string version of the argument if String#humanize exists. Otherwise, do some monkeying with the string manually.



41
42
43
44
# File 'lib/sequel/plugins/forme.rb', line 41

def humanize(s)
  s = s.to_s
  s.respond_to?(:humanize) ? s.humanize : s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
end

#namespaced_id(field) ⇒ Object

Return a unique id attribute for the field, handling nested attributes use.



102
103
104
# File 'lib/sequel/plugins/forme.rb', line 102

def namespaced_id(field)
  "#{namespaces.join('_')}_#{field}"
end

#namespaced_name(field, multiple = false) ⇒ Object

Return a unique name attribute for the field, handling nested attribute use. If multiple is true, end the name with [] so that param parsing will treat the name as part of an array.



109
110
111
112
# File 'lib/sequel/plugins/forme.rb', line 109

def namespaced_name(field, multiple=false)
  root, *nsps = namespaces
  "#{root}#{nsps.map{|n| "[#{n}]"}.join}[#{field}]#{'[]' if multiple}"
end

#subform(association, opts = {}, &block) ⇒ Object

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.

The following options are currently supported:

:inputs

Automatically call inputs with the given values. Using this, it is not required to pass a block to the method, though it will still work if you do.

:legend

If :inputs is also used, this is passed to it to override the default :legend used. 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.



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/sequel/plugins/forme.rb', line 61

def subform(association, opts={}, &block)
  nested_obj = opts.has_key?(:obj) ? opts[:obj] : obj.send(association)
  ref = obj.class.association_reflection(association)
  multiple = ref.returns_array?
  i = -1
  ins = opts[:inputs]
  Array(nested_obj).each do |no|
    begin
      nested_associations << obj
      namespaces << "#{association}_attributes"
      namespaces << (i+=1) if multiple
      @obj = no
      emit(input(ref.associated_class.primary_key, :type=>:hidden, :label=>nil)) unless no.new?
      if ins
        options = opts.dup
        if options.has_key?(:legend)
          if options[:legend].respond_to?(:call)
            options[:legend] = multiple ? options[:legend].call(no, i) : options[:legend].call(no)
          end
        else
          if multiple
            options[:legend] = humanize("#{obj.model.send(:singularize, association)} ##{i+1}")
          else
            options[:legend] = humanize(association)
          end
        end
        _inputs(ins, options, &block)  
      else
        yield
      end
    ensure
      @obj = nested_associations.pop
      namespaces.pop if multiple
      namespaces.pop
    end
  end
  nil
end