rabl 0.5.5.e → 0.5.5.f

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,11 +1,14 @@
1
1
  # CHANGELOG
2
2
 
3
- ## 0.5.5.a-e
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
- To use it with Rails just register bson mime type format.
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 even specify a root node label for the collection:
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:
@@ -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", :attributes, :root => true,
7
- # :child_root => true, :node, :child, :glue, :extends }
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(data, options={})
16
- @_data = data
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(:root => true)
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 @options[:root] || options[:root]
50
- @_root_name ||= data_name(@_data)
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
@@ -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
- builder.build(@_data, options)
37
+ options[:root_name] = root_name if options[:root]
38
+ builder.build(data, options)
38
39
  elsif is_collection?(data) # collection @users
39
- if options[:root] # only calculate root name if needed
40
- object_name = data_name(@_data).to_s.singularize # @users => :users
41
- data.map { |object| builder.build({ object => object_name }, options) }
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 = defined?(@_collection_name) ? { @_collection_name => to_hash(options) } : to_hash(options)
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 = defined?(@_collection_name) ? { @_collection_name => to_hash(options) } : to_hash(options)
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 defined?(@_collection_name)
82
- { @_collection_name => to_hash(options) }
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
- def collection(data)
103
- @_collection_name = data.values.first if data.respond_to?(:each_pair)
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 @_scope.respond_to?(:controller)
159
- full_name = @_scope.controller.controller_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) ? @_scope.params[:format] : nil
168
- if request = @_scope.respond_to?(:request) && @_scope.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
- @_scope.respond_to?(:params) ? @_scope.params : {}
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
- @_scope.respond_to?(name, include_private) ? true : super
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
- @_scope.respond_to?(name) ? @_scope.send(name, *args, &block) : super
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
@@ -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 = @_collection_name.to_s.singularize if defined? @_collection_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
@@ -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
- root_path = Rails.root
39
- view_path = options[:view_path] || File.join(root_path, "app/views/")
40
- file_path = Dir[File.join(view_path, file + ".{*.,}rabl")].first
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
@@ -1,3 +1,3 @@
1
1
  module Rabl
2
- VERSION = "0.5.5.e"
2
+ VERSION = "0.5.5.f"
3
3
  end
@@ -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, :root => true)
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({ User.new => "person" }, :root => true)
40
+ topic.build(User.new, :root_name => "person")
41
41
  end.equivalent_to({ "person" => { :name => "rabl" } })
42
42
 
43
43
  end
@@ -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 => :person
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 "{\"person\":[{},{}]}"
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
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: rabl
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: 6
5
- version: 0.5.5.e
5
+ version: 0.5.5.f
6
6
  platform: ruby
7
7
  authors:
8
8
  - Nathan Esquenazi