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



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

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

#build_container_coercion(type, value_type) ⇒ Object



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

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



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

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



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

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



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

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

#fetch_coercion(type) ⇒ Object



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

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

#inherited(klass) ⇒ Object



206
207
208
209
210
# File 'lib/hashie/extensions/coercion.rb', line 206

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.



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

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.



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

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