rabl 0.5.5.e → 0.5.5.f
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/CHANGELOG.md +4 -1
- data/README.md +11 -2
- data/lib/rabl/builder.rb +10 -9
- data/lib/rabl/engine.rb +24 -21
- data/lib/rabl/helpers.rb +22 -1
- data/lib/rabl/partials.rb +11 -3
- data/lib/rabl/version.rb +1 -1
- data/test/builder_test.rb +2 -2
- data/test/engine_test.rb +20 -3
- metadata +1 -1
data/CHANGELOG.md
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
-
## 0.5.5.a-
|
3
|
+
## 0.5.5.a-f
|
4
4
|
|
5
5
|
* Change engine to only instantiate one builder when rendering a collection
|
6
6
|
* Alias to\_msgpack to to\_mpac
|
7
7
|
* Cache template sources for faster partial lookups (thanks cj)
|
8
8
|
* Adds BSON format support (thanks Antiarchitect)
|
9
|
+
* Use template lookup mechanism to find templates in Rails 3 (thanks blakewatters)
|
10
|
+
* Adds a 'object_root' option to collection (thanks blakewatters)
|
11
|
+
* Adds a 'root_name' option to collection
|
9
12
|
|
10
13
|
## 0.5.4
|
11
14
|
|
data/README.md
CHANGED
@@ -165,7 +165,9 @@ To enable, include the bson gem in your project's Gemfile. Then use Rabl as norm
|
|
165
165
|
# Gemfile
|
166
166
|
gem 'bson', '~> 1.5.2'
|
167
167
|
```
|
168
|
-
|
168
|
+
|
169
|
+
To use it with Rails, also register the bson mime type format:
|
170
|
+
|
169
171
|
```ruby
|
170
172
|
# config/initializers/mime_types.rb
|
171
173
|
Mime::Type.register "application/bson", :bson
|
@@ -214,13 +216,20 @@ collection @users
|
|
214
216
|
# => [ { "user" : { ... } } ]
|
215
217
|
```
|
216
218
|
|
217
|
-
or
|
219
|
+
or specify a root node label for the collection:
|
218
220
|
|
219
221
|
```ruby
|
220
222
|
collection @users => :people
|
221
223
|
# => { "people" : [ { "person" : { ... } } ] }
|
222
224
|
```
|
223
225
|
|
226
|
+
or even specify both the child and root labels for a collection:
|
227
|
+
|
228
|
+
```ruby
|
229
|
+
collection @users, :root_name => "people", :object_root => "user"
|
230
|
+
# => { "people" : [ { "user" : { ... } } ] }
|
231
|
+
```
|
232
|
+
|
224
233
|
and this will be used as the default data for the rendering.
|
225
234
|
|
226
235
|
There can also be odd cases where the root-level of the response doesn't map directly to any object:
|
data/lib/rabl/builder.rb
CHANGED
@@ -3,25 +3,26 @@ module Rabl
|
|
3
3
|
include Rabl::Partials
|
4
4
|
|
5
5
|
# Constructs a new rabl hash based on given object and options
|
6
|
-
# options = { :format => "json", :
|
7
|
-
# :
|
6
|
+
# options = { :format => "json", :root => true, :child_root => true,
|
7
|
+
# :attributes, :node, :child, :glue, :extends }
|
8
|
+
#
|
8
9
|
def initialize(options={}, &block)
|
9
10
|
@options = options
|
10
11
|
@_scope = options[:scope]
|
11
12
|
end
|
12
13
|
|
13
14
|
# Given an object and options, returns the hash representation
|
14
|
-
# build(@user, :format => "json", :attributes => { ... })
|
15
|
-
def build(
|
16
|
-
@
|
17
|
-
@_object = data_object(data)
|
15
|
+
# build(@user, :format => "json", :attributes => { ... }, :root_name => "user")
|
16
|
+
def build(object, options={})
|
17
|
+
@_object = object
|
18
18
|
compile_hash(options)
|
19
19
|
end
|
20
20
|
|
21
21
|
protected
|
22
22
|
|
23
23
|
# Returns a hash representation of the data object
|
24
|
-
# compile_hash(:
|
24
|
+
# compile_hash(:root_name => false)
|
25
|
+
# compile_hash(:root_name => "user")
|
25
26
|
def compile_hash(options={})
|
26
27
|
@_result = {}
|
27
28
|
# Extends
|
@@ -46,8 +47,8 @@ module Rabl
|
|
46
47
|
end if @options.has_key?(:glue)
|
47
48
|
|
48
49
|
# Wrap result in root
|
49
|
-
if
|
50
|
-
@_root_name
|
50
|
+
if options[:root_name].present?
|
51
|
+
@_root_name = options[:root_name]
|
51
52
|
else # no root
|
52
53
|
@_root_name = nil
|
53
54
|
end
|
data/lib/rabl/engine.rb
CHANGED
@@ -31,17 +31,15 @@ module Rabl
|
|
31
31
|
# to_hash(:root => true, :child_root => true)
|
32
32
|
def to_hash(options={})
|
33
33
|
options = @_options.merge(options)
|
34
|
-
data = data_object(@_data)
|
34
|
+
data, root_name = data_object(@_data), data_name(@_data)
|
35
35
|
builder = Rabl::Builder.new(options)
|
36
36
|
if is_object?(data) || !data # object @user
|
37
|
-
|
37
|
+
options[:root_name] = root_name if options[:root]
|
38
|
+
builder.build(data, options)
|
38
39
|
elsif is_collection?(data) # collection @users
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
else # skip root name
|
43
|
-
data.map { |object| builder.build(object, options) }
|
44
|
-
end
|
40
|
+
options[:root_name] = object_root_name if object_root_name
|
41
|
+
options[:root_name] ||= root_name.to_s.singularize if options[:root]
|
42
|
+
data.map { |object| builder.build(object, options) }
|
45
43
|
end
|
46
44
|
end
|
47
45
|
|
@@ -50,7 +48,7 @@ module Rabl
|
|
50
48
|
def to_json(options={})
|
51
49
|
include_root = Rabl.configuration.include_json_root
|
52
50
|
options = options.reverse_merge(:root => include_root, :child_root => include_root)
|
53
|
-
result =
|
51
|
+
result = collection_root_name ? { collection_root_name => to_hash(options) } : to_hash(options)
|
54
52
|
format_json(result)
|
55
53
|
end
|
56
54
|
|
@@ -59,7 +57,7 @@ module Rabl
|
|
59
57
|
def to_msgpack(options={})
|
60
58
|
include_root = Rabl.configuration.include_msgpack_root
|
61
59
|
options = options.reverse_merge(:root => include_root, :child_root => include_root)
|
62
|
-
result =
|
60
|
+
result = collection_root_name ? { collection_root_name => to_hash(options) } : to_hash(options)
|
63
61
|
Rabl.configuration.msgpack_engine.pack result
|
64
62
|
end
|
65
63
|
alias_method :to_mpac, :to_msgpack
|
@@ -78,8 +76,8 @@ module Rabl
|
|
78
76
|
def to_bson(options={})
|
79
77
|
include_root = Rabl.configuration.include_bson_root
|
80
78
|
options = options.reverse_merge(:root => include_root, :child_root => include_root)
|
81
|
-
result = if
|
82
|
-
{
|
79
|
+
result = if collection_root_name
|
80
|
+
{ collection_root_name => to_hash(options) }
|
83
81
|
elsif is_collection?(@_data) && @_data.is_a?(Array)
|
84
82
|
{ data_name(@_data) => to_hash(options) }
|
85
83
|
else
|
@@ -99,8 +97,12 @@ module Rabl
|
|
99
97
|
# Sets the object as a collection casted to a simple array
|
100
98
|
# collection @users
|
101
99
|
# collection @users => :people
|
102
|
-
|
103
|
-
|
100
|
+
# collection @users, :root => :person
|
101
|
+
# collection @users, :object_root => :person
|
102
|
+
def collection(data, options={})
|
103
|
+
@_collection_name = options[:root] if options[:root]
|
104
|
+
@_collection_name ||= data.values.first if data.respond_to?(:each_pair)
|
105
|
+
@_object_root_name = options[:object_root] if options[:object_root]
|
104
106
|
self.object(data_object(data).to_a) if data
|
105
107
|
end
|
106
108
|
|
@@ -155,8 +157,8 @@ module Rabl
|
|
155
157
|
# Returns a guess at the default object for this template
|
156
158
|
# default_object => @user
|
157
159
|
def default_object
|
158
|
-
if
|
159
|
-
full_name =
|
160
|
+
if context_scope.respond_to?(:controller)
|
161
|
+
full_name = context_scope.controller.controller_name
|
160
162
|
instance_variable_get("@#{ full_name.split("::").last }")
|
161
163
|
end
|
162
164
|
end
|
@@ -164,8 +166,8 @@ module Rabl
|
|
164
166
|
# Returns a guess at the format in this scope
|
165
167
|
# request_format => "xml"
|
166
168
|
def request_format
|
167
|
-
format = self.request_params.has_key?(:format) ?
|
168
|
-
if request =
|
169
|
+
format = self.request_params.has_key?(:format) ? context_scope.params[:format] : nil
|
170
|
+
if request = context_scope.respond_to?(:request) && context_scope.request
|
169
171
|
format ||= request.format.to_sym.to_s if request.respond_to?(:format)
|
170
172
|
end
|
171
173
|
format && self.respond_to?("to_#{format}") ? format : "json"
|
@@ -174,7 +176,7 @@ module Rabl
|
|
174
176
|
# Returns the request parameters if available in the scope
|
175
177
|
# request_params => { :foo => "bar" }
|
176
178
|
def request_params
|
177
|
-
|
179
|
+
context_scope.respond_to?(:params) ? context_scope.params : {}
|
178
180
|
end
|
179
181
|
|
180
182
|
# Returns data as json embraced with callback when detected
|
@@ -188,12 +190,12 @@ module Rabl
|
|
188
190
|
|
189
191
|
# Augments respond to supporting scope methods
|
190
192
|
def respond_to?(name, include_private=false)
|
191
|
-
|
193
|
+
context_scope.respond_to?(name, include_private) ? true : super
|
192
194
|
end
|
193
195
|
|
194
196
|
# Supports calling helpers defined for the template scope using method_missing hook
|
195
197
|
def method_missing(name, *args, &block)
|
196
|
-
|
198
|
+
context_scope.respond_to?(name) ? context_scope.send(name, *args, &block) : super
|
197
199
|
end
|
198
200
|
|
199
201
|
def copy_instance_variables_from(object, exclude = []) #:nodoc:
|
@@ -210,6 +212,7 @@ module Rabl
|
|
210
212
|
@_options[:child] = []
|
211
213
|
@_options[:glue] = []
|
212
214
|
@_options[:extends] = []
|
215
|
+
@_options[:root_name] = nil
|
213
216
|
end
|
214
217
|
end
|
215
218
|
end
|
data/lib/rabl/helpers.rb
CHANGED
@@ -23,7 +23,8 @@ module Rabl
|
|
23
23
|
if data.respond_to?(:first)
|
24
24
|
data_name(data.first).to_s.pluralize if data.first.present?
|
25
25
|
else # actual data object
|
26
|
-
object_name =
|
26
|
+
object_name = object_root_name if object_root_name
|
27
|
+
object_name ||= collection_root_name.to_s.singularize if collection_root_name
|
27
28
|
object_name ||= data.class.respond_to?(:model_name) ? data.class.model_name.element : data.class.to_s.downcase
|
28
29
|
object_name
|
29
30
|
end
|
@@ -42,5 +43,25 @@ module Rabl
|
|
42
43
|
obj && data_object(obj).respond_to?(:each)
|
43
44
|
end
|
44
45
|
|
46
|
+
# Returns the scope wrapping this engine, used for retrieving data, invoking methods, etc
|
47
|
+
# In Rails, this is the controller and in Padrino this is the request context
|
48
|
+
def context_scope
|
49
|
+
defined?(@_scope) ? @_scope : nil
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns the root (if any) name for an object within a collection
|
53
|
+
# Sets the name of the object i.e "person"
|
54
|
+
# => { "users" : [{ "person" : {} }] }
|
55
|
+
def object_root_name
|
56
|
+
defined?(@_object_root_name) ? @_object_root_name : nil
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the root for the collection
|
60
|
+
# Sets the name of the collection i.e "people"
|
61
|
+
# => { "people" : [] }
|
62
|
+
def collection_root_name
|
63
|
+
defined?(@_collection_name) ? @_collection_name : nil
|
64
|
+
end
|
65
|
+
|
45
66
|
end
|
46
67
|
end
|
data/lib/rabl/partials.rb
CHANGED
@@ -7,6 +7,7 @@ module Rabl
|
|
7
7
|
# options must have :object
|
8
8
|
# options can have :view_path, :child_root, :root
|
9
9
|
def partial(file, options={}, &block)
|
10
|
+
raise ArgumentError, "Must provide an :object option to render a partial" unless options[:object]
|
10
11
|
object, view_path = options.delete(:object), options.delete(:view_path)
|
11
12
|
source, location = self.fetch_source(file, :view_path => view_path)
|
12
13
|
engine_options = options.merge(:source => source, :source_location => location)
|
@@ -35,9 +36,16 @@ module Rabl
|
|
35
36
|
# Padrino chops the extension, stitch it back on
|
36
37
|
file_path = File.join(@_scope.settings.views, (file_path.to_s + ".rabl"))
|
37
38
|
elsif defined? Rails
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
if defined?(@_scope) && @_scope.respond_to?(:find_template)
|
40
|
+
# use Rails's own template resolution mechanism (partials and no partial)
|
41
|
+
lookup_proc = lambda { |partial| @_scope.find_template(file, [], partial) }
|
42
|
+
template = lookup_proc.call(false) rescue lookup_proc.call(true)
|
43
|
+
file_path = File.join(Rails.root.to_s, template.inspect) if template
|
44
|
+
else # fallback to manual
|
45
|
+
root_path = Rails.root
|
46
|
+
view_path = options[:view_path] || File.join(root_path, "app/views/")
|
47
|
+
file_path = Dir[File.join(view_path, file + ".{*.,}rabl")].first
|
48
|
+
end
|
41
49
|
elsif defined? Sinatra
|
42
50
|
view_path = options[:view_path] || @_scope.settings.views
|
43
51
|
file_path = Dir[File.join(view_path, file + ".{*.,}rabl")].first
|
data/lib/rabl/version.rb
CHANGED
data/test/builder_test.rb
CHANGED
@@ -28,7 +28,7 @@ context "Rabl::Builder" do
|
|
28
28
|
|
29
29
|
setup { builder({ :attributes => { :name => :name } }) }
|
30
30
|
asserts "that the object is set properly" do
|
31
|
-
topic.build(User.new, :
|
31
|
+
topic.build(User.new, :root_name => "user")
|
32
32
|
end.equivalent_to({ "user" => { :name => "rabl" } })
|
33
33
|
|
34
34
|
end
|
@@ -37,7 +37,7 @@ context "Rabl::Builder" do
|
|
37
37
|
|
38
38
|
setup { builder({ :attributes => { :name => :name } }) }
|
39
39
|
asserts "that the object is set properly" do
|
40
|
-
topic.build(
|
40
|
+
topic.build(User.new, :root_name => "person")
|
41
41
|
end.equivalent_to({ "person" => { :name => "rabl" } })
|
42
42
|
|
43
43
|
end
|
data/test/engine_test.rb
CHANGED
@@ -263,15 +263,32 @@ context "Rabl::Engine" do
|
|
263
263
|
template.render(scope)
|
264
264
|
end.equals "[{},{}]"
|
265
265
|
|
266
|
-
asserts "that it sets root node for objects" do
|
266
|
+
asserts "that it sets root node for objects using hash" do
|
267
267
|
template = rabl %{
|
268
|
-
collection @users => :
|
268
|
+
collection @users => :people
|
269
269
|
}
|
270
270
|
scope = Object.new
|
271
271
|
scope.instance_variable_set :@users, [User.new, User.new]
|
272
272
|
template.render(scope)
|
273
|
-
end.equals "{\"
|
273
|
+
end.equals "{\"people\":[{},{}]}"
|
274
274
|
|
275
|
+
asserts "that it sets root node for objects using root option" do
|
276
|
+
template = rabl %{
|
277
|
+
collection @users, :root => :people
|
278
|
+
}
|
279
|
+
scope = Object.new
|
280
|
+
scope.instance_variable_set :@users, [User.new, User.new]
|
281
|
+
template.render(scope)
|
282
|
+
end.equals "{\"people\":[{},{}]}"
|
283
|
+
|
284
|
+
asserts "that it sets root node for objects using object_root option" do
|
285
|
+
template = rabl %{
|
286
|
+
collection @users, :root => :humans, :object_root => :person
|
287
|
+
}
|
288
|
+
scope = Object.new
|
289
|
+
scope.instance_variable_set :@users, [User.new, User.new]
|
290
|
+
template.render(scope)
|
291
|
+
end.equals %Q^{"humans":[{"person":{}},{"person":{}}]}^
|
275
292
|
end
|
276
293
|
|
277
294
|
context "#attribute" do
|