recursive-open-struct-sd 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.gitignore +50 -0
- data/.rspec +1 -0
- data/.travis.yml +13 -0
- data/AUTHORS.txt +15 -0
- data/CHANGELOG.md +151 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +21 -0
- data/README.md +60 -0
- data/Rakefile +60 -0
- data/lib/recursive-open-struct.rb +1 -0
- data/lib/recursive_open_struct.rb +130 -0
- data/lib/recursive_open_struct/debug_inspect.rb +38 -0
- data/lib/recursive_open_struct/deep_dup.rb +32 -0
- data/lib/recursive_open_struct/ruby_19_backport.rb +27 -0
- data/lib/recursive_open_struct/version.rb +7 -0
- data/recursive-open-struct-sd.gemspec +46 -0
- data/spec/recursive_open_struct/debug_inspect_spec.rb +70 -0
- data/spec/recursive_open_struct/indifferent_access_spec.rb +166 -0
- data/spec/recursive_open_struct/open_struct_behavior_spec.rb +92 -0
- data/spec/recursive_open_struct/ostruct_2_0_0_spec.rb +105 -0
- data/spec/recursive_open_struct/recursion_and_subclassing_spec.rb +14 -0
- data/spec/recursive_open_struct/recursion_spec.rb +299 -0
- data/spec/spec_helper.rb +19 -0
- metadata +174 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5244992a3f5ff4094c1b2b2cb3daa2e9784e3e6f
|
4
|
+
data.tar.gz: 11d6e66b3fda35da43f246d86ad6b8f82ce38acc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e106b2c0a0b66e0c6789bd73b3c1aa82c5abf38f45aee8c0942f4f773edc4d87d1986b9c7db4d174c77d996c322422e3d758abc20bc36af2ae7a85a9f6a94cbe
|
7
|
+
data.tar.gz: 24d7faf9c8502bf0316d35abf1f31dd8a5d5571f72de98dc900d545e0dbfcb4fe6fde19f50471709c19d85f8e0e3534d63ef171edb707711ce7b79a2b87c24c6
|
data/.document
ADDED
data/.gitignore
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# rcov generated
|
2
|
+
coverage
|
3
|
+
|
4
|
+
# rdoc generated
|
5
|
+
rdoc
|
6
|
+
|
7
|
+
# yard generated
|
8
|
+
doc
|
9
|
+
.yardoc
|
10
|
+
|
11
|
+
# bundler
|
12
|
+
.bundle
|
13
|
+
|
14
|
+
# jeweler generated
|
15
|
+
pkg
|
16
|
+
|
17
|
+
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
18
|
+
#
|
19
|
+
# * Create a file at ~/.gitignore
|
20
|
+
# * Include files you want ignored
|
21
|
+
# * Run: git config --global core.excludesfile ~/.gitignore
|
22
|
+
#
|
23
|
+
# After doing this, these files will be ignored in all your git projects,
|
24
|
+
# saving you from having to 'pollute' every project you touch with them
|
25
|
+
#
|
26
|
+
# Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
|
27
|
+
#
|
28
|
+
# For MacOS:
|
29
|
+
#
|
30
|
+
.DS_Store
|
31
|
+
|
32
|
+
# For TextMate
|
33
|
+
*.tmproj
|
34
|
+
tmtags
|
35
|
+
|
36
|
+
# For emacs:
|
37
|
+
*~
|
38
|
+
\#*
|
39
|
+
.\#*
|
40
|
+
|
41
|
+
# For vim:
|
42
|
+
*.swp
|
43
|
+
|
44
|
+
# For redcar:
|
45
|
+
#.redcar
|
46
|
+
|
47
|
+
# For rubinius:
|
48
|
+
#*.rbc
|
49
|
+
|
50
|
+
Gemfile.lock
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
data/AUTHORS.txt
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Recursive-open-struct was written by these fine people:
|
2
|
+
|
3
|
+
* Cédric Felizard <cedric@felizard.fr>
|
4
|
+
* Federico Aloi <federico.aloi@gmail.com>
|
5
|
+
* fervic <roberto@runawaybit.com>
|
6
|
+
* Kris Dekeyser <kris.dekeyser@libis.be>
|
7
|
+
* Matt Culpepper <matt@culpepper.co>
|
8
|
+
* Matthew O'Riordan <matthew.oriordan@gmail.com>
|
9
|
+
* Offirmo <offirmo.net@gmail.com>
|
10
|
+
* Peter Yeremenko <peter.yeremenko@gmail.com>
|
11
|
+
* Sebastian Gaul <sebastian@mgvmedia.com>
|
12
|
+
* Thiago Guimaraes <thiagogsr@gmail.com>
|
13
|
+
* Tom Chapin <tchapin@gmail.com>
|
14
|
+
* Victor Guzman <victor.guzman@runawaybit.com>
|
15
|
+
* William (B.J.) Snow Orvis <aetherknight@gmail.com>
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
1.0.1 / 2016-01-18
|
2
|
+
==================
|
3
|
+
|
4
|
+
* FIX [#42](https://github.com/aetherknight/recursive-open-struct/issues/42):
|
5
|
+
`[]` tried to call private methods if they existed instead of triggering the
|
6
|
+
`method_missing` code path. Thanks to @SaltwaterC for reporting.
|
7
|
+
|
8
|
+
1.0.0 / 2015-12-11
|
9
|
+
==================
|
10
|
+
|
11
|
+
* API-Breaking Change: Frederico Aloi: Change `to_h` to always return symbol
|
12
|
+
keys. This is more consistent with OpenStruct.
|
13
|
+
* API-Breaking Change: No longer officially supporting Ruby 1.9.3.
|
14
|
+
* NEW/FIX: Kris Dekeyser: Ensure that ROS continues to work with the new
|
15
|
+
version of OpenStruct included in dev versions of Ruby 2.2.x and Ruby 2.3. It
|
16
|
+
now implements lazy attribute creation, which broke ROS.
|
17
|
+
* NEW: Added `preserve_original_keys` option to revert to the 0.x behavior. Set
|
18
|
+
it to true if you want methods like `to_h` to return strings and perhaps
|
19
|
+
other non-symbols.
|
20
|
+
* NEW: Ensuring support for Ruby 2.0.0+ including the upcoming 2.3 release and
|
21
|
+
JRuby 9000.
|
22
|
+
* FIX: Peter Yeremenko: Fix a mistake in one of the examples in the README
|
23
|
+
|
24
|
+
0.6.5 / 2015-06-30
|
25
|
+
==================
|
26
|
+
|
27
|
+
* FIX: Fix ROS when initialized with nil instead of a hash.
|
28
|
+
|
29
|
+
0.6.4 / 2015-05-20
|
30
|
+
==================
|
31
|
+
|
32
|
+
* FIX: Kris Dekeyser: Fix indifferent subscript access (string or symbol). Also
|
33
|
+
backported several ostruct methods for Ruby 1.9.x.
|
34
|
+
* FIX: Partial fix for allowing an array in a RecursiveOpenStruct tree to be
|
35
|
+
modified. However, methods such as to_hash are still broken.
|
36
|
+
|
37
|
+
0.6.3 / 2015-04-11
|
38
|
+
==================
|
39
|
+
|
40
|
+
* FIX: Thiago Guimaraes: Restore being able to create an ROS from a hash that
|
41
|
+
contains strings for keys instead of symbols for keys.
|
42
|
+
|
43
|
+
0.6.2 / 2015-04-07
|
44
|
+
==================
|
45
|
+
|
46
|
+
* FIX: fervic: Address a bug in the Ruby 1.9's version of OpenStruct's `dup`
|
47
|
+
* FIX: Victor Guzman: Reset memoized values on assignment in order to force the
|
48
|
+
implementation to re-memoize them.
|
49
|
+
* MAINT: fervic: Simplified `initialize`
|
50
|
+
|
51
|
+
0.6.1 / 2015-03-28
|
52
|
+
==================
|
53
|
+
|
54
|
+
* FIX: Actually ensure that the internal @table is properly dependent or
|
55
|
+
independent of the input hash tree. I mistakenly refactored away an important
|
56
|
+
piece of code that fervic added.
|
57
|
+
* FIX: Actually ensure that `#dup` works.
|
58
|
+
* Also refactored how `#to_h` is implemented to use newer plumbing.
|
59
|
+
|
60
|
+
0.6.0 / 2015-03-28
|
61
|
+
==================
|
62
|
+
|
63
|
+
* NEW: fervic: Make subscript notation be recursive like dot-method notation
|
64
|
+
* NEW: fervic: Added a new option, `:mutate_input_hash`, that allows the caller
|
65
|
+
to determine whether the original hash is mutated or not when a nested value
|
66
|
+
in the ROS tree is modified. If false (the default), the ROS will not modify
|
67
|
+
the original hash tree. If tree, changes within the ROS tree will also be
|
68
|
+
reflected in the hash tree.
|
69
|
+
* FIX: fervic: Setting/updating a value nested deep in an ROS tree is kept
|
70
|
+
when the top-level ROS object is duped.
|
71
|
+
* MAINT: Extracted `#deep_dup` added by fervic into its own class. This makes it
|
72
|
+
possibly easier to use/copy for others, and it cleans up the main class file.
|
73
|
+
* MAINT: Moved `#debug_inspect` out to its own module. This cleans up the main
|
74
|
+
class file a bit. It is also something I may remove if I ever have a major
|
75
|
+
version bump.
|
76
|
+
* MAINT: Adding MRI 2.2 to Travis-CI
|
77
|
+
|
78
|
+
0.5.0 / 2014-06-14
|
79
|
+
==================
|
80
|
+
|
81
|
+
* NEW: Tom Chapin: Added a `#to_hash` alias for `#to_h`
|
82
|
+
* MAINT: Added Travis-CI support. Testing against MRI 1.9.3, MRI 2.0, MRI 2.1,
|
83
|
+
and JRuby in 1.9 mode. Not aiming to support 1.8.7 since it has been nearly a
|
84
|
+
year since it has officially been retired.
|
85
|
+
|
86
|
+
0.4.5 / 2013-10-23
|
87
|
+
==================
|
88
|
+
|
89
|
+
* FIX: Matt Culpepper: Allow ROS subclasses to use their own type when creating
|
90
|
+
nested objects in the tree.
|
91
|
+
|
92
|
+
0.4.4 / 2013-08-28
|
93
|
+
==================
|
94
|
+
|
95
|
+
* FIX: Ensure proper file permissions when building the gem archive
|
96
|
+
|
97
|
+
0.4.3 / 2013-05-30
|
98
|
+
==================
|
99
|
+
|
100
|
+
* FIX: Sebastian Gaul: Make `recurse_over_arrays` option work on more
|
101
|
+
deeply-nested hashes.
|
102
|
+
|
103
|
+
0.4.2 / 2013-05-29
|
104
|
+
==================
|
105
|
+
|
106
|
+
* FIX: Setting a value on a nested element, then getting that value should show
|
107
|
+
the updated value
|
108
|
+
* FIX: Calling `#to_h` on the top-level ROS object also reflects changed nested
|
109
|
+
elements.
|
110
|
+
|
111
|
+
0.4.1 / 2013-05-28
|
112
|
+
==================
|
113
|
+
|
114
|
+
* FIX: Fixing the `spec:coverage` Rake task
|
115
|
+
|
116
|
+
0.4.0 / 2013-05-26
|
117
|
+
==================
|
118
|
+
|
119
|
+
* NEW: Added `#to_h`
|
120
|
+
* MAINT: Stopped using jeweler for gem development/packaging
|
121
|
+
|
122
|
+
0.3.1 / 2012-10-23
|
123
|
+
==================
|
124
|
+
|
125
|
+
* FIX: Cédric Felizard: Fix to make it work with MRI 1.8.7 again
|
126
|
+
* MAINT: More spec fixups to improve spec runs on MRI 1.9.3
|
127
|
+
|
128
|
+
0.3.0 / 2013-10-23
|
129
|
+
==================
|
130
|
+
|
131
|
+
* NEW: Matthew O'Riordan: Add support for recursion working over Arrays
|
132
|
+
* NEW: Made recursion over Arrays optional with `recurse_over_arrays` option.
|
133
|
+
* NEW: Improving `#debug_inspect` so that it can use any IO object, not just
|
134
|
+
STDOUT.
|
135
|
+
* MAINT: Much cleanup of development dependencies, README file, etc.
|
136
|
+
|
137
|
+
0.2.1 / 2011-05-31
|
138
|
+
==================
|
139
|
+
|
140
|
+
* FIX: Offirmo: Slight improvement for `#debug_inspect`
|
141
|
+
|
142
|
+
0.2.0 / 2011-05-25
|
143
|
+
==================
|
144
|
+
|
145
|
+
* NEW: Offirmo: Added `debug_inspect`
|
146
|
+
* MAINT: Offirmo: Worked the development files so that it can be built as a gem
|
147
|
+
|
148
|
+
0.1.0 / 2010-01-12
|
149
|
+
==================
|
150
|
+
|
151
|
+
* Initial release
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2009-2016, The Recursive-open-struct developers (given in the
|
2
|
+
file AUTHORS.txt).
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# recursive-open-struct-sd
|
2
|
+
|
3
|
+
OpenStruct subclass that returns nested hash attributes as
|
4
|
+
RecursiveOpenStructs.
|
5
|
+
|
6
|
+
It allows for hashes within hashes to be called in a chain of methods:
|
7
|
+
|
8
|
+
ros = RecursiveOpenStruct.new( { fooa: { foob: 'fooc' } } )
|
9
|
+
|
10
|
+
ros.fooa.foob # => 'fooc'
|
11
|
+
|
12
|
+
Also, if needed, nested hashes can still be accessed as hashes:
|
13
|
+
|
14
|
+
ros.fooa_as_a_hash # { foob: 'fooc' }
|
15
|
+
|
16
|
+
RecursiveOpenStruct can also optionally recurse across arrays, although you
|
17
|
+
have to explicitly enable it:
|
18
|
+
|
19
|
+
h = { :somearr => [ { name: 'a'}, { name: 'b' } ] }
|
20
|
+
ros = RecursiveOpenStruct.new(h, recurse_over_arrays: true )
|
21
|
+
|
22
|
+
ros.somearr[0].name # => 'a'
|
23
|
+
ros.somearr[1].name # => 'b'
|
24
|
+
|
25
|
+
Also, by default it will turn all hash keys into symbols internally:
|
26
|
+
|
27
|
+
h = { 'fear' => 'is', 'the' => 'mindkiller' } }
|
28
|
+
ros = RecursiveOpenStruct.new(h)
|
29
|
+
ros.to_h # => { fear: 'is', the: 'mindkiller' }
|
30
|
+
|
31
|
+
You can preserve the original keys by enabling `:preserve_original_keys`:
|
32
|
+
|
33
|
+
h = { 'fear' => 'is', 'the' => 'mindkiller' } }
|
34
|
+
ros = RecursiveOpenStruct.new(h, preserve_original_keys: true)
|
35
|
+
ros.to_h # => { 'fear' => 'is', 'the' => 'mindkiller' }
|
36
|
+
|
37
|
+
## Installation
|
38
|
+
|
39
|
+
Available as a gem in rubygems, the default gem repository.
|
40
|
+
|
41
|
+
If you use bundler, just throw that in your gemfile :
|
42
|
+
|
43
|
+
gem 'recursive-open-struct'
|
44
|
+
|
45
|
+
You may also install the gem manually :
|
46
|
+
|
47
|
+
gem install recursive-open-struct
|
48
|
+
|
49
|
+
## Contributing
|
50
|
+
|
51
|
+
* Fork the project.
|
52
|
+
* Make your feature addition or bug fix.
|
53
|
+
* Add tests for your new or changed functionality. Make sure the tests you add
|
54
|
+
provide clean and clear explanation of the feature.
|
55
|
+
* Send me a pull request. Bonus points for topic branches.
|
56
|
+
|
57
|
+
## Copyright
|
58
|
+
|
59
|
+
Copyright (c) 2009-2016, The Recursive-open-struct developers (given in the
|
60
|
+
file AUTHORS.txt). See LICENSE.txt for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler/gem_tasks'
|
5
|
+
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
8
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
9
|
+
end
|
10
|
+
namespace :spec do
|
11
|
+
if RUBY_VERSION =~ /^1\.8/
|
12
|
+
desc "Rspec code coverage (1.8.7)"
|
13
|
+
RSpec::Core::RakeTask.new(:coverage) do |spec|
|
14
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
15
|
+
spec.rcov = true
|
16
|
+
end
|
17
|
+
else
|
18
|
+
desc "Rspec code coverage (1.9+)"
|
19
|
+
task :coverage do
|
20
|
+
ENV['COVERAGE'] = 'true'
|
21
|
+
Rake::Task["spec"].execute
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'rdoc/task'
|
27
|
+
Rake::RDocTask.new do |rdoc|
|
28
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
29
|
+
|
30
|
+
rdoc.rdoc_dir = 'rdoc'
|
31
|
+
rdoc.title = "recursive-open-struct #{version}"
|
32
|
+
rdoc.rdoc_files.include('README*')
|
33
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
34
|
+
end
|
35
|
+
|
36
|
+
task :default => :spec
|
37
|
+
|
38
|
+
task :fix_permissions do
|
39
|
+
File.umask 0022
|
40
|
+
filelist = `git ls-files`.split("\n")
|
41
|
+
FileUtils.chmod 0644, filelist, :verbose => true
|
42
|
+
FileUtils.chmod 0755, ['lib','spec'], :verbose => true
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Update the AUTHORS.txt file"
|
46
|
+
task :update_authors do
|
47
|
+
authors = `git log --format="%aN <%aE>"|sort -f|uniq`
|
48
|
+
File.open('AUTHORS.txt', 'w') do |f|
|
49
|
+
f.write("Recursive-open-struct was written by these fine people:\n\n")
|
50
|
+
f.write(authors.split("\n").map { |a| "* #{a}" }.join( "\n" ))
|
51
|
+
f.write("\n")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
task :build => [:update_authors, :fix_permissions]
|
56
|
+
|
57
|
+
desc "Run an interactive pry shell with ros required"
|
58
|
+
task :pry do
|
59
|
+
sh "pry -I lib -r recursive-open-struct"
|
60
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'recursive_open_struct'
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'recursive_open_struct/version'
|
3
|
+
|
4
|
+
require 'recursive_open_struct/debug_inspect'
|
5
|
+
require 'recursive_open_struct/deep_dup'
|
6
|
+
require 'recursive_open_struct/ruby_19_backport'
|
7
|
+
|
8
|
+
class RecursiveOpenStruct < OpenStruct
|
9
|
+
include Ruby19Backport if RUBY_VERSION =~ /\A1.9/
|
10
|
+
include DebugInspect
|
11
|
+
|
12
|
+
def initialize(hash=nil, args={})
|
13
|
+
hash ||= {}
|
14
|
+
@recurse_over_arrays = args.fetch(:recurse_over_arrays, false)
|
15
|
+
@preserve_original_keys = args.fetch(:preserve_original_keys, false)
|
16
|
+
@deep_dup = DeepDup.new(
|
17
|
+
recurse_over_arrays: @recurse_over_arrays,
|
18
|
+
preserve_original_keys: @preserve_original_keys
|
19
|
+
)
|
20
|
+
|
21
|
+
@table = args.fetch(:mutate_input_hash, false) ? hash : @deep_dup.call(hash)
|
22
|
+
|
23
|
+
@sub_elements = {}
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize_copy(orig)
|
27
|
+
super
|
28
|
+
|
29
|
+
# deep copy the table to separate the two objects
|
30
|
+
@table = @deep_dup.call(orig.instance_variable_get(:@table))
|
31
|
+
# Forget any memoized sub-elements
|
32
|
+
@sub_elements = {}
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_h
|
36
|
+
@deep_dup.call(@table)
|
37
|
+
end
|
38
|
+
|
39
|
+
alias_method :to_hash, :to_h
|
40
|
+
|
41
|
+
def [](name)
|
42
|
+
public_send(name)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Makes sure ROS responds as expected on #respond_to? and #method requests
|
46
|
+
def respond_to_missing?(mid, include_private = false)
|
47
|
+
mname = _get_key_from_table_(mid.to_s.chomp('=').chomp('_as_a_hash'))
|
48
|
+
@table.key?(mname) || super
|
49
|
+
end
|
50
|
+
|
51
|
+
# Adapted implementation of method_missing to accomodate the differences between ROS and OS.
|
52
|
+
def method_missing(mid, *args)
|
53
|
+
len = args.length
|
54
|
+
if mid =~ /^(.*)=$/
|
55
|
+
if len != 1
|
56
|
+
raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)
|
57
|
+
end
|
58
|
+
modifiable[new_ostruct_member($1.to_sym)] = args[0]
|
59
|
+
elsif len == 0
|
60
|
+
key = mid
|
61
|
+
key = $1 if key =~ /^(.*)_as_a_hash$/
|
62
|
+
if @table.key?(_get_key_from_table_(key))
|
63
|
+
new_ostruct_member(key)
|
64
|
+
send(mid)
|
65
|
+
end
|
66
|
+
else
|
67
|
+
err = NoMethodError.new "undefined method `#{mid}' for #{self}", mid, args
|
68
|
+
err.set_backtrace caller(1)
|
69
|
+
raise err
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def new_ostruct_member(name)
|
74
|
+
key_name = _get_key_from_table_ name
|
75
|
+
unless self.methods.include?(name.to_sym)
|
76
|
+
class << self; self; end.class_eval do
|
77
|
+
define_method(name) do
|
78
|
+
v = @table[key_name]
|
79
|
+
if v.is_a?(Hash)
|
80
|
+
@sub_elements[key_name] ||= self.class.new(
|
81
|
+
v,
|
82
|
+
recurse_over_arrays: @recurse_over_arrays,
|
83
|
+
preserve_original_keys: @preserve_original_keys,
|
84
|
+
mutate_input_hash: true
|
85
|
+
)
|
86
|
+
elsif v.is_a?(Array) and @recurse_over_arrays
|
87
|
+
@sub_elements[key_name] ||= recurse_over_array(v)
|
88
|
+
@sub_elements[key_name] = recurse_over_array(@sub_elements[key_name])
|
89
|
+
else
|
90
|
+
v
|
91
|
+
end
|
92
|
+
end
|
93
|
+
define_method("#{name}=") do |x|
|
94
|
+
@sub_elements.delete(key_name)
|
95
|
+
modifiable[key_name] = x
|
96
|
+
end
|
97
|
+
define_method("#{name}_as_a_hash") { @table[key_name] }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
key_name
|
101
|
+
end
|
102
|
+
|
103
|
+
def delete_field(name)
|
104
|
+
sym = _get_key_from_table_(name)
|
105
|
+
singleton_class.__send__(:remove_method, sym, "#{sym}=") rescue NoMethodError # ignore if methods not yet generated.
|
106
|
+
@sub_elements.delete sym
|
107
|
+
@table.delete sym
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def _get_key_from_table_(name)
|
113
|
+
return name.to_s if @table.has_key?(name.to_s)
|
114
|
+
return name.to_sym if @table.has_key?(name.to_sym)
|
115
|
+
name
|
116
|
+
end
|
117
|
+
|
118
|
+
def recurse_over_array(array)
|
119
|
+
array.each_with_index do |a, i|
|
120
|
+
if a.is_a? Hash
|
121
|
+
array[i] = self.class.new(a, :recurse_over_arrays => true,
|
122
|
+
:mutate_input_hash => true, :preserve_original_keys => @preserve_original_keys)
|
123
|
+
elsif a.is_a? Array
|
124
|
+
array[i] = recurse_over_array a
|
125
|
+
end
|
126
|
+
end
|
127
|
+
array
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|