uber 0.0.8 → 0.0.9
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/CHANGES.md +4 -0
- data/README.md +53 -11
- data/lib/uber/builder.rb +90 -0
- data/lib/uber/uber_version.rb +1 -1
- data/test/builder_test.rb +59 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 496f58fb856e20541ca2984b42e5ff34d6e5ce8d
|
4
|
+
data.tar.gz: 4344bb9b85e4e8ebaa198b1b532045b01cb6ebd9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5adad36ffeacd88e2b0e66aeec0d99eb4f7b51baa8bfaeef89045d23bfbf6adcb70c7d6a94f0fbdecb1fe7a9137b15c07775a9ebdaf9cc9e430119c9fda76c6f
|
7
|
+
data.tar.gz: 78c7dbe731c85b2d8150e020b5d5afeda6bb9cf247d9706cc9fd39c06aad16c7da9cdb4b877479534daed35cbb3cba5f46bcecbc018aacac1daf82a97dded431
|
data/CHANGES.md
CHANGED
data/README.md
CHANGED
@@ -6,7 +6,9 @@ _Gem-authoring tools like class method inheritance in modules, dynamic options a
|
|
6
6
|
|
7
7
|
Add this line to your application's Gemfile:
|
8
8
|
|
9
|
-
|
9
|
+
```ruby
|
10
|
+
gem 'uber'
|
11
|
+
```
|
10
12
|
|
11
13
|
Ready?
|
12
14
|
|
@@ -190,34 +192,74 @@ song.title #=> "helloween!"
|
|
190
192
|
|
191
193
|
Note how `#title` calls the original title and then downcases the string.
|
192
194
|
|
195
|
+
|
196
|
+
# Builder
|
197
|
+
|
198
|
+
When included, `Builder` allows to add builder instructions on the class level. These can then be evaluated when instantiating
|
199
|
+
the class to conditionally build (sub-)classes based on the incoming parameters.
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
class Listener
|
203
|
+
include Uber::Builder
|
204
|
+
|
205
|
+
builds do |params|
|
206
|
+
SignedIn if params[:current_user]
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
class SignedIn
|
211
|
+
end
|
212
|
+
```
|
213
|
+
|
214
|
+
The class then has to use the builder to compute a class name using the build blocks you defined.
|
215
|
+
|
216
|
+
```ruby
|
217
|
+
class Listener
|
218
|
+
def self.build(params)
|
219
|
+
class_builder.call(params).
|
220
|
+
new(params)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
```
|
224
|
+
|
225
|
+
As you can see, it's still up to you to _instantiate_ the object, the builder only helps you computing the concrete class.
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
Listener.build({}) #=> Listener
|
229
|
+
Listener.build({current_user: @current_user}) #=> SignedIn
|
230
|
+
```
|
231
|
+
|
232
|
+
This pattern is used in [Cells](https://github.com/apotonick/cells), [Trailblazer](https://github.com/apotonick/trailblazer) and soon Reform and Representable/Roar, too.
|
233
|
+
|
234
|
+
|
193
235
|
# Version
|
194
236
|
|
195
237
|
Writing gems against other gems often involves checking for versions and loading appropriate version strategies - e.g. _"is Rails >= 4.0?"_. Uber gives you `Version` for easy, semantic version deciders.
|
196
238
|
|
197
239
|
```ruby
|
198
|
-
|
240
|
+
version = Uber::Version.new("1.2.3")
|
199
241
|
```
|
200
242
|
|
201
243
|
The API currently gives you `#>=` and `#~`.
|
202
244
|
|
203
245
|
```ruby
|
204
|
-
|
205
|
-
|
246
|
+
version >= "1.1" #=> true
|
247
|
+
version >= "1.3" #=> false
|
206
248
|
```
|
207
249
|
|
208
250
|
The `~` method does a semantic check (currently on major and minor level, only).
|
209
251
|
|
210
252
|
```ruby
|
211
|
-
|
212
|
-
|
213
|
-
|
253
|
+
version.~ "1.1" #=> false
|
254
|
+
version.~ "1.2" #=> true
|
255
|
+
version.~ "1.3" #=> false
|
214
256
|
```
|
215
257
|
|
216
258
|
Accepting a list of versions, it makes it simple to check for multiple minor versions.
|
217
259
|
|
218
260
|
```ruby
|
219
|
-
|
220
|
-
|
261
|
+
version.~ "1.1", "1.0" #=> false
|
262
|
+
version.~ "1.1", "1.2" #=> true
|
221
263
|
```
|
222
264
|
|
223
265
|
|
@@ -225,10 +267,10 @@ Accepting a list of versions, it makes it simple to check for multiple minor ver
|
|
225
267
|
|
226
268
|
(Please don't read this!)
|
227
269
|
|
228
|
-
* You can enforce treating values as dynamic (or not): `Uber::Options::Value.new("time_to_live", dynamic: true)` will always run `#time_to_live` as an instance method on the context, even
|
270
|
+
* You can enforce treating values as dynamic (or not): `Uber::Options::Value.new("time_to_live", dynamic: true)` will always run `#time_to_live` as an instance method on the context, even though it is not a symbol.
|
229
271
|
|
230
272
|
# License
|
231
273
|
|
232
274
|
Copyright (c) 2014 by Nick Sutterer <apotonick@gmail.com>
|
233
275
|
|
234
|
-
Roar is released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
276
|
+
Roar is released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
data/lib/uber/builder.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'uber/inheritable_attr'
|
2
|
+
|
3
|
+
module Uber
|
4
|
+
# When included, allows to add builder on the class level.
|
5
|
+
#
|
6
|
+
# class Operation
|
7
|
+
# include Uber::Builder
|
8
|
+
#
|
9
|
+
# builds do |params|
|
10
|
+
# SignedIn if params[:current_user]
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# class SignedIn
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# The class then has to call the builder to compute a class name using the build blocks you defined.
|
17
|
+
#
|
18
|
+
# def self.build(params)
|
19
|
+
# class_builder.call(params).
|
20
|
+
# new(params)
|
21
|
+
# end
|
22
|
+
module Builder
|
23
|
+
def self.included(base)
|
24
|
+
base.extend(ClassMethods)
|
25
|
+
base.extend(InheritableAttr)
|
26
|
+
base.inheritable_attr :builders
|
27
|
+
base.builders = []
|
28
|
+
end
|
29
|
+
|
30
|
+
class Constant
|
31
|
+
def initialize(constant) # TODO: evaluate usage of builders and implement using Uber::Options::Value.
|
32
|
+
@constant = constant
|
33
|
+
@builders = @constant.builders # only dependency, must be a Cell::Base subclass.
|
34
|
+
end
|
35
|
+
|
36
|
+
def call(*args)
|
37
|
+
build_class_for(*args)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def build_class_for(*args)
|
42
|
+
@builders.each do |blk|
|
43
|
+
klass = run_builder_block(blk, *args) and return klass
|
44
|
+
end
|
45
|
+
@constant
|
46
|
+
end
|
47
|
+
|
48
|
+
def run_builder_block(block, *args)
|
49
|
+
block.call(*args)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module ClassMethods
|
54
|
+
# Adds a builder to the cell class. Builders are used in #cell to find out the concrete
|
55
|
+
# class for rendering. This is helpful if you frequently want to render subclasses according
|
56
|
+
# to different circumstances (e.g. login situations) and you don't want to place these deciders in
|
57
|
+
# your view code.
|
58
|
+
#
|
59
|
+
# Passes the model and options from #cell into the block.
|
60
|
+
#
|
61
|
+
# Multiple build blocks are ORed, if no builder matches the building cell is used.
|
62
|
+
#
|
63
|
+
# Example:
|
64
|
+
#
|
65
|
+
# Consider two different user box cells in your app.
|
66
|
+
#
|
67
|
+
# class AuthorizedUserBox < UserInfoBox
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# class AdminUserBox < UserInfoBox
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# Now you don't want to have deciders all over your views - use a declarative builder.
|
74
|
+
#
|
75
|
+
# UserInfoBox.build do |model, options|
|
76
|
+
# AuthorizedUserBox if options[:is_signed_in]
|
77
|
+
# AdminUserBox if model.admin?
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
# In your view #cell will instantiate the right cell for you now.
|
81
|
+
def builds(&block)
|
82
|
+
builders << block
|
83
|
+
end
|
84
|
+
|
85
|
+
def class_builder
|
86
|
+
@class_builder ||= Constant.new(self)
|
87
|
+
end
|
88
|
+
end # ClassMethods
|
89
|
+
end
|
90
|
+
end
|
data/lib/uber/uber_version.rb
CHANGED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require "uber/builder"
|
3
|
+
|
4
|
+
class BuilderTest < MiniTest::Spec
|
5
|
+
Evergreen = Struct.new(:title)
|
6
|
+
Hit = Struct.new(:title)
|
7
|
+
|
8
|
+
class Song
|
9
|
+
include Uber::Builder
|
10
|
+
|
11
|
+
builds do |options|
|
12
|
+
if options[:evergreen]
|
13
|
+
Evergreen
|
14
|
+
elsif options[:hit]
|
15
|
+
Hit
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.build(options)
|
20
|
+
class_builder.call(options).new
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# building class if no block matches
|
25
|
+
it { Song.build({}).must_be_instance_of Song }
|
26
|
+
|
27
|
+
it { Song.build({evergreen: true}).must_be_instance_of Evergreen }
|
28
|
+
it { Song.build({hit: true}).must_be_instance_of Hit }
|
29
|
+
|
30
|
+
# test chained builds.
|
31
|
+
class Track
|
32
|
+
include Uber::Builder
|
33
|
+
|
34
|
+
builds do |options|
|
35
|
+
Evergreen if options[:evergreen]
|
36
|
+
end
|
37
|
+
|
38
|
+
builds do |options|
|
39
|
+
Hit if options[:hit]
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.build(options)
|
43
|
+
class_builder.call(options).new
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it { Track.build({}).must_be_instance_of Track }
|
48
|
+
it { Track.build({evergreen: true}).must_be_instance_of Evergreen }
|
49
|
+
it { Track.build({hit: true}).must_be_instance_of Hit }
|
50
|
+
|
51
|
+
|
52
|
+
# test inheritance.
|
53
|
+
class Play < Song
|
54
|
+
end
|
55
|
+
|
56
|
+
it { Play.build({}).must_be_instance_of Play }
|
57
|
+
it { Play.build({evergreen: true}).must_be_instance_of Evergreen }
|
58
|
+
it { Play.build({hit: true}).must_be_instance_of Hit }
|
59
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uber
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-08
|
11
|
+
date: 2014-10-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -52,12 +52,14 @@ files:
|
|
52
52
|
- README.md
|
53
53
|
- Rakefile
|
54
54
|
- lib/uber.rb
|
55
|
+
- lib/uber/builder.rb
|
55
56
|
- lib/uber/callable.rb
|
56
57
|
- lib/uber/delegates.rb
|
57
58
|
- lib/uber/inheritable_attr.rb
|
58
59
|
- lib/uber/options.rb
|
59
60
|
- lib/uber/uber_version.rb
|
60
61
|
- lib/uber/version.rb
|
62
|
+
- test/builder_test.rb
|
61
63
|
- test/delegates_test.rb
|
62
64
|
- test/inheritable_attr_test.rb
|
63
65
|
- test/inheritance_test.rb
|
@@ -92,6 +94,7 @@ specification_version: 4
|
|
92
94
|
summary: Gem-authoring tools like class method inheritance in modules, dynamic options
|
93
95
|
and more.
|
94
96
|
test_files:
|
97
|
+
- test/builder_test.rb
|
95
98
|
- test/delegates_test.rb
|
96
99
|
- test/inheritable_attr_test.rb
|
97
100
|
- test/inheritance_test.rb
|