Skip to content

Commit

Permalink
Add initial support for partials
Browse files Browse the repository at this point in the history
  • Loading branch information
dewski committed Jul 5, 2012
1 parent 1def4d0 commit adb4b10
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 0 deletions.
12 changes: 12 additions & 0 deletions lib/json_builder/compiler.rb
@@ -1,5 +1,6 @@
require 'json'
require 'json_builder/member'
require 'json_builder/partial'

module JSONBuilder
class Compiler
Expand Down Expand Up @@ -71,6 +72,17 @@ def array(items, &block)
@_array = Elements.new(@_scope, items, &block)
end

# Public: Executes an extracted bit of JSONBuilder view code on the parent
# JSONBuilder::Compiler object.
#
# args - could be string or options
#
# Returns nothing.
def partial(*args)
partial = Partial.new(*args)
instance_eval partial.source
end

# Public: Called anytime the compiler is passed JSON keys,
# first checks to see if the parent object contains the method like
# a Rails helper.
Expand Down
48 changes: 48 additions & 0 deletions lib/json_builder/partial.rb
@@ -0,0 +1,48 @@
require 'active_support/notifications'

module JSONBuilder
class Partial
class MissingTemplate < StandardError; end;

attr_accessor :object
attr_accessor :options
attr_accessor :path

def initialize(*args)
@options = args.extract_options!
@object = args.first

setup @object, @options
end

def setup(object, options)
if (Object.const_defined?('ActiveRecord') && ActiveRecord::Base === object.superclass) || object.respond_to?(:to_partial_path)
begin
@path = object.to_partial_path
rescue
raise ArgumentError.new("'#{object.inspect}' is not an ActiveModel-compatible object. It must implement :to_partial_path.")
end
end

if String === object
@path = object
end
end

def source
instrument :template do
begin
File.read @path
rescue Errno::ENOENT
raise MissingTemplate
end
end
end

private

def instrument(name, options = {})
ActiveSupport::Notifications.instrument("render_#{name}.action_view", options) { yield }
end
end
end
10 changes: 10 additions & 0 deletions test/compiler_test.rb
Expand Up @@ -100,4 +100,14 @@ def test_newline_characters
newline "hello\nworld"
end
end

def test_partial_compilation
assert_builder_json('{"results": 500, "embedded": "partial", "metadata": {"expires": "soon"}}') do
results 500
partial File.expand_path('../fixtures/_partial.json_builder', __FILE__)
metadata do
expires "soon"
end
end
end
end
1 change: 1 addition & 0 deletions test/fixtures/_partial.json_builder
@@ -0,0 +1 @@
embedded "partial"
29 changes: 29 additions & 0 deletions test/partial_test.rb
@@ -0,0 +1,29 @@
# encoding: UTF-8

require 'test_helper'

class User
def to_partial_path
'users'
end
end

class TestPartial < Test::Unit::TestCase
def partial(*args)
JSONBuilder::Partial.new(*args)
end

def test_partial_file_path_from_model
assert_equal 'users', partial(User.new).path
end

def test_passed_in_partial_path
assert_equal 'custom/path', partial('custom/path').path
end

def test_missing_partial_file
assert_raise(JSONBuilder::Partial::MissingTemplate) {
partial('test/me').source
}
end
end

0 comments on commit adb4b10

Please sign in to comment.