sd_struct 0.1.0 → 0.1.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: db8247a8652fb98a73e935ce9c0737d3bcb60aeb
4
- data.tar.gz: e681ebbbe672b041dbe2d84e7e819123c7bfd966
3
+ metadata.gz: 3b7a67f6e73b67288c75959f12b9c28557326ef7
4
+ data.tar.gz: 0e4dc23fda1637c672516f58aad9e79e8492b1b9
5
5
  SHA512:
6
- metadata.gz: a46da494946f552eca4dc1912c1d6f96667f933539b9fe4f66d37f530600f52e6e508c7a9c26a4d541f71c433af85dd890008bef1b231af98fe8d30878027b03
7
- data.tar.gz: 3987632b1425ef16c1535a740ac68183170a644b9b1122e14ac3e2eab9c9d24c6745c357e957e5fe2266ef452f9a8a172e7bd097afeb9f8c5b2ab96b7c942837
6
+ metadata.gz: 1ac85d00a9d591074e27c9174cfb100cbdb220752060b8f811bf5c0d71d4acb357f91eef2bd7f6480c8b8529be51720898dd1e2d055b430d0be6a935fffa35c6
7
+ data.tar.gz: 58fa6f524bde91f41511e78d561eb829e746d8564965c136bf91c8462b5c4cdd835889a79894e4b41b43a00fdfc8f86a568affdb63dfc7d250d478de415bd2a6
data/README.md CHANGED
@@ -71,13 +71,13 @@ sd_struct.to_h
71
71
  ```
72
72
 
73
73
 
74
- > OpenStruct uses `method_missing` to create new field, while SDStruct prevent creation
75
- > of new field using dot notation.
74
+ > OpenStruct allows creation of a new field with dot notation while SDStruct
75
+ > prevents it
76
76
 
77
- SDStruct prevent creation of new field using dot notation once it is initialized
78
- to prevent assigning unintended field when you mistyped the key/field. SDStruct
79
- is stricter in that way. However, SDStruct can also be lenient. You can use
80
- square brackets when you want to assign a new field.
77
+ SDStruct disallows creation of a new field using dot notation to prevent
78
+ assigning unintended field when you mistyped the key/field. SDStruct is
79
+ stricter in that way. However, SDStruct can also be lenient. You can use square
80
+ brackets when you want to assign a new field.
81
81
 
82
82
  ```ruby
83
83
  ## OpenStruct
@@ -114,10 +114,10 @@ sd_struct.find('/array/0/one')
114
114
  sd_struct.find('object->a', separator: '->')
115
115
  # => "bau bau"
116
116
 
117
+ # You can push it to find deeper. It will return the first occurrence of the matched field
117
118
  sd_struct.find('.array..one', separator: '.')
118
119
  # => 1
119
120
 
120
- # You can push it to find deeper. It will return the first occurrence of the matched field
121
121
  sd_struct.find('//a')
122
122
  # => "bau bau"
123
123
 
@@ -274,6 +274,19 @@ that doesn't have deep search and deep convert capabilities.
274
274
  require 'sd_struct/base'
275
275
  ```
276
276
 
277
+ ## Attribution
278
+
279
+ OpenStruct is used as the base of this project.
280
+
281
+
282
+ ## TODO
283
+
284
+ * Add specs
285
+ * Add `method_missing` to define singleton method when a field/member/key is
286
+ called (and not during initialization) to execute initialization faster
287
+ * Reimplement SDStruct to extend Hash (possibly will make it faster)
288
+
289
+
277
290
  ## Contributing
278
291
 
279
292
  1. Fork it ( https://github.com/styd/sd_struct/fork )
@@ -6,7 +6,7 @@ class SDStruct
6
6
  using Module.new {
7
7
  refine Hash do
8
8
  #
9
- # Change current Hash object to SDStruct object
9
+ # Changes current Hash object to SDStruct object
10
10
  #
11
11
  # @return [SDStruct] SDStruct object
12
12
  #
@@ -16,9 +16,8 @@ class SDStruct
16
16
  end
17
17
 
18
18
  refine Array do
19
-
20
19
  #
21
- # Call `to_struct` to an Array to go deeper or to a Hash to change it to SDStruct
20
+ # Calls `to_struct` to an Array to go deeper or to a Hash to change it to SDStruct
22
21
  #
23
22
  # @return [Array<SDStruct,Object>] array of SDStruct or any other objects
24
23
  #
@@ -42,18 +41,23 @@ class SDStruct
42
41
  #
43
42
  # p data # -> #<SDStruct .name="Matz", ['coding language']=:ruby, .age="old">
44
43
  #
45
- def initialize(hash = nil, deep = true)
46
- @deep = deep
44
+ def initialize(hash = nil, opts = {})
45
+ opts = {
46
+ deep: true,
47
+ symbolize_keys: true
48
+ }.merge(opts)
49
+
50
+ @deep = opts[:deep]
47
51
  @table = {}
48
52
  if hash
49
53
  hash.each_pair do |k, v|
50
- @table[new_struct_member(k)] = structurize(v) # @deep is used in this method
54
+ @table[naturalize(k)] = structurize(v) # @deep is used in this method
51
55
  end
52
56
  end
53
57
  end
54
58
 
55
59
  #
56
- # Duplicate an SDStruct object members.
60
+ # Duplicates an SDStruct object members.
57
61
  #
58
62
  def initialize_copy(orig)
59
63
  super
@@ -92,7 +96,6 @@ class SDStruct
92
96
  # Used internally to define field properties
93
97
  #
94
98
  def new_struct_member(name)
95
- name = name.to_s.underscore.to_sym unless name[/^[A-Z]|\s+/]
96
99
  unless respond_to?(name)
97
100
  define_singleton_method(name) { @table[name] }
98
101
  define_singleton_method("#{name}=") { |x| @table[name] = x }
@@ -100,14 +103,22 @@ class SDStruct
100
103
  name
101
104
  end
102
105
 
106
+ def naturalize(key)
107
+ unless key[/^[A-Z]|\s+/]
108
+ key.to_s.underscore.to_sym
109
+ else
110
+ key
111
+ end
112
+ end
113
+
103
114
  #
104
- # Call to struct to a value if it is an Array or a Hash and @deep is true
115
+ # Calls to struct to a value if it is an Array or a Hash and @deep is true
105
116
  #
106
117
  def structurize(value)
107
118
  ( @deep && (value.is_a?(Hash) || value.is_a?(Array)) ) ? value.to_struct : value
108
119
  end
109
120
 
110
- protected :new_struct_member, :structurize
121
+ protected :new_struct_member, :naturalize, :structurize
111
122
 
112
123
 
113
124
  #
@@ -117,7 +128,7 @@ class SDStruct
117
128
  # person[:lang] # => ruby, same as person.lang
118
129
  #
119
130
  def [](name)
120
- @table.has_key?(name) ? @table[name] : @table[name.to_s.underscore.to_sym]
131
+ @table[name] || @table[naturalize(name)]
121
132
  end
122
133
 
123
134
  #
@@ -128,21 +139,19 @@ class SDStruct
128
139
  # person.lang # => ruby
129
140
  #
130
141
  def []=(name, value)
131
- unless self.[](name).nil? || value.is_a?(self.[](name).class)
142
+ unless self[name].nil? || value.is_a?(self[name].class)
132
143
  warn("You're assigning a value with different type as the previous value.")
133
144
  end
134
- @table[new_struct_member(name)] = structurize(value)
145
+ @table[new_struct_member(naturalize(name))] = structurize(value)
135
146
  end
136
147
 
137
- InspectKey = :__inspect_key__ # :nodoc:
138
-
139
148
  #
140
149
  # Returns a string containing a detailed summary of the keys and values.
141
150
  #
142
151
  def inspect
143
152
  str = "#<#{self.class}"
144
153
 
145
- ids = (Thread.current[InspectKey] ||= [])
154
+ ids = (Thread.current[:sd_struct] ||= [])
146
155
  if ids.include?(object_id)
147
156
  return str << ' ...>'
148
157
  end
@@ -181,7 +190,7 @@ class SDStruct
181
190
  end
182
191
 
183
192
  #
184
- # Compute a hash-code for this SDStruct.
193
+ # Computes a hash-code for this SDStruct.
185
194
  # Two hashes with the same content will have the same hash code
186
195
  # (and will be eql?).
187
196
  #
@@ -190,14 +199,14 @@ class SDStruct
190
199
  end
191
200
 
192
201
  #
193
- # Expose keys with space(s)
202
+ # Exposes keys with space(s)
194
203
  #
195
204
  def spaced_keys
196
205
  @table.keys - non_spaced_keys
197
206
  end
198
207
 
199
208
  #
200
- # Expose keys without space(s)
209
+ # Exposes keys without space(s)
201
210
  #
202
211
  def non_spaced_keys
203
212
  methods(false).select{|x| x[/^\S+[^=]$/]}
@@ -205,21 +214,34 @@ class SDStruct
205
214
  alias :fields :non_spaced_keys
206
215
 
207
216
  #
208
- # Expose all keys
217
+ # Exposes all keys
209
218
  #
210
219
  def keys
211
220
  @table.keys
212
221
  end
213
222
 
214
223
  #
215
- # Delete specified field or key
224
+ # Deletes specified field or key
216
225
  #
217
226
  def delete_field(name)
218
- sym = name.to_sym
219
- @table.delete(sym) do
220
- raise NameError.new("no field `#{sym}' in #{self}", sym)
227
+ name = @table.has_key?(name) ? name : naturalize(name)
228
+ @table.delete(name) do
229
+ raise NameError.new("no field `#{name}' in #{self}", name)
221
230
  end
222
- singleton_class.__send__(:remove_method, sym, "#{sym}=")
231
+ singleton_class.__send__(:remove_method, name, "#{name}=")
223
232
  end
224
233
  alias :delete_key :delete_field
234
+
235
+ def method_missing(m_id, *args)
236
+ m_nat = naturalize(m_id)
237
+ if args.length.zero?
238
+ if @table.key?(m_nat)
239
+ @table[new_struct_member(m_nat)]
240
+ end
241
+ else
242
+ err = NoMethodError.new "undefined method `#{m_id}' for #{self}", m_id, args
243
+ err.set_backtrace caller(1)
244
+ raise err
245
+ end
246
+ end
225
247
  end
@@ -3,7 +3,7 @@ class SDStruct
3
3
  refine Array do
4
4
 
5
5
  #
6
- # Dig deep into array until non-Array and non-Hash primitive data is found
6
+ # Digs deep into array until non-Array and non-Hash primitive data is found
7
7
  #
8
8
  # @param [Symbol] multiple symbols
9
9
  # @return [String,Integer,Float,Boolean,nil] first matched result
@@ -32,7 +32,7 @@ class SDStruct
32
32
  }
33
33
 
34
34
  #
35
- # Dig deep into Hash until non-Array and non-Hash primitive data is found
35
+ # Digs deep into Hash until non-Array and non-Hash primitive data is found
36
36
  #
37
37
  # @param [Symbol] multiple symbols
38
38
  # @return [SDStruct,Hash,Array,String,Integer,Float,Boolean,nil] first matched result
@@ -60,7 +60,7 @@ class SDStruct
60
60
  end
61
61
 
62
62
  #
63
- # Dig the content of @table which is a hash
63
+ # Digs the content of @table which is a hash
64
64
  #
65
65
  # @param [Symbol] multiple symbols
66
66
  # @return [SDStruct,Hash,Array,String,Integer,Float,Boolean,nil] first matched result
@@ -69,6 +69,13 @@ class SDStruct
69
69
  @table.dig(*args)
70
70
  end
71
71
 
72
+ #
73
+ # Finds value with keys specified like xpath
74
+ #
75
+ # @param [String] key string
76
+ # @param [Hash] option Hash
77
+ # @return [SDStruct,Hash,Array,String,Integer,Float,Boolean,nil] first matched result
78
+ #
72
79
  def find(key_str, opts = {})
73
80
  opts = {
74
81
  separator: "/"
@@ -86,7 +93,7 @@ class SDStruct
86
93
  if !!x[/\A[-+]?\d+\z/]
87
94
  x.to_i
88
95
  else
89
- if x[/^$|\s+/]
96
+ if x[/^$|^[A-Z]|\s+/]
90
97
  x
91
98
  else
92
99
  x.underscore.to_sym
@@ -1,3 +1,3 @@
1
1
  class SDStruct
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -24,4 +24,5 @@ with deep digging capabilities.}
24
24
  spec.add_development_dependency "bundler", "~> 1.14"
25
25
  spec.add_development_dependency "rake", "~> 10.0"
26
26
  spec.add_development_dependency "rspec", "~> 3.5"
27
+ spec.add_development_dependency "pry", "~> 0.10.4"
27
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sd_struct
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Setyadi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-19 00:00:00.000000000 Z
11
+ date: 2017-09-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '3.5'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.10.4
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.10.4
69
83
  description: |-
70
84
  An alternative to OpenStruct that more strict in assigning values and deeper in
71
85
  consuming the passed Hash and transforming it back to Hash or JSON, equipped