Update to 0.2.0

This commit is contained in:
Alex Smelik 2012-09-14 12:52:26 -07:00
commit 7a44da28d2
8 changed files with 36 additions and 25 deletions

View File

@ -1,7 +1,10 @@
# CHANGELOG # CHANGELOG
## 0.1.4 (Unreleased) ## 0.2.0 (unrelased)
* Use MultiJson's preferred JSON engine as default * Use MultiJson's preferred JSON engine as default
* 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
## 0.1.3 ## 0.1.3
* Render correctly when variables are not passed via the assigns ivar but as helper methods * Render correctly when variables are not passed via the assigns ivar but as helper methods
@ -19,4 +22,4 @@
* Remove unused test in loop * Remove unused test in loop
* Speed up rendering by not double copying variable from context * Speed up rendering by not double copying variable from context
* Rename private variable to avoid name conflict * Rename private variable to avoid name conflict
* Remove sqlite3 development dependency * Remove sqlite3 development dependency

View File

@ -7,7 +7,7 @@ module RablRails
def self.call(template) def self.call(template)
%{ %{
RablRails::Library.instance. RablRails::Library.instance.
get_rendered_template(#{template.source.inspect}, self) get_rendered_template(#{template.source.inspect}, self, local_assigns)
} }
end end
end end

View File

@ -8,14 +8,14 @@ module RablRails
@cached_templates = {} @cached_templates = {}
end end
def get_rendered_template(source, context) def get_rendered_template(source, context, locals = nil)
path = context.instance_variable_get(:@virtual_path) path = context.instance_variable_get(:@virtual_path)
@lookup_context = context.lookup_context @lookup_context = context.lookup_context
compiled_template = compile_template_from_source(source, path) compiled_template = compile_template_from_source(source, path)
format = context.params[:format] || 'json' format = context.params[:format] || 'json'
Renderers.const_get(format.upcase!).new(context).render(compiled_template) Renderers.const_get(format.upcase!).new(context, locals).render(compiled_template)
end end
def compile_template_from_source(source, path = nil) def compile_template_from_source(source, path = nil)

View File

@ -4,7 +4,7 @@ require 'rabl-rails/renderers/json'
module RablRails module RablRails
module Renderer module Renderer
class TemplateNotFound < StandardError; end class TemplateNotFound < StandardError; end
mattr_reader :view_path mattr_reader :view_path
@@view_path = 'app/views' @@view_path = 'app/views'
@ -33,7 +33,6 @@ module RablRails
# #
class Context class Context
attr_reader :format attr_reader :format
attr_accessor :target_object
def initialize(path, options) def initialize(path, options)
@virtual_path = path @virtual_path = path
@ -56,17 +55,17 @@ module RablRails
@lookup_context ||= LookupContext.new(@options[:view_path], format) @lookup_context ||= LookupContext.new(@options[:view_path], format)
end end
end end
# #
# Renders object with the given rabl template. # Renders object with the given rabl template.
# #
# Object can also be passed as an option : # Object can also be passed as an option :
# { locals: { object: obj_to_render } } # { locals: { object: obj_to_render } }
# #
# Default render format is JSON, but can be changed via # Default render format is JSON, but can be changed via
# an option: { format: 'xml' } # an option: { format: 'xml' }
# #
# If template includes uses of instance variables (usually # If template includes uses of instance variables (usually
# defined in the controller), you can passed them as locals # defined in the controller), you can passed them as locals
# options. # options.
# For example, if you have this template: # For example, if you have this template:
@ -80,12 +79,11 @@ module RablRails
object = options[:locals].delete(:object) if !object && options[:locals] object = options[:locals].delete(:object) if !object && options[:locals]
c = Context.new(template, options) c = Context.new(template, options)
c.target_object = object
t = c.lookup_context.find_template(template, [], false) t = c.lookup_context.find_template(template, [], false)
raise TemplateNotFound unless t raise TemplateNotFound unless t
Library.instance.get_rendered_template(t.source, c) Library.instance.get_rendered_template(t.source, c, resource: object)
end end
end end
end end

View File

@ -5,9 +5,10 @@ module RablRails
class Base class Base
attr_accessor :_options attr_accessor :_options
def initialize(context) # :nodoc: def initialize(context, locals = nil) # :nodoc:
@_context = context @_context = context
@_options = {} @_options = {}
@_resource = locals[:resource] if locals
setup_render_context setup_render_context
end end
@ -19,9 +20,13 @@ module RablRails
# #
def render(template) def render(template)
collection_or_resource = if template.data collection_or_resource = if template.data
template.data.to_s.start_with?('@') ? instance_variable_get(template.data) : @_context.send(template.data) if @_context.respond_to?(template.data)
@_context.send(template.data)
else
instance_variable_get(template.data)
end
end end
collection_or_resource = @_context.target_object unless collection_or_resource || template.data == false || !@_context.respond_to?(:target_object) collection_or_resource ||= @_resource
output_hash = collection_or_resource.respond_to?(:each) ? render_collection(collection_or_resource, template.source) : output_hash = collection_or_resource.respond_to?(:each) ? render_collection(collection_or_resource, template.source) :
render_resource(collection_or_resource, template.source) render_resource(collection_or_resource, template.source)
_options[:root_name] = template.root_name _options[:root_name] = template.root_name

View File

@ -5,15 +5,20 @@ module RablRails
# representation but instead use a rabl template # representation but instead use a rabl template
# #
class Responder < ActionController::Responder class Responder < ActionController::Responder
def initialize(controller, resources, options = {})
super
@api_template = @controller.respond_to?(:responder_default_template, true) ? controller.send(:responder_default_template) : nil
end
protected protected
def api_behavior(error) def api_behavior(error)
rabl_options = options.merge(template: RablRails.responder_default_template) rabl_options = options.merge(template: @api_template || RablRails.responder_default_template)
if get? if get?
controller.default_render rabl_options controller.default_render rabl_options
elsif post? elsif post?
controller.default_render rabl_options.merge!(status: :created, location: api_location) controller.default_render rabl_options.merge!(status: :created, location: api_location, locals: { resource: resource })
else else
head :no_content head :no_content
end end

View File

@ -6,7 +6,6 @@ class RenderTest < ActiveSupport::TestCase
setup do setup do
@user = User.new(1, 'Marty') @user = User.new(1, 'Marty')
@user.stub(:respond_to?).with(:each).and_return(false)
@tmp_path = Pathname.new(Dir.mktmpdir) @tmp_path = Pathname.new(Dir.mktmpdir)
end end
@ -29,16 +28,16 @@ class RenderTest < ActiveSupport::TestCase
end end
assert_equal %q({"user":{"id":1,"name":"Marty"}}), RablRails.render(@user, 'show', view_path: @tmp_path) assert_equal %q({"user":{"id":1,"name":"Marty"}}), RablRails.render(@user, 'show', view_path: @tmp_path)
end end
test "raise error if template is not found" do test "raise error if template is not found" do
assert_raises(RablRails::Renderer::TemplateNotFound) { RablRails.render(@user, 'not_found') } assert_raises(RablRails::Renderer::TemplateNotFound) { RablRails.render(@user, 'not_found') }
end end
test "instance variables can be passed via options[:locals]" do test "instance variables can be passed via options[:locals]" do
File.open(@tmp_path + "instance.json.rabl", "w") do |f| File.open(@tmp_path + "instance.json.rabl", "w") do |f|
f.puts %q{ f.puts %q{
object false object false
node(:username) { |_| @user.name } node(:username) { |_| @user.name }
} }
end end
assert_equal %q({"username":"Marty"}), RablRails.render(nil, 'instance', view_path: @tmp_path, locals: { user: @user }) assert_equal %q({"username":"Marty"}), RablRails.render(nil, 'instance', view_path: @tmp_path, locals: { user: @user })
@ -51,7 +50,7 @@ class RenderTest < ActiveSupport::TestCase
extends 'base' extends 'base'
} }
end end
File.open(@tmp_path + "base.json.rabl", "w") do |f| File.open(@tmp_path + "base.json.rabl", "w") do |f|
f.puts %q{ f.puts %q{
attribute :name, as: :extended_name attribute :name, as: :extended_name

View File

@ -89,6 +89,7 @@ class TestJsonRenderer < ActiveSupport::TestCase
end end
test "node with context method call" do 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(:respond_to?).with(:context_method).and_return(true)
@context.stub(:context_method).and_return('marty') @context.stub(:context_method).and_return('marty')
proc = lambda { |object| context_method } proc = lambda { |object| context_method }