bricks 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.md +8 -0
- data/README.md +23 -1
- data/VERSION +1 -1
- data/bricks.gemspec +3 -2
- data/lib/bricks/adapters/active_record.rb +2 -2
- data/lib/bricks/builder.rb +40 -37
- data/lib/bricks/builder_set.rb +2 -2
- data/lib/bricks/dsl.rb +9 -1
- data/lib/bricks.rb +1 -1
- data/spec/bricks_spec.rb +30 -4
- data/spec/support/active_record.rb +1 -0
- metadata +4 -3
data/History.md
ADDED
data/README.md
CHANGED
@@ -143,6 +143,16 @@ If you prepend a "~" to the association declaration, the record will be initiali
|
|
143
143
|
~publication # will search for a record with name "The Caribbean Times"
|
144
144
|
end
|
145
145
|
|
146
|
+
The same effect can be achieved in your tests using
|
147
|
+
|
148
|
+
~(build(Publication)).name!("The Daily Bugle")
|
149
|
+
|
150
|
+
but since this is ugly, you can just use `?` instead of `!` and you'll get (almost) the same effect:
|
151
|
+
|
152
|
+
build(Publication).name?("The Daily Bugle")
|
153
|
+
|
154
|
+
There is a slight difference between using `~` and `?`. `~` will permanently change the builder, while `?` will enable searching only when it's used.
|
155
|
+
|
146
156
|
#### One-to-many, Many-to-many (has many, has and belongs to many)
|
147
157
|
|
148
158
|
Bricks do
|
@@ -160,6 +170,16 @@ Each call to the *-to-many association name will add a new builder, which you ca
|
|
160
170
|
|
161
171
|
(Note that you don't use "!" here. That's only when building the records in your tests.)
|
162
172
|
|
173
|
+
### Passing the parent to association builder blocks
|
174
|
+
|
175
|
+
If you need access to the parent object when building an associated object, you'll find it as the second argument passed to a deferred block.
|
176
|
+
|
177
|
+
builder Article do
|
178
|
+
# ...
|
179
|
+
|
180
|
+
publication.name { |_, article| "#{article.title}'s publication" }
|
181
|
+
end
|
182
|
+
|
163
183
|
### Builder Inheritance
|
164
184
|
|
165
185
|
Given the builder:
|
@@ -230,7 +250,7 @@ Add `gem "bricks"` to your `Gemfile`, or, as a rails plugin:
|
|
230
250
|
|
231
251
|
$ rails plugin install git://github.com/mojotech/bricks.git # Rails 3
|
232
252
|
|
233
|
-
### RSpec
|
253
|
+
### RSpec [TODO: add instructions for other frameworks]
|
234
254
|
|
235
255
|
# you only need to add the following line if you're using the gem
|
236
256
|
require 'bricks/adapters/active_record'
|
@@ -239,6 +259,8 @@ Add `gem "bricks"` to your `Gemfile`, or, as a rails plugin:
|
|
239
259
|
# #build, #build!, #create and #create! in your specs
|
240
260
|
config.include Bricks::DSL
|
241
261
|
|
262
|
+
Finally, add a file to spec/support containing your builders. Call it whatever you'd like and make sure it gets loaded (rspec usually loads all .rb files under spec/support).
|
263
|
+
|
242
264
|
Copyright
|
243
265
|
---------
|
244
266
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.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.4.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-21}
|
13
13
|
s.email = %q{david@mojotech.com}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"LICENSE.txt",
|
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
".document",
|
20
20
|
".rspec",
|
21
21
|
"Gemfile",
|
22
|
+
"History.md",
|
22
23
|
"LICENSE.txt",
|
23
24
|
"README.md",
|
24
25
|
"Rakefile",
|
data/lib/bricks/builder.rb
CHANGED
@@ -23,43 +23,39 @@ module Bricks
|
|
23
23
|
self
|
24
24
|
end
|
25
25
|
|
26
|
-
def derive(
|
27
|
-
klass
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
"(#{args.size} for 0, 1 or 2)"
|
42
|
-
end
|
43
|
-
|
44
|
-
Builder.new(klass, @attrs, @traits, save)
|
45
|
-
end
|
46
|
-
|
47
|
-
def initialize(klass, attrs = nil, traits = nil, save = false, &block)
|
26
|
+
def derive(args = {})
|
27
|
+
klass = args[:class] || @class
|
28
|
+
save = args.has_key?(:save) ? args[:save] : @save
|
29
|
+
search = args.has_key?(:search) ? args[:search] : @search
|
30
|
+
|
31
|
+
Builder.new(klass, @attrs, @traits, save, search)
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(
|
35
|
+
klass,
|
36
|
+
attrs = nil,
|
37
|
+
traits = nil,
|
38
|
+
save = false,
|
39
|
+
search = false,
|
40
|
+
&block)
|
48
41
|
@class = klass
|
49
42
|
@attrs = attrs ? deep_copy(attrs) : []
|
50
43
|
@traits = traits ? Module.new { include traits } : Module.new
|
51
44
|
@save = save
|
45
|
+
@search = search
|
52
46
|
|
53
47
|
extend @traits
|
54
48
|
|
55
49
|
instance_eval &block if block_given?
|
56
50
|
end
|
57
51
|
|
58
|
-
def generate
|
59
|
-
|
52
|
+
def generate(opts = {})
|
53
|
+
parent = opts[:parent]
|
54
|
+
search = opts.has_key?(:search) ? opts[:search] : @search
|
55
|
+
obj = initialize_object(parent)
|
60
56
|
|
61
|
-
obj
|
62
|
-
save_object(obj)
|
57
|
+
obj = adapter.find(@class, Hash[*@attrs.flatten]) || obj if search
|
58
|
+
save_object(obj) if @save
|
63
59
|
|
64
60
|
obj
|
65
61
|
end
|
@@ -77,8 +73,7 @@ module Bricks
|
|
77
73
|
end
|
78
74
|
|
79
75
|
def method_missing(name, *args, &block)
|
80
|
-
attr
|
81
|
-
|
76
|
+
attr = (return_object = name.to_s =~ /[!?]$/) ? name.to_s.chop : name
|
82
77
|
result = if respond_to?(attr)
|
83
78
|
send(attr, *args)
|
84
79
|
elsif settable?(attr)
|
@@ -88,7 +83,10 @@ module Bricks
|
|
88
83
|
end
|
89
84
|
|
90
85
|
if return_object
|
91
|
-
|
86
|
+
opts = {:parent => @parent}
|
87
|
+
opts[:search] = name.to_s =~ /\?$/ || @search
|
88
|
+
|
89
|
+
generate opts
|
92
90
|
else
|
93
91
|
result
|
94
92
|
end
|
@@ -114,15 +112,15 @@ module Bricks
|
|
114
112
|
obj.save!
|
115
113
|
end
|
116
114
|
|
117
|
-
def initialize_object
|
115
|
+
def initialize_object(parent)
|
118
116
|
obj = @class.new
|
119
117
|
|
120
118
|
@attrs.each { |(k, v)|
|
121
119
|
val = case v
|
122
120
|
when Proc
|
123
|
-
v.call *[obj].take([v.arity, 0].max)
|
121
|
+
v.call *[obj, parent].take([v.arity, 0].max)
|
124
122
|
when Builder, BuilderSet
|
125
|
-
v.generate
|
123
|
+
v.generate(:parent => obj)
|
126
124
|
else
|
127
125
|
v
|
128
126
|
end
|
@@ -140,16 +138,21 @@ module Bricks
|
|
140
138
|
def set(name, val = nil, &block)
|
141
139
|
raise Bricks::BadSyntax, "Block and value given" if val && block_given?
|
142
140
|
|
143
|
-
|
141
|
+
nsym = name.to_sym
|
142
|
+
pair = @attrs.assoc(nsym) || (@attrs << [nsym, nil]).last
|
144
143
|
|
145
144
|
if block_given?
|
146
145
|
pair[-1] = block
|
146
|
+
|
147
|
+
self
|
147
148
|
elsif val
|
148
149
|
pair[-1] = val
|
149
|
-
|
150
|
-
|
151
|
-
elsif adapter.association?(@class,
|
152
|
-
pair[-1]
|
150
|
+
|
151
|
+
self
|
152
|
+
elsif adapter.association?(@class, nsym, :one)
|
153
|
+
pair[-1] = builder(adapter.association(@class, nsym).klass, @save)
|
154
|
+
elsif adapter.association?(@class, nsym, :many)
|
155
|
+
pair[-1] ||= BuilderSet.new(adapter.association(@class, nsym).klass)
|
153
156
|
else
|
154
157
|
raise Bricks::BadSyntax,
|
155
158
|
"No value or block given and not an association: #{name}."
|
data/lib/bricks/builder_set.rb
CHANGED
data/lib/bricks/dsl.rb
CHANGED
@@ -8,6 +8,10 @@ module Bricks
|
|
8
8
|
build(klass).generate
|
9
9
|
end
|
10
10
|
|
11
|
+
def build?(klass)
|
12
|
+
build(klass).generate(:search => true)
|
13
|
+
end
|
14
|
+
|
11
15
|
def create(klass)
|
12
16
|
builder(klass, true)
|
13
17
|
end
|
@@ -16,8 +20,12 @@ module Bricks
|
|
16
20
|
create(klass).generate
|
17
21
|
end
|
18
22
|
|
23
|
+
def create?(klass)
|
24
|
+
create(klass).generate(:search => true)
|
25
|
+
end
|
26
|
+
|
19
27
|
def builder(klass, save)
|
20
|
-
Bricks.builders[klass].derive(save)
|
28
|
+
Bricks.builders[klass].derive(:save => save)
|
21
29
|
end
|
22
30
|
end
|
23
31
|
end
|
data/lib/bricks.rb
CHANGED
data/spec/bricks_spec.rb
CHANGED
@@ -20,12 +20,14 @@ describe Bricks do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
builder Article do
|
23
|
-
author
|
24
|
-
title
|
25
|
-
body
|
23
|
+
author 'Jack Jupiter'
|
24
|
+
title 'a title'
|
25
|
+
body 'the body'
|
26
|
+
language 'Swahili'
|
27
|
+
|
26
28
|
formatted_title { |obj| obj.title + " by " + obj.author }
|
27
29
|
deferred { Time.now }
|
28
|
-
newspaper
|
30
|
+
newspaper.language { |_, article| article.language }
|
29
31
|
|
30
32
|
%w(Socrates Plato Aristotle).each { |n| readers.name(n) }
|
31
33
|
|
@@ -83,6 +85,18 @@ describe Bricks do
|
|
83
85
|
a.should be_saved
|
84
86
|
end
|
85
87
|
|
88
|
+
it "fetches an existing model instead of initializing it" do
|
89
|
+
create(Newspaper).name!("The First in Line")
|
90
|
+
|
91
|
+
create!(Newspaper).should == build?(Newspaper)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "fetches an existing model instead of creating it" do
|
95
|
+
create(Newspaper).name!("The First in Line")
|
96
|
+
|
97
|
+
create!(Newspaper).should == create?(Newspaper)
|
98
|
+
end
|
99
|
+
|
86
100
|
describe "with simple fields" do
|
87
101
|
it "initializes model fields" do
|
88
102
|
a = build!(Article)
|
@@ -101,6 +115,14 @@ describe Bricks do
|
|
101
115
|
it "uses the object being built in deferred initialization" do
|
102
116
|
build!(Article).formatted_title.should == "a title by Jack Jupiter"
|
103
117
|
end
|
118
|
+
|
119
|
+
it "fetches an existing model instead of creating it" do
|
120
|
+
create!(Newspaper)
|
121
|
+
|
122
|
+
n = create(Newspaper).name!("The Bugle Planet")
|
123
|
+
|
124
|
+
create(Newspaper).name?("The Bugle Planet").should == n
|
125
|
+
end
|
104
126
|
end
|
105
127
|
|
106
128
|
describe "with traits" do
|
@@ -144,6 +166,10 @@ describe Bricks do
|
|
144
166
|
should == 'The Daily Bugle'
|
145
167
|
end
|
146
168
|
|
169
|
+
it "passes the parent into a deferred block" do
|
170
|
+
build(Article).language!("Thai").newspaper.language.should == "Thai"
|
171
|
+
end
|
172
|
+
|
147
173
|
it "possibly looks for an existing record" do
|
148
174
|
n = create(Newspaper).daily_bugle!
|
149
175
|
a = create(Article).maybe_bugle!
|
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.4.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-21 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -70,6 +70,7 @@ files:
|
|
70
70
|
- .document
|
71
71
|
- .rspec
|
72
72
|
- Gemfile
|
73
|
+
- History.md
|
73
74
|
- LICENSE.txt
|
74
75
|
- README.md
|
75
76
|
- Rakefile
|
@@ -100,7 +101,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
100
101
|
requirements:
|
101
102
|
- - ">="
|
102
103
|
- !ruby/object:Gem::Version
|
103
|
-
hash: -
|
104
|
+
hash: -979563633
|
104
105
|
segments:
|
105
106
|
- 0
|
106
107
|
version: "0"
|