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, #parent_comp

Instance Method Summary collapse

Methods inherited from Compony::Component

#action, #add_content, #before_render, #comp_class_for, #comp_class_for!, #comp_cst, #comp_name, #content, #family_cst, #family_name, #id, #inspect, #param_name, #path, #path_hash, #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



105
106
107
# File 'lib/compony/components/form.rb', line 105

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.



99
100
101
102
# File 'lib/compony/components/form.rb', line 99

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.



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/compony/components/form.rb', line 79

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



36
37
38
39
# File 'lib/compony/components/form.rb', line 36

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



131
132
133
134
135
136
137
138
# File 'lib/compony/components/form.rb', line 131

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



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

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.



118
119
120
121
122
123
# File 'lib/compony/components/form.rb', line 118

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



126
127
128
# File 'lib/compony/components/form.rb', line 126

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



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

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



42
43
44
45
46
47
48
49
# File 'lib/compony/components/form.rb', line 42

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



141
142
143
# File 'lib/compony/components/form.rb', line 141

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.



70
71
72
73
74
75
# File 'lib/compony/components/form.rb', line 70

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