├── .gitignore ├── .travis.yml ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── jsonify-rails.gemspec ├── lib ├── jsonify-rails.rb └── jsonify-rails │ ├── jsonify_builder.rb │ └── version.rb └── spec ├── fixtures └── views │ └── simple_test.jsonify ├── jsonify_builder_spec.rb └── spec_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | pkg/ 2 | Gemfile*.lock 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | rvm: 2 | - 1.9.3 3 | - 1.9.2 4 | - 1.8.7 5 | - jruby 6 | - rbx 7 | env: 8 | - RAILS_VERSION='~>3.0' 9 | - RAILS_VERSION='~>3.1' 10 | - RAILS_VERSION='~>3.2' 11 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | # Gem dependencies are in jsonify-rails.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2011 Bill Siggelkow 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jsonify-Rails — Jsonify templates for Rails views [![Build Status](https://secure.travis-ci.org/bsiggelkow/jsonify-rails.png)](http://travis-ci.org/bsiggelkow/jsonify-rails) 2 | 3 | [Jsonify](https://github.com/bsiggelkow/jsonify) is to JSON as [Builder](https://github.com/jimweirich/builder) is to XML. 4 | 5 | ## Installation 6 | 7 | `gem install jsonify-rails` 8 | 9 | ## Usage 10 | 11 | Jsonify-Rails provides a Rails 3 template handler allowing you to create 12 | view templates using Jsonify. Any template with a `.jsonify` will be handled by Rails. 13 | 14 | The Jsonify template handler exposes a `Jsonify::Builder` instance to your template with the `json` variable: 15 | 16 | json.hello do 17 | json.world "Jsonify is Working!" 18 | end 19 | 20 | Just like with any other template, your Jsonify template will have access to 21 | any instance variables that are exposed through the controller. 22 | 23 | For optimum performance, Jsonify outputs the generated JSON string in plain format -- no newlines, or spaces -- this is best for production. However, if you want "pretty" output, you can configure Jsonify by adding the following configuration line to `application.rb`. 24 | 25 | config.jsonify_format = :pretty 26 | 27 | #### Partials 28 | 29 | You can use partials from Jsonify views, and you can create Jsonify partials. How your Jsonify template uses a partial depends on how the information the partial returns is structured. Keep in mind that any paritial, be it a Jsonify template, erb, or anything else, always a returns its result as a string. 30 | 31 | ##### Jsonify partials 32 | 33 | Any Jsonify partial — that is, the file has a `.jsonify` extension — 34 | will return, by design, a string that is valid JSON. It will represent either a JSON object,wrapped in curly braces ( {} ), or a JSON array, wrapped in square brackets ( [] ). 35 | 36 | To incorporate such a value into a Jsonify template, use the `ingest!` method. 37 | 38 | `ingest!` assumes that the value it receives is valid JSON representation. It parses the JSON into a Jsonify object graph, and then adds it to the current Jsonify builder. 39 | 40 | Let's assume this this is your main template, `index.jsonify`: 41 | 42 | json << 1 43 | json.ingest! (render :partial=>'my_partial') 44 | 45 | From the first line, you can tell that an array will be created as this line uses the append operator. 46 | On the second line, a partial is being added to the builder. Note that you cannot simply place `render :partial ...` on a line by itself as you can do with other templates like `erb` and `haml`. You have to explicitly tell Jsonify to add it to the builder. 47 | 48 | Let's say that the partial file, `_my_partial.jsonify`, is as follows: 49 | 50 | json << 3 51 | json << 4 52 | 53 | This `json` variable in this partial is a separate distinct `Jsonify::Builder` instance from the `json` variable in the main template. 54 | 55 | > Note: Figure out if a the `json` instance can be passed to the Jsonify partial. 56 | > It would make things easier and we wouldn't have to ingest the result. 57 | 58 | This partial results in the following string: 59 | 60 | "[3,4]" 61 | 62 | The `ingest!` method will actually parse this string back into a Jsonify-based object, and adds it to the builder's current state. The resulting output will be: 63 | 64 | "[1,[3,4]]" 65 | 66 | ##### Other partials 67 | 68 | You can also use output from non-Jsonify templates (e.g. erb); just remember that the output from a template is always a string and that you have to tell the builder how to include the result of the partial. 69 | 70 | For example, suppose you have the partial `_today.erb` with the following content: 71 | 72 | <%= Date.today %> 73 | 74 | You can then incorporate this partial into your Jsonify template just as you would any other string value: 75 | 76 | json << 1 77 | json << {:date => (render :partial => 'today')} 78 | 79 | renders ... 80 | 81 | [1,{"date":"2011-07-30"}] 82 | 83 | 84 | ## Related Projects 85 | - [Argonaut](https://github.com/jbr/argonaut) 86 | - [JSON Builder](https://github.com/dewski/json_builder) 87 | - [RABL](https://github.com/nesquena/rabl) 88 | - [Representative](https://github.com/mdub/representative) 89 | - [Tokamak](https://github.com/abril/tokamak) 90 | 91 | ## License 92 | 93 | This project is released under the MIT license. 94 | 95 | ## Authors 96 | 97 | * [Bill Siggelkow](https://github.com/bsiggelkow) 98 | 99 | ## Contributors 100 | 101 | * [Trym Skaar](https://github.com/trym) 102 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | require 'rspec/core/rake_task' 3 | 4 | RSpec::Core::RakeTask.new('spec') 5 | task :default => :spec -------------------------------------------------------------------------------- /jsonify-rails.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require "jsonify-rails/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "jsonify-rails" 7 | s.version = JsonifyRails::VERSION 8 | s.authors = ["Bill Siggelkow"] 9 | s.email = ["bsiggelkow@me.com"] 10 | s.homepage = "http://github.com/bsiggelkow/jsonify-rails" 11 | s.summary = %q{Use Jsonify for Rails View templates} 12 | s.description = s.summary 13 | 14 | s.rubyforge_project = s.name 15 | 16 | s.files = `git ls-files`.split("\n") 17 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 18 | s.require_paths = ["lib"] 19 | 20 | s.add_dependency 'jsonify', "< 0.4.0" 21 | s.add_dependency "actionpack" 22 | 23 | s.add_development_dependency 'bundler' 24 | s.add_development_dependency 'rake' 25 | s.add_development_dependency 'rspec' 26 | s.add_development_dependency 'json' unless RUBY_VERSION =~ /^1.9/ 27 | s.add_development_dependency 'rails', ENV["RAILS_VERSION"] || ">= 3.1.0" 28 | 29 | end 30 | -------------------------------------------------------------------------------- /lib/jsonify-rails.rb: -------------------------------------------------------------------------------- 1 | require 'jsonify' 2 | require 'jsonify-rails/jsonify_builder' -------------------------------------------------------------------------------- /lib/jsonify-rails/jsonify_builder.rb: -------------------------------------------------------------------------------- 1 | require 'action_view' 2 | module ActionView 3 | module Template::Handlers 4 | if ::Rails::VERSION::MAJOR == 3 && ::Rails::VERSION::MINOR < 1 5 | class JsonifyBuilder < Template::Handler 6 | include Compilable 7 | 8 | self.default_format = Mime::JSON 9 | 10 | def compile(template) 11 | "json = ::Jsonify::Builder.new(:format => :#{jsonify_format});" + 12 | template.source + 13 | ";\njson.compile!;" 14 | end 15 | 16 | private 17 | 18 | def jsonify_format 19 | Rails.application.config.respond_to?(:jsonify_format) ? Rails.application.config.jsonify_format : 'plain' 20 | end 21 | 22 | end 23 | else 24 | class JsonifyBuilder 25 | def default_format 26 | Mime::JSON 27 | end 28 | 29 | def self.call(template) 30 | "json = ::Jsonify::Builder.new(:format => :#{jsonify_format});" + 31 | template.source + 32 | ";\njson.compile!;" 33 | end 34 | 35 | private 36 | 37 | def self.jsonify_format 38 | Rails.application.config.respond_to?(:jsonify_format) ? Rails.application.config.jsonify_format : 'plain' 39 | end 40 | 41 | end 42 | end 43 | end 44 | end 45 | 46 | ActionView::Template.register_template_handler :jsonify, ActionView::Template::Handlers::JsonifyBuilder 47 | -------------------------------------------------------------------------------- /lib/jsonify-rails/version.rb: -------------------------------------------------------------------------------- 1 | module JsonifyRails 2 | VERSION = "0.3.2" 3 | end 4 | 5 | -------------------------------------------------------------------------------- /spec/fixtures/views/simple_test.jsonify: -------------------------------------------------------------------------------- 1 | json.hello 'world' -------------------------------------------------------------------------------- /spec/jsonify_builder_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'Jsonify template handler' do 4 | 5 | Handler = ActionView::Template::Handlers::JsonifyBuilder 6 | ViewTemplate = Struct.new(:source) 7 | 8 | let( :handler ) { Handler.new } 9 | 10 | let( :template ) do 11 | ViewTemplate.new("json.hello 'world'") 12 | end 13 | 14 | let( :template_with_trailing_comment ) do 15 | ViewTemplate.new("json.hello 'world' #trailing comment") 16 | end 17 | 18 | context "#{Rails.version}" do 19 | before do 20 | Rails.stub_chain(:application, :config, :jsonify_format).and_return( :plain ) 21 | end 22 | 23 | it 'should use JSON as its default output format' do 24 | handler.default_format.should == Mime::JSON 25 | end 26 | 27 | it 'should compile to JSON' do 28 | result = eval( Handler.call template ) 29 | result.should == '{"hello":"world"}' 30 | end 31 | 32 | it 'should ignore trailing comments' do 33 | result = eval( Handler.call template_with_trailing_comment ) 34 | result.should == '{"hello":"world"}' 35 | end 36 | 37 | describe 'when configured with ' do 38 | def expect_format(format) 39 | Jsonify::Builder.should_receive(:new).with({:format => format}).and_return( double("json").as_null_object ) 40 | end 41 | 42 | describe 'pretty' do 43 | before do 44 | Rails.stub_chain(:application, :config, :jsonify_format).and_return( :pretty ) 45 | end 46 | 47 | it 'should pass pretty to the builder' do 48 | expect_format :pretty 49 | eval( Handler.call template ) 50 | end 51 | end 52 | 53 | describe 'plain' do 54 | before do 55 | Rails.stub_chain(:application, :config, :jsonify_format).and_return( :plain ) 56 | end 57 | 58 | it 'should pass plain to the builder' do 59 | expect_format :plain 60 | eval( Handler.call template ) 61 | end 62 | end 63 | 64 | describe 'nothing' do 65 | before do 66 | Rails.stub_chain(:application, :config) 67 | end 68 | 69 | it 'should pass plain to the builder' do 70 | expect_format :plain 71 | eval( Handler.call template ) 72 | end 73 | end 74 | 75 | end 76 | end 77 | 78 | end -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | require 'bundler/setup' 3 | require 'rails' 4 | require 'jsonify' 5 | require 'jsonify-rails' 6 | 7 | RSpec.configure do |config| 8 | end --------------------------------------------------------------------------------