Module: Hashie::Extensions::Coercion::ClassMethods

Defined in:
lib/hashie/extensions/coercion.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#key_coercionsObject

Returns a hash of any existing key coercions.



84
85
86
# File 'lib/hashie/extensions/coercion.rb', line 84

def key_coercions
  @key_coercions ||= {}
end

Instance Method Details

#build_coercion(type) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/hashie/extensions/coercion.rb', line 160

def build_coercion(type)
  if type.is_a? Enumerable
    if type.class <= ::Hash
      type, key_type, value_type = type.class, *type.first
      build_hash_coercion(type, key_type, value_type)
    else # Enumerable but not Hash: Array, Set
      value_type = type.first
      type = type.class
      build_container_coercion(type, value_type)
    end
  elsif CORE_TYPES.key? type
    build_core_type_coercion(type)
  elsif type.respond_to? :coerce
    lambda do |value|
      return value if value.is_a? type
      type.coerce(value)
    end
  elsif type.respond_to? :new
    lambda do |value|
      return value if value.is_a? type
      type.new(value)
    end
  else
    raise TypeError, "#{type} is not a coercable type"
  end
end

#build_container_coercion(type, value_type) ⇒ Object



195
196
197
198
199
200
# File 'lib/hashie/extensions/coercion.rb', line 195

def build_container_coercion(type, value_type)
  value_coerce = fetch_coercion(value_type)
  lambda do |value|
    type.new(value.map { |v| value_coerce.call(v) })
  end
end

#build_core_type_coercion(type) ⇒ Object



202
203
204
205
206
207
208
# File 'lib/hashie/extensions/coercion.rb', line 202

def build_core_type_coercion(type)
  name = CORE_TYPES[type]
  lambda do |value|
    return value if value.is_a? type
    return value.send(name)
  end
end

#build_hash_coercion(type, key_type, value_type) ⇒ Object



187
188
189
190
191
192
193
# File 'lib/hashie/extensions/coercion.rb', line 187

def build_hash_coercion(type, key_type, value_type)
  key_coerce = fetch_coercion(key_type)
  value_coerce = fetch_coercion(value_type)
  lambda do |value|
    type[value.map { |k, v| [key_coerce.call(k), value_coerce.call(v)] }]
  end
end

#coerce_key(*attrs) ⇒ Object Also known as: coerce_keys

Set up a coercion rule such that any time the specified key is set it will be coerced into the specified class. Coercion will occur by first attempting to call Class.coerce and then by calling Class.new with the value as an argument in either case.

Examples:

Coerce a "user" subhash into a User object

class Tweet < Hash
  include Hashie::Extensions::Coercion
  coerce_key :user, User
end

Parameters:

  • key (Object)

    the key or array of keys you would like to be coerced.

  • into (Class)

    the class into which you want the key(s) coerced.



76
77
78
79
# File 'lib/hashie/extensions/coercion.rb', line 76

def coerce_key(*attrs)
  into = attrs.pop
  attrs.each { |key| key_coercions[key] = into }
end

#coerce_value(from, into, options = {}) ⇒ Object

Set up a coercion rule such that any time a value of the specified type is set it will be coerced into the specified class.

Examples:

Coerce all hashes into this special type of hash

class SpecialHash < Hash
  include Hashie::Extensions::Coercion
  coerce_value Hash, SpecialHash

  def initialize(hash = {})
    super
    hash.each_pair do |k,v|
      self[k] = v
    end
  end
end

Parameters:

  • from (Class)

    the type you would like coerced.

  • into (Class)

    the class into which you would like the value coerced.

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

    a customizable set of options

Options Hash (options):

  • :strict (Boolean) — default: true

    whether use exact source class only or include ancestors



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/hashie/extensions/coercion.rb', line 114

def coerce_value(from, into, options = {})
  options = { strict: true }.merge(options)

  if ABSTRACT_CORE_TYPES.key? from
    ABSTRACT_CORE_TYPES[from].each do |type|
      coerce_value type, into, options
    end
  end

  if options[:strict]
    strict_value_coercions[from] = into
  else
    while from.superclass && from.superclass != Object
      lenient_value_coercions[from] = into
      from = from.superclass
    end
  end
end

#coercion_cacheObject



154
155
156
157
158
# File 'lib/hashie/extensions/coercion.rb', line 154

def coercion_cache
  @coercion_cache ||= ::Hash.new do |hash, type|
    hash[type] = build_coercion(type)
  end
end

#fetch_coercion(type) ⇒ Object



149
150
151
152
# File 'lib/hashie/extensions/coercion.rb', line 149

def fetch_coercion(type)
  return type if type.is_a? Proc
  coercion_cache[type]
end

#inherited(klass) ⇒ Object



210
211
212
213
214
# File 'lib/hashie/extensions/coercion.rb', line 210

def inherited(klass)
  super

  klass.key_coercions = key_coercions.dup
end

#key_coercion(key) ⇒ Object

Returns the specific key coercion for the specified key, if one exists.



90
91
92
# File 'lib/hashie/extensions/coercion.rb', line 90

def key_coercion(key)
  key_coercions[key.to_sym]
end

#lenient_value_coercionsObject

Return all value coercions that have the :strict rule as false.



139
140
141
# File 'lib/hashie/extensions/coercion.rb', line 139

def lenient_value_coercions
  @lenient_value_coercions ||= {}
end

#strict_value_coercionsObject

Return all value coercions that have the :strict rule as true.



134
135
136
# File 'lib/hashie/extensions/coercion.rb', line 134

def strict_value_coercions
  @strict_value_coercions ||= {}
end

#value_coercion(value) ⇒ Object

Fetch the value coercion, if any, for the specified object.



144
145
146
147
# File 'lib/hashie/extensions/coercion.rb', line 144

def value_coercion(value)
  from = value.class
  strict_value_coercions[from] || lenient_value_coercions[from]
end