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.



80
81
82
# File 'lib/hashie/extensions/coercion.rb', line 80

def key_coercions
  @key_coercions ||= {}
end

Instance Method Details

#build_coercion(type) ⇒ Object



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/hashie/extensions/coercion.rb', line 155

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
      type, value_type = type.class, type.first
      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
    fail TypeError, "#{type} is not a coercable type"
  end
end

#build_container_coercion(type, value_type) ⇒ Object



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

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



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

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



181
182
183
184
185
186
187
# File 'lib/hashie/extensions/coercion.rb', line 181

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.



72
73
74
75
# File 'lib/hashie/extensions/coercion.rb', line 72

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



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/hashie/extensions/coercion.rb', line 110

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



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

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

#fetch_coercion(type) ⇒ Object



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

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

#inherited(klass) ⇒ Object



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

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.



86
87
88
# File 'lib/hashie/extensions/coercion.rb', line 86

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

#lenient_value_coercionsObject

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



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

def lenient_value_coercions
  @lenient_value_coercions ||= {}
end

#strict_value_coercionsObject

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



130
131
132
# File 'lib/hashie/extensions/coercion.rb', line 130

def strict_value_coercions
  @strict_value_coercions ||= {}
end

#value_coercion(value) ⇒ Object

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



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

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