bricks 0.3.0 → 0.4.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 +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"
|