recursive-open-struct-sd 1.0.2
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 +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
|