kv_accessor 0.1.0 → 0.1.1
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 +4 -4
- data/CHANGELOG.md +17 -0
- data/README.md +221 -0
- data/lib/kv_accessor.rb +98 -28
- data/lib/kv_accessor/version.rb +1 -1
- data/spec/lib/kv_accessor_spec.rb +62 -25
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a9825ad1d5e43106077b0948d9a7338ea0702554
|
4
|
+
data.tar.gz: f457ccbc9724f7e90ade499797c94c7d52ef7941
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d16a8b478d0431850f57dfab61efa763b99c5fa337dec5d13ba8093d9e8bce5c58af3c435e682b802475895de509134510858b0d463e6afbf06d9d5d16093b72
|
7
|
+
data.tar.gz: ed2ca4e9fe6f37f040e562f3238307b1f4261a34300402bf24a4a3bcc0d526bfc7269e0521e28b26bb2735dc5aa5de9ec433089b107e9893cb0fe6fb97f7f5e2
|
data/CHANGELOG.md
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Change Log
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
This project adheres to [Semantic Versioning](http://semver.org/).
|
4
|
+
|
5
|
+
## 0.1.1 - 2016-03-28
|
6
|
+
### Added
|
7
|
+
- README.md and CHANGELOG.md content.
|
8
|
+
|
9
|
+
### Changed
|
10
|
+
- `KvAccessor.kv_accessor`/`.kv_reader`/`.kv_writer` now return the hash of
|
11
|
+
`accessor_name => key` to have more meaning.
|
12
|
+
- Refactored/edited some of the specs.
|
13
|
+
|
14
|
+
### Fixed
|
15
|
+
- Some of the documentation
|
16
|
+
|
17
|
+
[Unreleased]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.1.0...HEAD
|
data/README.md
CHANGED
@@ -0,0 +1,221 @@
|
|
1
|
+
KvAccessor
|
2
|
+
==========
|
3
|
+
|
4
|
+
Define reader and writer accessor methods for an attribute/method that quacks
|
5
|
+
like a Hash (`respond_to?(:[])`).
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
class MyCar
|
9
|
+
extend KvAccessors
|
10
|
+
attr_accessor :details
|
11
|
+
|
12
|
+
kv_accessor :details, :make, 'model'
|
13
|
+
|
14
|
+
def initialize(details = {})
|
15
|
+
self.details = details
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
car = MyCar.new(:make => 'Chevrolet', 'model' => 'Camaro')
|
20
|
+
car.make #=> "Chevrolet"
|
21
|
+
car.model #=> "Camaro"
|
22
|
+
```
|
23
|
+
|
24
|
+
Installation
|
25
|
+
------------
|
26
|
+
|
27
|
+
Gem
|
28
|
+
|
29
|
+
```terminal
|
30
|
+
$ gem install kv_accessor
|
31
|
+
```
|
32
|
+
|
33
|
+
Bundler
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
gem 'kv_accessor'
|
37
|
+
```
|
38
|
+
|
39
|
+
Usage
|
40
|
+
-----
|
41
|
+
|
42
|
+
Easily encapsulate Hash like objects.
|
43
|
+
|
44
|
+
The reader/writer can be named separately from the `#[]`/`#[]=` key via an
|
45
|
+
alias_accessors argument (this allows for aliasing of complex keys or class
|
46
|
+
differences like Symbol vs. String).
|
47
|
+
|
48
|
+
No initializer is implemented, so any needed initialization is up to the owner.
|
49
|
+
|
50
|
+
A word of warning: `#inspect` is called on the `:[]` key the implimentation is
|
51
|
+
via `class_eval`. `#to_s` is called on the passed `method` name and the method
|
52
|
+
is called without regard to the receiver (eg. a Kernel method can be called
|
53
|
+
if no instance method overrides it).
|
54
|
+
|
55
|
+
No guarding against user input exists. Only values should come from user input.
|
56
|
+
|
57
|
+
Meant as a DSL for creating value style objects that encapsulate a Hash object
|
58
|
+
so as to avoid inheriting from Hash/OpenStruct. Take a look at Struct,
|
59
|
+
OpenStruct, and [Virtus](https://github.com/solnic/virtus) for alternatives with
|
60
|
+
other features.
|
61
|
+
|
62
|
+
An extended example:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
class MyCar
|
66
|
+
attr_accessor :details
|
67
|
+
extend KvAccessors
|
68
|
+
|
69
|
+
kv_accessor :details, :make, :year => 'model_year',
|
70
|
+
:blue_interior_cost => { 'leather' => 'blue' }
|
71
|
+
kv_reader :details, 'model', :ac?, :seats
|
72
|
+
kv_writer :details, 'price'
|
73
|
+
|
74
|
+
def initialize(details = {})
|
75
|
+
self.details = details
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
c = MyCar.new(:make => 'Chevrolet', 'model' => 'Camaro', 'model_year' => 1967,
|
80
|
+
'submodel' => 'SS', 'price' => 20_000.00, :ac? => true,
|
81
|
+
:seats => 4, { 'leather' => 'blue' } => 2_000.00)
|
82
|
+
c.make
|
83
|
+
#=> "Chevrolet"
|
84
|
+
c.model
|
85
|
+
#=> "Camaro"
|
86
|
+
|
87
|
+
# Even though the 'submodel' is a part of 'details', all the attributes need to
|
88
|
+
# be specified.
|
89
|
+
c.submodel
|
90
|
+
#=> NoMethodError
|
91
|
+
|
92
|
+
# '#model' was defined as a kv_reader only
|
93
|
+
c.model = 'Corvette'
|
94
|
+
#=> NoMethodError
|
95
|
+
|
96
|
+
# Full on accessor
|
97
|
+
c.year
|
98
|
+
#=> 1967
|
99
|
+
c.year = 1968
|
100
|
+
#=> 1968
|
101
|
+
c.year
|
102
|
+
#=> 1968
|
103
|
+
c.details['model_year']
|
104
|
+
#=> 1968
|
105
|
+
|
106
|
+
# Using a complex key with alias.
|
107
|
+
# This example is a little contrived, but this has plenty of uses, like using
|
108
|
+
# classes as keys.
|
109
|
+
# This example key lookup would be:
|
110
|
+
# 'details[{ 'leather' => 'blue' }]'
|
111
|
+
c.blue_interior_cost
|
112
|
+
#=> 2_000.00
|
113
|
+
c.blue_interior_cost = 4_000.00
|
114
|
+
#=> 4_000.00
|
115
|
+
c.details[{ 'leather' => 'blue' }]
|
116
|
+
#=> 4_000.00
|
117
|
+
|
118
|
+
# kv_writer with no reader present
|
119
|
+
c.price
|
120
|
+
#=> NoMethodError
|
121
|
+
c.price = 25_000.00
|
122
|
+
#=> 25_000.00
|
123
|
+
c.details['price']
|
124
|
+
#=> 25_000.00
|
125
|
+
|
126
|
+
c.details
|
127
|
+
#=> { :make => "Chevrolet", "model" => "Camaro", "model_year" => 1967,
|
128
|
+
# "submodel" => "SS", { "leather" => "blue" } => 4_000.00,
|
129
|
+
# "price" => 25_000.00}
|
130
|
+
```
|
131
|
+
|
132
|
+
Can be used for whatever attributes respond to '#[]'/'#[]='.
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
class Employee < ActiveRecord::Base
|
136
|
+
store :settings, coder: JSON
|
137
|
+
has_one :office
|
138
|
+
extend KvAccessors
|
139
|
+
|
140
|
+
# Could just use a normal delegator here, but this shows any object with a
|
141
|
+
# '#[]'/'#[]=' can work since ActiveRecord models define a '#[]' interface
|
142
|
+
# for their columns.
|
143
|
+
kv_reader :office, 'chair', 'table'
|
144
|
+
|
145
|
+
# Define for as many attributes as you like
|
146
|
+
kv_accessor :settings, 'wallpaper', :language
|
147
|
+
|
148
|
+
after_initialize { settings ||= {} }
|
149
|
+
end
|
150
|
+
|
151
|
+
c = Employee.new
|
152
|
+
|
153
|
+
# Since an '#office' hasn't been assigned yet, this will try to call '#[]' on
|
154
|
+
# nil. Best to always set a default like 'settings' in 'after_initialize'.
|
155
|
+
c.chair
|
156
|
+
#=> NoMethodError
|
157
|
+
|
158
|
+
c.office = Office.new(chair: true, table: false)
|
159
|
+
c.chair
|
160
|
+
#=> true
|
161
|
+
|
162
|
+
c.wallpaper = 'birdy'
|
163
|
+
```
|
164
|
+
|
165
|
+
Since the kv_accessor/reader/writer methods return a hash, an easy pattern to
|
166
|
+
manage the accessors during runtime would be to assign the result to a const.
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
class MyCar
|
170
|
+
extend KvAccessors
|
171
|
+
|
172
|
+
attr_accessor :details
|
173
|
+
|
174
|
+
# The kv_* methods return a hash of 'attribute_name => key' for convenience.
|
175
|
+
# I like to use this to easily filter out keys in the initializer.
|
176
|
+
SERIALIZABLE_ACCESSORS =
|
177
|
+
kv_accessor :details, :make, :year => 'model_year',
|
178
|
+
:blue_interior_cost => { 'leather' => 'blue' }
|
179
|
+
|
180
|
+
SERIALIZABL_READERS = SERIALIZABLE_ACCESSORS.merge(
|
181
|
+
kv_writer :details, 'model'
|
182
|
+
)
|
183
|
+
|
184
|
+
SERIALIZABLE_WRITERS = SERIALIZABLE_ACCESSORS.merge(
|
185
|
+
kv_writer :details, 'price'
|
186
|
+
)
|
187
|
+
|
188
|
+
def initialize(details = {})
|
189
|
+
self.details = details
|
190
|
+
end
|
191
|
+
|
192
|
+
def serializable_hash
|
193
|
+
ACCESSORS.merge(READERS).merge(WRITERS)
|
194
|
+
.map { |name, key| [name.to_s, details[key]] }.to_h
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
c = Car.new(:make => 'Chevrolet', 'model' => 'Camaro', 'model_year' => 1967,
|
199
|
+
'submodel' => 'SS', 'price' => 25_000.00,
|
200
|
+
{ 'leather' => 'blue' } => 4000.00)
|
201
|
+
|
202
|
+
c.serializable_hash
|
203
|
+
#=> { "make" => "Chevrolet", "model" => "Camaro", "year" => 1967,
|
204
|
+
# "blue_interior_cost" => 4000.00, "price" => 25_000.00}
|
205
|
+
```
|
206
|
+
|
207
|
+
Resources
|
208
|
+
---------
|
209
|
+
|
210
|
+
[rubydoc.info documentation](http://www.rubydoc.info/gems/kv_accessor)
|
211
|
+
|
212
|
+
Contributing
|
213
|
+
------------
|
214
|
+
|
215
|
+
Normal github PR flow.
|
216
|
+
|
217
|
+
|
218
|
+
LICENSE
|
219
|
+
-------
|
220
|
+
|
221
|
+
3 Clause BSD
|
data/lib/kv_accessor.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# Define reader and writer accessors for a Hash like instance method.
|
2
2
|
#
|
3
3
|
# Define reader and writer methods for a method returning a duck that quacks
|
4
|
-
# like a Hash (`respond_to?(:[]`). The reader/writer can be named separately
|
5
|
-
# from the '
|
6
|
-
# of complex keys).
|
4
|
+
# like a Hash (`respond_to?(:[])`). The reader/writer can be named separately
|
5
|
+
# from the '#[]'/'#[]=' key via the alias_accessors argument (this allows for
|
6
|
+
# aliasing of complex keys or types).
|
7
7
|
#
|
8
8
|
# A word of warning: '#inspect' is called on the ':[]' key,
|
9
9
|
# '#to_s' is called on the 'key' name and the implimentation is via
|
@@ -11,8 +11,10 @@
|
|
11
11
|
# is called without regard to the receiver (eg. a Kernel method can be called
|
12
12
|
# if no instance method overrides it).
|
13
13
|
#
|
14
|
-
#
|
15
|
-
#
|
14
|
+
# Meant as a DSL for creating value style objects that encapsulate a Hash object
|
15
|
+
# so as to avoid hacks like inheriting from Hash/OpenStruct. Take a look at
|
16
|
+
# Struct, OpenStruct, and [Virtus](https://github.com/solnic/virtus) for
|
17
|
+
# alternatives with other features.
|
16
18
|
#
|
17
19
|
# @example
|
18
20
|
# class MyCar
|
@@ -20,7 +22,7 @@
|
|
20
22
|
# extend KvAccessors
|
21
23
|
# kv_accessor :details, :make, year: 'model_year',
|
22
24
|
# options: { 'leather' => 'blue' }
|
23
|
-
# kv_reader 'model'
|
25
|
+
# kv_reader :details, 'model'
|
24
26
|
#
|
25
27
|
# def initialize(details = {})
|
26
28
|
# @details = details
|
@@ -96,28 +98,42 @@ module KvAccessor
|
|
96
98
|
# c.details
|
97
99
|
# #=> { :make => "Chevrolet", "model" => "Camaro", :model_year => 1968,
|
98
100
|
# # "submodel" => "SS"
|
101
|
+
#
|
102
|
+
# @param keys [#to_s] used for both the key and the attribute name
|
103
|
+
# @param aliased_accessors [Hash< #to_s, #inspect >] the key of
|
104
|
+
# aliased_accessors is used as the attribute method name and the value of
|
105
|
+
# aliased_accessors is used as the first argument to `#[]`/`#[]=` off
|
106
|
+
# `method`
|
107
|
+
#
|
108
|
+
# @return [Hash] all the attribute name => method[key] so this method can be
|
109
|
+
# meaningfully chained.
|
110
|
+
# @example
|
111
|
+
# class Employee
|
112
|
+
# attr_accessor :info
|
113
|
+
# ATTRIBUTES = kv_accessor :info, :ssid, :dob
|
114
|
+
#
|
115
|
+
# def initalize(info)
|
116
|
+
# self.info = info.select { |k, v| ATTRIBUTES.key?(k) }
|
117
|
+
# end
|
118
|
+
# end
|
99
119
|
def kv_accessor(method, *keys, **aliased_accessors)
|
100
|
-
kv_reader(method, *keys, **aliased_accessors)
|
101
|
-
|
120
|
+
kv_reader(method, *keys, **aliased_accessors).merge(
|
121
|
+
kv_writer(method, *keys, **aliased_accessors)
|
122
|
+
)
|
102
123
|
end
|
103
124
|
|
104
125
|
# Define reader accessors for a Hash like instance method.
|
105
126
|
#
|
106
|
-
# Define reader accessor methods for each
|
107
|
-
# the key name can be defined via +aliased_accessors+. Calls to
|
108
|
-
#
|
109
|
-
# +aliased_accessors+.
|
110
|
-
#
|
111
|
-
# See the overall {KvAccessors} docs for a better definition of what gets
|
112
|
-
# called on what.
|
113
|
-
#
|
114
|
-
# This is not guarded against any sort of user input. You have been warned.
|
127
|
+
# Define reader accessor methods for each keys+. Accessors named other than
|
128
|
+
# the key name can be defined via +aliased_accessors+. Calls to either a
|
129
|
+
# +keys+ attribute name or the key of +aliased_accessor+ will call ':[]' off
|
130
|
+
# of +method+ with either +key+ or the value described via +aliased_accessors+.
|
115
131
|
#
|
116
132
|
# @example
|
117
133
|
# class MyCar
|
118
134
|
# attr_accessor :details
|
119
135
|
# extend KvAccessors
|
120
|
-
#
|
136
|
+
# kv_reader :details, :make, 'model', year: :model_year
|
121
137
|
#
|
122
138
|
# def initialize(details = {})
|
123
139
|
# @details = details
|
@@ -129,12 +145,40 @@ module KvAccessor
|
|
129
145
|
# c.make #=> "Chevrolet"
|
130
146
|
# c.model #=> "Camaro"
|
131
147
|
# c.year #=> 1967
|
132
|
-
# c.year = 1968
|
133
|
-
# c.year #=> 1968
|
148
|
+
# c.year = 1968 #=> NoMethodError
|
134
149
|
# c.submodel #=> NoMethodError
|
135
150
|
# c.details
|
136
|
-
# #=> { :make => "Chevrolet", "model" => "Camaro", :model_year =>
|
151
|
+
# #=> { :make => "Chevrolet", "model" => "Camaro", :model_year => 1967,
|
137
152
|
# "submodel" => "SS" }
|
153
|
+
#
|
154
|
+
# See the overall {KvAccessors} docs for a better definition of what gets
|
155
|
+
# called on what.
|
156
|
+
#
|
157
|
+
# This is not guarded against any sort of user input. You have been warned.
|
158
|
+
#
|
159
|
+
# @see kv_accessor
|
160
|
+
#
|
161
|
+
# @param keys [#to_s] used for both the key and the attribute name
|
162
|
+
# @param aliased_accessors [Hash< #to_s, #inspect >] the key of
|
163
|
+
# aliased_accessors is used as the attribute method name and the value of
|
164
|
+
# aliased_accessors is used as the argument to `#[]` off `method`
|
165
|
+
#
|
166
|
+
# @return [Hash] all the attribute name => method[key] so this method can be
|
167
|
+
# meaningfully chained.
|
168
|
+
# @example
|
169
|
+
# class Employee
|
170
|
+
# attr_accessor :info
|
171
|
+
# ATTRIBUTES = kv_reader :info, :ssid, :birth
|
172
|
+
#
|
173
|
+
# def initalize(info)
|
174
|
+
# self.info = info.select { |k, v| ATTRIBUTES.key?(k) }
|
175
|
+
# end
|
176
|
+
# end
|
177
|
+
# employee = Employee.new(ssid: '123-456-7890', birth: '1979-06-23',
|
178
|
+
# eye_color: 'brown')
|
179
|
+
# employee.birth #=> '1979-06-23'
|
180
|
+
# employee.info
|
181
|
+
# #=> { ssid: '123-456-7890', birth: '1979-06-23' }
|
138
182
|
def kv_reader(method, *keys, **aliased_accessors)
|
139
183
|
accessors = Hash[keys.map { |v| [v, v] }].merge(aliased_accessors)
|
140
184
|
accessors.each do |name, key|
|
@@ -157,15 +201,11 @@ module KvAccessor
|
|
157
201
|
# Define writter accessors for a Hash like instance method.
|
158
202
|
#
|
159
203
|
# Define writter accessor methods for each +keys+. Accessors named other than
|
160
|
-
# the key name can be defined via +aliased_accessors+. Calls to
|
161
|
-
#
|
204
|
+
# the key name can be defined via +aliased_accessors+. Calls to either a
|
205
|
+
# +keys+ attribute name or the key of +aliased_accessor+ will call '#:[]=' off
|
206
|
+
# of +method+ with either +key+ or the value described via
|
162
207
|
# +aliased_accessors+.
|
163
208
|
#
|
164
|
-
# See the overall {KvAccessors} docs for a better definition of what gets
|
165
|
-
# called on what.
|
166
|
-
#
|
167
|
-
# This is not guarded against any sort of user input. You have been warned.
|
168
|
-
#
|
169
209
|
# @example
|
170
210
|
# class MyCar
|
171
211
|
# attr_accessor :details
|
@@ -193,6 +233,36 @@ module KvAccessor
|
|
193
233
|
# c.details
|
194
234
|
# #=> { :make => "Chevrolet", "model" => "Corvette", :model_year => 1968,
|
195
235
|
# # "submodel" => "SS"
|
236
|
+
#
|
237
|
+
# See the overall {KvAccessors} docs for a better definition of what gets
|
238
|
+
# called on what.
|
239
|
+
#
|
240
|
+
# This is not guarded against any sort of user input. You have been warned.
|
241
|
+
#
|
242
|
+
# @see kv_accessor
|
243
|
+
#
|
244
|
+
# @param keys [#to_s] used for both the key and the attribute name
|
245
|
+
# @param aliased_accessors [Hash< #to_s, #inspect >] the key of
|
246
|
+
# aliased_accessors is used as the attribute method name and the value of
|
247
|
+
# aliased_accessors is used as the argument to `#[]=` off `method`
|
248
|
+
#
|
249
|
+
# @return [Hash] all the attribute name => method[key] so this method can be
|
250
|
+
# meaningfully chained.
|
251
|
+
# @example
|
252
|
+
# class Employee
|
253
|
+
# attr_accessor :info
|
254
|
+
# ATTRIBUTES = kv_writer :info, :ssid, :birth
|
255
|
+
#
|
256
|
+
# def initalize(info)
|
257
|
+
# self.info = info.select { |k, v| ATTRIBUTES.key?(k) }
|
258
|
+
# end
|
259
|
+
# end
|
260
|
+
#
|
261
|
+
# employee = Employee.new(ssid: '123-456-7890', birth: '1979-06-23',
|
262
|
+
# eye_color: 'brown')
|
263
|
+
# employee.ssid = '555-555-5555'
|
264
|
+
# employee.info
|
265
|
+
# #=> { ssid: '555-555-5555', birth: '1979-06-23' }
|
196
266
|
def kv_writer(method, *keys, **aliased_accessors)
|
197
267
|
accessors = Hash[keys.map { |v| [v, v] }].merge(aliased_accessors)
|
198
268
|
accessors.each do |name, key|
|
data/lib/kv_accessor/version.rb
CHANGED
@@ -16,12 +16,21 @@ RSpec.describe KvAccessor do
|
|
16
16
|
attr_accessor :details, :other
|
17
17
|
extend KvAccessor
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
# The self is required for consts in anonymous classes.
|
20
|
+
self::DETAILS_ACCESSORS =
|
21
|
+
kv_accessor :details, :make, year: 'model_year',
|
22
|
+
blue_interior: { 'leather' => 'blue' }
|
23
23
|
|
24
|
-
|
24
|
+
self::DETAILS_READERS = self::DETAILS_ACCESSORS.merge(
|
25
|
+
kv_reader :details, 'model', :price
|
26
|
+
)
|
27
|
+
|
28
|
+
self::DETAILS_WRITERS = self::DETAILS_ACCESSORS.merge(
|
29
|
+
kv_writer :details, 'color', :price
|
30
|
+
)
|
31
|
+
|
32
|
+
self::OTHER_ACCESSORS =
|
33
|
+
kv_accessor :other, :upc
|
25
34
|
|
26
35
|
def initialize(details, other)
|
27
36
|
self.details = details
|
@@ -33,46 +42,74 @@ RSpec.describe KvAccessor do
|
|
33
42
|
# For the expect to change, the duping is somehow necessary
|
34
43
|
subject(:data_object) { kv_class.new(default_details.dup, default_other.dup) }
|
35
44
|
|
36
|
-
it 'responds to all the accessor names' do
|
45
|
+
it 'responds to all the accessor names specified' do
|
37
46
|
expect(data_object).to respond_to(:make, :year, :blue_interior, :make=,
|
38
47
|
:year=, :blue_interior=, :model, :price,
|
39
48
|
:color=, :price=, :upc)
|
40
49
|
end
|
41
50
|
|
42
|
-
it 'does not respond to unspecified
|
51
|
+
it 'does not respond to unspecified readers/writers' do
|
43
52
|
expect(data_object).not_to respond_to(:submodel, :model=)
|
44
53
|
end
|
45
54
|
|
46
|
-
it '
|
55
|
+
it 'fetches all corresponding reader attributes' do
|
47
56
|
expect(data_object).to have_attributes(
|
48
57
|
make: 'Chevrolet', model: 'Camaro', blue_interior: 2_000.00,
|
49
58
|
price: 40_000.00, year: 1967, upc: '808'
|
50
59
|
)
|
51
60
|
end
|
52
61
|
|
53
|
-
|
54
|
-
|
55
|
-
# `change { }`, and `expect { }`. `change { }.from` doesn't seem to compare
|
56
|
-
# the objects first, before running the expect statement. I think it only
|
57
|
-
# saves the initial output, runs the expect statement, runs the change block
|
58
|
-
# again, and then finally compares the results. So any order dependent
|
59
|
-
# results need to be another copy.
|
60
|
-
expect {
|
62
|
+
describe 'attribute assignment' do
|
63
|
+
before do
|
61
64
|
data_object.make = 'Ford'
|
62
65
|
data_object.price = 41_000.00
|
63
66
|
data_object.year = 1968
|
64
67
|
data_object.blue_interior = 3_000.00
|
65
68
|
data_object.color = 'red'
|
66
69
|
data_object.upc = '809'
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
:make => 'Ford', :price => 41_000.00,
|
72
|
-
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'updates the specified key-value objects' do
|
73
|
+
expect(data_object).to have_attributes(
|
74
|
+
details: default_details.merge(:make => 'Ford', :price => 41_000.00,
|
75
|
+
'model_year' => 1968, 'color' => 'red',
|
76
|
+
{ 'leather' => 'blue' } => 3_000.00),
|
77
|
+
other: { upc: '809' }
|
73
78
|
)
|
74
|
-
|
75
|
-
|
76
|
-
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'all the updates are available via the attribute methods' do
|
82
|
+
expect(data_object).to have_attributes(
|
83
|
+
make: 'Ford', price: 41_000.00, year: 1968, blue_interior: 3_000.00,
|
84
|
+
upc: '809'
|
85
|
+
)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '.kv_accessor' do
|
90
|
+
it 'returns the hash of attributes for the kv_accessor' do
|
91
|
+
expect(
|
92
|
+
Class.new { extend KvAccessor }
|
93
|
+
.kv_accessor(:attributes, :mayonnaise, year: 'release date')
|
94
|
+
).to eq(mayonnaise: :mayonnaise, year: 'release date')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '.kv_reader' do
|
99
|
+
it 'returns the hash of attributes for the kv_reader' do
|
100
|
+
expect(
|
101
|
+
Class.new { extend KvAccessor }
|
102
|
+
.kv_reader(:attributes, :iscariot, release: 'born')
|
103
|
+
).to eq(iscariot: :iscariot, release: 'born')
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe '.kv_writer' do
|
108
|
+
it 'returns the hash of attributes for the kv_writer' do
|
109
|
+
expect(
|
110
|
+
Class.new { extend KvAccessor }
|
111
|
+
.kv_writer(:attributes, :adore, vocals: 'singers')
|
112
|
+
).to eq(adore: :adore, vocals: 'singers')
|
113
|
+
end
|
77
114
|
end
|
78
115
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kv_accessor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremiah McCann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -65,3 +65,4 @@ summary: Generate accessor methods for an indexed object
|
|
65
65
|
test_files:
|
66
66
|
- spec/lib/kv_accessor_spec.rb
|
67
67
|
- spec/spec_helper.rb
|
68
|
+
has_rdoc:
|