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 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
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
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
@@ -0,0 +1,13 @@
1
+ ---
2
+ language: ruby
3
+ rvm:
4
+ - 2.0.0
5
+ - 2.1.10
6
+ - 2.2.5
7
+ - 2.3.1
8
+ - 2.4.0
9
+ - ruby-head
10
+ - jruby-19mode
11
+ - jruby-9.0.5.0
12
+ - jruby-head
13
+ sudo: false
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
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
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