Class: DryCrud::Form::Builder

Inherits:
ActionView::Helpers::FormBuilder
  • Object
show all
Defined in:
app/helpers/dry_crud/form/builder.rb

Overview

A form builder that automatically selects the corresponding input field for ActiveRecord column types. Convenience methods for each column type allow one to customize the different fields.

All field methods may be prefixed with labeled_ in order to render a standard label, required mark and an optional help block with them.

Use #labeled_input_field or #input_field to render a input field corresponding to the given attribute.

See the Control class for how to customize the html rendered for a single input field.

Instance Attribute Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object

Dispatch methods starting with 'labeled_' to render a label and the corresponding input field. E.g. labeled_boolean_field(:checked, class: 'bold') To add an additional help text, use the help option. E.g. labeled_boolean_field(:checked, help: 'Some Help')


251
252
253
254
255
256
257
258
# File 'app/helpers/dry_crud/form/builder.rb', line 251

def method_missing(name, *args)
  field_method = labeled_field_method?(name)
  if field_method
    build_labeled_field(field_method, *args)
  else
    super
  end
end

Instance Attribute Details

#templateObject (readonly)

Returns the value of attribute template


21
22
23
# File 'app/helpers/dry_crud/form/builder.rb', line 21

def template
  @template
end

Instance Method Details

#belongs_to_field(attr, html_options = {}) ⇒ Object

Render a select element for a :belongs_to association defined by attr. Use additional html_options for the select element. To pass a custom element list, specify the list with the :list key or define an instance variable with the pluralized name of the association.


119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'app/helpers/dry_crud/form/builder.rb', line 119

def belongs_to_field(attr, html_options = {})
  list = association_entries(attr, html_options).to_a
  if list.present?
    add_css_class(html_options, 'form-control')
    collection_select(attr, list, :id, :to_s,
                      select_options(attr, html_options),
                      html_options)
  else
    # rubocop:disable Rails/OutputSafety
    none = ta(:none_available, association(@object, attr)).html_safe
    # rubocop:enable Rails/OutputSafety
    static_text(none)
  end
end

#boolean_field(attr, html_options = {}) ⇒ Object

Render a boolean field.


73
74
75
76
77
78
79
80
# File 'app/helpers/dry_crud/form/builder.rb', line 73

def boolean_field(attr, html_options = {})
  tag.div(class: 'checkbox') do
    tag.label do
      detail = html_options.delete(:detail) || ' '.html_safe
      safe_join([check_box(attr, html_options), ' ', detail])
    end
  end
end

Render a cancel link pointing to the given url.


191
192
193
194
# File 'app/helpers/dry_crud/form/builder.rb', line 191

def cancel_link(url = nil)
  url ||= cancel_url
  link_to(ti('button.cancel'), url, class: 'cancel')
end

#decimal_field(attr, html_options = {}) ⇒ Object


101
102
103
104
105
# File 'app/helpers/dry_crud/form/builder.rb', line 101

def decimal_field(attr, html_options = {})
  html_options[:step] ||=
    (10**-column_property(object, attr, :scale)).to_f
  number_field(attr, html_options)
end

#error_messagesObject

Render the error messages for the current form.


152
153
154
155
156
# File 'app/helpers/dry_crud/form/builder.rb', line 152

def error_messages
  @template.render('shared/error_messages',
                   errors: @object.errors,
                   object: @object)
end

#float_field(attr, html_options = {}) ⇒ Object


96
97
98
99
# File 'app/helpers/dry_crud/form/builder.rb', line 96

def float_field(attr, html_options = {})
  html_options[:step] ||= 'any'
  number_field(attr, html_options)
end

#has_many_field(attr, html_options = {}) ⇒ Object

Render a multi select element for a :has_many or :has_and_belongs_to_many association defined by attr. Use additional html_options for the select element. To pass a custom element list, specify the list with the :list key or define an instance variable with the pluralized name of the association.


142
143
144
145
146
# File 'app/helpers/dry_crud/form/builder.rb', line 142

def has_many_field(attr, html_options = {})
  html_options[:multiple] = true
  add_css_class(html_options, 'multiselect')
  belongs_to_field(attr, html_options)
end

#help_block(text) ⇒ Object

Generates a help block for fields


172
173
174
# File 'app/helpers/dry_crud/form/builder.rb', line 172

def help_block(text)
  tag.p(text, class: 'help-block')
end

#input_field(attr, html_options = {}) ⇒ Object

Render a corresponding input control for the given attribute. The input field is chosen based on the ActiveRecord column type.

The following options may be passed:

  • :addon - Addon content displayd just after the input field.

  • :help - A help text displayd below the input field.

  • :span - Number of columns the input field should span.

  • :field_method - Different method to create the input field.

Use additional html_options for the input element.


62
63
64
# File 'app/helpers/dry_crud/form/builder.rb', line 62

def input_field(attr, html_options = {})
  control_class.new(self, attr, html_options).render_content
end

#integer_field(attr, html_options = {}) ⇒ Object


91
92
93
94
# File 'app/helpers/dry_crud/form/builder.rb', line 91

def integer_field(attr, html_options = {})
  html_options[:step] ||= 1
  number_field(attr, html_options)
end

#labeled(attr, content = {}, options = {}, &block) ⇒ Object

Render a label for the given attribute with the passed content. The content may be given as an argument or as a block:

labeled(:attr) { #content }
labeled(:attr, content)

The following options may be passed:

  • :span - Number of columns the content should span.

  • :caption - Different caption for the label.


237
238
239
240
241
242
243
244
# File 'app/helpers/dry_crud/form/builder.rb', line 237

def labeled(attr, content = {}, options = {}, &block)
  if block_given?
    options = content
    content = capture(&block)
  end
  control = control_class.new(self, attr, options)
  control.render_labeled(content)
end

#labeled_input_field(attr, html_options = {}) ⇒ Object

Render a corresponding input control and label for the given attribute. The input field is chosen based on the ActiveRecord column type.

The following options may be passed:

  • :addon - Addon content displayd just after the input field.

  • :help - A help text displayd below the input field.

  • :span - Number of columns the input field should span.

  • :caption - Different caption for the label.

  • :field_method - Different method to create the input field.

Use additional html_options for the input element.


48
49
50
# File 'app/helpers/dry_crud/form/builder.rb', line 48

def labeled_input_field(attr, html_options = {})
  control_class.new(self, attr, html_options).render_labeled
end

#labeled_input_fields(*attrs) ⇒ Object

Render multiple input controls together with a label for the given attributes.


32
33
34
35
# File 'app/helpers/dry_crud/form/builder.rb', line 32

def labeled_input_fields(*attrs)
  options = attrs.extract_options!
  safe_join(attrs) { |a| labeled_input_field(a, options.dup) }
end

#required?(attr) ⇒ Boolean

Returns true if the given attribute must be present.

Returns:

  • (Boolean)

218
219
220
221
222
223
224
225
226
227
# File 'app/helpers/dry_crud/form/builder.rb', line 218

def required?(attr)
  attr, attr_id = assoc_and_id_attr(attr)
  validators = @object.class.validators_on(attr) +
               @object.class.validators_on(attr_id)
  validators.any? do |v|
    v.kind == :presence &&
      !v.options.key?(:if) &&
      !v.options.key?(:unless)
  end
end

#respond_to_missing?(name, include_private = false) ⇒ Boolean

Overriden to fullfill contract with method_missing 'labeled_' methods.

Returns:

  • (Boolean)

261
262
263
# File 'app/helpers/dry_crud/form/builder.rb', line 261

def respond_to_missing?(name, include_private = false) # rubocop:disable Style/OptionalBooleanParameter
  labeled_field_method?(name).present? || super
end

#select_options(attr, options = {}) ⇒ Object

Depending if the given attribute must be present, return only an initial selection prompt or a blank option, respectively.


198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'app/helpers/dry_crud/form/builder.rb', line 198

def select_options(attr, options = {})
  prompt = options.delete(:prompt)
  blank = options.delete(:include_blank)
  if options[:multiple]
    {}
  elsif prompt
    { prompt: prompt }
  elsif blank
    { include_blank: blank }
  else
    assoc = association(@object, attr)
    if required?(attr)
      { prompt: ta(:please_select, assoc) }
    else
      { include_blank: ta(:no_entry, assoc) }
    end
  end
end

#standard_actions(submit_label = ti('button.save'), cancel_url = nil) ⇒ Object

Render a submit button and a cancel link for this form.


177
178
179
180
181
182
183
# File 'app/helpers/dry_crud/form/builder.rb', line 177

def standard_actions(submit_label = ti('button.save'), cancel_url = nil)
  tag.div(class: 'col-md-offset-2 col-md-8') do
    safe_join([submit_button(submit_label),
               cancel_link(cancel_url)],
              ' ')
  end
end

#static_text(text) ⇒ Object

Renders a static text where otherwise form inputs appear.


167
168
169
# File 'app/helpers/dry_crud/form/builder.rb', line 167

def static_text(text)
  tag.p(text, class: 'form-control-static')
end

#string_field(attr, html_options = {}) ⇒ Object

Render a standard string field with column contraints.


67
68
69
70
# File 'app/helpers/dry_crud/form/builder.rb', line 67

def string_field(attr, html_options = {})
  html_options[:maxlength] ||= column_property(@object, attr, :limit)
  text_field(attr, html_options)
end

#submit_button(label = ti('button.save')) ⇒ Object

Render a standard submit button with the given label.


186
187
188
# File 'app/helpers/dry_crud/form/builder.rb', line 186

def submit_button(label = ti('button.save'))
  button(label, class: 'btn btn-primary', data: { disable_with: label })
end

#text_area(attr, html_options = {}) ⇒ Object

Customize the standard text area to have 5 rows by default.


108
109
110
111
112
# File 'app/helpers/dry_crud/form/builder.rb', line 108

def text_area(attr, html_options = {})
  add_css_class(html_options, 'form-control')
  html_options[:rows] ||= 5
  super(attr, html_options)
end

#with_addon(content, addon) ⇒ Object

Renders the given content with an addon.


159
160
161
162
163
164
# File 'app/helpers/dry_crud/form/builder.rb', line 159

def with_addon(content, addon)
  tag.div(class: 'input-group') do
    html = tag.span(addon, class: 'input-group-text')
    content + tag.div(html, class: 'input-group-append')
  end
end