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.
- data/CHANGELOG.md +11 -3
- data/Gemfile +2 -1
- data/README.md +43 -24
- data/lib/rabl-rails.rb +17 -6
- data/lib/rabl-rails/compiler.rb +4 -0
- data/lib/rabl-rails/handler.rb +1 -1
- data/lib/rabl-rails/library.rb +2 -2
- data/lib/rabl-rails/renderer.rb +7 -8
- data/lib/rabl-rails/renderers/base.rb +8 -3
- data/lib/rabl-rails/renderers/xml.rb +14 -0
- data/lib/rabl-rails/responder.rb +14 -3
- data/lib/rabl-rails/version.rb +1 -1
- data/test/compiler_test.rb +12 -2
- data/test/render_test.rb +4 -5
- data/test/renderers/json_renderer_test.rb +1 -0
- data/test/renderers/xml_renderer_test.rb +131 -0
- metadata +5 -2
data/CHANGELOG.md
CHANGED
@@ -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
|
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
|
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
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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 (
|
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
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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
|
|
data/lib/rabl-rails.rb
CHANGED
@@ -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 "#{
|
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 =
|
66
|
+
self.json_engine = MultiJson.default_engine
|
67
|
+
self.xml_engine = 'LibXML' if defined?(LibXML)
|
57
68
|
end
|
58
69
|
end
|
data/lib/rabl-rails/compiler.rb
CHANGED
data/lib/rabl-rails/handler.rb
CHANGED
data/lib/rabl-rails/library.rb
CHANGED
@@ -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)
|
data/lib/rabl-rails/renderer.rb
CHANGED
@@ -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
|
-
|
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
|
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
|
data/lib/rabl-rails/responder.rb
CHANGED
@@ -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
|
-
|
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?
|
data/lib/rabl-rails/version.rb
CHANGED
data/test/compiler_test.rb
CHANGED
@@ -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)
|
data/test/render_test.rb
CHANGED
@@ -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.
|
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
|
+
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
|