attr_extras 3.2.0 → 4.0.0
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 +8 -8
- data/LICENSE.txt +22 -0
- data/README.md +69 -38
- data/lib/attr_extras.rb +5 -1
- data/lib/attr_extras/version.rb +1 -1
- data/spec/attr_implement_spec.rb +14 -2
- data/spec/method_object_spec.rb +8 -9
- data/spec/static_facade_spec.rb +29 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YTEzMGU2ZTk5YTFhZTRkOGRjN2NjMDNkYTU4MDM4NTVkNDExNmVkOQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MDZkNDRkNzc2MDMyOGUwMzVjODE1YmE5NGNkODNhMjY4YTM5NzZjYw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MWNjNjMyYjQ3ZTMyMDE5MTQwYWIyY2NjYzQxMjJkNTNjNTQxOGZhMzY2NjAw
|
10
|
+
MmZkM2U3NzNiOTBjMWVmYzQyODA4MzBhMWU3ODIyYmZkNjFjODRhYTAzOTlm
|
11
|
+
MGY0NjEzYWIxZjU5MDhlNjRmNDkzYmZlMWVjMmY0ODQ5MWY0YWI=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MWNiMmYwMDI5MDYzZjBjYWY2OGFhNTMyZWIyZjJjZDkzNDRlOWUxY2Q3NzNm
|
14
|
+
ZWJhYWViN2I5NmU1ZWY1OWFhODQ3NGEwOTY1YmE3MGZjNWY5YTU0NTY5YWU2
|
15
|
+
ODgwNjZmOGE2MjQzZmQ0MzE5ZDY5OTYyMzhjNjVlODk2NzMyMGQ=
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012-2014 Barsoom AB (http://barsoom.se)
|
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
CHANGED
@@ -83,18 +83,57 @@ attr_value :foo, :bar
|
|
83
83
|
The `attr_initialize` notation for hash arguments is also supported: `vattr_initialize :foo, [:bar, :baz!]`
|
84
84
|
|
85
85
|
|
86
|
-
### `
|
86
|
+
### `static_facade :fooable?, :foo`<br>
|
87
87
|
|
88
|
-
Defines a `.fooable?` class method that
|
88
|
+
Defines a `.fooable?` class method that delegates to an instance method by the same name, having first provided `foo` as a private reader.
|
89
89
|
|
90
|
-
This is
|
90
|
+
This is handy when a class-method API makes sense but you still want [the refactorability of instance methods](http://blog.codeclimate.com/blog/2012/11/14/why-ruby-class-methods-resist-refactoring/).
|
91
|
+
|
92
|
+
``` ruby
|
93
|
+
class PublishingPolicy
|
94
|
+
static_facade :allow?, :user
|
95
|
+
static_facade :disallow?, :user
|
96
|
+
|
97
|
+
def allow?
|
98
|
+
user.admin? && …
|
99
|
+
end
|
100
|
+
|
101
|
+
def disallow?
|
102
|
+
!allow?
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
PublishingPolicy.allow?(user)
|
107
|
+
```
|
108
|
+
|
109
|
+
`static_facade :fooable?, :foo` is a shortcut for
|
110
|
+
|
111
|
+
``` ruby
|
112
|
+
pattr_initialize :foo
|
113
|
+
|
114
|
+
def self.fooable?(foo)
|
115
|
+
new(foo).fooable?
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
The `attr_initialize` notation for hash arguments is also supported: `static_facade :fooable?, :foo, [:bar, :baz!]`
|
120
|
+
|
121
|
+
You don't have to specify arguments/readers if you don't want them: just `static_facade :fooable?` is also valid.
|
122
|
+
|
123
|
+
|
124
|
+
### `method_object :foo`
|
125
|
+
|
126
|
+
*NOTE: v4.0.0 made a breaking change! `static_facade` does exactly what `method_object` used to do; the new `method_object` no longer accepts a method name argument.*
|
127
|
+
|
128
|
+
Defines a `.call` class method that delegates to an instance method by the same name, having first provided `foo` as a private reader.
|
129
|
+
|
130
|
+
This is a special case of `static_facade` for when you want a [Method Object](http://refactoring.com/catalog/replaceMethodWithMethodObject.html), and the class name itself will communicate the action it performs.
|
91
131
|
|
92
132
|
``` ruby
|
93
133
|
class PriceCalculator
|
94
|
-
method_object :
|
95
|
-
:order
|
134
|
+
method_object :order
|
96
135
|
|
97
|
-
def
|
136
|
+
def call
|
98
137
|
total * factor
|
99
138
|
end
|
100
139
|
|
@@ -111,27 +150,30 @@ end
|
|
111
150
|
|
112
151
|
class Order
|
113
152
|
def price
|
114
|
-
PriceCalculator.
|
153
|
+
PriceCalculator.call(self)
|
115
154
|
end
|
116
|
-
|
117
|
-
# …
|
118
155
|
end
|
119
156
|
```
|
120
157
|
|
121
|
-
|
158
|
+
`method_object :foo` is a shortcut for
|
159
|
+
|
160
|
+
``` ruby
|
161
|
+
static_facade :call, :foo
|
162
|
+
```
|
163
|
+
|
164
|
+
which is a shortcut for
|
122
165
|
|
123
166
|
``` ruby
|
124
|
-
|
125
|
-
attr_private :foo
|
167
|
+
pattr_initialize :foo
|
126
168
|
|
127
|
-
def self.
|
128
|
-
new(foo).
|
169
|
+
def self.call(foo)
|
170
|
+
new(foo).call
|
129
171
|
end
|
130
172
|
```
|
131
173
|
|
132
|
-
The `attr_initialize` notation for hash arguments is also supported: `method_object :
|
174
|
+
The `attr_initialize` notation for hash arguments is also supported: `method_object :foo, [:bar, :baz!]`
|
133
175
|
|
134
|
-
You don't have to specify readers if you don't want them: `method_object
|
176
|
+
You don't have to specify arguments/readers if you don't want them: just `method_object` is also valid.
|
135
177
|
|
136
178
|
|
137
179
|
### `attr_id_query :foo?, :bar?`<br>
|
@@ -151,6 +193,16 @@ Defines nullary (0-argument) methods `foo` and `bar` that raise e.g. `"Implement
|
|
151
193
|
|
152
194
|
This is suitable for [abstract methods](http://en.wikipedia.org/wiki/Abstract_method#Abstract_methods) in base classes, e.g. when using the [template method pattern](http://en.wikipedia.org/wiki/Template_method_pattern).
|
153
195
|
|
196
|
+
It's more or less a shortcut for
|
197
|
+
|
198
|
+
``` ruby
|
199
|
+
def my_method
|
200
|
+
raise "Implement me in a subclass!"
|
201
|
+
end
|
202
|
+
```
|
203
|
+
|
204
|
+
though it is shorter, more declarative, gives you a clear message and handles edge cases you might not have thought about (see tests).
|
205
|
+
|
154
206
|
|
155
207
|
## Philosophy
|
156
208
|
|
@@ -211,25 +263,4 @@ Or to see warnings (try not to have any):
|
|
211
263
|
|
212
264
|
## License
|
213
265
|
|
214
|
-
|
215
|
-
|
216
|
-
MIT License
|
217
|
-
|
218
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
219
|
-
a copy of this software and associated documentation files (the
|
220
|
-
"Software"), to deal in the Software without restriction, including
|
221
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
222
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
223
|
-
permit persons to whom the Software is furnished to do so, subject to
|
224
|
-
the following conditions:
|
225
|
-
|
226
|
-
The above copyright notice and this permission notice shall be
|
227
|
-
included in all copies or substantial portions of the Software.
|
228
|
-
|
229
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
230
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
231
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
232
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
233
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
234
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
235
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
266
|
+
[MIT](LICENSE.txt)
|
data/lib/attr_extras.rb
CHANGED
@@ -46,7 +46,7 @@ module AttrExtras
|
|
46
46
|
attr_value(*Utils.flat_names(names))
|
47
47
|
end
|
48
48
|
|
49
|
-
def
|
49
|
+
def static_facade(method_name, *names)
|
50
50
|
define_singleton_method(method_name) do |*values|
|
51
51
|
new(*values).public_send(method_name)
|
52
52
|
end
|
@@ -54,6 +54,10 @@ module AttrExtras
|
|
54
54
|
pattr_initialize(*names)
|
55
55
|
end
|
56
56
|
|
57
|
+
def method_object(*names)
|
58
|
+
static_facade :call, *names
|
59
|
+
end
|
60
|
+
|
57
61
|
def attr_query(*names)
|
58
62
|
AttrQuery.define_with_suffix(self, "", *names)
|
59
63
|
end
|
data/lib/attr_extras/version.rb
CHANGED
data/spec/attr_implement_spec.rb
CHANGED
@@ -38,9 +38,13 @@ describe Object, ".attr_implement" do
|
|
38
38
|
subklass.new.foo.must_equal "bar"
|
39
39
|
end
|
40
40
|
|
41
|
-
# E.g. Active Record defines column query methods like "admin?"
|
41
|
+
# E.g. when Active Record defines column query methods like "admin?"
|
42
42
|
# higher up in the ancestor chain.
|
43
43
|
it "does not raise if method is implemented in a superclass" do
|
44
|
+
foo_interface = Module.new do
|
45
|
+
attr_implement :foo
|
46
|
+
end
|
47
|
+
|
44
48
|
superklass = Class.new do
|
45
49
|
def foo
|
46
50
|
"bar"
|
@@ -48,9 +52,17 @@ describe Object, ".attr_implement" do
|
|
48
52
|
end
|
49
53
|
|
50
54
|
klass = Class.new(superklass) do
|
51
|
-
|
55
|
+
include foo_interface
|
52
56
|
end
|
53
57
|
|
54
58
|
klass.new.foo.must_equal "bar"
|
55
59
|
end
|
60
|
+
|
61
|
+
it "does not mess up missing-method handling" do
|
62
|
+
klass = Class.new do
|
63
|
+
attr_implement :foo
|
64
|
+
end
|
65
|
+
|
66
|
+
lambda { klass.new.some_other_method }.must_raise NoMethodError
|
67
|
+
end
|
56
68
|
end
|
data/spec/method_object_spec.rb
CHANGED
@@ -1,29 +1,28 @@
|
|
1
1
|
require_relative "spec_helper"
|
2
2
|
|
3
3
|
describe Object, ".method_object" do
|
4
|
-
it "creates a class method that instantiates and runs
|
4
|
+
it "creates a .call class method that instantiates and runs the #call instance method" do
|
5
5
|
klass = Class.new do
|
6
|
-
method_object :
|
7
|
-
:foo
|
6
|
+
method_object :foo
|
8
7
|
|
9
|
-
def
|
8
|
+
def call
|
10
9
|
foo
|
11
10
|
end
|
12
11
|
end
|
13
12
|
|
14
|
-
assert klass.
|
15
|
-
refute klass.
|
13
|
+
assert klass.call(true)
|
14
|
+
refute klass.call(false)
|
16
15
|
end
|
17
16
|
|
18
17
|
it "doesn't require attributes" do
|
19
18
|
klass = Class.new do
|
20
|
-
method_object
|
19
|
+
method_object
|
21
20
|
|
22
|
-
def
|
21
|
+
def call
|
23
22
|
true
|
24
23
|
end
|
25
24
|
end
|
26
25
|
|
27
|
-
assert klass.
|
26
|
+
assert klass.call
|
28
27
|
end
|
29
28
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe Object, ".static_facade" do
|
4
|
+
it "creates a class method that instantiates and runs that instance method" do
|
5
|
+
klass = Class.new do
|
6
|
+
static_facade :fooable?,
|
7
|
+
:foo
|
8
|
+
|
9
|
+
def fooable?
|
10
|
+
foo
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
assert klass.fooable?(true)
|
15
|
+
refute klass.fooable?(false)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "doesn't require attributes" do
|
19
|
+
klass = Class.new do
|
20
|
+
static_facade :fooable?
|
21
|
+
|
22
|
+
def fooable?
|
23
|
+
true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
assert klass.fooable?
|
28
|
+
end
|
29
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attr_extras
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henrik Nyh
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2015-01-
|
13
|
+
date: 2015-01-16 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake
|
@@ -37,6 +37,7 @@ files:
|
|
37
37
|
- .rvmrc
|
38
38
|
- .travis.yml
|
39
39
|
- Gemfile
|
40
|
+
- LICENSE.txt
|
40
41
|
- README.md
|
41
42
|
- Rakefile
|
42
43
|
- attr_extras.gemspec
|
@@ -56,6 +57,7 @@ files:
|
|
56
57
|
- spec/method_object_spec.rb
|
57
58
|
- spec/pattr_initialize_spec.rb
|
58
59
|
- spec/spec_helper.rb
|
60
|
+
- spec/static_facade_spec.rb
|
59
61
|
- spec/vattr_initialize_spec.rb
|
60
62
|
homepage: https://github.com/barsoom/attr_extras
|
61
63
|
licenses:
|
@@ -92,4 +94,5 @@ test_files:
|
|
92
94
|
- spec/method_object_spec.rb
|
93
95
|
- spec/pattr_initialize_spec.rb
|
94
96
|
- spec/spec_helper.rb
|
97
|
+
- spec/static_facade_spec.rb
|
95
98
|
- spec/vattr_initialize_spec.rb
|