Class: Metadata::FormBuilder
- Inherits:
-
BuilderBase
- Object
- ActionView::Helpers::FormBuilder
- BuilderBase
- Metadata::FormBuilder
- Defined in:
- app/models/metadata/form_builder.rb
Instance Attribute Summary
Attributes inherited from BuilderBase
Instance Method Summary collapse
-
#append_class!(options, klass) ⇒ Hash
Mutates the input html_options hash to add klass to the css classes while maintaining any existing classes.
-
#change_select_options_for(field, options) ⇒ Object
Allows the options of the specified ‘field’ to be changed based on the value of another field.
-
#document_field(field, options) ⇒ Object
Creates a file upload field that will be properly handled by Document instances.
-
#finalize_related_fields ⇒ Object
Renders the Javascript for dealing with showing and hiding the related fields.
- #header(field, options = {}) ⇒ Object
-
#initialize(*args) ⇒ FormBuilder
constructor
A new instance of FormBuilder.
-
#radio_select(method, choices, options = {}, html_options = {}) ⇒ Object
rubocop:todo Metrics/MethodLength.
-
#related_fields(options) ⇒ Object
Handles wrapping certain fields so that they are only shown when another field is a certain value.
- #select(method, choices, options = {}, html_options = {}, &block) ⇒ Object
- #select_by_association(association, options = {}, html_options = {}) ⇒ Object
Methods inherited from BuilderBase
Constructor Details
#initialize(*args) ⇒ FormBuilder
Returns a new instance of FormBuilder.
3 4 5 6 7 8 9 10 11 |
# File 'app/models/metadata/form_builder.rb', line 3 def initialize(*args, &) super view_for(:field, 'shared/metadata/edit_field') view_for(:radio_field, 'shared/metadata/radio_field') view_for(:header, 'shared/metadata/header') view_for(:document, 'shared/metadata/edit_document_field') @related_fields, @changing = [], [] end |
Instance Method Details
#append_class!(options, klass) ⇒ Hash
Mutates the input html_options hash to add klass to the css classes while maintaining any existing classes
93 94 95 96 97 |
# File 'app/models/metadata/form_builder.rb', line 93 def append_class!(, klass) [:class] = Array([:class]) [:class] << klass end |
#change_select_options_for(field, options) ⇒ Object
Allows the options of the specified ‘field’ to be changed based on the value of another field.
Inputs: field [Symbol] The affected field e.g. :data_release_timing options [Hash] Contains the controlling field, & a map of controlling values to resulting values (see e.g. below)
All this method does is reformat the values hash to separate out keys that are arrays e.g. changing the options hash as follows:
{ :when=>:data_release_strategy, :values=>{ “not applicable”=>“never”, [“open”, “managed”]=>[“standard”, “immediate”, “delayed”] } } becomes { :when=>:data_release_strategy, :values=>{ “not applicable”=>, “open”=>[“standard”, “immediate”, “delayed”], “managed”=>[“standard”, “immediate”, “delayed”] } }
It then passes the modified arguments on to the @changing array.
148 149 150 151 152 153 |
# File 'app/models/metadata/form_builder.rb', line 148 def (field, ) [:values] = [:values].inject({}) do |values, (key, value)| values.tap { Array(key).each { |k| values[k.to_s] = Array(value) } } end @changing.push([field, ]) 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! ++
19 20 21 22 23 24 25 |
# File 'app/models/metadata/form_builder.rb', line 19 def document_field(field, ) property_field(:document, field, ) do fields_for(:"#{field}_attributes", builder: ActionView::Helpers::FormBuilder) do |fields| fields.file_field(:uploaded_data) end end end |
#finalize_related_fields ⇒ Object
Renders the Javascript for dealing with showing and hiding the related fields.
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'app/models/metadata/form_builder.rb', line 156 def = @related_fields.compact.uniq.map(&:to_s) unless .empty? concat( render( partial: 'shared/metadata/related_fields', locals: { root: sanitized_object_name, related: , changing_fields: @changing } ) ) end end |
#header(field, options = {}) ⇒ Object
99 100 101 |
# File 'app/models/metadata/form_builder.rb', line 99 def header(field, = {}) render_view(:header, field, ) end |
#radio_select(method, choices, options = {}, html_options = {}) ⇒ Object
rubocop:todo Metrics/MethodLength
55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'app/models/metadata/form_builder.rb', line 55 def radio_select(method, choices, = {}, = {}) # rubocop:todo Metrics/MethodLength group = .delete(:grouping) || .delete(:grouping) property_field(:radio_field, method, grouping: group) do choices.each_with_object(+''.html_safe) do |(label_text, option_value), output| output << tag.div(class: %w[custom-control custom-radio custom-control-inline]) do value = option_value || label_text concat (method, value, class: 'custom-control-input', required: true) concat label(method, label_text, class: 'custom-control-label', value: value) end end end end |
#related_fields(options) ⇒ Object
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
107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'app/models/metadata/form_builder.rb', line 107 def (, &) # rubocop:todo Metrics/AbcSize .symbolize_keys! values = (.fetch(:in, Array([:when])) - Array([:not])).map do |v| v.to_s.downcase.gsub(/[^a-z0-9]+/, '_') end content = capture(&) concat(tag.div(content, class: [:related_to, [:to], values].flatten.join(' '))) @related_fields.push([: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, = {}, = {}, &block) group = .delete(:grouping) || .delete(:grouping) append_class!(, 'custom-select select2') property_field(:field, method, grouping: group) { super(method, choices, , , &block) } end |
#select_by_association(association, options = {}, html_options = {}) ⇒ Object
27 28 29 30 31 32 33 34 |
# File 'app/models/metadata/form_builder.rb', line 27 def select_by_association(association, = {}, = {}) append_class!(, 'select2') association_target = association.to_s.classify.constantize if @object.send(association).nil? && association_target.default.present? [:selected] = association_target.default.for_select_dropdown.last end select(:"#{association}_id", association_target.for_select_association, , ) end |