rabl-rails 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,15 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.2.0
4
+ * Add `root` in DSL to set root without changing the data source
5
+ * Add XML renderer
6
+ * Use MultiJson's preferred JSON engine as default (shmeltex)
7
+ * Default template to render with responder can be set per controller
8
+ * Reponder works out of the box with devise
9
+ * object or collection can be skipped if use with `respond_to` blocks
10
+
3
11
  ## 0.1.3
4
- * Render correcly when variables are not passed via the assigns ivar but as helper methods
12
+ * Render correctly when variables are not passed via the assigns ivar but as helper methods
5
13
  (decent_exposure, focused_controller)
6
14
  * Add custom Responder
7
15
 
@@ -13,7 +21,7 @@
13
21
  ## 0.1.1
14
22
 
15
23
  * Add CHANGELOG
16
- * Remove unnused test in loop
24
+ * Remove unused test in loop
17
25
  * Speed up rendering by not double copying variable from context
18
26
  * Rename private variable to avoid name conflict
19
- * Remove sqlite3 development dependency
27
+ * Remove sqlite3 development dependency
data/Gemfile CHANGED
@@ -2,7 +2,8 @@ source "http://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'yajl-ruby'
5
+ gem 'oj'
6
+ gem 'libxml-ruby'
6
7
 
7
8
  group :test do
8
9
  gem 'rspec-mocks'
data/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  RABL (Ruby API Builder Language) is a ruby templating system for rendering resources in different format (JSON, XML, BSON, ...). You can find documentation [here](http://github.com/nesquena/rabl).
4
4
 
5
- RABL-rails only target Rails 3+ application because Rails 2 applications are becoming less and less present and will be obsolete with Rails 4. So let's look to the future !
5
+ rabl-rails is **faster** and uses **less memory** than the standard rabl gem while letting you access the same features. There are some slight changes to do on your templates to get this gem to work but it should't take you more than 5 minutes.
6
6
 
7
- So now you ask why used `rabl-rails` if `rabl` already exists and supports Rails. Rabl-rails is **faster** and uses **less memory** than standard rabl gem while letting you access same features. Of course, there are some slight changes to do on your templates to get this gem to work but it should't take you more than 5 minutes.
7
+ rabl-rails only target **Rails 3+ application**.
8
8
 
9
9
  ## Installation
10
10
 
@@ -24,7 +24,7 @@ And that's it !
24
24
 
25
25
  ## Overview
26
26
 
27
- Once you have installed RABL, you can directly used RABL templates to render your resources without changing anything to you controller. As example,
27
+ Once you have installed rabl-rails, you can directly used RABL-rails templates to render your resources without changing anything to you controller. As example,
28
28
  assuming you have a `Post` model filled with blog posts, and a `PostController` that look like this :
29
29
 
30
30
  ```ruby
@@ -32,7 +32,7 @@ class PostController < ApplicationController
32
32
  respond_to :html, :json, :xml
33
33
 
34
34
  def index
35
- @posts = Post.order('created_at DESC')
35
+ @posts = Post.order('created_at DESC')
36
36
  respond_with(@posts)
37
37
  end
38
38
  end
@@ -71,9 +71,9 @@ The only places where you can actually used instance variables are into Proc (o
71
71
  ```ruby
72
72
  # We reference the @posts varibles that will be used at rendering time
73
73
  collection :@posts
74
-
74
+
75
75
  # Here you can use directly the instance variable because it
76
- # will be evaluated when rendering the object
76
+ # will be evaluated when rendering the object
77
77
  node(:read) { |post| post.read_by?(@user) }
78
78
  ```
79
79
 
@@ -83,16 +83,19 @@ After the template is compiled into a hash, Rabl-rails will use a renderer to do
83
83
 
84
84
  ## Configuration
85
85
 
86
- RablRails works out of the box, with default options and fastest engine available (yajl, libxml). But depending on your needs, you might want to change that or how your output looks like. You can set global configuration in your application:
86
+ RablRails works out of the box, with default options and fastest engine available (oj, libxml). But depending on your needs, you might want to change that or how your output looks like. You can set global configuration in your application:
87
87
 
88
88
  ```ruby
89
- # config/initializers/rabl_rails.rb
90
- RablRails.configure do |config|
91
- # These are the default
92
- # config.cache_templates = true
93
- # config.include_json_root = true
94
- # config.json_engine = :yajl
95
- end
89
+ # config/initializers/rabl_rails.rb
90
+ RablRails.configure do |config|
91
+ # These are the default
92
+ # config.cache_templates = true
93
+ # config.include_json_root = true
94
+ # config.json_engine = :oj
95
+ # config.xml_engine = 'LibXML'
96
+ # config.use_custom_responder = false
97
+ # config.default_responder_template = 'show'
98
+ end
96
99
  ```
97
100
 
98
101
  ## Usage
@@ -127,6 +130,24 @@ node(:some_count) { |_| @user.posts.count }
127
130
  child(:@user) { attribute :name }
128
131
  ```
129
132
 
133
+ If you use gem like *decent_exposure* or *focused_controller*, you can use your variable directly without the leading `@`
134
+
135
+ ```ruby
136
+ object :object_exposed
137
+ ```
138
+
139
+ You can even skip data declaration at all. If you used `respond_with`, rabl-rails will render the data you passed to it.
140
+ As there is no name, you can set a root via the `root` macro. This allow you to use your template without caring about variables passed to it.
141
+
142
+ ```ruby
143
+ # in controller
144
+ respond_with(@post)
145
+
146
+ # in rabl-rails template
147
+ root :article
148
+ attribute :title
149
+ ```
150
+
130
151
  ### Attributes / Methods
131
152
 
132
153
  Basic usage is to declared attributes to include in the response. These can be database attributes or any instance method.
@@ -139,7 +160,7 @@ You can aliases these attributes in your response
139
160
 
140
161
  ```ruby
141
162
  attributes title: :foo, to_s: :bar
142
- # => { "foo" : <title value>, "bar" : <to_s value> }
163
+ # => { "foo" : <title value>, "bar" : <to_s value> }
143
164
  ```
144
165
 
145
166
  ### Child nodes
@@ -175,7 +196,7 @@ node(:full_name) { |u| u.first_name + " " + u.last_name }
175
196
  You can add the node only if a condition is true
176
197
 
177
198
  ```ruby
178
- node(:email, if: -> { |u| u.valid_email? }) do |u|
199
+ node(:email, if: -> { |u| u.valid_email? }) do |u|
179
200
  u.email
180
201
  end
181
202
  ```
@@ -232,12 +253,6 @@ child :posts do
232
253
  end
233
254
  ```
234
255
 
235
- ### Caching
236
-
237
- Caching is not a part of Rabl-rails. It is already in Rails itself, because caching all view output is the same as action caching (Rails caching is even better because it will also not run your queries).
238
-
239
- Moreover caching each object in a collection can be really not effective with big collections or simple objects. This is also a nightmare with cache expiration.
240
-
241
256
  ### Render object directly
242
257
 
243
258
  There are cases when you want to render object outside Rails view context. For instance to render objects in the console or to create message queue payloads. For these situations, you can use `RablRails.render` as show below:
@@ -246,13 +261,17 @@ There are cases when you want to render object outside Rails view context. For i
246
261
  Rabl.render(object, template, :view_path => 'app/views', :format => :json) #=> "{...}"
247
262
  ```
248
263
 
249
- You can find more informations about how to use this method in the [wiki](http://github.com/ccocchi/rabl-rails/wiki/Render-object-directly)
264
+ You can find more informations about how to use this method in the [wiki](http://github.com/ccocchi/rabl-rails/wiki/Render-object-directly)
265
+
266
+ ### Other features
267
+
268
+ You can find more informations about other features (caching, custom_responder, ...) in the [WIKI](https://github.com/ccocchi/rabl-rails/wiki)
250
269
 
251
270
  ## Performance
252
271
 
253
272
  Benchmarks have been made using this [application](http://github.com/ccocchi/rabl-benchmark), with rabl 0.6.14 and rabl-rails 0.1.0
254
273
 
255
- Overall, Rabl-rails is **20% faster and use 10% less memory**.
274
+ Overall, Rabl-rails is **20% faster and use 10% less memory**, even **twice faster** when rendering collections with extends.
256
275
 
257
276
  You can see full tests on test application repository.
258
277
 
@@ -26,9 +26,6 @@ module RablRails
26
26
  mattr_accessor :include_json_root
27
27
  @@include_json_root = true
28
28
 
29
- mattr_reader :json_engine
30
- @@json_engine = :yajl
31
-
32
29
  mattr_accessor :use_custom_responder
33
30
  @@use_custom_responder = false
34
31
 
@@ -43,9 +40,22 @@ module RablRails
43
40
 
44
41
  def self.json_engine=(name)
45
42
  MultiJson.engine = name
46
- @@json_engine = name
47
43
  rescue LoadError
48
- Rails.logger.warn %Q(WARNING: rabl-rails could not load "#{self.json_engine}" as JSON engine, fallback to default)
44
+ Rails.logger.warn %Q(WARNING: rabl-rails could not load "#{name}" as JSON engine, fallback to default)
45
+ end
46
+
47
+ def self.json_engine
48
+ MultiJson.engine
49
+ end
50
+
51
+ def self.xml_engine=(name)
52
+ ActiveSupport::XmlMini.backend = name
53
+ rescue LoadError, NameError
54
+ Rails.logger.warn %Q(WARNING: rabl-rails could not load "#{name}" as XML engine, fallback to default)
55
+ end
56
+
57
+ def self.xml_engine
58
+ ActiveSupport::XmlMini.backend
49
59
  end
50
60
 
51
61
  def self.cache_templates?
@@ -53,6 +63,7 @@ module RablRails
53
63
  end
54
64
 
55
65
  def self.load_default_engines!
56
- self.json_engine = :yajl
66
+ self.json_engine = MultiJson.default_engine
67
+ self.xml_engine = 'LibXML' if defined?(LibXML)
57
68
  end
58
69
  end
@@ -30,6 +30,10 @@ module RablRails
30
30
  end
31
31
  alias_method :collection, :object
32
32
 
33
+ def root(name)
34
+ @template.root_name = name
35
+ end
36
+
33
37
  #
34
38
  # Includes the attribute or method in the output
35
39
  # Example:
@@ -7,7 +7,7 @@ module RablRails
7
7
  def self.call(template)
8
8
  %{
9
9
  RablRails::Library.instance.
10
- get_rendered_template(#{template.source.inspect}, self)
10
+ get_rendered_template(#{template.source.inspect}, self, local_assigns)
11
11
  }
12
12
  end
13
13
  end
@@ -8,14 +8,14 @@ module RablRails
8
8
  @cached_templates = {}
9
9
  end
10
10
 
11
- def get_rendered_template(source, context)
11
+ def get_rendered_template(source, context, locals = nil)
12
12
  path = context.instance_variable_get(:@virtual_path)
13
13
  @lookup_context = context.lookup_context
14
14
 
15
15
  compiled_template = compile_template_from_source(source, path)
16
16
 
17
17
  format = context.params[:format] || 'json'
18
- Renderers.const_get(format.upcase!).new(context).render(compiled_template)
18
+ Renderers.const_get(format.upcase!).new(context, locals).render(compiled_template)
19
19
  end
20
20
 
21
21
  def compile_template_from_source(source, path = nil)
@@ -1,10 +1,11 @@
1
1
  require 'rabl-rails/renderers/base'
2
2
  require 'rabl-rails/renderers/json'
3
+ require 'rabl-rails/renderers/xml'
3
4
 
4
5
  module RablRails
5
6
  module Renderer
6
7
  class TemplateNotFound < StandardError; end
7
-
8
+
8
9
  mattr_reader :view_path
9
10
  @@view_path = 'app/views'
10
11
 
@@ -33,7 +34,6 @@ module RablRails
33
34
  #
34
35
  class Context
35
36
  attr_reader :format
36
- attr_accessor :target_object
37
37
 
38
38
  def initialize(path, options)
39
39
  @virtual_path = path
@@ -56,17 +56,17 @@ module RablRails
56
56
  @lookup_context ||= LookupContext.new(@options[:view_path], format)
57
57
  end
58
58
  end
59
-
59
+
60
60
  #
61
61
  # Renders object with the given rabl template.
62
- #
62
+ #
63
63
  # Object can also be passed as an option :
64
64
  # { locals: { object: obj_to_render } }
65
65
  #
66
66
  # Default render format is JSON, but can be changed via
67
67
  # an option: { format: 'xml' }
68
68
  #
69
- # If template includes uses of instance variables (usually
69
+ # If template includes uses of instance variables (usually
70
70
  # defined in the controller), you can passed them as locals
71
71
  # options.
72
72
  # For example, if you have this template:
@@ -80,12 +80,11 @@ module RablRails
80
80
  object = options[:locals].delete(:object) if !object && options[:locals]
81
81
 
82
82
  c = Context.new(template, options)
83
- c.target_object = object
84
-
85
83
  t = c.lookup_context.find_template(template, [], false)
84
+
86
85
  raise TemplateNotFound unless t
87
86
 
88
- Library.instance.get_rendered_template(t.source, c)
87
+ Library.instance.get_rendered_template(t.source, c, resource: object)
89
88
  end
90
89
  end
91
90
  end
@@ -5,9 +5,10 @@ module RablRails
5
5
  class Base
6
6
  attr_accessor :_options
7
7
 
8
- def initialize(context) # :nodoc:
8
+ def initialize(context, locals = nil) # :nodoc:
9
9
  @_context = context
10
10
  @_options = {}
11
+ @_resource = locals[:resource] if locals
11
12
  setup_render_context
12
13
  end
13
14
 
@@ -19,9 +20,13 @@ module RablRails
19
20
  #
20
21
  def render(template)
21
22
  collection_or_resource = if template.data
22
- template.data.to_s.start_with?('@') ? instance_variable_get(template.data) : @_context.send(template.data)
23
+ if @_context.respond_to?(template.data)
24
+ @_context.send(template.data)
25
+ else
26
+ instance_variable_get(template.data)
27
+ end
23
28
  end
24
- collection_or_resource = @_context.target_object unless collection_or_resource || template.data == false || !@_context.respond_to?(:target_object)
29
+ collection_or_resource ||= @_resource
25
30
  output_hash = collection_or_resource.respond_to?(:each) ? render_collection(collection_or_resource, template.source) :
26
31
  render_resource(collection_or_resource, template.source)
27
32
  _options[:root_name] = template.root_name
@@ -0,0 +1,14 @@
1
+ require 'active_support/core_ext/hash/conversions'
2
+
3
+ module RablRails
4
+ module Renderers
5
+ class XML < Base
6
+ DEFAULT_OPTIONS = { dasherize: true, skip_types: false }
7
+
8
+ def format_output(hash)
9
+ xml_options = { root: _options[:root_name] }.merge!(DEFAULT_OPTIONS)
10
+ hash.to_xml(xml_options)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -5,11 +5,22 @@ module RablRails
5
5
  # representation but instead use a rabl template
6
6
  #
7
7
  class Responder < ActionController::Responder
8
+ def initialize(controller, resources, options = {})
9
+ super
10
+ if options[:locals]
11
+ options[:locals][:resource] = resource
12
+ else
13
+ options[:locals] = { resource: resource }
14
+ end
15
+ end
16
+
8
17
  protected
9
-
18
+
10
19
  def api_behavior(error)
11
- rabl_options = options.merge(template: RablRails.responder_default_template)
12
-
20
+ template = @controller.respond_to?(:responder_default_template, true) ? controller.send(:responder_default_template)
21
+ : RablRails.responder_default_template
22
+ rabl_options = options.merge(template: template)
23
+
13
24
  if get?
14
25
  controller.default_render rabl_options
15
26
  elsif post?
@@ -1,3 +1,3 @@
1
1
  module RablRails
2
- VERSION = '0.1.3'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -24,6 +24,16 @@ class CompilerTest < ActiveSupport::TestCase
24
24
  assert_equal({}, t.source)
25
25
  end
26
26
 
27
+ test "root can be defined via keyword" do
28
+ t = @compiler.compile_source(%{ root :author })
29
+ assert_equal :author, t.root_name
30
+ end
31
+
32
+ test "root keyword override object root" do
33
+ t = @compiler.compile_source(%{ object :@user ; root :author })
34
+ assert_equal :author, t.root_name
35
+ end
36
+
27
37
  test "collection set the data for the template" do
28
38
  t = @compiler.compile_source(%{ collection :@user })
29
39
  assert_equal :@user, t.data
@@ -42,7 +52,7 @@ class CompilerTest < ActiveSupport::TestCase
42
52
  assert_equal :@user, t.data
43
53
  assert_equal :users, t.root_name
44
54
  end
45
-
55
+
46
56
  test "root can be set to false via options" do
47
57
  t = @compiler.compile_source(%( object :@user, root: false))
48
58
  assert_equal false, t.root_name
@@ -154,7 +164,7 @@ class CompilerTest < ActiveSupport::TestCase
154
164
  assert_equal({ :user => { :_data => :@user, :id => :id } }, t.source)
155
165
  assert_equal false, t.data
156
166
  end
157
-
167
+
158
168
  test "name extraction from argument" do
159
169
  assert_equal [:@users, 'users'], @compiler.send(:extract_data_and_name, :@users)
160
170
  assert_equal [:users, :users], @compiler.send(:extract_data_and_name, :users)
@@ -6,7 +6,6 @@ class RenderTest < ActiveSupport::TestCase
6
6
 
7
7
  setup do
8
8
  @user = User.new(1, 'Marty')
9
- @user.stub(:respond_to?).with(:each).and_return(false)
10
9
  @tmp_path = Pathname.new(Dir.mktmpdir)
11
10
  end
12
11
 
@@ -29,16 +28,16 @@ class RenderTest < ActiveSupport::TestCase
29
28
  end
30
29
  assert_equal %q({"user":{"id":1,"name":"Marty"}}), RablRails.render(@user, 'show', view_path: @tmp_path)
31
30
  end
32
-
31
+
33
32
  test "raise error if template is not found" do
34
33
  assert_raises(RablRails::Renderer::TemplateNotFound) { RablRails.render(@user, 'not_found') }
35
34
  end
36
-
35
+
37
36
  test "instance variables can be passed via options[:locals]" do
38
37
  File.open(@tmp_path + "instance.json.rabl", "w") do |f|
39
38
  f.puts %q{
40
39
  object false
41
- node(:username) { |_| @user.name }
40
+ node(:username) { |_| @user.name }
42
41
  }
43
42
  end
44
43
  assert_equal %q({"username":"Marty"}), RablRails.render(nil, 'instance', view_path: @tmp_path, locals: { user: @user })
@@ -51,7 +50,7 @@ class RenderTest < ActiveSupport::TestCase
51
50
  extends 'base'
52
51
  }
53
52
  end
54
-
53
+
55
54
  File.open(@tmp_path + "base.json.rabl", "w") do |f|
56
55
  f.puts %q{
57
56
  attribute :name, as: :extended_name
@@ -89,6 +89,7 @@ class TestJsonRenderer < ActiveSupport::TestCase
89
89
  end
90
90
 
91
91
  test "node with context method call" do
92
+ @context.stub(:respond_to?).with(:@data).and_return(false)
92
93
  @context.stub(:respond_to?).with(:context_method).and_return(true)
93
94
  @context.stub(:context_method).and_return('marty')
94
95
  proc = lambda { |object| context_method }
@@ -0,0 +1,131 @@
1
+ require 'test_helper'
2
+
3
+ class TestXmlRenderer < ActiveSupport::TestCase
4
+ INDENT_REGEXP = /\n(\s)*/
5
+ HEADER_REGEXP = /<[^>]+>/
6
+
7
+ setup do
8
+ @data = User.new(1, 'foobar', 'male')
9
+
10
+ @context = Context.new
11
+ @context.assigns['data'] = @data
12
+
13
+ @template = RablRails::CompiledTemplate.new
14
+ @template.data = :@data
15
+ @template.root_name = :user
16
+ end
17
+
18
+ def render_xml_output
19
+ RablRails::Renderers::XML.new(@context).render(@template).to_s.gsub!(INDENT_REGEXP, '').sub!(HEADER_REGEXP, '')
20
+ end
21
+
22
+ test "render object simple object" do
23
+ @template.source = {}
24
+ assert_equal %q(<user></user>), render_xml_output
25
+ end
26
+
27
+ test "render collection with empty template" do
28
+ @context.assigns['data'] = [@data]
29
+ @template.source = {}
30
+ @template.root_name = :users
31
+ assert_equal %q(<users type="array"><user></user></users>), render_xml_output
32
+ end
33
+
34
+ test "render object with local methods (used by decent_exposure)" do
35
+ @context.stub(:user).and_return(@data)
36
+ @template.source = { :id => :id }
37
+ assert_equal %q(<user><id type="integer">1</id></user>), render_xml_output
38
+ end
39
+
40
+ test "render single object attributes" do
41
+ @template.source = { :name => :name }
42
+ assert_equal %q(<user><name>foobar</name></user>), render_xml_output
43
+ end
44
+
45
+ test "render child with arbitrary data source" do
46
+ @template.source = { :author => { :_data => :@data, :name => :name } }
47
+ @template.root_name = :post
48
+ assert_equal %q(<post><author><name>foobar</name></author></post>), render_xml_output
49
+ end
50
+
51
+ test "render child with local methods (used by decent_exposure)" do
52
+ @context.stub(:user).and_return(@data)
53
+ @template.source = { :author => { :_data => :user, :name => :name } }
54
+ @template.root_name = :post
55
+ assert_equal %q(<post><author><name>foobar</name></author></post>), render_xml_output
56
+ end
57
+
58
+ test "render glued attributes from single object" do
59
+ @template.source = { :_glue0 => { :_data => :@data, :name => :name } }
60
+ assert_equal %q(<user><name>foobar</name></user>), render_xml_output
61
+ end
62
+
63
+ test "render collection with attributes" do
64
+ @data = [User.new(1, 'foo', 'male'), User.new(2, 'bar', 'female')]
65
+ @context.assigns['data'] = @data
66
+ @template.root_name = :users
67
+ @template.source = { :uid => :id, :name => :name }
68
+ assert_equal %q(<users type="array"><user><uid type="integer">1</uid><name>foo</name></user><user><uid type="integer">2</uid><name>bar</name></user></users>), render_xml_output
69
+ end
70
+
71
+ test "render node property" do
72
+ proc = lambda { |object| object.name }
73
+ @template.source = { :name => proc }
74
+ assert_equal %q(<user><name>foobar</name></user>), render_xml_output
75
+ end
76
+
77
+ test "render node property with true condition" do
78
+ condition = lambda { |u| true }
79
+ proc = lambda { |object| object.name }
80
+ @template.source = { :name => [condition, proc] }
81
+ assert_equal %q(<user><name>foobar</name></user>), render_xml_output
82
+ end
83
+
84
+ test "render node property with false condition" do
85
+ condition = lambda { |u| false }
86
+ proc = lambda { |object| object.name }
87
+ @template.source = { :name => [condition, proc] }
88
+ assert_equal %q(<user></user>), render_xml_output
89
+ end
90
+
91
+ test "node with context method call" do
92
+ @context.stub(:respond_to?).with(:@data).and_return(false)
93
+ @context.stub(:respond_to?).with(:context_method).and_return(true)
94
+ @context.stub(:context_method).and_return('marty')
95
+ proc = lambda { |object| context_method }
96
+ @template.source = { :name => proc }
97
+ assert_equal %q(<user><name>marty</name></user>), render_xml_output
98
+ end
99
+
100
+ test "partial should be evaluated at rendering time" do
101
+ # Set assigns
102
+ @context.assigns['user'] = @data
103
+
104
+ # Stub Library#get
105
+ t = RablRails::CompiledTemplate.new
106
+ t.source = { :name => :name }
107
+ RablRails::Library.reset_instance
108
+ RablRails::Library.instance.should_receive(:compile_template_from_path).with('users/base').and_return(t)
109
+
110
+ @template.data = false
111
+ @template.root_name = :post
112
+ @template.source = { :user => ->(s) { partial('users/base', :object => @user) } }
113
+
114
+ assert_equal %q(<post><user><name>foobar</name></user></post>), render_xml_output
115
+ end
116
+
117
+ test "partial with no values should raise an error" do
118
+ @template.data = false
119
+ @template.source = { :user => ->(s) { partial('users/base') } }
120
+
121
+ assert_raises(RablRails::Renderers::PartialError) { render_xml_output }
122
+ end
123
+
124
+ test "partial with empty values should not raise an error" do
125
+ @template.data = false
126
+ @template.root_name = :list
127
+ @template.source = { :users => ->(s) { partial('users/base', :object => []) } }
128
+
129
+ assert_equal %q(<list><users type="array"/></list>), render_xml_output
130
+ end
131
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rabl-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.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: 2012-09-12 00:00:00.000000000 Z
12
+ date: 2012-09-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -80,6 +80,7 @@ files:
80
80
  - lib/rabl-rails/renderer.rb
81
81
  - lib/rabl-rails/renderers/base.rb
82
82
  - lib/rabl-rails/renderers/json.rb
83
+ - lib/rabl-rails/renderers/xml.rb
83
84
  - lib/rabl-rails/responder.rb
84
85
  - lib/rabl-rails/template.rb
85
86
  - lib/rabl-rails/version.rb
@@ -91,6 +92,7 @@ files:
91
92
  - test/non_restful_response_test.rb
92
93
  - test/render_test.rb
93
94
  - test/renderers/json_renderer_test.rb
95
+ - test/renderers/xml_renderer_test.rb
94
96
  - test/test_helper.rb
95
97
  homepage: https://github.com/ccocchi/rabl-rails
96
98
  licenses: []
@@ -123,4 +125,5 @@ test_files:
123
125
  - test/non_restful_response_test.rb
124
126
  - test/render_test.rb
125
127
  - test/renderers/json_renderer_test.rb
128
+ - test/renderers/xml_renderer_test.rb
126
129
  - test/test_helper.rb