Class: Compony::Components::Form

Inherits:
Compony::Component show all
Defined in:
lib/compony/components/form.rb

Overview

This component is used for the _form partial in the Rails paradigm.

Instance Attribute Summary

Attributes inherited from Compony::Component

#comp_opts, #content_blocks, #parent_comp

Instance Method Summary collapse

Methods inherited from Compony::Component

#action, #before_render, #comp_cst, #comp_name, #content, #family_cst, #family_name, #id, #inspect, #param_name, #path, #path_hash, #remove_content, #render, #render_actions, #resourceful?, #root_comp, #root_comp?, setup, #skip_action, #sub_comp

Constructor Details

#initializeForm

Returns a new instance of Form.



6
7
8
9
# File 'lib/compony/components/form.rb', line 6

def initialize(...)
  @schema_lines_for_data = [] # Array of procs taking data returning a Schemacop proc
  super
end

Instance Method Details

#collectObject

Quick access for wrapping collections in Rails compatible format



116
117
118
# File 'lib/compony/components/form.rb', line 116

def collect(...)
  Compony::ModelFields::Anchormodel.collect(...)
end

#fObject

Called inside the form_fields block. This makes the method f available in the block. See also notes for with_simpleform.



110
111
112
113
# File 'lib/compony/components/form.rb', line 110

def f
  fail("The `f` method may only be called inside `form_fields` for #{inspect}.") unless @simpleform
  return @simpleform
end

#field(name, **input_opts) ⇒ Object

Called inside the form_fields block. This makes the method field available in the block. See also notes for with_simpleform.



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/compony/components/form.rb', line 90

def field(name, **input_opts)
  fail("The `field` method may only be called inside `form_fields` for #{inspect}.") unless @simpleform

  hidden = input_opts.delete(:hidden)
  model_field = @simpleform.object.fields[name.to_sym]
  fail("Field #{name.to_sym.inspect} is not defined on #{@simpleform.object.inspect} but was requested in #{inspect}.") unless model_field

  if hidden
    return model_field.simpleform_input_hidden(@simpleform, self, **input_opts)
  else
    unless @focus_given || @skip_autofocus
      input_opts[:autofocus] = true unless input_opts.key? :autofocus
      @focus_given = true
    end
    return model_field.simpleform_input(@simpleform, self, **input_opts)
  end
end

#form_fields(&block) ⇒ Object

DSL method, use to set the form content



47
48
49
50
# File 'lib/compony/components/form.rb', line 47

def form_fields(&block)
  return @form_fields unless block_given?
  @form_fields = block
end

#schema(wrapper_key, &block) ⇒ Object (protected)

DSL method, use to replace the form’s schema and wrapper key for a completely manual schema



142
143
144
145
146
147
148
149
# File 'lib/compony/components/form.rb', line 142

def schema(wrapper_key, &block)
  if block_given?
    @schema_wrapper_key = wrapper_key
    @schema_block = block
  else
    fail 'schema requires a block to be given'
  end
end

#schema_block_for(data) ⇒ Object

Attr reader for @schema_block with auto-calculated default



63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/compony/components/form.rb', line 63

def schema_block_for(data)
  if @schema_block
    return @schema_block
  else
    # If schema was not called, auto-infer a default
    local_schema_lines_for_data = @schema_lines_for_data
    return proc do
      local_schema_lines_for_data.each do |schema_line|
        instance_exec(&schema_line.call(data))
      end
    end
  end
end

#schema_field(field_name) ⇒ Object (protected)

DSL method, adds a new field to the schema whitelisting a single field of data_class This auto-generates the correct schema line for the field.



129
130
131
132
133
134
# File 'lib/compony/components/form.rb', line 129

def schema_field(field_name)
  @schema_lines_for_data << proc do |data|
    field = data.class.fields[field_name.to_sym] || fail("No field #{field_name.to_sym.inspect} found for #{data.inspect} in #{inspect}.")
    next field.schema_line
  end
end

#schema_fields(*field_names) ⇒ Object (protected)

DSL method, mass-assigns schema fields



137
138
139
# File 'lib/compony/components/form.rb', line 137

def schema_fields(*field_names)
  field_names.each { |field_name| schema_field(field_name) }
end

#schema_line(&block) ⇒ Object (protected)

DSL method, adds a new line to the schema whitelisting a single param inside the schema’s wrapper



123
124
125
# File 'lib/compony/components/form.rb', line 123

def schema_line(&block)
  @schema_lines_for_data << proc { block }
end

#schema_wrapper_key_for(data) ⇒ Object

Attr reader for @schema_wrapper_key with auto-calculated default



53
54
55
56
57
58
59
60
# File 'lib/compony/components/form.rb', line 53

def schema_wrapper_key_for(data)
  if @schema_wrapper_key.present?
    return @schema_wrapper_key
  else
    # If schema was not called, auto-infer a default
    data.model_name.singular
  end
end

#skip_autofocusObject (protected)

DSL method, skips adding autofocus to the first field



152
153
154
# File 'lib/compony/components/form.rb', line 152

def skip_autofocus
  @skip_autofocus = true
end

#with_simpleform(simpleform) ⇒ Object

TODO:

Refactor? Could this be greatly simplified by having form_field to |f| ?

This method is used by render to store the simpleform instance inside the component such that we can call methods from inside form_fields. This is a workaround required because the form does not exist when the RequestContext is being built, and we want the method field to be available inside the form_fields block.



81
82
83
84
85
86
# File 'lib/compony/components/form.rb', line 81

def with_simpleform(simpleform)
  @simpleform = simpleform
  @focus_given = false
  yield
  @simpleform = nil
end