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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZWFjODUyMWM5ZDQwYTllYzlkYWU4YjkwNzBkOWQ1YjY0NTE5MWY0ZQ==
4
+ YTEzMGU2ZTk5YTFhZTRkOGRjN2NjMDNkYTU4MDM4NTVkNDExNmVkOQ==
5
5
  data.tar.gz: !binary |-
6
- NzI4N2YyZjcwN2ZkZDIzMmIyN2I2NmI3NDJjMGNlZTQyNjZkOGNmYw==
6
+ MDZkNDRkNzc2MDMyOGUwMzVjODE1YmE5NGNkODNhMjY4YTM5NzZjYw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NTUxMDVlN2I2NzI4NzY4MjBkMGM4OWQ0OGM5M2NjNGRkYzdiNzRiOWNiYzQ5
10
- YTEyZTFhMjkxNjg3YTU2ZWJkMTgxNjU0OTU5NjcxNzY2YjYzODA0NTNlZmY4
11
- MzYxZTc2ZTE5YzdiMjg1OTEzMmE1ODNmYzJjYmQ5OTkxMzZiODI=
9
+ MWNjNjMyYjQ3ZTMyMDE5MTQwYWIyY2NjYzQxMjJkNTNjNTQxOGZhMzY2NjAw
10
+ MmZkM2U3NzNiOTBjMWVmYzQyODA4MzBhMWU3ODIyYmZkNjFjODRhYTAzOTlm
11
+ MGY0NjEzYWIxZjU5MDhlNjRmNDkzYmZlMWVjMmY0ODQ5MWY0YWI=
12
12
  data.tar.gz: !binary |-
13
- YmRlYTAwYWQzMmJiODA2ZTk5YzEyMDVkNGVmY2JiODI5MGUxYTAxNWQzNDIx
14
- MjAyZWM3OTUwOWMzN2Y0NDkxZjhkOGYwYmM0ZmNjM2JhMTg0MDQ1ZGM3NGQw
15
- ZmE2YzM1MGE2ODU2YTExZGZmNGM5NmZhYzI3YzgwMTFjODNjMzQ=
13
+ MWNiMmYwMDI5MDYzZjBjYWY2OGFhNTMyZWIyZjJjZDkzNDRlOWUxY2Q3NzNm
14
+ ZWJhYWViN2I5NmU1ZWY1OWFhODQ3NGEwOTY1YmE3MGZjNWY5YTU0NTY5YWU2
15
+ ODgwNjZmOGE2MjQzZmQ0MzE5ZDY5OTYyMzhjNjVlODk2NzMyMGQ=
@@ -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
- ### `method_object :fooable?, :foo`<br>
86
+ ### `static_facade :fooable?, :foo`<br>
87
87
 
88
- Defines a `.fooable?` class method that takes arguments (`foo`) and delegates to an instance method that can access those arguments as private readers.
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 useful for [method objects](http://refactoring.com/catalog/replaceMethodWithMethodObject.html):
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 :calculate,
95
- :order
134
+ method_object :order
96
135
 
97
- def calculate
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.calculate(self)
153
+ PriceCalculator.call(self)
115
154
  end
116
-
117
- # …
118
155
  end
119
156
  ```
120
157
 
121
- Shortcut for
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
- attr_initialize :foo
125
- attr_private :foo
167
+ pattr_initialize :foo
126
168
 
127
- def self.fooable?(foo)
128
- new(foo).fooable?
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 :fooable?, :foo, [:bar, :baz!]`
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 :fooable?` is also valid.
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
- Copyright (c) 2012-2014 [Barsoom AB](http://barsoom.se)
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)
@@ -46,7 +46,7 @@ module AttrExtras
46
46
  attr_value(*Utils.flat_names(names))
47
47
  end
48
48
 
49
- def method_object(method_name, *names)
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
@@ -1,3 +1,3 @@
1
1
  module AttrExtras
2
- VERSION = "3.2.0"
2
+ VERSION = "4.0.0"
3
3
  end
@@ -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
- attr_implement :foo
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
@@ -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 that instance method" do
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 :fooable?,
7
- :foo
6
+ method_object :foo
8
7
 
9
- def fooable?
8
+ def call
10
9
  foo
11
10
  end
12
11
  end
13
12
 
14
- assert klass.fooable?(true)
15
- refute klass.fooable?(false)
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 :fooable?
19
+ method_object
21
20
 
22
- def fooable?
21
+ def call
23
22
  true
24
23
  end
25
24
  end
26
25
 
27
- assert klass.fooable?
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: 3.2.0
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-10 00:00:00.000000000 Z
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