bldr 0.7.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Gemfile +3 -1
- data/HISTORY.md +3 -2
- data/README.md +89 -18
- data/lib/action_view/template/handlers/bldr.rb +24 -0
- data/lib/bldr.rb +1 -0
- data/lib/bldr/node.rb +104 -41
- data/lib/bldr/railtie.rb +9 -0
- data/lib/bldr/version.rb +1 -1
- data/spec/fixtures/templates/rails/people/index.json.bldr +4 -0
- data/spec/fixtures/templates/rails/people/show.json.bldr +7 -0
- data/spec/functional/helpers_spec.rb +57 -0
- data/spec/functional/params_spec.rb +26 -0
- data/spec/integration/rails_32_spec.rb +84 -0
- data/spec/integration/sinatra_spec.rb +20 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/unit/node_spec.rb +15 -4
- metadata +16 -3
data/Gemfile
CHANGED
data/HISTORY.md
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
## 0.7.0 (2013-
|
2
|
-
*
|
1
|
+
## 0.7.0 (2013-02-24)
|
2
|
+
* Full support for instance variables
|
3
3
|
* Breaking change: Node#attribute block syntax no longer inherits
|
4
4
|
context from current_object. See 941608e7 for more
|
5
|
+
* Block variables for `object` and `collection` methods
|
5
6
|
* Breaking change: Drop ruby 1.8 support
|
6
7
|
|
7
8
|
## 0.6.1 (2013-02-18) -- yanked
|
data/README.md
CHANGED
@@ -3,11 +3,67 @@
|
|
3
3
|
|
4
4
|
# Bldr
|
5
5
|
|
6
|
-
Bldr is a minimalist templating
|
7
|
-
json documents from ruby objects.
|
8
|
-
|
6
|
+
Bldr is a minimalist templating DSL that provides a simple syntax for generating
|
7
|
+
json documents from ruby objects. Bldr supports Sinatra and Rails
|
8
|
+
3.2.
|
9
9
|
|
10
|
-
|
10
|
+
Bldr enables to quickly generate json documents from ruby with a
|
11
|
+
simple and intuitive DSL.
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
# app/views/posts/index.json.bldr
|
15
|
+
|
16
|
+
collection @posts do |post|
|
17
|
+
attributes :title, :body, :created_at, :slug
|
18
|
+
|
19
|
+
object :author => post.author do |author|
|
20
|
+
attribute(:name) { author.display_name }
|
21
|
+
end
|
22
|
+
|
23
|
+
collection :comments => post.comments do |comment|
|
24
|
+
attribute :spamminess
|
25
|
+
attribute :created_at
|
26
|
+
attribute(:body) do
|
27
|
+
xss_filter(comment.body)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
This would output the following json document:
|
34
|
+
|
35
|
+
```json
|
36
|
+
[
|
37
|
+
{
|
38
|
+
"title": "Some title",
|
39
|
+
"body": "blah blah",
|
40
|
+
"slug": "some-title",
|
41
|
+
"created_at": "2013-04-11T15:46:17-07:00",
|
42
|
+
"author": {
|
43
|
+
"name": "Joe Author"
|
44
|
+
},
|
45
|
+
"comments": [
|
46
|
+
{
|
47
|
+
"spamminess": 1.0,
|
48
|
+
"created_at": "2013-04-11T15:46:17-07:00",
|
49
|
+
"body": "a comment"
|
50
|
+
}
|
51
|
+
]
|
52
|
+
}
|
53
|
+
]
|
54
|
+
```
|
55
|
+
|
56
|
+
## Usage
|
57
|
+
|
58
|
+
Bldr is a very concise DSL, containing only four core methods:
|
59
|
+
|
60
|
+
* `object`
|
61
|
+
* `collection`
|
62
|
+
* `attribute`
|
63
|
+
* `attributes`
|
64
|
+
|
65
|
+
These four methods provide a great deal of power and flexibility in describing
|
66
|
+
json responses.
|
11
67
|
|
12
68
|
## Why
|
13
69
|
|
@@ -15,18 +71,29 @@ If you're building an API, `Model#to_json` just doesn't cut it. Besides the JSON
|
|
15
71
|
representation of your models arguably being a presentation concern, trying
|
16
72
|
to cram all of this logic into an `#as_json` method quickly turns into pure chaos.
|
17
73
|
|
18
|
-
There are other json templating libraries available
|
74
|
+
There are other json templating libraries available such as
|
75
|
+
[rabl](https://github.com/nesquena/rabl) or [json_builder](https://github.com/dewski/json_builder).
|
76
|
+
Bldr is in the same vein as these libraries, but with a simpler synxtax.
|
19
77
|
|
20
|
-
##
|
78
|
+
## Usage & Examples
|
21
79
|
|
22
|
-
|
23
|
-
|
24
|
-
* Partials
|
80
|
+
See [Examples on the wiki](https://github.com/ajsharp/bldr/wiki/Documentation-&-Examples)
|
81
|
+
for documentation and usage examples.
|
25
82
|
|
26
83
|
## Installation
|
27
84
|
|
28
|
-
|
29
|
-
|
85
|
+
In your gemfile:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
gem 'bldr'
|
89
|
+
```
|
90
|
+
|
91
|
+
## Configuration
|
92
|
+
|
93
|
+
No additional configuration is required for rails applications.
|
94
|
+
|
95
|
+
For sinatra apps, dependening on whether you're using a modular or classic
|
96
|
+
application style, do one of the following:
|
30
97
|
|
31
98
|
```ruby
|
32
99
|
|
@@ -48,10 +115,6 @@ class MyApp < Sinatra::Base
|
|
48
115
|
end
|
49
116
|
```
|
50
117
|
|
51
|
-
## Usage
|
52
|
-
|
53
|
-
See the [Documentation & Examples](https://github.com/ajsharp/bldr/wiki/Documentation-&-Examples) page on the wiki.
|
54
|
-
|
55
118
|
## Deprecations & Breaking Changes
|
56
119
|
|
57
120
|
### 0.7.0: current_object deprecation
|
@@ -123,16 +186,24 @@ See [941608e](https://github.com/ajsharp/bldr/commit/d0bfbd8) and [d0bfbd8](http
|
|
123
186
|
|
124
187
|
## Editor Syntax Support
|
125
188
|
|
126
|
-
|
189
|
+
### Vim
|
190
|
+
|
191
|
+
Add this line to your .vimrc:
|
127
192
|
|
128
193
|
```
|
129
194
|
au BufRead,BufNewFile *.bldr set filetype=ruby
|
130
195
|
```
|
131
196
|
|
197
|
+
### Emacs
|
198
|
+
|
199
|
+
Add this to your `~/.emacs.d/init.el`:
|
200
|
+
|
201
|
+
```
|
202
|
+
(add-to-list 'auto-mode-alist '("\\.bldr$" . ruby-mode))
|
203
|
+
```
|
204
|
+
|
132
205
|
## TODO
|
133
206
|
|
134
|
-
* Rails 3 support. An attempt for this was made for this but was reverted in e1cfd7fcbe130b316d95773d8c73ece4e247200e. Feel free to take a shot.
|
135
|
-
* Replace current_object with a block param for collection methods
|
136
207
|
* XML support
|
137
208
|
|
138
209
|
## Acknowledgements
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ActionView::Template::Handlers
|
2
|
+
class Bldr
|
3
|
+
|
4
|
+
# @param [ActionView::Template] template the template instance
|
5
|
+
# @return [String] the rendered ruby code string to render the template
|
6
|
+
def self.call(template, opts = {})
|
7
|
+
source = if template.source.empty?
|
8
|
+
File.read(template.identifier)
|
9
|
+
else
|
10
|
+
template.source
|
11
|
+
end
|
12
|
+
|
13
|
+
%{
|
14
|
+
node = ::Bldr::Node.new(nil, parent: self, root: true) {
|
15
|
+
#{source}
|
16
|
+
}
|
17
|
+
MultiJson.encode node.result
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
ActionView::Template.register_template_handler :bldr, ActionView::Template::Handlers::Bldr
|
data/lib/bldr.rb
CHANGED
data/lib/bldr/node.rb
CHANGED
@@ -1,12 +1,22 @@
|
|
1
|
+
require 'forwardable'
|
1
2
|
|
2
3
|
module Bldr
|
3
4
|
|
4
5
|
class Node
|
6
|
+
extend Forwardable
|
5
7
|
|
8
|
+
# These do not get copied into child nodes. All other instance variables do.
|
6
9
|
PROTECTED_IVARS = [:@current_object, :@result, :@parent, :@opts, :@views, :@locals]
|
7
10
|
|
11
|
+
# List of bldr public api method. So we don't overwrite them when we do
|
12
|
+
# crazy ruby metaprogramming when we build nodes.
|
13
|
+
API_METHODS = [:object, :collection, :attribute, :attributes]
|
14
|
+
|
8
15
|
attr_reader :current_object, :result, :parent, :opts, :views, :locals
|
9
16
|
|
17
|
+
# @!attribute [r] request params from a rails or sinatra controller
|
18
|
+
attr_reader :params
|
19
|
+
|
10
20
|
# Initialize a new Node instance.
|
11
21
|
#
|
12
22
|
# @example Building a simple node
|
@@ -20,6 +30,9 @@ module Bldr
|
|
20
30
|
#
|
21
31
|
# @param [Object] value an object to serialize.
|
22
32
|
# @param [Hash] opts
|
33
|
+
# @option opts [Object] :parent The parent object is used to copy instance variables
|
34
|
+
# into each node in the node tree.
|
35
|
+
# @option opts [Boolean] :root indicates whether this is the root node or not
|
23
36
|
# @option [Object] opts :parent used to copy instance variables into self
|
24
37
|
def initialize(value = nil, opts = {}, &block)
|
25
38
|
@current_object = value
|
@@ -27,10 +40,27 @@ module Bldr
|
|
27
40
|
@parent = opts[:parent]
|
28
41
|
@views = opts[:views]
|
29
42
|
@locals = opts[:locals]
|
30
|
-
# Storage hash for all descendant nodes
|
31
|
-
@result = {}
|
43
|
+
@result = {} # Storage hash for all descendant nodes
|
32
44
|
|
33
|
-
|
45
|
+
# opts[:parent] will only get set to an ActionView::Base instance
|
46
|
+
# when rails renders a bldr template. This logic doesn't belong here,
|
47
|
+
# and there's a concept to be extracted here.
|
48
|
+
#
|
49
|
+
# The upshot of initializing the root node like this is that all child
|
50
|
+
# nodes will have access to rails helper methods. This is necessary
|
51
|
+
# due to the way bldr makes judicious use of instance_eval.
|
52
|
+
#
|
53
|
+
# @todo refactor this
|
54
|
+
if opts[:root] && @parent
|
55
|
+
# assign @parent to @view so it will be copied down to each child nod
|
56
|
+
# @parent is in PROTECTED_IVARS and won't be copied. This effectively
|
57
|
+
# gives all child nodes access to helper methods passed into the parent
|
58
|
+
@view = @parent
|
59
|
+
end
|
60
|
+
|
61
|
+
copy_instance_variables(@parent) if @parent
|
62
|
+
delegate_helpers if @view
|
63
|
+
assign_params if @parent
|
34
64
|
|
35
65
|
if block_given?
|
36
66
|
if value && block.arity > 0
|
@@ -94,12 +124,11 @@ module Bldr
|
|
94
124
|
value = nil
|
95
125
|
end
|
96
126
|
|
97
|
-
#
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
return nil if value.nil? and keyed_object?(base)
|
127
|
+
# handle nil objects
|
128
|
+
if value.nil? && keyed_object?(base)
|
129
|
+
merge_result!(key, nil)
|
130
|
+
return self
|
131
|
+
end
|
103
132
|
|
104
133
|
node = Node.new(value, opts.merge(:parent => self), &block)
|
105
134
|
merge_result!(key, node.result)
|
@@ -160,7 +189,7 @@ module Bldr
|
|
160
189
|
else
|
161
190
|
@result = massage_value(vals)
|
162
191
|
end
|
163
|
-
|
192
|
+
|
164
193
|
self
|
165
194
|
end
|
166
195
|
|
@@ -173,28 +202,7 @@ module Bldr
|
|
173
202
|
#
|
174
203
|
# @example Attribute aliasing
|
175
204
|
# object :person => dude do
|
176
|
-
# attributes :surname => :last_name
|
177
|
-
# end
|
178
|
-
#
|
179
|
-
# @example Dynamic attributes (explicit object context)
|
180
|
-
# object :person => employee do
|
181
|
-
# collection :colleagues => employee.colleagues do |colleague|
|
182
|
-
# attribute :isBoss do |colleague|
|
183
|
-
# employee.works_with?(colleague) && colleague.admin?
|
184
|
-
# end
|
185
|
-
# end
|
186
|
-
# end
|
187
|
-
#
|
188
|
-
# @example Dynamic attributes (implicit object context)
|
189
|
-
# object :person => dude do
|
190
|
-
# collection :colleagues => employee.colleagues do |colleague|
|
191
|
-
# attribute :rank do
|
192
|
-
# # method called on colleague
|
193
|
-
# if admin? && superior_to?(employee)
|
194
|
-
# "High Up"
|
195
|
-
# end
|
196
|
-
# end
|
197
|
-
# end
|
205
|
+
# attributes :surname => :last_name # invokes dude.last_name
|
198
206
|
# end
|
199
207
|
#
|
200
208
|
# @return [Nil]
|
@@ -213,25 +221,61 @@ module Bldr
|
|
213
221
|
self
|
214
222
|
end
|
215
223
|
|
216
|
-
|
224
|
+
# @example Dynamic attributes
|
225
|
+
# object :person => employee do
|
226
|
+
# collection :colleagues => employee.colleagues do |colleague|
|
227
|
+
# attribute :isBoss do
|
228
|
+
# employee.works_with?(colleague) && colleague.admin?
|
229
|
+
# end
|
230
|
+
# end
|
231
|
+
# end
|
232
|
+
#
|
233
|
+
def attribute(*args, &block)
|
217
234
|
if block_given?
|
218
|
-
|
219
|
-
|
235
|
+
# e.g. attribute(:one, :two) { "value" }
|
236
|
+
if args.size > 1
|
237
|
+
raise(ArgumentError, "You may only pass one argument to #attribute when using the block syntax.")
|
238
|
+
end
|
239
|
+
|
240
|
+
# e.g.
|
241
|
+
# object do
|
242
|
+
# attribute { 'value' }
|
243
|
+
# end
|
244
|
+
if block.arity > 0 && @current_object.nil?
|
245
|
+
raise(ArgumentError, "You cannot use a block of arity > 0 if current_object is not present.")
|
246
|
+
end
|
247
|
+
|
220
248
|
if block.arity > 0
|
249
|
+
# object(person: @person) do
|
250
|
+
# attribute(:name) { |person| person.name }
|
251
|
+
# end
|
221
252
|
merge_result! args.first, block.call(@current_object)
|
222
253
|
else
|
254
|
+
# object(person: @person) do
|
255
|
+
# attribute(:name) # i.e. @person.name
|
256
|
+
# end
|
223
257
|
merge_result! args.first, block.call
|
224
258
|
end
|
225
259
|
else
|
226
260
|
case args.size
|
227
|
-
when 1
|
261
|
+
when 1
|
262
|
+
# object do
|
263
|
+
# attribute(:name)
|
264
|
+
# end
|
228
265
|
raise(ArgumentError, "#attribute can't be used when there is no current_object.") if @current_object.nil?
|
229
266
|
if args[0].is_a?(Hash)
|
267
|
+
# object(person: @person) do
|
268
|
+
# attribute :key => :display_name # i.e. @person.display_name
|
269
|
+
# end
|
230
270
|
merge_result!(args[0].keys.first, @current_object.send(args[0].values.first))
|
231
271
|
else
|
272
|
+
# object(person: @person) do
|
273
|
+
# attribute :name
|
274
|
+
# end
|
232
275
|
merge_result!(args[0], @current_object.send(args[0]))
|
233
276
|
end
|
234
|
-
when 2
|
277
|
+
when 2
|
278
|
+
# attribute :name, @person.name
|
235
279
|
merge_result!(args[0], args[1])
|
236
280
|
else
|
237
281
|
raise(ArgumentError, "You cannot pass more than two arguments to #attribute.")
|
@@ -246,7 +290,7 @@ module Bldr
|
|
246
290
|
# object :person => dude do
|
247
291
|
# template "path/to/template"
|
248
292
|
# end
|
249
|
-
#
|
293
|
+
#
|
250
294
|
# @example Using locals
|
251
295
|
# object :person => dude do
|
252
296
|
# template "path/to/template", :locals => {:foo => 'bar'}
|
@@ -269,13 +313,32 @@ module Bldr
|
|
269
313
|
# current scope.
|
270
314
|
#
|
271
315
|
# @param [Object] object The object to copy instance variables from.
|
272
|
-
def
|
316
|
+
def copy_instance_variables(object)
|
273
317
|
ivar_names = (object.instance_variables - PROTECTED_IVARS).map(&:to_s)
|
274
318
|
ivar_names.map do |name|
|
275
319
|
instance_variable_set(name, object.instance_variable_get(name))
|
276
320
|
end
|
277
321
|
end
|
278
322
|
|
323
|
+
# Delegate helper methods on the @view to @view
|
324
|
+
def delegate_helpers
|
325
|
+
# ActionView::Base instances carry a method called helpers,
|
326
|
+
# which is a module that contains helper methods available in a rails
|
327
|
+
# controller.
|
328
|
+
@_helpers = @view.helpers if @view.respond_to?(:helpers)
|
329
|
+
|
330
|
+
# Delegate all helper methods, minus those with the same name as any
|
331
|
+
# bldr api methods to @view via this object's metaclass
|
332
|
+
if @_helpers
|
333
|
+
(class << self; self; end).def_delegators :@view, *(@_helpers.instance_methods - API_METHODS)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
# Assigns the params attribute from the parent.
|
338
|
+
def assign_params
|
339
|
+
@params = @parent.params if @parent.respond_to?(:params)
|
340
|
+
end
|
341
|
+
|
279
342
|
# Determines if an object was passed in with a key pointing to it, or if
|
280
343
|
# it was passed in as the "root" of the current object. Essentially, this
|
281
344
|
# checks if `obj` quacks like a hash.
|
@@ -285,7 +348,7 @@ module Bldr
|
|
285
348
|
def keyed_object?(obj)
|
286
349
|
obj.respond_to?(:keys)
|
287
350
|
end
|
288
|
-
|
351
|
+
|
289
352
|
def find_template(template)
|
290
353
|
path = []
|
291
354
|
path << views if views
|
@@ -312,6 +375,6 @@ module Bldr
|
|
312
375
|
val
|
313
376
|
end
|
314
377
|
end
|
315
|
-
|
378
|
+
|
316
379
|
end
|
317
380
|
end
|
data/lib/bldr/railtie.rb
ADDED
data/lib/bldr/version.rb
CHANGED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Bldr
|
4
|
+
describe Node, 'delegating helper methods' do
|
5
|
+
before do
|
6
|
+
# mock version of a module of methods that would be attached
|
7
|
+
# to an ActionView::Base instance
|
8
|
+
helpers = Module.new do
|
9
|
+
def my_helper
|
10
|
+
'my helper'
|
11
|
+
end
|
12
|
+
|
13
|
+
def helper_with_args_and_block(one, two)
|
14
|
+
yield if block_given?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# set up a mock ActionView::Base instance
|
19
|
+
mock_action_view = Struct.new(:helpers)
|
20
|
+
@view = mock_action_view.new(helpers)
|
21
|
+
@view.extend(helpers)
|
22
|
+
|
23
|
+
@node = Node.new(nil, root: true, parent: @view)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'delegates the methods to the parent object' do
|
27
|
+
@view.should_receive(:my_helper)
|
28
|
+
@node.my_helper
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'gives access to helper methods to child nodes' do
|
32
|
+
node = Node.new(nil, root: true, parent: @view) do
|
33
|
+
object(:foo => Object.new) do
|
34
|
+
attribute(:bar) { my_helper }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
node.result.should == {foo: {bar: 'my helper'}}
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'assigns opts[:parent] as a @view instance variable' do
|
41
|
+
@node.instance_variable_get(:@view).should == @view
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'delegates arguments and blocks to the parent' do
|
45
|
+
lam = lambda { }
|
46
|
+
@view.should_receive(:helper_with_args_and_block).with(1, 2, lam)
|
47
|
+
@node.helper_with_args_and_block(1, 2, lam)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'defines helper methods on a per-instance basis' do
|
51
|
+
@node.methods.should include :my_helper
|
52
|
+
|
53
|
+
new_parent = Struct.new(nil).new
|
54
|
+
Node.new(nil, root: true, parent: new_parent).methods.should_not include :my_helper
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Bldr
|
4
|
+
describe Node, 'access to the params hash' do
|
5
|
+
let(:params) { {foo: 'bar'} }
|
6
|
+
let(:parent) { Struct.new(:params).new(params) }
|
7
|
+
|
8
|
+
it 'has access in the root node' do
|
9
|
+
Node.new(nil, parent: parent) do
|
10
|
+
attribute(:foo) { params[:foo] }
|
11
|
+
end.result.should == {
|
12
|
+
foo: 'bar'
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'has access in child nodes' do
|
17
|
+
Node.new(nil, parent: parent) do
|
18
|
+
object(:foo) do
|
19
|
+
attribute(:baz) { params[:foo] }
|
20
|
+
end
|
21
|
+
end.result.should == {
|
22
|
+
foo: {baz: 'bar'}
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rails'
|
3
|
+
require 'action_controller/railtie'
|
4
|
+
require 'bldr/railtie'
|
5
|
+
|
6
|
+
describe 'a template for a rails controller' do
|
7
|
+
TestRailsApp = Class.new(Rails::Application) do
|
8
|
+
routes.append do
|
9
|
+
resources :people
|
10
|
+
end
|
11
|
+
|
12
|
+
config.secret_token = "secret"
|
13
|
+
config.session_store = :disabled
|
14
|
+
config.active_support.deprecation = nil
|
15
|
+
config.middleware.delete 'ActionDispatch::Session::CookieStore'
|
16
|
+
end
|
17
|
+
|
18
|
+
class PeopleController < ActionController::Base
|
19
|
+
helper_method :boss?
|
20
|
+
|
21
|
+
# GET /people
|
22
|
+
def index
|
23
|
+
@people = [Person.new('Dave Chappelle'), Person.new('Chris Rock')]
|
24
|
+
render 'spec/fixtures/templates/rails/people/index', handlers: [:bldr], formats: [:json]
|
25
|
+
end
|
26
|
+
|
27
|
+
# GET /people/:id
|
28
|
+
def show
|
29
|
+
@person = Person.new('Dave Chappelle')
|
30
|
+
render 'spec/fixtures/templates/rails/people/show', handlers: [:bldr], formats: [:json]
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def boss?(person)
|
35
|
+
person.name == 'Dave Chappelle'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
TestRailsApp.initialize!
|
40
|
+
|
41
|
+
def app
|
42
|
+
TestRailsApp.app
|
43
|
+
end
|
44
|
+
|
45
|
+
def get(url)
|
46
|
+
Rack::MockRequest.new(app).get(url)
|
47
|
+
end
|
48
|
+
|
49
|
+
def decode(d)
|
50
|
+
MultiJson.decode(d)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'returns 200' do
|
54
|
+
get('/people').status.should == 200
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'returns a json response body' do
|
58
|
+
decode(get('/people').body).should == [
|
59
|
+
{'name' => 'Dave Chappelle'},
|
60
|
+
{'name' => 'Chris Rock'}
|
61
|
+
]
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'returns json content type' do
|
65
|
+
get('/people').content_type.should =~ %r{application/json}
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'has access to controller helper methods' do
|
69
|
+
response = get('/people/123?use_boss_helper=true')
|
70
|
+
response.status.should == 200
|
71
|
+
decode(response.body).should == {
|
72
|
+
'id' => '123',
|
73
|
+
'name' => 'Dave Chappelle',
|
74
|
+
'boss' => true
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'has access to params' do
|
79
|
+
decode(get('/people/123').body).should == {
|
80
|
+
'id' => '123',
|
81
|
+
'name' => 'Dave Chappelle'
|
82
|
+
}
|
83
|
+
end
|
84
|
+
end
|
@@ -11,6 +11,19 @@ describe "Using Bldr with a sinatra app" do
|
|
11
11
|
disable :show_exceptions
|
12
12
|
enable :raise_errors
|
13
13
|
|
14
|
+
get '/people/:id' do
|
15
|
+
@alex = Person.new("alex", 25)
|
16
|
+
|
17
|
+
tpl = %{
|
18
|
+
object(:person => @alex) do
|
19
|
+
attribute(:id) { params['id'] }
|
20
|
+
attribute :name
|
21
|
+
end
|
22
|
+
}
|
23
|
+
status 200
|
24
|
+
bldr tpl
|
25
|
+
end
|
26
|
+
|
14
27
|
get '/' do
|
15
28
|
alex = Person.new("alex", 25)
|
16
29
|
tpl = <<-RUBY
|
@@ -67,6 +80,13 @@ describe "Using Bldr with a sinatra app" do
|
|
67
80
|
end
|
68
81
|
end
|
69
82
|
|
83
|
+
it 'has access to the params hash in bldr templates' do
|
84
|
+
response = Rack::MockRequest.new(TestApp).get('/people/123')
|
85
|
+
decode(response.body).should == {
|
86
|
+
'person' => { 'id' => '123', 'name' => 'alex'}
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
70
90
|
it 'passes ivars through to the template' do
|
71
91
|
response = Rack::MockRequest.new(TestApp).get('/ivar')
|
72
92
|
decode(response.body).should == {'person' => {'name' => 'bert', 'age' => 99}}
|
data/spec/spec_helper.rb
CHANGED
data/spec/unit/node_spec.rb
CHANGED
@@ -163,6 +163,19 @@ module Bldr
|
|
163
163
|
end
|
164
164
|
|
165
165
|
describe Node, "#object" do
|
166
|
+
it 'renders the object structure for a nil object' do
|
167
|
+
node = Node.new do
|
168
|
+
object :person => nil do
|
169
|
+
attributes :name
|
170
|
+
end
|
171
|
+
attribute(:foo) { "bar" }
|
172
|
+
end
|
173
|
+
node.result.should == {
|
174
|
+
person: nil,
|
175
|
+
foo: 'bar'
|
176
|
+
}
|
177
|
+
end
|
178
|
+
|
166
179
|
it 'is passes block the block variable to the block' do
|
167
180
|
denver = Person.new('John Denver')
|
168
181
|
node = Node.new do
|
@@ -231,7 +244,6 @@ module Bldr
|
|
231
244
|
end
|
232
245
|
end
|
233
246
|
|
234
|
-
|
235
247
|
describe "#attributes" do
|
236
248
|
describe "when an object key is passed a null value" do
|
237
249
|
subject {
|
@@ -250,13 +262,14 @@ module Bldr
|
|
250
262
|
}.not_to raise_error(ArgumentError, ERROR_MESSAGES[:attributes_inferred_missing])
|
251
263
|
end
|
252
264
|
|
253
|
-
its(:result) { should == {} }
|
265
|
+
its(:result) { should == {:person => nil} }
|
254
266
|
end
|
255
267
|
|
256
268
|
it "renders each argument against the inferred object" do
|
257
269
|
node = wrap { attributes(:name, :age) }
|
258
270
|
node.result.should == {:person => {:name => 'alex', :age => 25}}
|
259
271
|
end
|
272
|
+
|
260
273
|
it "renders nil attributes" do
|
261
274
|
node = node_wrap do
|
262
275
|
object :person => Person.new('alex') do
|
@@ -266,9 +279,7 @@ module Bldr
|
|
266
279
|
|
267
280
|
node.result.should == {:person => {:name => 'alex', :age => nil}}
|
268
281
|
end
|
269
|
-
|
270
282
|
end
|
271
|
-
|
272
283
|
end
|
273
284
|
|
274
285
|
describe "embedded objects" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bldr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-05-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: multi_json
|
@@ -124,8 +124,10 @@ files:
|
|
124
124
|
- README.md
|
125
125
|
- Rakefile
|
126
126
|
- bldr.gemspec
|
127
|
+
- lib/action_view/template/handlers/bldr.rb
|
127
128
|
- lib/bldr.rb
|
128
129
|
- lib/bldr/node.rb
|
130
|
+
- lib/bldr/railtie.rb
|
129
131
|
- lib/bldr/template.rb
|
130
132
|
- lib/bldr/version.rb
|
131
133
|
- lib/sinatra/bldr.rb
|
@@ -140,8 +142,13 @@ files:
|
|
140
142
|
- spec/fixtures/root_partial.bldr
|
141
143
|
- spec/fixtures/root_template.json.bldr
|
142
144
|
- spec/fixtures/some/include.json.bldr
|
145
|
+
- spec/fixtures/templates/rails/people/index.json.bldr
|
146
|
+
- spec/fixtures/templates/rails/people/show.json.bldr
|
143
147
|
- spec/functional/handlers_spec.rb
|
148
|
+
- spec/functional/helpers_spec.rb
|
149
|
+
- spec/functional/params_spec.rb
|
144
150
|
- spec/functional/tilt_template_spec.rb
|
151
|
+
- spec/integration/rails_32_spec.rb
|
145
152
|
- spec/integration/sinatra_spec.rb
|
146
153
|
- spec/models/comment.rb
|
147
154
|
- spec/models/person.rb
|
@@ -170,7 +177,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
177
|
version: '0'
|
171
178
|
requirements: []
|
172
179
|
rubyforge_project: bldr
|
173
|
-
rubygems_version: 1.8.
|
180
|
+
rubygems_version: 1.8.25
|
174
181
|
signing_key:
|
175
182
|
specification_version: 3
|
176
183
|
summary: Templating library with a simple, minimalist DSL.
|
@@ -183,8 +190,13 @@ test_files:
|
|
183
190
|
- spec/fixtures/root_partial.bldr
|
184
191
|
- spec/fixtures/root_template.json.bldr
|
185
192
|
- spec/fixtures/some/include.json.bldr
|
193
|
+
- spec/fixtures/templates/rails/people/index.json.bldr
|
194
|
+
- spec/fixtures/templates/rails/people/show.json.bldr
|
186
195
|
- spec/functional/handlers_spec.rb
|
196
|
+
- spec/functional/helpers_spec.rb
|
197
|
+
- spec/functional/params_spec.rb
|
187
198
|
- spec/functional/tilt_template_spec.rb
|
199
|
+
- spec/integration/rails_32_spec.rb
|
188
200
|
- spec/integration/sinatra_spec.rb
|
189
201
|
- spec/models/comment.rb
|
190
202
|
- spec/models/person.rb
|
@@ -193,3 +205,4 @@ test_files:
|
|
193
205
|
- spec/spec_helper.rb
|
194
206
|
- spec/unit/bldr_spec.rb
|
195
207
|
- spec/unit/node_spec.rb
|
208
|
+
has_rdoc:
|