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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0665bfd37394ce176ce0d33f2c1d1f55f32dfa70
4
- data.tar.gz: 9a7bf2915ff6dd350d8d99c92c6a4b4afb9b6510
3
+ metadata.gz: 496f58fb856e20541ca2984b42e5ff34d6e5ce8d
4
+ data.tar.gz: 4344bb9b85e4e8ebaa198b1b532045b01cb6ebd9
5
5
  SHA512:
6
- metadata.gz: b5dc8ce07c0dc65cf1f818294f785f6c6bba0849a4ddf45152a379747ecbc3c981d895a6a6e9f0e8964eecd972234dc1838cbcb27b15f12f25bc12f44268dfbf
7
- data.tar.gz: d2dec91003d742e658c4c53350430f3793d3cf2edd43f4ae7644aeb6e12e9cab68c584bbcc4c7b9352feb6e970789fc4ce1ff8699347bf20ed353d825d2c3990
6
+ metadata.gz: 5adad36ffeacd88e2b0e66aeec0d99eb4f7b51baa8bfaeef89045d23bfbf6adcb70c7d6a94f0fbdecb1fe7a9137b15c07775a9ebdaf9cc9e430119c9fda76c6f
7
+ data.tar.gz: 78c7dbe731c85b2d8150e020b5d5afeda6bb9cf247d9706cc9fd39c06aad16c7da9cdb4b877479534daed35cbb3cba5f46bcecbc018aacac1daf82a97dded431
data/CHANGES.md CHANGED
@@ -1,3 +1,7 @@
1
+ # 0.0.9
2
+
3
+ * Add `Uber::Builder`.
4
+
1
5
  # 0.0.8
2
6
 
3
7
  * Add `Uber::Delegates` that provides delegation that can be overridden and called with `super`.
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
- gem 'uber'
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
- version = Uber::Version.new("1.2.3")
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
- version >= "1.1" #=> true
205
- version >= "1.3" #=> false
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
- version.~ "1.1" #=> false
212
- version.~ "1.2" #=> true
213
- version.~ "1.3" #=> false
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
- version.~ "1.1", "1.0" #=> false
220
- version.~ "1.1", "1.2" #=> true
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 thou it is not a symbol.
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).
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Uber
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
@@ -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.8
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-01 00:00:00.000000000 Z
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