fancy-open-struct 0.1.2 → 0.1.3

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.
@@ -0,0 +1 @@
1
+ repo_token: ATscazUF1vqixUbLan70hDzMHNPsrSu0b
data/.rspec CHANGED
@@ -1 +1,2 @@
1
1
  --color
2
+ --format progress
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.8.7"
4
+ - "1.9.2"
5
+ - "1.9.3"
6
+ - "2.0.0"
7
+ - jruby-18mode # JRuby in 1.8 mode
8
+ - jruby-19mode # JRuby in 1.9 mode
9
+ - rbx
10
+ # uncomment this line if your project needs to run something other than `rake`:
11
+ # script: bundle exec rspec spec
data/Gemfile CHANGED
@@ -7,5 +7,4 @@ group :development do
7
7
  else
8
8
  gem 'simplecov'
9
9
  end
10
- gem 'pry'
11
10
  end
@@ -1,9 +1,23 @@
1
- = fancy-open-struct
1
+ = FancyOpenStruct
2
2
 
3
- OpenStruct subclass that returns nested (recursive) hash attributes as FancyOpenStructs,
4
- and also allows usage of Hash methods for getting and setting values.
3
+ {<img src="http://allthebadges.io/tomchapin/fancy-open-struct/badge_fury.png" alt="Version" />}[http://allthebadges.io/tomchapin/fancy-open-struct/badge_fury]
4
+ {<img src="http://allthebadges.io/tomchapin/fancy-open-struct/gemnasium.png" alt="Dependencies" />}[http://allthebadges.io/tomchapin/fancy-open-struct/gemnasium]
5
+ {<img src="http://allthebadges.io/tomchapin/fancy-open-struct/travis.png" alt="Build Status" />}[http://allthebadges.io/tomchapin/fancy-open-struct/travis]
6
+ {<img src="http://allthebadges.io/tomchapin/fancy-open-struct/coveralls.png" alt="Coverage" />}[http://allthebadges.io/tomchapin/fancy-open-struct/coveralls]
7
+ {<img src="http://allthebadges.io/tomchapin/fancy-open-struct/code_climate.png" alt="Code Climate" />}[http://allthebadges.io/tomchapin/fancy-open-struct/code_climate]
5
8
 
6
- It allows for hashes within hashes to be called in a chain of methods:
9
+ FancyOpenStruct is a subclass of OpenStruct, and is a variant of RecursiveOpenStruct.
10
+
11
+ This gem allows you to convert nested hashes into a structure where keys and values can be
12
+ navigated and modified via dot-syntax, like: foo.bar = :something. This particular gem also adds support
13
+ for the Hash methods you know and love (such as length or merge), and also allows you to access and modify
14
+ the contained data structure the same way that you would handle a normal Hash.
15
+
16
+ == Usage
17
+
18
+ FancyOpenStruct allows for hashes within hashes to be called in a chain of methods:
19
+
20
+ require 'fancy-open-struct'
7
21
 
8
22
  fos = FancyOpenStruct.new( { :fooa => { :foob => 'fooc' } } )
9
23
 
@@ -15,6 +29,8 @@ Also, if needed, nested hashes can still be accessed as hashes:
15
29
 
16
30
  Get and set values either via dot syntax, or hash syntax (Hash keys are handled as Symbols):
17
31
 
32
+ fos = FancyOpenStruct.new
33
+
18
34
  fos.foo = 'bar'
19
35
  fos[:foo] # 'bar'
20
36
 
data/Rakefile CHANGED
@@ -42,4 +42,4 @@ task :fix_permissions do
42
42
  FileUtils.chmod 0755, ['lib','spec'], :verbose => true
43
43
  end
44
44
 
45
- task :build => :fix_permissions
45
+ task :build => :fix_permissions
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
- require './lib/fancy_open_struct'
3
+ require './lib/fancy-open-struct'
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "fancy-open-struct"
@@ -12,38 +12,32 @@ Gem::Specification.new do |s|
12
12
  s.licenses = ["MIT"]
13
13
 
14
14
  s.summary = "OpenStruct subclass that returns nested hash attributes as FancyOpenStructs"
15
- s.description = <<-QUOTE .gsub(/^ /,'')
15
+ s.description = <<-QUOTE.gsub(/^ /, '')
16
16
  FancyOpenStruct is a subclass of OpenStruct, and is a variant of RecursiveOpenStruct.
17
- It differs from OpenStruct in that it allows nested hashes to be treated in a recursive
18
- fashion, and it also provides Hash methods for getting and setting values.
17
+ This allows you to convert nested hashes into a structure where keys and values can be
18
+ navigated and modified via dot-syntax, like: foo.bar = :something. This particular gem
19
+ also adds support for Hash methods (such as length or merge), and also allows you to
20
+ access and modify the data structure the same way that you would handle a normal Hash.
19
21
 
20
- For example:
21
-
22
- fos = FancyOpenStruct.new({ :a => { :b => 'c' } })
23
- fos.a.b # 'c'
24
-
25
- fos.foo = 'bar'
26
- fos[:foo] # 'bar'
27
-
28
- fos.length # 2
29
-
30
- Also, nested hashes can still be accessed as hashes:
31
-
32
- fos.a_as_a_hash # { :b => 'c' }
33
-
34
- QUOTE
22
+ QUOTE
35
23
 
36
24
  s.files = `git ls-files`.split("\n")
37
25
  s.test_files = `git ls-files spec`.split("\n")
38
26
  s.require_paths = ["lib"]
39
27
  s.extra_rdoc_files = [
40
- "LICENSE.txt",
41
- "README.rdoc"
28
+ "LICENSE.txt",
29
+ "README.rdoc"
42
30
  ]
43
31
 
44
- s.add_development_dependency(%q<rspec>, [">= 0"])
45
- s.add_development_dependency(%q<bundler>, [">= 0"])
46
- s.add_development_dependency(%q<rdoc>, [">= 0"])
47
- s.add_development_dependency(%q<pry>, [">= 0"])
32
+ s.add_development_dependency "bundler"
33
+ s.add_development_dependency "rake"
34
+ s.add_development_dependency "rspec"
35
+ s.add_development_dependency "rdoc"
36
+ s.add_development_dependency "pry"
37
+ s.add_development_dependency "coveralls"
38
+ s.add_development_dependency "guard"
39
+ s.add_development_dependency "guard-rspec"
40
+ s.add_development_dependency "guard-bundler"
41
+ s.add_development_dependency "simplecov-multi"
48
42
  end
49
43
 
@@ -1 +1,125 @@
1
- require 'fancy_open_struct'
1
+ require 'ostruct'
2
+ require 'forwardable'
3
+
4
+ class FancyOpenStruct < OpenStruct
5
+ VERSION = "0.1.3"
6
+
7
+ extend Forwardable
8
+
9
+ hash_methods = Hash.instance_methods(false) - (Hash.instance_methods(false) & OpenStruct.instance_methods(false))
10
+ def_delegators :@table, *hash_methods
11
+
12
+ def initialize(hash=nil, args={})
13
+ @recurse_over_arrays = args.fetch(:recurse_over_arrays, false)
14
+ @table = {}
15
+ if hash
16
+ for k, v in hash
17
+ @table[k.to_sym] = v
18
+ new_ostruct_member(k)
19
+ end
20
+ end
21
+ @sub_elements = {}
22
+ end
23
+
24
+ def to_h
25
+ @table.dup.update(@sub_elements) do |k, oldval, newval|
26
+ if newval.kind_of?(self.class)
27
+ newval.to_h
28
+ elsif newval.kind_of?(Array)
29
+ newval.map { |a| a.kind_of?(self.class) ? a.to_h : a }
30
+ else
31
+ raise "Cached value of unsupported type: #{newval.inspect}"
32
+ end
33
+ end
34
+ end
35
+
36
+ def new_ostruct_member(name)
37
+ name = name.to_sym
38
+ unless self.respond_to?(name)
39
+ define_singleton_method name do
40
+ v = @table[name]
41
+ if v.is_a?(Hash)
42
+ @sub_elements[name] ||= self.class.new(v, :recurse_over_arrays => @recurse_over_arrays)
43
+ elsif v.is_a?(Array) and @recurse_over_arrays
44
+ @sub_elements[name] ||= recurse_over_array v
45
+ else
46
+ v
47
+ end
48
+ end
49
+ define_singleton_method("#{name}=") { |x| modifiable[name] = x }
50
+ define_singleton_method("#{name}_as_a_hash") { @table[name] }
51
+ end
52
+ name
53
+ end
54
+
55
+ def recurse_over_array array
56
+ array.map do |a|
57
+ if a.is_a? Hash
58
+ self.class.new(a, :recurse_over_arrays => true)
59
+ elsif a.is_a? Array
60
+ recurse_over_array a
61
+ else
62
+ a
63
+ end
64
+ end
65
+ end
66
+
67
+ def debug_inspect(io = STDOUT, indent_level = 0, recursion_limit = 12)
68
+ display_recursive_open_hash(io, @table, indent_level, recursion_limit)
69
+ end
70
+
71
+ def display_recursive_open_hash(io, ostrct_or_hash, indent_level, recursion_limit)
72
+
73
+ if recursion_limit <= 0
74
+ # protection against recursive structure (like in the tests)
75
+ io.puts ' '*indent_level + '(recursion limit reached)'
76
+ else
77
+ #puts ostrct_or_hash.inspect
78
+ if ostrct_or_hash.is_a?(self.class)
79
+ ostrct_or_hash = ostrct_or_hash.marshal_dump
80
+ end
81
+
82
+ # We'll display the key values like this : key = value
83
+ # to align display, we look for the maximum key length of the data that will be displayed
84
+ # (everything except hashes)
85
+ data_indent = ostrct_or_hash \
86
+ .reject { |k, v| v.is_a?(self.class) || v.is_a?(Hash) } \
87
+ .max { |a, b| a[0].to_s.length <=> b[0].to_s.length }[0].to_s.length
88
+ # puts "max length = #{data_indent}"
89
+
90
+ ostrct_or_hash.each do |key, value|
91
+ if value.is_a?(self.class) || value.is_a?(Hash)
92
+ io.puts ' '*indent_level + key.to_s + '.'
93
+ display_recursive_open_hash(io, value, indent_level + 1, recursion_limit - 1)
94
+ else
95
+ io.puts ' '*indent_level + key.to_s + ' '*(data_indent - key.to_s.length) + ' = ' + value.inspect
96
+ end
97
+ end
98
+ end
99
+
100
+ true
101
+ end
102
+
103
+ def []=(*args)
104
+ len = args.length
105
+ raise ArgumentError, "wrong number of arguments (#{len} for 2)", caller(1) if len != 2
106
+ modifiable[new_ostruct_member(args[0].to_sym)] = args[1]
107
+ end
108
+
109
+ def method_missing(mid, *args) # :nodoc:
110
+ mname = mid.id2name
111
+ len = args.length
112
+ if mname.chomp!('=')
113
+ raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1) if len != 1
114
+ # Set up an instance method to point to the key/value in the table and set the value
115
+ modifiable[new_ostruct_member(mname.to_sym)] = args[0]
116
+ elsif @table.has_key?(mid)
117
+ # The table has apparently been modified externally, so we need to set up
118
+ # an instance method to point to the key/value in the table.
119
+ new_ostruct_member(mname.to_sym)
120
+ self.send(mid)
121
+ else
122
+ nil
123
+ end
124
+ end
125
+ end
@@ -1,125 +1 @@
1
- require 'ostruct'
2
- require 'forwardable'
3
-
4
- class FancyOpenStruct < OpenStruct
5
- VERSION = "0.1.2"
6
-
7
- extend Forwardable
8
-
9
- hash_methods = Hash.instance_methods(false) - (Hash.instance_methods(false) & OpenStruct.instance_methods(false))
10
- def_delegators :@table, *hash_methods
11
-
12
- def initialize(hash=nil, args={})
13
- @recurse_over_arrays = args.fetch(:recurse_over_arrays, false)
14
- @table = {}
15
- if hash
16
- for k, v in hash
17
- @table[k.to_sym] = v
18
- new_ostruct_member(k)
19
- end
20
- end
21
- @sub_elements = {}
22
- end
23
-
24
- def to_h
25
- @table.dup.update(@sub_elements) do |k, oldval, newval|
26
- if newval.kind_of?(self.class)
27
- newval.to_h
28
- elsif newval.kind_of?(Array)
29
- newval.map { |a| a.kind_of?(self.class) ? a.to_h : a }
30
- else
31
- raise "Cached value of unsupported type: #{newval.inspect}"
32
- end
33
- end
34
- end
35
-
36
- def new_ostruct_member(name)
37
- name = name.to_sym
38
- unless self.respond_to?(name)
39
- define_singleton_method name do
40
- v = @table[name]
41
- if v.is_a?(Hash)
42
- @sub_elements[name] ||= self.class.new(v, :recurse_over_arrays => @recurse_over_arrays)
43
- elsif v.is_a?(Array) and @recurse_over_arrays
44
- @sub_elements[name] ||= recurse_over_array v
45
- else
46
- v
47
- end
48
- end
49
- define_singleton_method("#{name}=") { |x| modifiable[name] = x }
50
- define_singleton_method("#{name}_as_a_hash") { @table[name] }
51
- end
52
- name
53
- end
54
-
55
- def recurse_over_array array
56
- array.map do |a|
57
- if a.is_a? Hash
58
- self.class.new(a, :recurse_over_arrays => true)
59
- elsif a.is_a? Array
60
- recurse_over_array a
61
- else
62
- a
63
- end
64
- end
65
- end
66
-
67
- def debug_inspect(io = STDOUT, indent_level = 0, recursion_limit = 12)
68
- display_recursive_open_hash(io, @table, indent_level, recursion_limit)
69
- end
70
-
71
- def display_recursive_open_hash(io, ostrct_or_hash, indent_level, recursion_limit)
72
-
73
- if recursion_limit <= 0
74
- # protection against recursive structure (like in the tests)
75
- io.puts ' '*indent_level + '(recursion limit reached)'
76
- else
77
- #puts ostrct_or_hash.inspect
78
- if ostrct_or_hash.is_a?(self.class)
79
- ostrct_or_hash = ostrct_or_hash.marshal_dump
80
- end
81
-
82
- # We'll display the key values like this : key = value
83
- # to align display, we look for the maximum key length of the data that will be displayed
84
- # (everything except hashes)
85
- data_indent = ostrct_or_hash \
86
- .reject { |k, v| v.is_a?(self.class) || v.is_a?(Hash) } \
87
- .max { |a, b| a[0].to_s.length <=> b[0].to_s.length }[0].to_s.length
88
- # puts "max length = #{data_indent}"
89
-
90
- ostrct_or_hash.each do |key, value|
91
- if value.is_a?(self.class) || value.is_a?(Hash)
92
- io.puts ' '*indent_level + key.to_s + '.'
93
- display_recursive_open_hash(io, value, indent_level + 1, recursion_limit - 1)
94
- else
95
- io.puts ' '*indent_level + key.to_s + ' '*(data_indent - key.to_s.length) + ' = ' + value.inspect
96
- end
97
- end
98
- end
99
-
100
- true
101
- end
102
-
103
- def []=(*args)
104
- len = args.length
105
- raise ArgumentError, "wrong number of arguments (#{len} for 2)", caller(1) if len != 2
106
- modifiable[new_ostruct_member(args[0].to_sym)] = args[1]
107
- end
108
-
109
- def method_missing(mid, *args) # :nodoc:
110
- mname = mid.id2name
111
- len = args.length
112
- if mname.chomp!('=')
113
- raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1) if len != 1
114
- # Set up an instance method to point to the key/value in the table and set the value
115
- modifiable[new_ostruct_member(mname.to_sym)] = args[0]
116
- elsif @table.has_key?(mid)
117
- # The table has apparently been modified externally, so we need to set up
118
- # an instance method to point to the key/value in the table.
119
- new_ostruct_member(mname.to_sym)
120
- self.send(mid)
121
- else
122
- nil
123
- end
124
- end
125
- end
1
+ require 'fancy-open-struct'
@@ -5,6 +5,12 @@ require 'pry'
5
5
 
6
6
  if ENV['COVERAGE'] == 'true'
7
7
  require 'simplecov'
8
+ require 'coveralls'
9
+
10
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
11
+ SimpleCov::Formatter::HTMLFormatter,
12
+ Coveralls::SimpleCov::Formatter
13
+ ]
8
14
  SimpleCov.start
9
15
  end
10
16
 
@@ -13,6 +19,7 @@ end
13
19
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
14
20
 
15
21
  RSpec.configure do |config|
16
- config.filter_run focus: true
22
+ config.treat_symbols_as_metadata_keys_with_true_values = true
17
23
  config.run_all_when_everything_filtered = true
24
+ config.filter_run :focus
18
25
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fancy-open-struct
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,10 +9,10 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-05-26 00:00:00.000000000 Z
12
+ date: 2014-05-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: rspec
15
+ name: bundler
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
@@ -28,7 +28,23 @@ dependencies:
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
30
  - !ruby/object:Gem::Dependency
31
- name: bundler
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
32
48
  requirement: !ruby/object:Gem::Requirement
33
49
  none: false
34
50
  requirements:
@@ -75,12 +91,102 @@ dependencies:
75
91
  - - ! '>='
76
92
  - !ruby/object:Gem::Version
77
93
  version: '0'
78
- description: ! "FancyOpenStruct is a subclass of OpenStruct, and is a variant of RecursiveOpenStruct.\nIt
79
- differs from OpenStruct in that it allows nested hashes to be treated in a recursive\nfashion,
80
- and it also provides Hash methods for getting and setting values.\n\nFor example:\n\n
81
- \ fos = FancyOpenStruct.new({ :a => { :b => 'c' } })\n fos.a.b # 'c'\n\n fos.foo
82
- = 'bar'\n fos[:foo] # 'bar'\n\n fos.length # 2\n\nAlso, nested hashes can
83
- still be accessed as hashes:\n\n fos.a_as_a_hash # { :b => 'c' }\n\n"
94
+ - !ruby/object:Gem::Dependency
95
+ name: coveralls
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: guard
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: guard-rspec
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: guard-bundler
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: simplecov-multi
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ description: ! 'FancyOpenStruct is a subclass of OpenStruct, and is a variant of RecursiveOpenStruct.
175
+
176
+ This allows you to convert nested hashes into a structure where keys and values
177
+ can be
178
+
179
+ navigated and modified via dot-syntax, like: foo.bar = :something. This particular
180
+ gem
181
+
182
+ also adds support for Hash methods (such as length or merge), and also allows you
183
+ to
184
+
185
+ access and modify the data structure the same way that you would handle a normal
186
+ Hash.
187
+
188
+
189
+ '
84
190
  email: tchapin@gmail.com
85
191
  executables: []
86
192
  extensions: []
@@ -88,9 +194,11 @@ extra_rdoc_files:
88
194
  - LICENSE.txt
89
195
  - README.rdoc
90
196
  files:
197
+ - .coveralls.yml
91
198
  - .document
92
199
  - .gitignore
93
200
  - .rspec
201
+ - .travis.yml
94
202
  - Gemfile
95
203
  - LICENSE.txt
96
204
  - README.rdoc