Class: Metadata::FormBuilder

Inherits:
BuilderBase
  • Object
show all
Defined in:
app/models/metadata/form_builder.rb

Instance Attribute Summary

Attributes inherited from BuilderBase

#locals

Instance Method Summary collapse

Methods inherited from BuilderBase

#filter, #view_for

Constructor Details

#initialize(*args, &block) ⇒ FormBuilder

Returns a new instance of FormBuilder


2
3
4
5
6
7
8
9
10
# File 'app/models/metadata/form_builder.rb', line 2

def initialize(*args, &block)
  super
  view_for(:field, 'shared/metadata/edit_field')
  view_for(:header, 'shared/metadata/header')
  view_for(:document, 'shared/metadata/edit_document_field')
  view_for(:checktext, 'shared/metadata/edit_checktext_field')

  @related_fields, @changing = [], []
end

Instance Method Details

#change_select_options_for(field, options) ⇒ Object

Allows the options of the specified 'field' to be changed based on the value of another field.


102
103
104
105
106
107
108
109
# File 'app/models/metadata/form_builder.rb', line 102

def change_select_options_for(field, options)
  options[:values] = options[:values].inject({}) do |values, (key, value)|
    values.tap do
      Array(key).each { |k| values[k.to_s] = Array(value) }
    end
  end
  @changing.push([field, options])
end

#checktext_field(field, options = {}) ⇒ Object


31
32
33
# File 'app/models/metadata/form_builder.rb', line 31

def checktext_field(field, options = {})
  render_view(:checktext, field, options)
end

#document_field(field, _options = {}) ⇒ Object

Creates a file upload field that will be properly handled by Document instances. It's a bit of a hack because the field we're actually rendering is not what is requested in 'field', but 'field_attributes', so we have to also use a special view for it to alter that. – NOTE: This is immediately overridden by the block below so don't move it! ++


18
19
20
21
22
# File 'app/models/metadata/form_builder.rb', line 18

def document_field(field, _options = {})
  fields_for(:"#{field}_attributes", builder: ActionView::Helpers::FormBuilder) do |fields|
    fields.file_field(:uploaded_data)
  end
end

Renders the Javascript for dealing with showing and hiding the related fields.


112
113
114
115
116
117
118
119
120
121
122
# File 'app/models/metadata/form_builder.rb', line 112

def finalize_related_fields
  related = @related_fields.compact.uniq.map(&:to_s)
  concat(render(
           partial: 'shared/metadata/related_fields',
           locals: {
             root: sanitized_object_name,
             related: related,
             changing_fields: @changing
           }
         )) unless related.empty?
end

#header(field, options = {}) ⇒ Object


82
83
84
# File 'app/models/metadata/form_builder.rb', line 82

def header(field, options = {})
  render_view(:header, field, options)
end

Handles wrapping certain fields so that they are only shown when another field is a certain value. You can use `:to` to give the name of the field, `:when` for the single value when the fields should be shown, and `:in` for a group of values. You must call finalize_related_fields at the end of your view to get the appropriate behaviour


90
91
92
93
94
95
96
97
98
99
# File 'app/models/metadata/form_builder.rb', line 90

def related_fields(options, &block)
  options.symbolize_keys!

  values  = (options.fetch(:in, Array(options[:when])) - Array(options[:not])).map { |v| v.to_s.downcase.gsub(/[^a-z0-9]+/, '_') }
  content = capture(&block)
  concat((:div, content, class: [:related_to, options[:to], values].flatten.join(' ')))

  @related_fields.push(options[:to])
  content
end

#select(method, choices, options = {}, html_options = {}, &block) ⇒ Object


49
50
51
52
53
# File 'app/models/metadata/form_builder.rb', line 49

def select(method, choices, options = {}, html_options = {}, &block)
  html_options[:class] ||= ''
  html_options[:class] << ' custom-select'
  super(method, choices, options, html_options, &block)
end

#select_by_association(association, options = {}, html_options = {}) ⇒ Object


24
25
26
27
28
29
# File 'app/models/metadata/form_builder.rb', line 24

def select_by_association(association, options = {}, html_options = {})
  html_options[:class] ||= 'select2'
  association_target = association.to_s.classify.constantize
  options[:selected] = association_target.default.for_select_dropdown.last if @object.send(association).nil? and association_target.default.present?
  select(:"#{association}_id", association_target.for_select_association, options, html_options)
end