bldr 0.7.0 → 1.0.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/.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:
|