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.



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

def key_coercions
  @key_coercions ||= {}
end

Instance Method Details

#build_coercion(type) ⇒ Object



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/hashie/extensions/coercion.rb', line 167

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
      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



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

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



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

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



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

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.



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

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



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/hashie/extensions/coercion.rb', line 121

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



161
162
163
164
165
# File 'lib/hashie/extensions/coercion.rb', line 161

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

#fetch_coercion(type) ⇒ Object



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

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

#inherited(klass) ⇒ Object



217
218
219
220
221
# File 'lib/hashie/extensions/coercion.rb', line 217

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.



96
97
98
# File 'lib/hashie/extensions/coercion.rb', line 96

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

#lenient_value_coercionsObject

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



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

def lenient_value_coercions
  @lenient_value_coercions ||= {}
end

#strict_value_coercionsObject

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



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

def strict_value_coercions
  @strict_value_coercions ||= {}
end

#value_coercion(value) ⇒ Object

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



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

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