uber 0.0.14 → 0.0.15

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: f71a66b9f3f5b51c0ceb68c2aa396d9f1571d28b
4
- data.tar.gz: 243f81afa103da2cc3b1c2d8f9d1445b9acf8013
3
+ metadata.gz: d35993c8fa8e0378bda6e3207c7a34c79fcaf901
4
+ data.tar.gz: 57e3c7e6251134b7c38f4e946768f795d842da1e
5
5
  SHA512:
6
- metadata.gz: c67f0fe6bf6fe588af3848e9a243f4fe5ca2857468c7ccdf9e0100e3a94b717a923e395ec77c2cc31edb301593663f8de6483f06f7cfb6cf53fb603cea1b43a9
7
- data.tar.gz: 4c3ef47a30140dc3191d582e678a28362477ec0786ab30194f9434e26ced92bc12ce937385a7848918e715b22218ea7c12329e17bb5f64e65d171f85dd48d730
6
+ metadata.gz: 02482631941669e1ce796a484b4876e3b9e82dc1a163935579b6ce46acba7a6533ad0b3655df7cb455bec8ac723108ca256c0effb6895a759a584b2e9dd559b4
7
+ data.tar.gz: 47e7927839f0d30ba4ef9ea11e400b114744d65ade257036d8f018476c17a4ada0bfdaed5c2667d4cd7336987c424d2d298b55717ca5fe8b751ff751b8127023
data/CHANGES.md CHANGED
@@ -1,3 +1,9 @@
1
+ # 0.0.15
2
+
3
+ * `Value#evaluate` is now `#call`. This will make it easier to introduce Null objects.
4
+ * Options passed to `::builds` are now wrapped in `Uber::Options::Value` which allows specifying builder _class methods_ using `builds :builder_method`.
5
+ * `Builder::class_builder` now accepts an optional context object which is used to `instance_exec` the builder blocks. This allows to share predefined builder blocks between different classes while resolving the constants in the respective class.
6
+
1
7
  # 0.0.14
2
8
 
3
9
  * Add `inheritable_attr :title, clone: false`. Thanks to @katafrakt.
data/README.md CHANGED
@@ -222,7 +222,7 @@ Note how `#title` calls the original title and then downcases the string.
222
222
  When included, `Builder` allows to add builder instructions on the class level. These can then be evaluated when instantiating
223
223
  the class to conditionally build (sub-)classes based on the incoming parameters.
224
224
 
225
- Builders can be defined in two different ways.
225
+ Builders can be defined in three different ways.
226
226
 
227
227
  ## Block Syntax
228
228
 
@@ -271,6 +271,33 @@ end
271
271
 
272
272
  This makes the block extremely readable.
273
273
 
274
+ ## Method Syntax
275
+
276
+ You can also specify a build method.
277
+
278
+ ```ruby
279
+ build :build_method
280
+
281
+ def self.build_method(params)
282
+ return SignedIn if params[:current_user]
283
+ end
284
+ ```
285
+
286
+ The method has to be a class method on the building class.
287
+
288
+ ## Build Context
289
+
290
+ Normally, build blocks and methods are run in the context where they were defined in. You can change that by passing any context object to `class_builder`.
291
+
292
+ ```ruby
293
+ def self.build(params)
294
+ class_builder(context_object) # ...
295
+ end
296
+ ```
297
+
298
+ This allows copying builders to other classes and evaluate blocks in the new context.
299
+
300
+ ## More On Builders
274
301
 
275
302
  Note that builders are _not_ inherited to subclasses. This allows instantiating subclasses directly without running builders.
276
303
 
@@ -1,3 +1,5 @@
1
+ require "uber/options"
2
+
1
3
  module Uber
2
4
  # When included, allows to add builder on the class level.
3
5
  #
@@ -28,9 +30,11 @@ module Uber
28
30
  end
29
31
  end
30
32
 
33
+ # Computes the concrete target class.
31
34
  class Constant
32
- def initialize(constant) # TODO: evaluate usage of builders and implement using Uber::Options::Value.
35
+ def initialize(constant, context)
33
36
  @constant = constant
37
+ @context = context
34
38
  @builders = @constant.builders # only dependency, must be a Cell::Base subclass.
35
39
  end
36
40
 
@@ -47,7 +51,7 @@ module Uber
47
51
  end
48
52
 
49
53
  def run_builder_block(block, *args)
50
- block.call(*args)
54
+ block.(@context, *args) # Uber::Value.call()
51
55
  end
52
56
  end
53
57
 
@@ -78,13 +82,15 @@ module Uber
78
82
  # AdminUserBox if model.admin?
79
83
  # end
80
84
  #
81
- # In your view #cell will instantiate the right cell for you now.
85
+ # In your view #cell will instantiate the right class for you now.
82
86
  def builds(proc=nil, &block)
83
- builders << (proc.kind_of?(Proc) ? proc : block)
87
+ builders << Uber::Options::Value.new(proc.nil? ? block : proc) # TODO: provide that in Uber::O:Value.
84
88
  end
85
89
 
86
- def class_builder
87
- @class_builder ||= Constant.new(self)
90
+ # Call this from your classes' own ::build method to compute the concrete target class.
91
+ # The class_builder is cached, you can't change the context once it's set.
92
+ def class_builder(context=nil)
93
+ @class_builder ||= Constant.new(self, context)
88
94
  end
89
95
  end # ClassMethods
90
96
  end
@@ -54,11 +54,12 @@ module Uber
54
54
  @dynamic = @proc || @callable || @method
55
55
  end
56
56
 
57
- def evaluate(context, *args)
57
+ def call(context, *args)
58
58
  return @value unless dynamic?
59
59
 
60
60
  evaluate_for(context, *args)
61
61
  end
62
+ alias_method :evaluate, :call
62
63
 
63
64
  def dynamic?
64
65
  @dynamic
@@ -1,3 +1,3 @@
1
1
  module Uber
2
- VERSION = "0.0.14"
2
+ VERSION = "0.0.15"
3
3
  end
@@ -72,4 +72,67 @@ class BuilderTest < MiniTest::Spec
72
72
 
73
73
  it { Boomerang.build({}).must_be_instance_of Boomerang }
74
74
  it { Boomerang.build({hit: true}).must_be_instance_of Song }
75
+ end
76
+
77
+
78
+ class BuilderScopeTest < MiniTest::Spec
79
+ def self.builder_method(options)
80
+ options[:from_builder_method] and return self
81
+ end
82
+
83
+ class Hit; end
84
+
85
+ class Song
86
+ class Hit
87
+ end
88
+
89
+ include Uber::Builder
90
+
91
+ builds :builder_method # i get called first.
92
+ builds ->(options) do # and i second.
93
+ self::Hit
94
+ end
95
+
96
+ def self.build(context, options={})
97
+ class_builder(context).call(options)
98
+ end
99
+ end
100
+
101
+ class Evergreen
102
+ class Hit
103
+ end
104
+
105
+ include Uber::Builder
106
+
107
+ class << self
108
+ attr_writer :builders
109
+ end
110
+ self.builders = Song.builders
111
+
112
+ def self.build(context, options={})
113
+ class_builder(context).call(options)
114
+ end
115
+
116
+ def self.builder_method(options)
117
+ options[:from_builder_method] and return self
118
+ end
119
+ end
120
+
121
+ it do
122
+ Song.build(self.class).must_equal BuilderScopeTest::Hit
123
+
124
+ # this runs BuilderScopeTest::builder_method and returns self.
125
+ Song.build(self.class, from_builder_method: true).must_equal BuilderScopeTest
126
+
127
+ # since the class_builder gets cached, this won't change.
128
+ Song.build(Song).must_equal BuilderScopeTest::Hit
129
+ end
130
+
131
+
132
+ it do
133
+ # running the "copied" block in Evergreen will reference the correct @context.
134
+ Evergreen.build(Evergreen).must_equal BuilderScopeTest::Evergreen::Hit
135
+
136
+ Evergreen.build(Evergreen, from_builder_method: true).must_equal BuilderScopeTest::Evergreen
137
+ end
75
138
  end
@@ -25,24 +25,28 @@ class UberOptionTest < MiniTest::Spec
25
25
  it { Value.new(Callable.new).dynamic?.must_equal true }
26
26
  end
27
27
 
28
- describe "#evaluate" do
28
+ describe "#call" do
29
29
  let (:version) { Module.new { def version; 999 end } }
30
30
 
31
- it { Value.new(nil).evaluate(Object.new).must_equal nil }
32
- # it { Value.new(nil, :dynamic => true).evaluate(Object.new).must_equal nil } # DISCUSS: should we handle that?
31
+ it { Value.new(nil).(Object.new).must_equal nil }
32
+ # it { Value.new(nil, :dynamic => true).(Object.new).must_equal nil } # DISCUSS: should we handle that?
33
33
 
34
- it { Value.new(true).evaluate(Object.new).must_equal true }
34
+ it { Value.new(true).(Object.new).must_equal true }
35
35
 
36
- it { Value.new(:version).evaluate(object.extend(version)).must_equal 999 }
37
- it { Value.new("version", :dynamic => true).evaluate(object.extend(version)).must_equal 999 }
38
- it { Value.new(:version, :dynamic => false).evaluate(object.extend(version)).must_equal :version }
39
- it { Value.new(lambda { self }).evaluate(object).must_equal object }
40
- it { Value.new(lambda { self }).evaluate(nil).must_equal self }
36
+ it { Value.new(:version).(object.extend(version)).must_equal 999 }
37
+ it { Value.new("version", :dynamic => true).(object.extend(version)).must_equal 999 }
38
+ it { Value.new(:version, :dynamic => false).(object.extend(version)).must_equal :version }
39
+ it { Value.new(lambda { self }).(object).must_equal object }
40
+ it { Value.new(lambda { self }).(nil).must_equal self }
41
41
 
42
- it { Value.new(lambda { :loud }, :dynamic => true).evaluate(object).must_equal :loud }
42
+ it { Value.new(lambda { :loud }, :dynamic => true).(object).must_equal :loud }
43
43
 
44
44
  # Uber::Callable
45
- it { Value.new(Callable.new).evaluate(nil).must_equal 999 }
45
+ it { Value.new(Callable.new).(nil).must_equal 999 }
46
+ end
47
+
48
+ it "#call is aliased to evaluate" do
49
+ Value.new(Callable.new).(nil).must_equal 999
46
50
  end
47
51
 
48
52
  describe "passing options" do
@@ -50,9 +54,9 @@ class UberOptionTest < MiniTest::Spec
50
54
  let (:block) { Proc.new { |*args| args.inspect } }
51
55
  let (:callable) { (Class.new { include Uber::Callable; def call(*args); args.inspect; end }).new }
52
56
 
53
- it { Value.new(:version).evaluate(object.extend(version), 1, 2, 3).must_equal "[1, 2, 3]" }
54
- it { Value.new(block).evaluate(object, 1, 2, 3).must_equal "[1, 2, 3]" }
55
- it { Value.new(callable).evaluate(Object, 1, 2, 3).must_equal "[Object, 1, 2, 3]" }
57
+ it { Value.new(:version).(object.extend(version), 1, 2, 3).must_equal "[1, 2, 3]" }
58
+ it { Value.new(block).(object, 1, 2, 3).must_equal "[1, 2, 3]" }
59
+ it { Value.new(callable).(Object, 1, 2, 3).must_equal "[Object, 1, 2, 3]" }
56
60
  end
57
61
 
58
62
  # it "speed" do
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.14
4
+ version: 0.0.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-14 00:00:00.000000000 Z
11
+ date: 2015-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake