hashie 2.1.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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