Class: Effective::FormBuilderInputs::EffectiveSelect

Inherits:
Effective::FormBuilderInput show all
Defined in:
app/models/effective/form_builder_inputs/effective_select.rb

Instance Method Summary collapse

Methods inherited from Effective::FormBuilderInput

#field_name, #initialize, #value

Constructor Details

This class inherits a constructor from Effective::FormBuilderInput

Instance Method Details

#collectionObject

This is a grouped polymorphic collection

[“Clinics”, [[“Clinc 50”, “Clinic_50”], [“Clinic 43”, “Clinic_43”]]], [“Contacts”, [[“Contact 544”, “Contact_544”]]]


45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'app/models/effective/form_builder_inputs/effective_select.rb', line 45

def collection
  @collection ||= begin
    collection = options.delete(:collection) || []
    grouped = collection[0].kind_of?(Array) && collection[0][0].kind_of?(String) && collection[0][1].respond_to?(:to_a) && (collection[0][1] != nil) # Array or ActiveRecord_Relation

    if options[:grouped] && !grouped && collection.present?
      raise "Grouped collection expecting a Hash {'Posts' => Post.all, 'Events' => Event.all} or a Hash {'Posts' => [['Post A', 1], ['Post B', 2]], 'Events' => [['Event A', 1], ['Event B', 2]]}"
    end

    if grouped && !options[:polymorphic] && collection[0][1].kind_of?(ActiveRecord::Relation)
      options[:option_value_method] = :to_s if options[:option_value_method] == default_options[:option_value_method]
      options[:option_key_method] = :id if options[:option_key_method] == default_options[:option_key_method]
    end

    if grouped && !options[:polymorphic]
      if collection[0][1].kind_of?(ActiveRecord::Relation)
        options[:option_value_method] = :to_s if options[:option_value_method] == default_options[:option_value_method]
        options[:option_key_method] = :id if options[:option_key_method] == default_options[:option_key_method]
      end

      if collection[0][1].kind_of?(Array) && !collection[0][1][0].kind_of?(Array)
        options[:option_value_method] = :to_s if options[:option_value_method] == default_options[:option_value_method]
        options[:option_key_method] = :to_s if options[:option_key_method] == default_options[:option_key_method]
      end
    end

    if grouped
      collection.each_with_index do |(name, group), index|
        collection[index][1] = group.respond_to?(:call) ? group.call : group.to_a
      end
    else
      collection = collection.respond_to?(:call) ? collection.call : collection.to_a
    end

    if options[:polymorphic]
      if grouped
        collection.each { |_, group| polymorphize_collection!(group) }
      else
        polymorphize_collection!(collection)
      end
    end

    collection.respond_to?(:call) ? collection.call : collection.to_a
  end
end

#default_input_htmlObject



14
15
16
# File 'app/models/effective/form_builder_inputs/effective_select.rb', line 14

def default_input_html
  {class: 'effective_select', placeholder: 'Please choose'}
end

#default_input_jsObject



10
11
12
# File 'app/models/effective/form_builder_inputs/effective_select.rb', line 10

def default_input_js
  { theme: 'bootstrap', minimumResultsForSearch: 6, tokenSeparators: [',', ';', '\n', '\t'], width: 'style', placeholder: 'Please choose' }
end

#default_optionsObject



6
7
8
# File 'app/models/effective/form_builder_inputs/effective_select.rb', line 6

def default_options
  { label_method: :to_s, value_method: :to_s, group_label_method: :first, group_method: :last, option_value_method: :first, option_key_method: :second }
end

#html_optionsObject



154
155
156
157
158
159
160
161
162
# File 'app/models/effective/form_builder_inputs/effective_select.rb', line 154

def html_options
  super().tap do |html_options|
    html_options[:multiple] = options[:multiple]
    html_options[:class] << 'polymorphic' if options[:polymorphic]
    html_options[:class] << 'grouped' if options[:grouped]
    html_options[:class] << 'hide-disabled' if options[:hide_disabled]
    html_options[:class] << 'tags-input' if options[:tags]
  end
end

#js_optionsObject



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'app/models/effective/form_builder_inputs/effective_select.rb', line 164

def js_options
  @effective_select_js_options ||= super().tap do |js_options|
    js_options[:allowClear] = (options[:multiple] != true)
    js_options[:tags] = (options[:tags] == true) unless js_options.key?(:tags)
    js_options[:tokenSeparators] = nil if options[:tags] != true
    js_options[:template] = options[:template] if options[:template].present?

    # select2 doesn't support adding css classes to its input, so we support it through the
    # js_options[:containerClass] and js_options[:dropdownClass] methods
    # When we use options[:hide_disabled], we add the 'hide-disabled' class to both the container and the dropdown
    if options[:hide_disabled]
      js_options[:containerClass] = (arrayize_html_class_key(js_options[:containerClass]) + ['hide-disabled']).join(' ')
      js_options[:dropdownClass] = (arrayize_html_class_key(js_options[:dropdownClass]) + ['hide-disabled']).join(' ')
    end
  end
end

#optionsObject



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'app/models/effective/form_builder_inputs/effective_select.rb', line 124

def options
  @effective_select_options ||= super().tap do |options|
    options[:multiple] = true if (options[:tags] == true)
    options[:include_blank] = (options[:multiple] != true)

    # Fix the selected value, depending on our use case
    unless value.nil?
      case value
      when Array
        if options[:polymorphic]
          options[:selected] = value.map { |value| (polymorhpic_value(value) rescue value) }
        elsif value.first.respond_to?(options[:value_method])  # This is probably a belongs_to ActiveRecord object
          options[:selected] = value.map { |value| (value.public_send(options[:value_method]) rescue value) }
        end
      when Integer
        options[:selected] = value
      else  # Value is not an Array
        if options[:polymorphic]
          options[:selected] = polymorphic_value(value)
        elsif value.respond_to?(options[:value_method])  # This is probably a belongs_to ActiveRecord object
          options[:selected] = value.public_send(options[:value_method])
        end
      end

      options[:selected] ||= value
    end

  end
end

#polymorphic_id_methodObject



108
109
110
# File 'app/models/effective/form_builder_inputs/effective_select.rb', line 108

def polymorphic_id_method
  @method.to_s.sub('_id', '') + '_id'
end

#polymorphic_id_valueObject



120
121
122
# File 'app/models/effective/form_builder_inputs/effective_select.rb', line 120

def polymorphic_id_value
  value.try(:id)
end

#polymorphic_type_methodObject



104
105
106
# File 'app/models/effective/form_builder_inputs/effective_select.rb', line 104

def polymorphic_type_method
  @method.to_s.sub('_id', '') + '_type'
end

#polymorphic_type_valueObject



116
117
118
# File 'app/models/effective/form_builder_inputs/effective_select.rb', line 116

def polymorphic_type_value
  value.try(:class).try(:model_name)
end

#polymorphic_value(obj) ⇒ Object



112
113
114
# File 'app/models/effective/form_builder_inputs/effective_select.rb', line 112

def polymorphic_value(obj)
  "#{obj.class.model_name}_#{obj.id}" if obj.present?
end

#polymorphize_collection!(collection) ⇒ Object

Translate our Collection into a polymorphic collection



92
93
94
95
96
97
98
99
100
101
102
# File 'app/models/effective/form_builder_inputs/effective_select.rb', line 92

def polymorphize_collection!(collection)
  unless options[:grouped] || collection[0].kind_of?(ActiveRecord::Base) || (collection[0].kind_of?(Array) && collection[0].length >= 2)
    raise "Polymorphic collection expecting a flat Array of mixed ActiveRecord::Base objects, or an Array of Arrays like [['Post A', 'Post_1'], ['Event B', 'Event_2']]"
  end

  collection.each_with_index do |obj, index|
    if obj.kind_of?(ActiveRecord::Base)
      collection[index] = [obj.public_send(options[:label_method]), "#{obj.class.model_name}_#{obj.id}"]
    end
  end
end

#to_htmlObject



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'app/models/effective/form_builder_inputs/effective_select.rb', line 18

def to_html
  html = if options[:grouped] && options[:polymorphic]
    grouped_collection_select(@object_name, polymorphic_id_method, collection, options[:group_method], options[:group_label_method], options[:option_key_method], options[:option_value_method], options, tag_options)
  elsif options[:grouped]
    grouped_collection_select(@object_name, @method, collection, options[:group_method], options[:group_label_method], options[:option_key_method], options[:option_value_method], options, tag_options)
  elsif options[:polymorphic]
    collection_select(@object_name, polymorphic_id_method, collection, :second, :first, options, tag_options)
  else
    collection_select(@object_name, @method, collection, options[:value_method], options[:label_method], options, tag_options)
  end

  if options[:polymorphic]
    html += hidden_field(@object_name, polymorphic_type_method, value: polymorphic_type_value)
    html += hidden_field(@object_name, polymorphic_id_method, value: polymorphic_id_value)
  end

  if options[:single_selected]
    if html.sub!('selected="selected"', "selected='selected'")
      html.gsub!('selected="selected"', '')
    end
  end

  html
end