commit
9f0a92ecd7
|
@ -1,7 +1,8 @@
|
|||
# CHANGELOG
|
||||
|
||||
## 0.2.0 (unrelased)
|
||||
* Use MultiJson's preferred JSON engine as default
|
||||
* Add XML renderer
|
||||
* Use MultiJson's preferred JSON engine as default (shmeltex)
|
||||
* Default template to render with responder can be set per controller
|
||||
* Reponder works out of the box with devise
|
||||
* object or collection can be skipped if use with `respond_to` blocks
|
||||
|
|
1
Gemfile
1
Gemfile
|
@ -3,6 +3,7 @@ source "http://rubygems.org"
|
|||
gemspec
|
||||
|
||||
gem 'yajl-ruby'
|
||||
gem 'libxml-ruby'
|
||||
|
||||
group :test do
|
||||
gem 'rspec-mocks'
|
||||
|
|
11
README.md
11
README.md
|
@ -71,9 +71,9 @@ The only places where you can actually used instance variables are into Proc (o
|
|||
```ruby
|
||||
# We reference the @posts varibles that will be used at rendering time
|
||||
collection :@posts
|
||||
|
||||
|
||||
# Here you can use directly the instance variable because it
|
||||
# will be evaluated when rendering the object
|
||||
# will be evaluated when rendering the object
|
||||
node(:read) { |post| post.read_by?(@user) }
|
||||
```
|
||||
|
||||
|
@ -92,6 +92,7 @@ RablRails works out of the box, with default options and fastest engine availabl
|
|||
# config.cache_templates = true
|
||||
# config.include_json_root = true
|
||||
# config.json_engine = :yajl
|
||||
# config.xml_engine = 'LibXML'
|
||||
end
|
||||
```
|
||||
|
||||
|
@ -139,7 +140,7 @@ You can aliases these attributes in your response
|
|||
|
||||
```ruby
|
||||
attributes title: :foo, to_s: :bar
|
||||
# => { "foo" : <title value>, "bar" : <to_s value> }
|
||||
# => { "foo" : <title value>, "bar" : <to_s value> }
|
||||
```
|
||||
|
||||
### Child nodes
|
||||
|
@ -175,7 +176,7 @@ node(:full_name) { |u| u.first_name + " " + u.last_name }
|
|||
You can add the node only if a condition is true
|
||||
|
||||
```ruby
|
||||
node(:email, if: -> { |u| u.valid_email? }) do |u|
|
||||
node(:email, if: -> { |u| u.valid_email? }) do |u|
|
||||
u.email
|
||||
end
|
||||
```
|
||||
|
@ -246,7 +247,7 @@ There are cases when you want to render object outside Rails view context. For i
|
|||
Rabl.render(object, template, :view_path => 'app/views', :format => :json) #=> "{...}"
|
||||
```
|
||||
|
||||
You can find more informations about how to use this method in the [wiki](http://github.com/ccocchi/rabl-rails/wiki/Render-object-directly)
|
||||
You can find more informations about how to use this method in the [wiki](http://github.com/ccocchi/rabl-rails/wiki/Render-object-directly)
|
||||
|
||||
## Performance
|
||||
|
||||
|
|
|
@ -48,11 +48,22 @@ module RablRails
|
|||
MultiJson.engine
|
||||
end
|
||||
|
||||
def self.xml_engine=(name)
|
||||
ActiveSupport::XmlMini.backend = name
|
||||
rescue LoadError, NameError
|
||||
Rails.logger.warn %Q(WARNING: rabl-rails could not load "#{name}" as XML engine, fallback to default)
|
||||
end
|
||||
|
||||
def self.xml_engine
|
||||
ActiveSupport::XmlMini.backend
|
||||
end
|
||||
|
||||
def self.cache_templates?
|
||||
ActionController::Base.perform_caching && @@cache_templates
|
||||
end
|
||||
|
||||
def self.load_default_engines!
|
||||
self.json_engine = MultiJson.default_engine
|
||||
self.xml_engine = 'LibXML'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
require 'rabl-rails/renderers/base'
|
||||
require 'rabl-rails/renderers/json'
|
||||
require 'rabl-rails/renderers/xml'
|
||||
|
||||
module RablRails
|
||||
module Renderer
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
require 'active_support/core_ext/hash/conversions'
|
||||
|
||||
module RablRails
|
||||
module Renderers
|
||||
class XML < Base
|
||||
DEFAULT_OPTIONS = { dasherize: true, skip_types: false }
|
||||
|
||||
def format_output(hash)
|
||||
xml_options = { root: _options[:root_name] }.merge!(DEFAULT_OPTIONS)
|
||||
hash.to_xml(xml_options)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,131 @@
|
|||
require 'test_helper'
|
||||
|
||||
class TestXmlRenderer < ActiveSupport::TestCase
|
||||
INDENT_REGEXP = /\n(\s)*/
|
||||
HEADER_REGEXP = /<[^>]+>/
|
||||
|
||||
setup do
|
||||
@data = User.new(1, 'foobar', 'male')
|
||||
|
||||
@context = Context.new
|
||||
@context.assigns['data'] = @data
|
||||
|
||||
@template = RablRails::CompiledTemplate.new
|
||||
@template.data = :@data
|
||||
@template.root_name = :user
|
||||
end
|
||||
|
||||
def render_xml_output
|
||||
RablRails::Renderers::XML.new(@context).render(@template).to_s.gsub!(INDENT_REGEXP, '').sub!(HEADER_REGEXP, '')
|
||||
end
|
||||
|
||||
test "render object simple object" do
|
||||
@template.source = {}
|
||||
assert_equal %q(<user></user>), render_xml_output
|
||||
end
|
||||
|
||||
test "render collection with empty template" do
|
||||
@context.assigns['data'] = [@data]
|
||||
@template.source = {}
|
||||
@template.root_name = :users
|
||||
assert_equal %q(<users type="array"><user></user></users>), render_xml_output
|
||||
end
|
||||
|
||||
test "render object with local methods (used by decent_exposure)" do
|
||||
@context.stub(:user).and_return(@data)
|
||||
@template.source = { :id => :id }
|
||||
assert_equal %q(<user><id type="integer">1</id></user>), render_xml_output
|
||||
end
|
||||
|
||||
test "render single object attributes" do
|
||||
@template.source = { :name => :name }
|
||||
assert_equal %q(<user><name>foobar</name></user>), render_xml_output
|
||||
end
|
||||
|
||||
test "render child with arbitrary data source" do
|
||||
@template.source = { :author => { :_data => :@data, :name => :name } }
|
||||
@template.root_name = :post
|
||||
assert_equal %q(<post><author><name>foobar</name></author></post>), render_xml_output
|
||||
end
|
||||
|
||||
test "render child with local methods (used by decent_exposure)" do
|
||||
@context.stub(:user).and_return(@data)
|
||||
@template.source = { :author => { :_data => :user, :name => :name } }
|
||||
@template.root_name = :post
|
||||
assert_equal %q(<post><author><name>foobar</name></author></post>), render_xml_output
|
||||
end
|
||||
|
||||
test "render glued attributes from single object" do
|
||||
@template.source = { :_glue0 => { :_data => :@data, :name => :name } }
|
||||
assert_equal %q(<user><name>foobar</name></user>), render_xml_output
|
||||
end
|
||||
|
||||
test "render collection with attributes" do
|
||||
@data = [User.new(1, 'foo', 'male'), User.new(2, 'bar', 'female')]
|
||||
@context.assigns['data'] = @data
|
||||
@template.root_name = :users
|
||||
@template.source = { :uid => :id, :name => :name }
|
||||
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
|
||||
end
|
||||
|
||||
test "render node property" do
|
||||
proc = lambda { |object| object.name }
|
||||
@template.source = { :name => proc }
|
||||
assert_equal %q(<user><name>foobar</name></user>), render_xml_output
|
||||
end
|
||||
|
||||
test "render node property with true condition" do
|
||||
condition = lambda { |u| true }
|
||||
proc = lambda { |object| object.name }
|
||||
@template.source = { :name => [condition, proc] }
|
||||
assert_equal %q(<user><name>foobar</name></user>), render_xml_output
|
||||
end
|
||||
|
||||
test "render node property with false condition" do
|
||||
condition = lambda { |u| false }
|
||||
proc = lambda { |object| object.name }
|
||||
@template.source = { :name => [condition, proc] }
|
||||
assert_equal %q(<user></user>), render_xml_output
|
||||
end
|
||||
|
||||
test "node with context method call" do
|
||||
@context.stub(:respond_to?).with(:@data).and_return(false)
|
||||
@context.stub(:respond_to?).with(:context_method).and_return(true)
|
||||
@context.stub(:context_method).and_return('marty')
|
||||
proc = lambda { |object| context_method }
|
||||
@template.source = { :name => proc }
|
||||
assert_equal %q(<user><name>marty</name></user>), render_xml_output
|
||||
end
|
||||
|
||||
test "partial should be evaluated at rendering time" do
|
||||
# Set assigns
|
||||
@context.assigns['user'] = @data
|
||||
|
||||
# Stub Library#get
|
||||
t = RablRails::CompiledTemplate.new
|
||||
t.source = { :name => :name }
|
||||
RablRails::Library.reset_instance
|
||||
RablRails::Library.instance.should_receive(:compile_template_from_path).with('users/base').and_return(t)
|
||||
|
||||
@template.data = false
|
||||
@template.root_name = :post
|
||||
@template.source = { :user => ->(s) { partial('users/base', :object => @user) } }
|
||||
|
||||
assert_equal %q(<post><user><name>foobar</name></user></post>), render_xml_output
|
||||
end
|
||||
|
||||
test "partial with no values should raise an error" do
|
||||
@template.data = false
|
||||
@template.source = { :user => ->(s) { partial('users/base') } }
|
||||
|
||||
assert_raises(RablRails::Renderers::PartialError) { render_xml_output }
|
||||
end
|
||||
|
||||
test "partial with empty values should not raise an error" do
|
||||
@template.data = false
|
||||
@template.root_name = :list
|
||||
@template.source = { :users => ->(s) { partial('users/base', :object => []) } }
|
||||
|
||||
assert_equal %q(<list><users type="array"/></list>), render_xml_output
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue