hashie 2.1.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,17 +1,14 @@
1
1
  module Hashie
2
- autoload :Clash, 'hashie/clash'
3
- autoload :Dash, 'hashie/dash'
4
- autoload :Hash, 'hashie/hash'
5
- autoload :HashExtensions, 'hashie/hash_extensions'
6
- autoload :Mash, 'hashie/mash'
7
- autoload :PrettyInspect, 'hashie/hash_extensions'
8
- autoload :Trash, 'hashie/trash'
9
- autoload :Rash, 'hashie/rash'
2
+ autoload :Clash, 'hashie/clash'
3
+ autoload :Dash, 'hashie/dash'
4
+ autoload :Hash, 'hashie/hash'
5
+ autoload :Mash, 'hashie/mash'
6
+ autoload :Trash, 'hashie/trash'
7
+ autoload :Rash, 'hashie/rash'
10
8
 
11
9
  module Extensions
12
10
  autoload :Coercion, 'hashie/extensions/coercion'
13
11
  autoload :DeepMerge, 'hashie/extensions/deep_merge'
14
- autoload :KeyConversion, 'hashie/extensions/key_conversion'
15
12
  autoload :IgnoreUndeclared, 'hashie/extensions/ignore_undeclared'
16
13
  autoload :IndifferentAccess, 'hashie/extensions/indifferent_access'
17
14
  autoload :MergeInitializer, 'hashie/extensions/merge_initializer'
@@ -19,8 +16,18 @@ module Hashie
19
16
  autoload :MethodQuery, 'hashie/extensions/method_access'
20
17
  autoload :MethodReader, 'hashie/extensions/method_access'
21
18
  autoload :MethodWriter, 'hashie/extensions/method_access'
22
- autoload :StringifyKeys, 'hashie/extensions/key_conversion'
23
- autoload :SymbolizeKeys, 'hashie/extensions/key_conversion'
19
+ autoload :StringifyKeys, 'hashie/extensions/stringify_keys'
20
+ autoload :SymbolizeKeys, 'hashie/extensions/symbolize_keys'
24
21
  autoload :DeepFetch, 'hashie/extensions/deep_fetch'
22
+ autoload :PrettyInspect, 'hashie/extensions/pretty_inspect'
23
+ autoload :KeyConversion, 'hashie/extensions/key_conversion'
24
+
25
+ module Mash
26
+ autoload :ActiveModel, 'hashie/extensions/mash/active_model'
27
+ end
28
+
29
+ module Dash
30
+ autoload :IndifferentAccess, 'hashie/extensions/dash/indifferent_access'
31
+ end
25
32
  end
26
33
  end
@@ -13,7 +13,8 @@ module Hashie
13
13
  # It is preferrable to a Struct because of the in-class
14
14
  # API for defining properties as well as per-property defaults.
15
15
  class Dash < Hash
16
- include PrettyInspect
16
+ include Hashie::Extensions::PrettyInspect
17
+
17
18
  alias_method :to_s, :inspect
18
19
 
19
20
  # Defines a property on the Dash. Options are
@@ -28,8 +29,6 @@ module Hashie
28
29
  # existing Dash.
29
30
  #
30
31
  def self.property(property_name, options = {})
31
- property_name = property_name.to_sym
32
-
33
32
  properties << property_name
34
33
 
35
34
  if options.key?(:default)
@@ -39,9 +38,9 @@ module Hashie
39
38
  end
40
39
 
41
40
  unless instance_methods.map { |m| m.to_s }.include?("#{property_name}=")
42
- define_method(property_name) { |&block| self.[](property_name.to_s, &block) }
41
+ define_method(property_name) { |&block| self.[](property_name, &block) }
43
42
  property_assignment = property_name.to_s.concat('=').to_sym
44
- define_method(property_assignment) { |value| self.[]=(property_name.to_s, value) }
43
+ define_method(property_assignment) { |value| self.[]=(property_name, value) }
45
44
  end
46
45
 
47
46
  if defined? @subclasses
@@ -69,13 +68,13 @@ module Hashie
69
68
  # Check to see if the specified property has already been
70
69
  # defined.
71
70
  def self.property?(name)
72
- properties.include? name.to_sym
71
+ properties.include? name
73
72
  end
74
73
 
75
74
  # Check to see if the specified property is
76
75
  # required.
77
76
  def self.required?(name)
78
- required_properties.include? name.to_sym
77
+ required_properties.include? name
79
78
  end
80
79
 
81
80
  # You may initialize a Dash with an attributes hash
@@ -103,7 +102,7 @@ module Hashie
103
102
  # property's default value if it hasn't been set).
104
103
  def [](property)
105
104
  assert_property_exists! property
106
- value = super(property.to_s)
105
+ value = super(property)
107
106
  # If the value is a lambda, proc, or whatever answers to call, eval the thing!
108
107
  if value.is_a? Proc
109
108
  self[property] = value.call # Set the result of the call as a value
@@ -118,7 +117,7 @@ module Hashie
118
117
  def []=(property, value)
119
118
  assert_property_required! property, value
120
119
  assert_property_exists! property
121
- super(property.to_s, value)
120
+ super(property, value)
122
121
  end
123
122
 
124
123
  def merge(other_hash)
@@ -21,7 +21,7 @@ module Hashie
21
21
  super(key, value)
22
22
  end
23
23
 
24
- def custom_writer(key, value, convert = true)
24
+ def custom_writer(key, value, _convert = true)
25
25
  self[key] = value
26
26
  end
27
27
 
@@ -0,0 +1,21 @@
1
+ module Hashie
2
+ module Extensions
3
+ module Dash
4
+ module IndifferentAccess
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ base.send :include, Hashie::Extensions::IndifferentAccess
8
+ end
9
+
10
+ module ClassMethods
11
+ # Check to see if the specified property has already been
12
+ # defined.
13
+ def property?(name)
14
+ name = name.to_s
15
+ !!properties.find { |property| property.to_s == name }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -18,7 +18,7 @@ module Hashie
18
18
  begin
19
19
  arg = Integer(arg) if obj.kind_of? Array
20
20
  obj.fetch(arg)
21
- rescue ArgumentError, IndexError => e
21
+ rescue ArgumentError, IndexError, NoMethodError => e
22
22
  break block.call(arg) if block
23
23
  raise UndefinedPathError, "Could not fetch path (#{args.join(' > ')}) at #{arg}", e.backtrace
24
24
  end
@@ -5,7 +5,7 @@ module Hashie
5
5
  # raising an error. This is useful when using a Trash to
6
6
  # capture a subset of a larger hash.
7
7
  #
8
- # Note that attempting to retrieve an undeclared property
8
+ # Note that attempting to retrieve or set an undeclared property
9
9
  # will still raise a NoMethodError, even if a value for
10
10
  # that property was provided at initialization.
11
11
  #
@@ -36,6 +36,10 @@ module Hashie
36
36
  end
37
37
  end if attributes
38
38
  end
39
+
40
+ def property_exists?(property)
41
+ self.class.property?(property)
42
+ end
39
43
  end
40
44
  end
41
45
  end
@@ -1,87 +1,5 @@
1
1
  module Hashie
2
2
  module Extensions
3
- module StringifyKeys
4
- # Convert all keys in the hash to strings.
5
- #
6
- # @example
7
- # test = {:abc => 'def'}
8
- # test.stringify_keys!
9
- # test # => {'abc' => 'def'}
10
- def stringify_keys!
11
- keys.each do |k|
12
- stringify_keys_recursively!(self[k])
13
- self[k.to_s] = delete(k)
14
- end
15
- self
16
- end
17
-
18
- # Return a new hash with all keys converted
19
- # to strings.
20
- def stringify_keys
21
- dup.stringify_keys!
22
- end
23
-
24
- protected
25
-
26
- # Stringify all keys recursively within nested
27
- # hashes and arrays.
28
- def stringify_keys_recursively!(object)
29
- if self.class === object
30
- object.stringify_keys!
31
- elsif ::Array === object
32
- object.each do |i|
33
- stringify_keys_recursively!(i)
34
- end
35
- object
36
- elsif object.respond_to?(:stringify_keys!)
37
- object.stringify_keys!
38
- else
39
- object
40
- end
41
- end
42
- end
43
-
44
- module SymbolizeKeys
45
- # Convert all keys in the hash to symbols.
46
- #
47
- # @example
48
- # test = {'abc' => 'def'}
49
- # test.symbolize_keys!
50
- # test # => {:abc => 'def'}
51
- def symbolize_keys!
52
- keys.each do |k|
53
- symbolize_keys_recursively!(self[k])
54
- self[k.to_sym] = delete(k)
55
- end
56
- self
57
- end
58
-
59
- # Return a new hash with all keys converted
60
- # to symbols.
61
- def symbolize_keys
62
- dup.symbolize_keys!
63
- end
64
-
65
- protected
66
-
67
- # Symbolize all keys recursively within nested
68
- # hashes and arrays.
69
- def symbolize_keys_recursively!(object)
70
- if self.class === object
71
- object.symbolize_keys!
72
- elsif ::Array === object
73
- object.each do |i|
74
- symbolize_keys_recursively!(i)
75
- end
76
- object
77
- elsif object.respond_to?(:symbolize_keys!)
78
- object.symbolize_keys!
79
- else
80
- object
81
- end
82
- end
83
- end
84
-
85
3
  module KeyConversion
86
4
  def self.included(base)
87
5
  base.send :include, SymbolizeKeys
@@ -0,0 +1,19 @@
1
+ module Hashie
2
+ module Extensions
3
+ module PrettyInspect
4
+ def self.included(base)
5
+ base.send :alias_method, :hash_inspect, :inspect
6
+ base.send :alias_method, :inspect, :hashie_inspect
7
+ end
8
+
9
+ def hashie_inspect
10
+ ret = "#<#{self.class}"
11
+ keys.sort_by { |key| key.to_s }.each do |key|
12
+ ret << " #{key}=#{self[key].inspect}"
13
+ end
14
+ ret << '>'
15
+ ret
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,44 @@
1
+ module Hashie
2
+ module Extensions
3
+ module StringifyKeys
4
+ # Convert all keys in the hash to strings.
5
+ #
6
+ # @example
7
+ # test = {:abc => 'def'}
8
+ # test.stringify_keys!
9
+ # test # => {'abc' => 'def'}
10
+ def stringify_keys!
11
+ keys.each do |k|
12
+ stringify_keys_recursively!(self[k])
13
+ self[k.to_s] = delete(k)
14
+ end
15
+ self
16
+ end
17
+
18
+ # Return a new hash with all keys converted
19
+ # to strings.
20
+ def stringify_keys
21
+ dup.stringify_keys!
22
+ end
23
+
24
+ protected
25
+
26
+ # Stringify all keys recursively within nested
27
+ # hashes and arrays.
28
+ def stringify_keys_recursively!(object)
29
+ if self.class === object
30
+ object.stringify_keys!
31
+ elsif ::Array === object
32
+ object.each do |i|
33
+ stringify_keys_recursively!(i)
34
+ end
35
+ object
36
+ elsif object.respond_to?(:stringify_keys!)
37
+ object.stringify_keys!
38
+ else
39
+ object
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,44 @@
1
+ module Hashie
2
+ module Extensions
3
+ module SymbolizeKeys
4
+ # Convert all keys in the hash to symbols.
5
+ #
6
+ # @example
7
+ # test = {'abc' => 'def'}
8
+ # test.symbolize_keys!
9
+ # test # => {:abc => 'def'}
10
+ def symbolize_keys!
11
+ keys.each do |k|
12
+ symbolize_keys_recursively!(self[k])
13
+ self[k.to_sym] = delete(k)
14
+ end
15
+ self
16
+ end
17
+
18
+ # Return a new hash with all keys converted
19
+ # to symbols.
20
+ def symbolize_keys
21
+ dup.symbolize_keys!
22
+ end
23
+
24
+ protected
25
+
26
+ # Symbolize all keys recursively within nested
27
+ # hashes and arrays.
28
+ def symbolize_keys_recursively!(object)
29
+ if self.class === object
30
+ object.symbolize_keys!
31
+ elsif ::Array === object
32
+ object.each do |i|
33
+ symbolize_keys_recursively!(i)
34
+ end
35
+ object
36
+ elsif object.respond_to?(:symbolize_keys!)
37
+ object.symbolize_keys!
38
+ else
39
+ object
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,25 +1,37 @@
1
- require 'hashie/hash_extensions'
1
+ require 'hashie/extensions/stringify_keys'
2
+ require 'hashie/extensions/pretty_inspect'
2
3
 
3
4
  module Hashie
4
5
  # A Hashie Hash is simply a Hash that has convenience
5
6
  # functions baked in such as stringify_keys that may
6
7
  # not be available in all libraries.
7
8
  class Hash < ::Hash
8
- include HashExtensions
9
+ include Hashie::Extensions::PrettyInspect
10
+ include Hashie::Extensions::StringifyKeys
11
+
12
+ # Convert this hash into a Mash
13
+ def to_mash
14
+ ::Hashie::Mash.new(self)
15
+ end
9
16
 
10
17
  # Converts a mash back to a hash (with stringified or symbolized keys)
11
18
  def to_hash(options = {})
12
19
  out = {}
13
20
  keys.each do |k|
14
- assignment_key = k.to_s
15
- assignment_key = assignment_key.to_sym if options[:symbolize_keys]
21
+ assignment_key = if options[:stringify_keys]
22
+ k.to_s
23
+ elsif options[:symbolize_keys]
24
+ k.to_s.to_sym
25
+ else
26
+ k
27
+ end
16
28
  if self[k].is_a?(Array)
17
29
  out[assignment_key] ||= []
18
30
  self[k].each do |array_object|
19
31
  out[assignment_key] << (Hash === array_object ? flexibly_convert_to_hash(array_object, options) : array_object)
20
32
  end
21
33
  else
22
- out[assignment_key] = (Hash === self[k] || self[k].respond_to?(:to_hash)) ? flexibly_convert_to_hash(self[k], options) : self[k]
34
+ out[assignment_key] = Hash === self[k] ? flexibly_convert_to_hash(self[k], options) : self[k]
23
35
  end
24
36
  end
25
37
  out
@@ -55,8 +55,10 @@ module Hashie
55
55
  # mash.author # => <Mash>
56
56
  #
57
57
  class Mash < Hash
58
+ include Hashie::Extensions::PrettyInspect
59
+
58
60
  ALLOWED_SUFFIXES = %w(? ! = _)
59
- include Hashie::PrettyInspect
61
+
60
62
  alias_method :to_s, :inspect
61
63
 
62
64
  # If you pass in an existing hash, it will
@@ -185,11 +187,15 @@ module Hashie
185
187
  self
186
188
  end
187
189
 
188
- # Will return true if the Mash has had a key
189
- # set in addition to normal respond_to? functionality.
190
- def respond_to?(method_name, include_private = false)
191
- return true if key?(method_name) || prefix_method?(method_name)
192
- super
190
+ def respond_to_missing?(method_name, *args)
191
+ return true if key?(method_name)
192
+ _, suffix = method_suffix(method_name)
193
+ case suffix
194
+ when '=', '?', '!', '_'
195
+ return true
196
+ else
197
+ super
198
+ end
193
199
  end
194
200
 
195
201
  def prefix_method?(method_name)
@@ -199,17 +205,16 @@ module Hashie
199
205
 
200
206
  def method_missing(method_name, *args, &blk)
201
207
  return self.[](method_name, &blk) if key?(method_name)
202
- suffixes_regex = ALLOWED_SUFFIXES.join
203
- match = method_name.to_s.match(/(.*?)([#{suffixes_regex}]?)$/)
204
- case match[2]
208
+ name, suffix = method_suffix(method_name)
209
+ case suffix
205
210
  when '='
206
- self[match[1]] = args.first
211
+ self[name] = args.first
207
212
  when '?'
208
- !!self[match[1]]
213
+ !!self[name]
209
214
  when '!'
210
- initializing_reader(match[1])
215
+ initializing_reader(name)
211
216
  when '_'
212
- underbang_reader(match[1])
217
+ underbang_reader(name)
213
218
  else
214
219
  default(method_name)
215
220
  end
@@ -217,6 +222,12 @@ module Hashie
217
222
 
218
223
  protected
219
224
 
225
+ def method_suffix(method_name)
226
+ suffixes_regex = ALLOWED_SUFFIXES.join
227
+ match = method_name.to_s.match(/(.*?)([#{suffixes_regex}]?)$/)
228
+ [match[1], match[2]]
229
+ end
230
+
220
231
  def convert_key(key) #:nodoc:
221
232
  key.to_s
222
233
  end