bricks 0.4.1 → 0.5.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.
- data/History.md +6 -0
- data/README.md +25 -0
- data/VERSION +1 -1
- data/bricks.gemspec +2 -2
- data/lib/bricks/builder.rb +58 -11
- data/spec/bricks/builder_spec.rb +16 -1
- data/spec/bricks_spec.rb +14 -0
- data/spec/support/active_record.rb +1 -0
- metadata +3 -3
data/History.md
CHANGED
data/README.md
CHANGED
@@ -18,6 +18,7 @@ We'll use the following domain to describe *Brick's* features:
|
|
18
18
|
# title :string(255)
|
19
19
|
# author :string(255)
|
20
20
|
# formatted_title :string(510)
|
21
|
+
# popularity :integer(4)
|
21
22
|
# publication_id :integer(4)
|
22
23
|
#
|
23
24
|
class Article < ActiveRecord::Base
|
@@ -244,6 +245,30 @@ Note that if you want to override a *-to-many association inside a trait, you ne
|
|
244
245
|
|
245
246
|
For an executable version of this documentation, please see spec/bricks_spec.rb.
|
246
247
|
|
248
|
+
### Hooks
|
249
|
+
|
250
|
+
*Bricks includes a simple, general hook framework. It allows you to do something like this:
|
251
|
+
|
252
|
+
builder Article
|
253
|
+
# ...
|
254
|
+
|
255
|
+
trait :on_the_bugle do
|
256
|
+
publication.name "The Daily Bugle"
|
257
|
+
popularity 75
|
258
|
+
end
|
259
|
+
|
260
|
+
trait :on_the_planet do
|
261
|
+
publication.name "The Daily Planet"
|
262
|
+
popularity 85
|
263
|
+
end
|
264
|
+
|
265
|
+
after :clone do
|
266
|
+
send %w(on_the_bugle on_the_planet)[rand(2)]
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
*Bricks* supports a single hook right now: after(:clone). It will be executed whenever you use any of #build, #build!, #create or #create!, right before you start customizing the resulting builder on your test.
|
271
|
+
|
247
272
|
Installation
|
248
273
|
------------
|
249
274
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/bricks.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{bricks}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.5.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["David Leal"]
|
12
|
-
s.date = %q{2011-06-
|
12
|
+
s.date = %q{2011-06-29}
|
13
13
|
s.email = %q{david@mojotech.com}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"LICENSE.txt",
|
data/lib/bricks/builder.rb
CHANGED
@@ -23,6 +23,12 @@ module Bricks
|
|
23
23
|
self
|
24
24
|
end
|
25
25
|
|
26
|
+
def after(hook, &block)
|
27
|
+
@traits.class_eval do
|
28
|
+
define_method "__after_#{hook}", &block
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
26
32
|
def derive(args = {})
|
27
33
|
build_attrs
|
28
34
|
|
@@ -30,7 +36,9 @@ module Bricks
|
|
30
36
|
save = args.has_key?(:save) ? args[:save] : @save
|
31
37
|
search = args.has_key?(:search) ? args[:search] : @search
|
32
38
|
|
33
|
-
Builder.new(klass, @attrs, @traits, save, search)
|
39
|
+
Builder.new(klass, @attrs, @traits, save, search).tap { |b|
|
40
|
+
b.run_hook :after, :clone if ! args[:class]
|
41
|
+
}
|
34
42
|
end
|
35
43
|
|
36
44
|
def initialize(
|
@@ -80,7 +88,8 @@ module Bricks
|
|
80
88
|
elsif settable?(attr)
|
81
89
|
set attr, *args, &block
|
82
90
|
else
|
83
|
-
raise Bricks::NoAttributeOrTrait,
|
91
|
+
raise Bricks::NoAttributeOrTrait,
|
92
|
+
"Can't find `#{name}' on builder for #{@class}."
|
84
93
|
end
|
85
94
|
|
86
95
|
if return_object
|
@@ -93,6 +102,14 @@ module Bricks
|
|
93
102
|
end
|
94
103
|
end
|
95
104
|
|
105
|
+
protected
|
106
|
+
|
107
|
+
def run_hook(position, name)
|
108
|
+
full_name = "__#{position}_#{name}"
|
109
|
+
|
110
|
+
send full_name if respond_to?(full_name)
|
111
|
+
end
|
112
|
+
|
96
113
|
private
|
97
114
|
|
98
115
|
def subject
|
@@ -113,23 +130,53 @@ module Bricks
|
|
113
130
|
obj.save!
|
114
131
|
end
|
115
132
|
|
116
|
-
|
117
|
-
obj
|
133
|
+
class Proxy
|
134
|
+
attr_reader :obj
|
135
|
+
|
136
|
+
def initialize(obj, attrs, parent)
|
137
|
+
@obj = obj
|
138
|
+
@attrs_in = attrs.dup
|
139
|
+
@attrs_out = {}
|
140
|
+
@parent = parent
|
141
|
+
end
|
118
142
|
|
119
|
-
|
120
|
-
|
143
|
+
def method_missing(name, *args)
|
144
|
+
name_y = name.to_sym
|
145
|
+
|
146
|
+
if @attrs_in.assoc(name_y) && ! @attrs_out.has_key?(name_y)
|
147
|
+
fix_attr name
|
148
|
+
else
|
149
|
+
@obj.send name, *args
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def build
|
154
|
+
@attrs_in.each { |(k, _)| send k }
|
155
|
+
|
156
|
+
@obj
|
157
|
+
end
|
158
|
+
|
159
|
+
def fix_attr(name)
|
160
|
+
val = case v = @attrs_in.assoc(name).last
|
121
161
|
when Proc
|
122
|
-
v.call
|
162
|
+
case r = v.call(*[self, @parent].take([v.arity, 0].max))
|
163
|
+
when Proxy
|
164
|
+
r.obj
|
165
|
+
else
|
166
|
+
r
|
167
|
+
end
|
123
168
|
when Builder, BuilderSet
|
124
|
-
v.generate(:parent =>
|
169
|
+
v.generate(:parent => self)
|
125
170
|
else
|
126
171
|
v
|
127
172
|
end
|
128
173
|
|
129
|
-
obj.send
|
130
|
-
|
174
|
+
@attrs_out[name] = @obj.send("#{name}=", val)
|
175
|
+
end
|
176
|
+
end
|
131
177
|
|
132
|
-
|
178
|
+
def initialize_object(parent)
|
179
|
+
Proxy.new(@class.new, @attrs, parent).build
|
133
180
|
end
|
134
181
|
|
135
182
|
def settable?(name)
|
data/spec/bricks/builder_spec.rb
CHANGED
@@ -11,7 +11,7 @@ describe Bricks::Builder do
|
|
11
11
|
}.new
|
12
12
|
|
13
13
|
class Person
|
14
|
-
attr_accessor :name
|
14
|
+
attr_accessor :name, :first_name, :last_name
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -38,4 +38,19 @@ describe Bricks::Builder do
|
|
38
38
|
|
39
39
|
b.generate.object_id.should_not == b.generate.object_id
|
40
40
|
end
|
41
|
+
|
42
|
+
describe "attribute evaluation ordering" do
|
43
|
+
before :all do
|
44
|
+
end
|
45
|
+
|
46
|
+
it "doesn't care which order the attributes are declared" do
|
47
|
+
b = Bricks::Builder.new Person do
|
48
|
+
name { |obj| obj.first_name + " " + obj.last_name }
|
49
|
+
first_name { "Jack" }
|
50
|
+
last_name { "Black" }
|
51
|
+
end
|
52
|
+
|
53
|
+
b.derive.generate.name.should == "Jack Black"
|
54
|
+
end
|
55
|
+
end
|
41
56
|
end
|
data/spec/bricks_spec.rb
CHANGED
@@ -44,6 +44,10 @@ describe Bricks do
|
|
44
44
|
|
45
45
|
%w(Tom Dick Harry).each { |n| readers.name(n) }
|
46
46
|
end
|
47
|
+
|
48
|
+
after :clone do
|
49
|
+
popularity (1..100).to_a[rand(100)]
|
50
|
+
end
|
47
51
|
end
|
48
52
|
|
49
53
|
builder Newspaper do
|
@@ -217,5 +221,15 @@ describe Bricks do
|
|
217
221
|
build!(Reader).should be_a(Reader)
|
218
222
|
end
|
219
223
|
end
|
224
|
+
|
225
|
+
describe "hooks" do
|
226
|
+
it "executes the `generate' hook after a builder is cloned" do
|
227
|
+
build!(Article).popularity.should_not == build!(Article).popularity
|
228
|
+
end
|
229
|
+
|
230
|
+
it "it does not override values set after the builder is cloned" do
|
231
|
+
build(Article).popularity!(50).popularity.should == 50
|
232
|
+
end
|
233
|
+
end
|
220
234
|
end
|
221
235
|
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: bricks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.5.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- David Leal
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-06-
|
13
|
+
date: 2011-06-29 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -101,7 +101,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
101
101
|
requirements:
|
102
102
|
- - ">="
|
103
103
|
- !ruby/object:Gem::Version
|
104
|
-
hash: -
|
104
|
+
hash: -614702947
|
105
105
|
segments:
|
106
106
|
- 0
|
107
107
|
version: "0"
|