Module: Gourami::Coercer

Included in:
Form
Defined in:
lib/gourami/coercer.rb

Instance Method Summary collapse

Instance Method Details

#coerce_array(value, options = {}) ⇒ Array

Coerce the value into an Array.

TODO docs for the rest of the options

Parameters:

  • value (Object)

    The value to be coerced.

  • element_type (Hash)

    a customizable set of options

Returns:

  • (Array)

    The coerced Array.



70
71
72
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
# File 'lib/gourami/coercer.rb', line 70

def coerce_array(value, options = {})
  return if options[:allow_nil] && value.nil?

  element_type = options[:element_type]
  value = value.values if value.is_a?(Hash)

  if options[:split_by] && value.is_a?(String)
    value = value.split(options[:split_by]).map(&:strip)
  end

  return [] unless value.is_a?(Array)
  return value unless element_type

  if element_type.is_a?(Hash)
    element_type_options = element_type
    element_type = element_type[:type]
  else
    element_type_options = {}
  end

  element_type_options[:type] = element_type
  element_type_options = self.class.merge_default_attribute_options(element_type_options) if self.class.respond_to?(:merge_default_attribute_options)

  coercer_method_name = :"coerce_#{element_type}"

  value.map do |array_element|
    send(coercer_method_name, array_element, element_type_options)
  end
end

#coerce_boolean(value, options = {}) ⇒ Boolean?

Corce the value into true or false.

Parameters:

  • value (Object)
  • allow_nil (Hash)

    a customizable set of options

Returns:

  • (Boolean, nil)


51
52
53
54
55
# File 'lib/gourami/coercer.rb', line 51

def coerce_boolean(value, options = {})
  return if options[:allow_nil] && (value.nil? || value == "")
  return false if value.to_s.strip == "false"
  !!value && !coerce_string(value, :allow_nil => false).strip.empty?
end

#coerce_date(value, options = {}) ⇒ Date?

Coerce the value into a Date.

Parameters:

  • value (Object)

    The value to be coerced.

Returns:

  • (Date, nil)

    A Date if the value can be coerced or nil otherwise.



188
189
190
191
192
193
194
195
196
# File 'lib/gourami/coercer.rb', line 188

def coerce_date(value, options = {})
  value = coerce_string(value, options)
  return if value.nil?
  begin
    Date.strptime(value, "%Y-%m-%d")
  rescue ArgumentError
    nil
  end
end

#coerce_file(value, _options = {}) ⇒ Hash?

Coerce the value into a File. For the value to be successfully accepted as, it should be a hash containing the :filename (String) and :tempfile (File).

Parameters:

  • value (Object)

Returns:

  • (Hash, nil)

    The hash will contain the file String :filename and the File :tempfile, or nil otherwise.



225
226
227
228
229
230
231
232
# File 'lib/gourami/coercer.rb', line 225

def coerce_file(value, _options = {})
  return unless value.is_a?(Hash) && !value[:filename].to_s.empty?

  tempfile = value[:tempfile]
  return unless tempfile.is_a?(File) || tempfile.is_a?(Tempfile)

  value
end

#coerce_float(value, _options = {}) ⇒ Float?

Coerce the value into a Float.

Parameters:

  • value (Object)

Returns:

  • (Float, nil)


105
106
107
# File 'lib/gourami/coercer.rb', line 105

def coerce_float(value, _options = {})
  Float(value) rescue nil
end

#coerce_hash(value, options = {}) ⇒ Hash, ActiveSupport::HashWithIndifferentAccess

Coerce the value into a Hash.

Parameters:

  • value (Object)

    The value to be coerced.

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :key_type (Symbol, Callable) — default: nil

    The type of the hash keys to coerce, no coersion if value is nil.

  • :value_type (Symbol, Callable) — default: nil

    The type of the hash values to coerce, no coersion if value is nil.

  • :indifferent_access (Boolean) — default: false

    When true, the resulting Hash will be an ActiveSupport::HashWithIndifferentAccess

Returns:

  • (Hash, ActiveSupport::HashWithIndifferentAccess)

    The coerced Hash.



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/gourami/coercer.rb', line 133

def coerce_hash(value, options = {})
  return if options[:allow_nil] && value.nil?

  hash_key_type = options[:key_type]
  hash_value_type = options[:value_type]

  hash_class = options[:indifferent_access] ? ActiveSupport::HashWithIndifferentAccess : Hash
  hash = hash_class.new

  return hash unless value.is_a?(Hash) || (defined?(Sequel::Postgres::JSONHash) && value.is_a?(Sequel::Postgres::JSONHash))

  value.each_with_object(hash) do |(key, value), coerced_hash|
    key_type = hash_key_type.respond_to?(:call) ? hash_key_type.call(key, value) : hash_key_type
    key = send(:"coerce_#{key_type}", key) if key_type

    value_type = hash_value_type.respond_to?(:call) ? hash_value_type.call(key, value) : hash_value_type

    # TODO: Refactor shared logic here and coerce_array to a method like `type, options = resolve_coercer_type_and_options`
    if value_type.is_a?(Hash)
      value_type_options = value_type
      value_type = value_type[:type]
    else
      value_type_options = {}
    end

    value_type_options[:type] = value_type
    value_type_options = self.class.merge_default_attribute_options(value_type_options) if self.class.respond_to?(:merge_default_attribute_options)

    value = send(:"coerce_#{value_type}", value, value_type_options) if value_type

    coerced_hash[key] = value
  end
end

#coerce_integer(value, _options = {}) ⇒ Integer?

Coerce the value into an Integer.

Parameters:

  • value (Object)

    The value to be coerced.

Returns:

  • (Integer, nil)

    An Integer if the value can be coerced or nil otherwise.



174
175
176
177
178
179
# File 'lib/gourami/coercer.rb', line 174

def coerce_integer(value, _options = {})
  value = value.to_s
  return unless value =~ /\A0|[1-9]\d*\z/

  value.to_i
end

#coerce_phone(value, options = {}) ⇒ String?

Coerce the value into an international phone String.

Parameters:

  • value (Object)

    The value to be coerced.

Returns:

  • (String, nil)


115
116
117
118
# File 'lib/gourami/coercer.rb', line 115

def coerce_phone(value, options = {})
  value = coerce_string(value, options)
  value ? value.upcase.gsub(/[^+0-9A-Z]/, "") : nil
end

#coerce_string(value, options = {}) ⇒ String?

Coerce the value into a String.

Parameters:

  • value (Object)
  • allow_nil (Hash)

    a customizable set of options

  • nil_when_empty (Hash)

    a customizable set of options

  • upcase (Hash)

    a customizable set of options

  • strip (Hash)

    a customizable set of options

Returns:

  • (String, nil)


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/gourami/coercer.rb', line 28

def coerce_string(value, options = {})
  if options.fetch(:allow_nil, true)
    return if value.nil?
    value = value.to_s
    return if value.empty? && options.fetch(:nil_when_empty, false)
  end

  value = value.to_s.dup.force_encoding(Encoding::UTF_8)

  # TODO: Instead of providing unconfigurable defaults like this, use
  # set_default_attribute_options at the gem level or consumer level.
  value.strip! if options.fetch(:strip, true)
  value.upcase! if options.fetch(:upcase, false)

  value
end

#coerce_time(value, options = {}) ⇒ Time?

Coerce the value into a Time.

Parameters:

  • value (Object)

    The value to be coerced.

Returns:

  • (Time, nil)

    A Time if the value can be coerced or nil otherwise.



205
206
207
208
209
210
211
212
213
214
# File 'lib/gourami/coercer.rb', line 205

def coerce_time(value, options = {})
  value = coerce_string(value, options)
  return if !value || value.empty?

  begin
    Time.parse(value).utc
  rescue ArgumentError
    nil
  end
end

#setter_filter(attribute_name, value, options) ⇒ *

When it is being set, coerce the value of the attribute according to the :type option.

Parameters:

  • attribute_name (Symbol)

    name of the attribute

  • value (*)

    the value as it is passed into the setter

  • options (Hash)

    attribute options

Returns:

  • (*)


12
13
14
15
16
17
# File 'lib/gourami/coercer.rb', line 12

def setter_filter(attribute_name, value, options)
  type = options[:type]
  value = send(:"coerce_#{type}", value, options) if type

  super(attribute_name, value, options)
end