Module: Formtastic::Inputs::Base::Collections

Included in:
CheckBoxesInput, RadioInput, SelectInput
Defined in:
lib/formtastic/inputs/base/collections.rb

Instance Method Summary collapse

Instance Method Details

#collectionObject



49
50
51
52
53
54
55
56
57
58
59
# File 'lib/formtastic/inputs/base/collections.rb', line 49

def collection
  # Return if we have a plain string
  return raw_collection if raw_collection.instance_of?(String) || raw_collection.instance_of?(ActiveSupport::SafeBuffer)

  # Return if we have an Array of strings, fixnums or arrays
  return raw_collection if (raw_collection.instance_of?(Array) || raw_collection.instance_of?(Range)) &&
                       [Array, Fixnum, String].include?(raw_collection.first.class) &&
                       !(options.include?(:member_label) || options.include?(:member_value))

  raw_collection.map { |o| [send_or_call(label_method, o), send_or_call(value_method, o)] }
end

#collection_for_booleanObject



107
108
109
110
111
112
113
114
# File 'lib/formtastic/inputs/base/collections.rb', line 107

def collection_for_boolean
  true_text = options[:true] || Formtastic::I18n.t(:yes)
  false_text = options[:false] || Formtastic::I18n.t(:no)

  # TODO options[:value_as_class] = true unless options.key?(:value_as_class)

  [ [true_text, true], [false_text, false] ]
end

#collection_from_associationObject



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/formtastic/inputs/base/collections.rb', line 73

def collection_from_association
  if reflection
    if reflection.respond_to?(:options)
      raise PolymorphicInputWithoutCollectionError.new(
                "A collection must be supplied for #{method} input. Collections cannot be guessed for polymorphic associations."
            ) if reflection.options[:polymorphic] == true
    end

    find_options_from_options = options[:find_options] || {}
    conditions_from_options = find_options_from_options[:conditions] || {}
    conditions_from_reflection = (reflection.respond_to?(:options) && reflection.options[:conditions]) || {}
    conditions_from_reflection = conditions_from_reflection.call if conditions_from_reflection.is_a?(Proc)

    scope_conditions = conditions_from_reflection.empty? ? nil : {:conditions => conditions_from_reflection}
    if conditions_from_options.any?
      if Util.rails3?
        reflection.klass.scoped(scope_conditions).where(conditions_from_options)
      else
        reflection.klass.where(scope_conditions[:conditions]).where(conditions_from_options)
      end
    else
      
      if Util.rails3?
        find_options_from_options.merge!(:include => group_by) if self.respond_to?(:group_by) && group_by
        reflection.klass.scoped(scope_conditions).where(find_options_from_options)
      else
        coll = reflection.klass.where(scope_conditions)
        coll = coll.includes(group_by) if self.respond_to?(:group_by) && group_by
        coll.where(find_options_from_options)
      end
    end
  end
end

#collection_from_optionsObject



61
62
63
64
65
66
67
68
69
70
71
# File 'lib/formtastic/inputs/base/collections.rb', line 61

def collection_from_options
  items = options[:collection]
  case items
  when Hash
    items.to_a
  when Range
    items.to_a.collect{ |c| [c.to_s, c] }
  else
    items
  end
end

#label_and_value_methodObject



22
23
24
# File 'lib/formtastic/inputs/base/collections.rb', line 22

def label_and_value_method
  @label_and_value_method ||= label_and_value_method_from_collection(raw_collection)
end

#label_and_value_method_from_collection(_collection) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/formtastic/inputs/base/collections.rb', line 26

def label_and_value_method_from_collection(_collection)
  sample = _collection.first || _collection.last

  case sample
  when Array
    label, value = :first, :last
  when Integer
    label, value = :to_s, :to_i
  when Symbol, String, NilClass
    label, value = :to_s, :to_s
  end

  # Order of preference: user supplied method, class defaults, auto-detect
  label ||= builder.collection_label_methods.find { |m| sample.respond_to?(m) }
  value ||= builder.collection_value_methods.find { |m| sample.respond_to?(m) }

  [label, value]
end

#label_methodObject



6
7
8
# File 'lib/formtastic/inputs/base/collections.rb', line 6

def label_method
  @label_method ||= (label_method_from_options || label_and_value_method.first)
end

#label_method_from_optionsObject



10
11
12
# File 'lib/formtastic/inputs/base/collections.rb', line 10

def label_method_from_options
  options[:member_label]
end

#raw_collectionObject



45
46
47
# File 'lib/formtastic/inputs/base/collections.rb', line 45

def raw_collection
  @raw_collection ||= (collection_from_options || collection_from_association || collection_for_boolean)
end

#send_or_call(duck, object) ⇒ Object



116
117
118
119
120
121
122
# File 'lib/formtastic/inputs/base/collections.rb', line 116

def send_or_call(duck, object)
  if duck.respond_to?(:call)
    duck.call(object)
  elsif object.respond_to? duck.to_sym
    object.send(duck)
  end
end

#send_or_call_or_object(duck, object) ⇒ Object

Avoids an issue where send_or_call can be a String and duck can be something simple like :first, which obviously String responds to.



126
127
128
129
# File 'lib/formtastic/inputs/base/collections.rb', line 126

def send_or_call_or_object(duck, object)
  return object if object.is_a?(String) || object.is_a?(Integer) || object.is_a?(Symbol) # TODO what about other classes etc?
  send_or_call(duck, object)
end

#value_methodObject



14
15
16
# File 'lib/formtastic/inputs/base/collections.rb', line 14

def value_method
  @value_method ||= (value_method_from_options || label_and_value_method.last)
end

#value_method_from_optionsObject



18
19
20
# File 'lib/formtastic/inputs/base/collections.rb', line 18

def value_method_from_options
  options[:member_value]
end