nested_accessors 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.
- checksums.yaml +15 -0
- data/.gitignore +21 -0
- data/Gemfile +6 -0
- data/LICENSE +22 -0
- data/README.md +142 -0
- data/Rakefile +10 -0
- data/lib/nested_accessors.rb +113 -0
- data/lib/nested_accessors/railtie.rb +9 -0
- data/lib/nested_accessors/version.rb +3 -0
- data/nested_accessors.gemspec +24 -0
- data/spec/nested_accessors_spec.rb +179 -0
- metadata +99 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NTlmMmU3YzY3YjFlYmU5NzFhMTJiNjIzOTE2Y2RhMzE4YTMxZmJjZg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MDlmMDI1Zjg4ZGE0NGM4ZDdjYzQ0ZTI1YjQ5ZDg0M2Y2MjAxMzZmMw==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
N2FkOTQ0ZWVlZDViNWY2NmZiMmI4YzRlODEzZWRhMDJmZmQwZWQyYzc3MmYy
|
10
|
+
MDA4NjIzMTlmZDNmMDBlYjVjZTRiNzUyOGRkNjlmMzY4NGQ4NGRjMGNjOTc3
|
11
|
+
ZTk0NmYzNTU1NTlkOTRmZjU4ZDhhMjdlY2FhNjNiMWJkYTA3YTM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZjkzODdiMDk5OWRmNDdlNGU5OTg2MDYxZTcyODdlOTNmZDE4NTkxYTBkZTZi
|
14
|
+
NDVhZDJiZjE3OGY0MGYzZWNjMDU0NGUyMmM2NjdmZjQ3MzQ5YzZlYTQ3Y2Fl
|
15
|
+
MDU2NzM4YzA2MTA4ZWZlYWM1OTdhZjNjZDdhZTM2MzBlMzEwNzA=
|
data/.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
.DS_Store
|
2
|
+
*.sublime*
|
3
|
+
.git-old
|
4
|
+
*.gem
|
5
|
+
*.rbc
|
6
|
+
.bundle
|
7
|
+
.config
|
8
|
+
.yardoc
|
9
|
+
Gemfile.lock
|
10
|
+
InstalledFiles
|
11
|
+
_yardoc
|
12
|
+
coverage
|
13
|
+
doc/
|
14
|
+
lib/bundler/man
|
15
|
+
pkg
|
16
|
+
rdoc
|
17
|
+
spec/reports
|
18
|
+
test/tmp
|
19
|
+
test/version_tmp
|
20
|
+
tmp
|
21
|
+
Readme.txt
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Oskar L-B
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
[](https://travis-ci.org/avocade/nested_accessors) [](https://codeclimate.com/github/avocade/nested_accessors)
|
2
|
+
|
3
|
+
NestedAccessors
|
4
|
+
==============
|
5
|
+
|
6
|
+
This class lets you quickly add serialized, nested hash accessors in ActiveRecord
|
7
|
+
model objects, using regular `text` database columns.
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
class Person < ActiveRecord::Base
|
11
|
+
include NestedAccessors
|
12
|
+
|
13
|
+
nested_accessor :info, [ :name, :phone ]
|
14
|
+
end
|
15
|
+
```
|
16
|
+
|
17
|
+
This would synthesize accessors to the `name` and `phone` properties contained
|
18
|
+
in the `info` hash.
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
foo = Foo.new
|
22
|
+
foo.name = "bar"
|
23
|
+
foo.phone = "+46-123-45678"
|
24
|
+
foo.info #=> { "name" => "bar", "phone" => "+46-123-45678" }
|
25
|
+
```
|
26
|
+
|
27
|
+
If we want just a single `name` accessor we can remove the array:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
nested_accessor :info, :name
|
31
|
+
```
|
32
|
+
|
33
|
+
|
34
|
+
Installation
|
35
|
+
------------
|
36
|
+
|
37
|
+
- Add the gem to your `Gemfile`:
|
38
|
+
|
39
|
+
source :rubygems
|
40
|
+
gem 'nested_accessors', :git => 'git@github.com:avocade/nested_accessors.git'
|
41
|
+
|
42
|
+
- Run `bundle install`
|
43
|
+
|
44
|
+
|
45
|
+
Dependencies
|
46
|
+
------------
|
47
|
+
|
48
|
+
Requires `ActiveRecord` for the `serialize` class method. _(To be
|
49
|
+
reconsidered.)_
|
50
|
+
|
51
|
+
|
52
|
+
Nested hash
|
53
|
+
------------
|
54
|
+
|
55
|
+
You can nest accessors one level deep. To add more than one
|
56
|
+
nested hash accessor to `address` we specify `street` and `city`
|
57
|
+
inside an array.
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
nested_accessor :info, address: [ :street, :city ]
|
61
|
+
```
|
62
|
+
|
63
|
+
This gives:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
object.address_street # these two are nested inside the "address" hash
|
67
|
+
object.address_city
|
68
|
+
```
|
69
|
+
|
70
|
+
To just specify just one accessor, eg `address[street]`, we can simplify:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
nested_accessor :info, address: street
|
74
|
+
```
|
75
|
+
|
76
|
+
**Note**: The hash keys are always strings, never symbols. This is for
|
77
|
+
consistency of input/output.
|
78
|
+
|
79
|
+
|
80
|
+
Testing
|
81
|
+
-------
|
82
|
+
|
83
|
+
Run the `minitest` specs using:
|
84
|
+
|
85
|
+
rake
|
86
|
+
|
87
|
+
|
88
|
+
TODO
|
89
|
+
-----
|
90
|
+
|
91
|
+
- Add assertion checking for args
|
92
|
+
- Switch to using `supermodel` gem for testing `active_model` serialize
|
93
|
+
dependency properly instead of stubbing it out
|
94
|
+
- Allow setting default value for each accessor, eg `last_name: "Doe"`
|
95
|
+
- Create object wrappers for each nested hash, so can get accessors like `person.address.street` for `person[address][street]`
|
96
|
+
- Add two-level nesting, eg `foo[bar][name][surname]`
|
97
|
+
- Array with nested Hash objects inside, eg `foo[bar][1][name]`
|
98
|
+
- Perhaps switch convention to always use symbolic keys instead of
|
99
|
+
stringified keys, so can use new ruby 1.9 hash syntax:
|
100
|
+
|
101
|
+
foo.info = { name: "Anders" }
|
102
|
+
foo.info[:name]
|
103
|
+
|
104
|
+
- Add typed arguments for each accessor (defaults to `String`)
|
105
|
+
|
106
|
+
nested_accessor :info, phone: Integer
|
107
|
+
|
108
|
+
Author
|
109
|
+
------
|
110
|
+
|
111
|
+
Oskar Boethius Lissheim is a Product Designer and iOS & Ruby on Rails developer. He currently lives in Gothenburg, Sweden.
|
112
|
+
|
113
|
+
You can reach him on App.net at
|
114
|
+
[@avocade](http://alpha.app.net/avocade), or
|
115
|
+
[Twitter](http://twitter.com/avocade).
|
116
|
+
|
117
|
+
|
118
|
+
License
|
119
|
+
-------
|
120
|
+
|
121
|
+
This code is offered under the MIT License.
|
122
|
+
|
123
|
+
Copyright © 2012 Oskar Boethius Lissheim.
|
124
|
+
|
125
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
126
|
+
copy of this software and associated documentation files (the
|
127
|
+
"Software"), to deal in the Software without restriction, including
|
128
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
129
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
130
|
+
permit persons to whom the Software is furnished to do so, subject to
|
131
|
+
the following conditions:
|
132
|
+
|
133
|
+
The above copyright notice and this permission notice shall be included
|
134
|
+
in all copies or substantial portions of the Software.
|
135
|
+
|
136
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
137
|
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
138
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
139
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
140
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
141
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
142
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
require_relative "nested_accessors/version"
|
2
|
+
require_relative "nested_accessors/railtie" if defined? Rails
|
3
|
+
|
4
|
+
module NestedAccessors
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
##
|
11
|
+
# Creates new method +nested_accessor+ for adding dynamic accessors to nested hashes, using:
|
12
|
+
# <tt>nested_accessor :pz_settings, confirmation_token: String, subsettings: { foo: String, bar: Integer }</tt>
|
13
|
+
def nested_accessor(name, *args)
|
14
|
+
self.class_eval do
|
15
|
+
serialize name, Hash
|
16
|
+
end
|
17
|
+
|
18
|
+
args.each do |an_arg|
|
19
|
+
if an_arg.is_a? Hash
|
20
|
+
# nested_accessor :info, address: [:foo]
|
21
|
+
an_arg.each do |subroot,propnames|
|
22
|
+
if propnames.is_a? Array # eg "address: [:city, :zipcode]"
|
23
|
+
define_first_level_nesting_methods_for_subroot(name, subroot, Hash, propnames)
|
24
|
+
elsif propnames == Array # eg "address: Array"
|
25
|
+
define_first_level_nesting_methods_for_subroot(name, subroot, Array)
|
26
|
+
elsif propnames.is_a? Symbol # eg "auth: :facebook"
|
27
|
+
define_first_level_nesting_methods_for_subroot(name, subroot, Hash, [propnames])
|
28
|
+
elsif propnames.is_a? Hash # eg "subregion: { address: [:street, :city] }"
|
29
|
+
propnames.each do |subsubroot,subpropnames|
|
30
|
+
define_first_level_nesting_methods_for_subroot(name, subroot, Hash, [subsubroot])
|
31
|
+
define_second_level_nesting_methods(subroot, subsubroot, subpropnames)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
elsif an_arg.is_a? Array
|
36
|
+
an_arg.each do |a_propname|
|
37
|
+
define_first_level_nesting_methods_for_property(name, a_propname)
|
38
|
+
end
|
39
|
+
elsif an_arg.is_a? Symbol
|
40
|
+
define_first_level_nesting_methods_for_property(name, an_arg)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# HELPER METHODS
|
48
|
+
def define_first_level_nesting_methods_for_property(root, propname)
|
49
|
+
class_eval <<-RUBY, __FILE__, __LINE__+1
|
50
|
+
def #{propname}=(val)
|
51
|
+
#{root}.store("#{propname}", val.to_s)
|
52
|
+
end
|
53
|
+
|
54
|
+
def #{propname}
|
55
|
+
#{root}.store("#{propname}", nil) unless (#{root}.has_key?("#{propname}"))
|
56
|
+
#{root}.fetch "#{propname}"
|
57
|
+
end
|
58
|
+
RUBY
|
59
|
+
end
|
60
|
+
|
61
|
+
def define_first_level_nesting_methods_for_subroot(root, subroot, subroot_type, propnames=nil)
|
62
|
+
subroot_value = case subroot_type.to_s
|
63
|
+
when "Array" then []
|
64
|
+
else {}
|
65
|
+
end
|
66
|
+
|
67
|
+
class_eval <<-RUBY, __FILE__, __LINE__+1
|
68
|
+
def #{subroot}
|
69
|
+
#{root}.store("#{subroot}", #{subroot_value}) unless (#{root}.has_key?("#{subroot}") and #{root}.fetch("#{subroot}").is_a?(#{subroot_value}.class))
|
70
|
+
#{root}.fetch "#{subroot}"
|
71
|
+
end
|
72
|
+
RUBY
|
73
|
+
|
74
|
+
if propnames
|
75
|
+
propnames.each do |a_propname|
|
76
|
+
self.class_eval <<-RUBY, __FILE__, __LINE__+1
|
77
|
+
def #{subroot}_#{a_propname}=(val)
|
78
|
+
#{subroot}.store("#{a_propname}".to_s, val.to_s)
|
79
|
+
end
|
80
|
+
|
81
|
+
def #{subroot}_#{a_propname}
|
82
|
+
#{subroot}.store("#{a_propname}", nil) unless (#{subroot}.has_key?("#{a_propname}"))
|
83
|
+
#{subroot}.fetch "#{a_propname}".to_s
|
84
|
+
end
|
85
|
+
RUBY
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def define_second_level_nesting_methods(subroot, subsubroot, propnames)
|
91
|
+
self.class_eval <<-RUBY, __FILE__, __LINE__+1
|
92
|
+
def #{subroot}_#{subsubroot}
|
93
|
+
#{subroot}.store("#{subsubroot}", {}) unless (#{subroot}.has_key?("#{subsubroot}") and #{subroot}.fetch("#{subsubroot}").is_a?(Hash))
|
94
|
+
#{subroot}.fetch "#{subsubroot}"
|
95
|
+
end
|
96
|
+
RUBY
|
97
|
+
|
98
|
+
if propnames
|
99
|
+
propnames.each do |a_propname|
|
100
|
+
self.class_eval <<-RUBY, __FILE__, __LINE__+1
|
101
|
+
def #{subroot}_#{subsubroot}_#{a_propname}=(val)
|
102
|
+
#{subroot}_#{subsubroot}.store("#{a_propname}", val.to_s)
|
103
|
+
end
|
104
|
+
|
105
|
+
def #{subroot}_#{subsubroot}_#{a_propname}
|
106
|
+
#{subroot}_#{subsubroot}.store("#{a_propname}", nil) unless (#{subroot}_#{subsubroot}.has_key?("#{a_propname}"))
|
107
|
+
#{subroot}_#{subsubroot}.fetch "#{a_propname}"
|
108
|
+
end
|
109
|
+
RUBY
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/nested_accessors/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Oskar Boethius Lissheim"]
|
6
|
+
gem.email = ["oskar@OLBproductions.com"]
|
7
|
+
gem.homepage = "http://OLBproductions.com"
|
8
|
+
gem.description = %q{Quickly add serialized, nested hash accessors in ActiveRecord model objects}
|
9
|
+
gem.summary = %q{Without having to write your own accessor methods for getting at serialized hash properties}
|
10
|
+
gem.homepage = "http://OLBproductions.com"
|
11
|
+
gem.license = 'MIT'
|
12
|
+
|
13
|
+
gem.files = `git ls-files`.split($\)
|
14
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
15
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
16
|
+
gem.name = "nested_accessors"
|
17
|
+
gem.require_paths = ["lib"]
|
18
|
+
gem.version = NestedAccessors::VERSION
|
19
|
+
gem.extra_rdoc_files = ['README.md']
|
20
|
+
|
21
|
+
gem.add_development_dependency "minitest"
|
22
|
+
gem.add_development_dependency "simple_mock"
|
23
|
+
gem.add_development_dependency "minitest-colorize"
|
24
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'minitest/spec'
|
3
|
+
require 'simple_mock'
|
4
|
+
require 'minitest-colorize'
|
5
|
+
|
6
|
+
require_relative '../lib/nested_accessors'
|
7
|
+
|
8
|
+
# STUBBING OUT active_record "serialized" class method
|
9
|
+
class Person #< ActiveRecord::Base # must inherit from activerecord to get "serialize" class method
|
10
|
+
# Stubs out the "serialize :name, Hash" method
|
11
|
+
# So don't have to use activerecord
|
12
|
+
# Creates eg a :info hash accessor and returns hash
|
13
|
+
def self.serialize(name, klass)
|
14
|
+
attr_accessor name
|
15
|
+
define_method name do
|
16
|
+
@serialized_hash = {} if @serialized_hash.nil?
|
17
|
+
@serialized_hash
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# must include module after the serialize method has been defined (it's defined in the superclass when inherited from activerecord)
|
22
|
+
include NestedAccessors
|
23
|
+
|
24
|
+
# USAGE in active_record model:
|
25
|
+
# nested_accessor :info, :phone, address: [ :street, :zipcode ]
|
26
|
+
end
|
27
|
+
|
28
|
+
# SPECS
|
29
|
+
describe NestedAccessors do
|
30
|
+
describe 'init method for hash accessors' do
|
31
|
+
it 'should init root object to Hash if blank or not a Hash' do
|
32
|
+
Person.class_eval %q{ nested_accessor :info }
|
33
|
+
Person.new.info.class.must_equal Hash
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "with phone accessor" do
|
37
|
+
before(:each) do
|
38
|
+
Person.class_eval %q{ nested_accessor :info, :phone }
|
39
|
+
end
|
40
|
+
|
41
|
+
let(:person) { Person.new }
|
42
|
+
|
43
|
+
it 'should use stringified keys' do
|
44
|
+
person.phone = "12378"
|
45
|
+
person.info.keys.must_include "phone"
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should init key to nil if blank' do
|
49
|
+
person.info.keys.must_be_empty
|
50
|
+
person.phone.must_be_nil # shouldn't raise exception since it couldn't find the key
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'sets up accessors for first level of nesting' do
|
54
|
+
person.phone = "123-2345"
|
55
|
+
person.phone.must_equal "123-2345"
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'read accessor should return value typed to String by default (to_s)' do
|
59
|
+
person.phone = 123
|
60
|
+
person.phone.must_equal "123"
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'write accessor should save value typed to String' do
|
64
|
+
person.phone = 234
|
65
|
+
person.info["phone"].must_equal "234"
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'each subvalue should be nil if regular value param' do
|
69
|
+
person.info["phone"].must_be_nil
|
70
|
+
person.info["address"].must_be_nil
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'can set multiple properties if first param is Array type' do
|
74
|
+
Person.class_eval %q{ nested_accessor :info, [:phone1, :phone2] }
|
75
|
+
person = Person.new
|
76
|
+
person.info["phone1"] = "2365"
|
77
|
+
person.phone1.must_equal "2365"
|
78
|
+
person.phone2 = "9090"
|
79
|
+
person.info["phone2"].must_equal "9090"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'subhashes' do
|
84
|
+
it 'should init as hash if gets Array with multiple params for a property name in Hash' do
|
85
|
+
# Gives self.info["address"]["street"] and ["city"]
|
86
|
+
Person.class_eval %q{ nested_accessor :info, address: [:street, :city] }
|
87
|
+
person = Person.new
|
88
|
+
person.address.must_be_kind_of Hash
|
89
|
+
person.address["city"] = "Goteborg"
|
90
|
+
person.address["city"].must_equal "Goteborg"
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should init subhash to nil value if blank' do
|
94
|
+
Person.class_eval %q{ nested_accessor :info, address: [:street, :city] }
|
95
|
+
person = Person.new
|
96
|
+
person.address.must_be_kind_of Hash
|
97
|
+
person.address_street.must_be_nil # shouldn't raise exception since it couldn't find the key
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should init with just one param in array' do
|
101
|
+
Person.class_eval %q{ nested_accessor :info, snub: [:identifier] }
|
102
|
+
person = Person.new
|
103
|
+
person.snub.must_be_kind_of Hash
|
104
|
+
person.snub_identifier = "Achaplan"
|
105
|
+
person.snub_identifier.must_equal "Achaplan"
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should init with just one param symbol in hash as well' do
|
109
|
+
Person.class_eval %q{ nested_accessor :info, auth: :facebook }
|
110
|
+
person = Person.new
|
111
|
+
person.auth.must_be_kind_of Hash
|
112
|
+
person.auth_facebook = "12k3j"
|
113
|
+
person.auth_facebook.must_equal "12k3j"
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should create shallow accessor methods for each hash propname' do
|
117
|
+
Person.class_eval %q{ nested_accessor :bank, branch: [:designator, :account_number] }
|
118
|
+
person = Person.new
|
119
|
+
person.branch.must_be_kind_of Hash
|
120
|
+
person.branch_designator = "123"
|
121
|
+
person.branch_designator.must_equal "123"
|
122
|
+
person.branch_account_number = "999"
|
123
|
+
person.branch_account_number.must_equal "999"
|
124
|
+
end
|
125
|
+
|
126
|
+
# it 'should perhaps create accessor methods on the subroot object, for each subparam in hash' do
|
127
|
+
# Person.class_eval %q{ nested_accessor :info, address: [:street, :city] }
|
128
|
+
# person = Person.new
|
129
|
+
# person.address.must_be_kind_of Hash
|
130
|
+
# # the subroot method must thus return an object and define attr_accessor methods on it for each propname
|
131
|
+
# person.address.street = "Storgatan"
|
132
|
+
# person.address.street.must_equal "Storgatan"
|
133
|
+
# person.address.city = "Bigtown"
|
134
|
+
# person.address.city.must_equal "Bigtown"
|
135
|
+
# end
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'should init subvalue with Array if type set to array for accessor' do
|
139
|
+
# nested_accessor :info, balls: Array
|
140
|
+
#=> self.info["Balls"] == []
|
141
|
+
Person.class_eval %q{ nested_accessor :things, balls: Array }
|
142
|
+
person = Person.new
|
143
|
+
person.balls.must_be_kind_of Array
|
144
|
+
person.balls << "bob"
|
145
|
+
person.balls << "alice"
|
146
|
+
person.balls.must_include "bob"
|
147
|
+
person.balls.must_include "alice"
|
148
|
+
end
|
149
|
+
|
150
|
+
describe 'second level nesting' do
|
151
|
+
it 'sets up accessors for two level deep hash' do
|
152
|
+
# nested_accessor :info, subregion: { address: [:street, :city] }
|
153
|
+
#=> foo.info[address][subregion] = {}
|
154
|
+
# Person.class_eval %q{ nested_accessor :home, subregion: { address: [:street, :city] } }
|
155
|
+
Person.class_eval %q{ nested_accessor :home, budget: { heating: [:highest, :lowest] } }
|
156
|
+
person = Person.new
|
157
|
+
person.budget_heating.must_be_kind_of Hash
|
158
|
+
person.budget.must_be_kind_of Hash
|
159
|
+
person.budget.has_key?("heating").must_equal true # can only test that hash has the key after we've used the subregion command since that instantiates the nested hash
|
160
|
+
person.budget_heating_highest = "32 C"
|
161
|
+
person.budget_heating_highest.must_equal "32 C"
|
162
|
+
person.budget_heating_lowest = "10 C"
|
163
|
+
person.budget_heating_lowest.must_equal "10 C"
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'should init deep hash values to nil value if blank' do
|
167
|
+
Person.class_eval %q{ nested_accessor :place, location: { coordinate: [:lat, :lon] } }
|
168
|
+
person = Person.new
|
169
|
+
person.location_coordinate.must_be_kind_of Hash
|
170
|
+
person.location_coordinate_lat.must_be_nil # shouldn't raise exception since it couldn't find the key
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'should set deep hash values and not overwrite others in the same subhash' do
|
174
|
+
# TODO: Must test so we don't just write a new hash when changing a value
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nested_accessors
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Oskar Boethius Lissheim
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-06-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: minitest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: simple_mock
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest-colorize
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Quickly add serialized, nested hash accessors in ActiveRecord model objects
|
56
|
+
email:
|
57
|
+
- oskar@OLBproductions.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files:
|
61
|
+
- README.md
|
62
|
+
files:
|
63
|
+
- .gitignore
|
64
|
+
- Gemfile
|
65
|
+
- LICENSE
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- lib/nested_accessors.rb
|
69
|
+
- lib/nested_accessors/railtie.rb
|
70
|
+
- lib/nested_accessors/version.rb
|
71
|
+
- nested_accessors.gemspec
|
72
|
+
- spec/nested_accessors_spec.rb
|
73
|
+
homepage: http://OLBproductions.com
|
74
|
+
licenses:
|
75
|
+
- MIT
|
76
|
+
metadata: {}
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ! '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubyforge_project:
|
93
|
+
rubygems_version: 2.0.3
|
94
|
+
signing_key:
|
95
|
+
specification_version: 4
|
96
|
+
summary: Without having to write your own accessor methods for getting at serialized
|
97
|
+
hash properties
|
98
|
+
test_files:
|
99
|
+
- spec/nested_accessors_spec.rb
|