jbuilder-2.3.1/ 0000755 0000041 0000041 00000000000 12556325572 013361 5 ustar www-data www-data jbuilder-2.3.1/Rakefile 0000644 0000041 0000041 00000000776 12556325572 015040 0 ustar www-data www-data require "bundler/setup" require "bundler/gem_tasks" require "rake/testtask" if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"] require "appraisal/task" Appraisal::Task.new task default: :appraisal else Rake::TestTask.new do |test| require "rails/version" test.libs << "test" if Rails::VERSION::MAJOR == 3 test.test_files = %w[test/jbuilder_template_test.rb test/jbuilder_test.rb] else test.test_files = FileList["test/*_test.rb"] end end task default: :test end jbuilder-2.3.1/Gemfile 0000644 0000041 0000041 00000000151 12556325572 014651 0 ustar www-data www-data source "https://rubygems.org" gemspec gem "rake" gem "mocha", require: false gem "appraisal" gem "pry" jbuilder-2.3.1/MIT-LICENSE 0000644 0000041 0000041 00000002074 12556325572 015020 0 ustar www-data www-data Copyright (c) 2011-2014 David Heinemeier Hansson, 37signals Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. jbuilder-2.3.1/.travis.yml 0000644 0000041 0000041 00000001400 12556325572 015465 0 ustar www-data www-data language: ruby rvm: - 1.9 - 2.0 - 2.1 - 2.2 - ruby-head - jruby-19mode - rbx gemfile: - gemfiles/rails_3_0.gemfile - gemfiles/rails_3_1.gemfile - gemfiles/rails_3_2.gemfile - gemfiles/rails_4_0.gemfile - gemfiles/rails_4_1.gemfile - gemfiles/rails_4_2.gemfile - gemfiles/rails_edge.gemfile matrix: allow_failures: - rvm: jruby-19mode - rvm: rbx - rvm: ruby-head fast_finish: true exclude: - rvm: 1.9 gemfile: gemfiles/rails_edge.gemfile - rvm: 2.0 gemfile: gemfiles/rails_edge.gemfile - rvm: 2.1 gemfile: gemfiles/rails_edge.gemfile - rvm: jruby-19mode gemfile: gemfiles/rails_edge.gemfile - rvm: rbx gemfile: gemfiles/rails_edge.gemfile notifications: email: false jbuilder-2.3.1/lib/ 0000755 0000041 0000041 00000000000 12556325572 014127 5 ustar www-data www-data jbuilder-2.3.1/lib/jbuilder/ 0000755 0000041 0000041 00000000000 12556325572 015727 5 ustar www-data www-data jbuilder-2.3.1/lib/jbuilder/errors.rb 0000644 0000041 0000041 00000000601 12556325572 017565 0 ustar www-data www-data require 'jbuilder/jbuilder' class Jbuilder class NullError < ::NoMethodError def self.build(key) message = "Failed to add #{key.to_s.inspect} property to null object" new(message) end end class ArrayError < ::StandardError def self.build(key) message = "Failed to add #{key.to_s.inspect} property to an array" new(message) end end end jbuilder-2.3.1/lib/jbuilder/jbuilder_template.rb 0000644 0000041 0000041 00000011762 12556325572 021756 0 ustar www-data www-data require 'jbuilder/jbuilder' require 'action_dispatch/http/mime_type' require 'active_support/cache' class JbuilderTemplate < Jbuilder class << self attr_accessor :template_lookup_options end self.template_lookup_options = { handlers: [:jbuilder] } def initialize(context, *args) @context = context super *args end def partial!(*args) if args.one? && _is_active_model?(args.first) _render_active_model_partial args.first else _render_explicit_partial *args end end # Caches the json constructed within the block passed. Has the same signature as the `cache` helper # method in `ActionView::Helpers::CacheHelper` and so can be used in the same way. # # Example: # # json.cache! ['v1', @person], expires_in: 10.minutes do # json.extract! @person, :name, :age # end def cache!(key=nil, options={}) if @context.controller.perform_caching value = ::Rails.cache.fetch(_cache_key(key, options), options) do _scope { yield self } end merge! value else yield end end # Conditionally caches the json depending in the condition given as first parameter. Has the same # signature as the `cache` helper method in `ActionView::Helpers::CacheHelper` and so can be used in # the same way. # # Example: # # json.cache_if! !admin?, @person, expires_in: 10.minutes do # json.extract! @person, :name, :age # end def cache_if!(condition, *args) condition ? cache!(*args, &::Proc.new) : yield end def array!(collection = [], *args) options = args.first if args.one? && _partial_options?(options) partial! options.merge(collection: collection) else super end end def set!(name, object = BLANK, *args) options = args.first if args.one? && _partial_options?(options) _set_inline_partial name, object, options else super end end private def _render_partial_with_options(options) options.reverse_merge! locals: {} options.reverse_merge! ::JbuilderTemplate.template_lookup_options as = options[:as] if as && options.key?(:collection) as = as.to_sym collection = options.delete(:collection) locals = options.delete(:locals) array! collection do |member| member_locals = locals.clone member_locals.merge! collection: collection member_locals.merge! as => member _render_partial options.merge(locals: member_locals) end else _render_partial options end end def _render_partial(options) options[:locals].merge! json: self @context.render options end def _cache_key(key, options) key = _fragment_name_with_digest(key, options) key = url_for(key).split('://', 2).last if ::Hash === key ::ActiveSupport::Cache.expand_cache_key(key, :jbuilder) end def _fragment_name_with_digest(key, options) if @context.respond_to?(:cache_fragment_name) # Current compatibility, fragment_name_with_digest is private again and cache_fragment_name # should be used instead. @context.cache_fragment_name(key, options) elsif @context.respond_to?(:fragment_name_with_digest) # Backwards compatibility for period of time when fragment_name_with_digest was made public. @context.fragment_name_with_digest(key) else key end end def _partial_options?(options) ::Hash === options && options.key?(:as) && options.key?(:partial) end def _is_active_model?(object) object.class.respond_to?(:model_name) && object.respond_to?(:to_partial_path) end def _set_inline_partial(name, object, options) value = if object.nil? [] elsif _is_collection?(object) _scope{ _render_partial_with_options options.merge(collection: object) } else locals = ::Hash[options[:as], object] _scope{ _render_partial options.merge(locals: locals) } end set! name, value end def _render_explicit_partial(name_or_options, locals = {}) case name_or_options when ::Hash # partial! partial: 'name', foo: 'bar' options = name_or_options else # partial! 'name', locals: {foo: 'bar'} if locals.one? && (locals.keys.first == :locals) options = locals.merge(partial: name_or_options) else options = { partial: name_or_options, locals: locals } end # partial! 'name', foo: 'bar' as = locals.delete(:as) options[:as] = as if as.present? options[:collection] = locals[:collection] if locals.key?(:collection) end _render_partial_with_options options end def _render_active_model_partial(object) @context.render object, json: self end end class JbuilderHandler cattr_accessor :default_format self.default_format = Mime::JSON def self.call(template) # this juggling is required to keep line numbers right in the error %{__already_defined = defined?(json); json||=JbuilderTemplate.new(self); #{template.source} json.target! unless (__already_defined && __already_defined != "method")} end end jbuilder-2.3.1/lib/jbuilder/blank.rb 0000644 0000041 0000041 00000000203 12556325572 017336 0 ustar www-data www-data class Jbuilder class Blank def ==(other) super || Blank === other end def empty? true end end end jbuilder-2.3.1/lib/jbuilder/key_formatter.rb 0000644 0000041 0000041 00000001255 12556325572 021132 0 ustar www-data www-data require 'jbuilder/jbuilder' require 'active_support/core_ext/array' class Jbuilder class KeyFormatter def initialize(*args) @format = {} @cache = {} options = args.extract_options! args.each do |name| @format[name] = [] end options.each do |name, paramaters| @format[name] = paramaters end end def initialize_copy(original) @cache = {} end def format(key) @cache[key] ||= @format.inject(key.to_s) do |result, args| func, args = args if ::Proc === func func.call result, *args else result.send func, *args end end end end end jbuilder-2.3.1/lib/jbuilder/railtie.rb 0000644 0000041 0000041 00000001554 12556325572 017712 0 ustar www-data www-data require 'rails/railtie' require 'jbuilder/jbuilder_template' class Jbuilder class Railtie < ::Rails::Railtie initializer :jbuilder do |app| ActiveSupport.on_load :action_view do ActionView::Template.register_template_handler :jbuilder, JbuilderHandler require 'jbuilder/dependency_tracker' end if app.config.respond_to?(:api_only) && app.config.api_only ActiveSupport.on_load :action_controller do include ActionView::Rendering include ActionController::Helpers include ActionController::ImplicitRender end end end if Rails::VERSION::MAJOR >= 4 generators do |app| Rails::Generators.configure! app.config.generators Rails::Generators.hidden_namespaces.uniq! require 'generators/rails/scaffold_controller_generator' end end end end jbuilder-2.3.1/lib/jbuilder/jbuilder.rb 0000644 0000041 0000041 00000000273 12556325572 020056 0 ustar www-data www-data Jbuilder = Class.new(begin require 'active_support/proxy_object' ActiveSupport::ProxyObject rescue LoadError require 'active_support/basic_object' ActiveSupport::BasicObject end) jbuilder-2.3.1/lib/jbuilder/dependency_tracker.rb 0000644 0000041 0000041 00000003265 12556325572 022113 0 ustar www-data www-data require 'jbuilder/jbuilder' dependency_tracker = false begin require 'action_view' require 'action_view/dependency_tracker' dependency_tracker = ::ActionView::DependencyTracker rescue LoadError begin require 'cache_digests' dependency_tracker = ::CacheDigests::DependencyTracker rescue LoadError end end if dependency_tracker class Jbuilder module DependencyTrackerMethods # Matches: # json.partial! "messages/message" # json.partial!('messages/message') # DIRECT_RENDERS = / \w+\.partial! # json.partial! \(?\s* # optional parenthesis (['"])([^'"]+)\1 # quoted value /x # Matches: # json.partial! partial: "comments/comment" # json.comments @post.comments, partial: "comments/comment", as: :comment # json.array! @posts, partial: "posts/post", as: :post # = render partial: "account" # INDIRECT_RENDERS = / (?::partial\s*=>|partial:) # partial: or :partial => \s* # optional whitespace (['"])([^'"]+)\1 # quoted value /x def dependencies direct_dependencies + indirect_dependencies + explicit_dependencies end private def direct_dependencies source.scan(DIRECT_RENDERS).map(&:second) end def indirect_dependencies source.scan(INDIRECT_RENDERS).map(&:second) end end end ::Jbuilder::DependencyTracker = Class.new(dependency_tracker::ERBTracker) ::Jbuilder::DependencyTracker.send :include, ::Jbuilder::DependencyTrackerMethods dependency_tracker.register_tracker :jbuilder, ::Jbuilder::DependencyTracker end jbuilder-2.3.1/lib/generators/ 0000755 0000041 0000041 00000000000 12556325572 016300 5 ustar www-data www-data jbuilder-2.3.1/lib/generators/rails/ 0000755 0000041 0000041 00000000000 12556325572 017412 5 ustar www-data www-data jbuilder-2.3.1/lib/generators/rails/jbuilder_generator.rb 0000644 0000041 0000041 00000002567 12556325572 023617 0 ustar www-data www-data require 'rails/generators/named_base' require 'rails/generators/resource_helpers' module Rails module Generators class JbuilderGenerator < NamedBase # :nodoc: include Rails::Generators::ResourceHelpers source_root File.expand_path('../templates', __FILE__) argument :attributes, type: :array, default: [], banner: 'field:type field:type' def create_root_folder path = File.join('app/views', controller_file_path) empty_directory path unless File.directory?(path) end def copy_view_files %w(index show).each do |view| filename = filename_with_extensions(view) template filename, File.join('app/views', controller_file_path, filename) end end protected def attributes_names [:id] + super end def filename_with_extensions(name) [name, :json, :jbuilder] * '.' end def attributes_list_with_timestamps attributes_list(attributes_names + %w(created_at updated_at)) end def attributes_list(attributes = attributes_names) if self.attributes.any? {|attr| attr.name == 'password' && attr.type == :digest} attributes = attributes.reject {|name| %w(password password_confirmation).include? name} end attributes.map { |a| ":#{a}"} * ', ' end end end end jbuilder-2.3.1/lib/generators/rails/templates/ 0000755 0000041 0000041 00000000000 12556325572 021410 5 ustar www-data www-data jbuilder-2.3.1/lib/generators/rails/templates/index.json.jbuilder 0000644 0000041 0000041 00000000343 12556325572 025211 0 ustar www-data www-data json.array!(@<%= plural_table_name %>) do |<%= singular_table_name %>| json.extract! <%= singular_table_name %>, <%= attributes_list %> json.url <%= singular_table_name %>_url(<%= singular_table_name %>, format: :json) end jbuilder-2.3.1/lib/generators/rails/templates/api_controller.rb 0000644 0000041 0000041 00000003670 12556325572 024757 0 ustar www-data www-data <% if namespaced? -%> require_dependency "<%= namespaced_file_path %>/application_controller" <% end -%> <% module_namespacing do -%> class <%= controller_class_name %>Controller < ApplicationController before_action :set_<%= singular_table_name %>, only: [:show, :update, :destroy] # GET <%= route_url %> # GET <%= route_url %>.json def index @<%= plural_table_name %> = <%= orm_class.all(class_name) %> end # GET <%= route_url %>/1 # GET <%= route_url %>/1.json def show end # POST <%= route_url %> # POST <%= route_url %>.json def create @<%= singular_table_name %> = <%= orm_class.build(class_name, "#{singular_table_name}_params") %> if @<%= orm_instance.save %> render :show, status: :created, location: <%= "@#{singular_table_name}" %> else render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity end end # PATCH/PUT <%= route_url %>/1 # PATCH/PUT <%= route_url %>/1.json def update if @<%= orm_instance.update("#{singular_table_name}_params") %> render :show, status: :ok, location: <%= "@#{singular_table_name}" %> else render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity end end # DELETE <%= route_url %>/1 # DELETE <%= route_url %>/1.json def destroy @<%= orm_instance.destroy %> end private # Use callbacks to share common setup or constraints between actions. def set_<%= singular_table_name %> @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %> end # Never trust parameters from the scary internet, only allow the white list through. def <%= "#{singular_table_name}_params" %> <%- if attributes_names.empty? -%> params[<%= ":#{singular_table_name}" %>] <%- else -%> params.require(<%= ":#{singular_table_name}" %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>) <%- end -%> end end <% end -%> jbuilder-2.3.1/lib/generators/rails/templates/show.json.jbuilder 0000644 0000041 0000041 00000000122 12556325572 025055 0 ustar www-data www-data json.extract! @<%= singular_table_name %>, <%= attributes_list_with_timestamps %> jbuilder-2.3.1/lib/generators/rails/templates/controller.rb 0000644 0000041 0000041 00000005401 12556325572 024120 0 ustar www-data www-data <% if namespaced? -%> require_dependency "<%= namespaced_file_path %>/application_controller" <% end -%> <% module_namespacing do -%> class <%= controller_class_name %>Controller < ApplicationController before_action :set_<%= singular_table_name %>, only: [:show, :edit, :update, :destroy] # GET <%= route_url %> # GET <%= route_url %>.json def index @<%= plural_table_name %> = <%= orm_class.all(class_name) %> end # GET <%= route_url %>/1 # GET <%= route_url %>/1.json def show end # GET <%= route_url %>/new def new @<%= singular_table_name %> = <%= orm_class.build(class_name) %> end # GET <%= route_url %>/1/edit def edit end # POST <%= route_url %> # POST <%= route_url %>.json def create @<%= singular_table_name %> = <%= orm_class.build(class_name, "#{singular_table_name}_params") %> respond_to do |format| if @<%= orm_instance.save %> format.html { redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully created.'" %> } format.json { render :show, status: :created, location: <%= "@#{singular_table_name}" %> } else format.html { render :new } format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity } end end end # PATCH/PUT <%= route_url %>/1 # PATCH/PUT <%= route_url %>/1.json def update respond_to do |format| if @<%= orm_instance.update("#{singular_table_name}_params") %> format.html { redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully updated.'" %> } format.json { render :show, status: :ok, location: <%= "@#{singular_table_name}" %> } else format.html { render :edit } format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity } end end end # DELETE <%= route_url %>/1 # DELETE <%= route_url %>/1.json def destroy @<%= orm_instance.destroy %> respond_to do |format| format.html { redirect_to <%= index_helper %>_url, notice: <%= "'#{human_name} was successfully destroyed.'" %> } format.json { head :no_content } end end private # Use callbacks to share common setup or constraints between actions. def set_<%= singular_table_name %> @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %> end # Never trust parameters from the scary internet, only allow the white list through. def <%= "#{singular_table_name}_params" %> <%- if attributes_names.empty? -%> params[<%= ":#{singular_table_name}" %>] <%- else -%> params.require(<%= ":#{singular_table_name}" %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>) <%- end -%> end end <% end -%> jbuilder-2.3.1/lib/generators/rails/scaffold_controller_generator.rb 0000644 0000041 0000041 00000000462 12556325572 026033 0 ustar www-data www-data require 'rails/generators' require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator' module Rails module Generators class ScaffoldControllerGenerator source_paths << File.expand_path('../templates', __FILE__) hook_for :jbuilder, default: true end end end jbuilder-2.3.1/lib/jbuilder.rb 0000644 0000041 0000041 00000020637 12556325572 016264 0 ustar www-data www-data require 'jbuilder/jbuilder' require 'jbuilder/blank' require 'jbuilder/key_formatter' require 'jbuilder/errors' require 'multi_json' require 'ostruct' class Jbuilder @@key_formatter = nil @@ignore_nil = false def initialize(options = {}) @attributes = {} @key_formatter = options.fetch(:key_formatter){ @@key_formatter ? @@key_formatter.clone : nil} @ignore_nil = options.fetch(:ignore_nil, @@ignore_nil) yield self if ::Kernel.block_given? end # Yields a builder and automatically turns the result into a JSON string def self.encode(*args, &block) new(*args, &block).target! end BLANK = Blank.new NON_ENUMERABLES = [ ::Struct, ::OpenStruct ].to_set def set!(key, value = BLANK, *args) result = if ::Kernel.block_given? if !_blank?(value) # json.comments @post.comments { |comment| ... } # { "comments": [ { ... }, { ... } ] } _scope{ array! value, &::Proc.new } else # json.comments { ... } # { "comments": ... } _merge_block(key){ yield self } end elsif args.empty? if ::Jbuilder === value # json.age 32 # json.person another_jbuilder # { "age": 32, "person": { ... } value.attributes! else # json.age 32 # { "age": 32 } value end elsif _is_collection?(value) # json.comments @post.comments, :content, :created_at # { "comments": [ { "content": "hello", "created_at": "..." }, { "content": "world", "created_at": "..." } ] } _scope{ array! value, *args } else # json.author @post.creator, :name, :email_address # { "author": { "name": "David", "email_address": "david@loudthinking.com" } } _merge_block(key){ extract! value, *args } end _set_value key, result end def method_missing(*args) if ::Kernel.block_given? set! *args, &::Proc.new else set! *args end end # Specifies formatting to be applied to the key. Passing in a name of a function # will cause that function to be called on the key. So :upcase will upper case # the key. You can also pass in lambdas for more complex transformations. # # Example: # # json.key_format! :upcase # json.author do # json.name "David" # json.age 32 # end # # { "AUTHOR": { "NAME": "David", "AGE": 32 } } # # You can pass parameters to the method using a hash pair. # # json.key_format! camelize: :lower # json.first_name "David" # # { "firstName": "David" } # # Lambdas can also be used. # # json.key_format! ->(key){ "_" + key } # json.first_name "David" # # { "_first_name": "David" } # def key_format!(*args) @key_formatter = KeyFormatter.new(*args) end # Same as the instance method key_format! except sets the default. def self.key_format(*args) @@key_formatter = KeyFormatter.new(*args) end # If you want to skip adding nil values to your JSON hash. This is useful # for JSON clients that don't deal well with nil values, and would prefer # not to receive keys which have null values. # # Example: # json.ignore_nil! false # json.id User.new.id # # { "id": null } # # json.ignore_nil! # json.id User.new.id # # {} # def ignore_nil!(value = true) @ignore_nil = value end # Same as instance method ignore_nil! except sets the default. def self.ignore_nil(value = true) @@ignore_nil = value end # Turns the current element into an array and yields a builder to add a hash. # # Example: # # json.comments do # json.child! { json.content "hello" } # json.child! { json.content "world" } # end # # { "comments": [ { "content": "hello" }, { "content": "world" } ]} # # More commonly, you'd use the combined iterator, though: # # json.comments(@post.comments) do |comment| # json.content comment.formatted_content # end def child! @attributes = [] unless ::Array === @attributes @attributes << _scope{ yield self } end # Turns the current element into an array and iterates over the passed collection, adding each iteration as # an element of the resulting array. # # Example: # # json.array!(@people) do |person| # json.name person.name # json.age calculate_age(person.birthday) # end # # [ { "name": David", "age": 32 }, { "name": Jamie", "age": 31 } ] # # If you are using Ruby 1.9+, you can use the call syntax instead of an explicit extract! call: # # json.(@people) { |person| ... } # # It's generally only needed to use this method for top-level arrays. If you have named arrays, you can do: # # json.people(@people) do |person| # json.name person.name # json.age calculate_age(person.birthday) # end # # { "people": [ { "name": David", "age": 32 }, { "name": Jamie", "age": 31 } ] } # # If you omit the block then you can set the top level array directly: # # json.array! [1, 2, 3] # # [1,2,3] def array!(collection = [], *attributes) array = if collection.nil? [] elsif ::Kernel.block_given? _map_collection(collection, &::Proc.new) elsif attributes.any? _map_collection(collection) { |element| extract! element, *attributes } else collection.to_a end merge! array end # Extracts the mentioned attributes or hash elements from the passed object and turns them into attributes of the JSON. # # Example: # # @person = Struct.new(:name, :age).new('David', 32) # # or you can utilize a Hash # # @person = { name: 'David', age: 32 } # # json.extract! @person, :name, :age # # { "name": David", "age": 32 }, { "name": Jamie", "age": 31 } # # You can also use the call syntax instead of an explicit extract! call: # # json.(@person, :name, :age) def extract!(object, *attributes) if ::Hash === object _extract_hash_values(object, attributes) else _extract_method_values(object, attributes) end end def call(object, *attributes) if ::Kernel.block_given? array! object, &::Proc.new else extract! object, *attributes end end # Returns the nil JSON. def nil! @attributes = nil end alias_method :null!, :nil! # Returns the attributes of the current builder. def attributes! @attributes end # Merges hash or array into current builder. def merge!(hash_or_array) @attributes = _merge_values(@attributes, hash_or_array) end # Encodes the current builder as JSON. def target! ::MultiJson.dump(@attributes) end private def _extract_hash_values(object, attributes) attributes.each{ |key| _set_value key, object.fetch(key) } end def _extract_method_values(object, attributes) attributes.each{ |key| _set_value key, object.public_send(key) } end def _merge_block(key) current_value = _blank? ? BLANK : @attributes.fetch(_key(key), BLANK) raise NullError.build(key) if current_value.nil? new_value = _scope{ yield self } _merge_values(current_value, new_value) end def _merge_values(current_value, updates) if _blank?(updates) current_value elsif _blank?(current_value) || updates.nil? updates elsif ::Array === updates ::Array === current_value ? current_value + updates : updates elsif ::Hash === current_value current_value.merge(updates) else raise "Can't merge #{updates.inspect} with #{current_value.inspect}" end end def _key(key) @key_formatter ? @key_formatter.format(key) : key.to_s end def _set_value(key, value) raise NullError.build(key) if @attributes.nil? raise ArrayError.build(key) if ::Array === @attributes return if @ignore_nil && value.nil? or _blank?(value) @attributes = {} if _blank? @attributes[_key(key)] = value end def _map_collection(collection) collection.map do |element| _scope{ yield element } end - [BLANK] end def _scope parent_attributes, parent_formatter = @attributes, @key_formatter @attributes = BLANK yield @attributes ensure @attributes, @key_formatter = parent_attributes, parent_formatter end def _is_collection?(object) _object_respond_to?(object, :map, :count) && NON_ENUMERABLES.none?{ |klass| klass === object } end def _blank?(value=@attributes) BLANK == value end def _object_respond_to?(object, *methods) methods.all?{ |m| object.respond_to?(m) } end end require 'jbuilder/railtie' if defined?(Rails) jbuilder-2.3.1/gemfiles/ 0000755 0000041 0000041 00000000000 12556325572 015154 5 ustar www-data www-data jbuilder-2.3.1/gemfiles/rails_4_1.gemfile 0000644 0000041 0000041 00000000371 12556325572 020264 0 ustar www-data www-data # This file was generated by Appraisal source "https://rubygems.org" gem "rake" gem "mocha", :require => false gem "appraisal" gem "pry" gem "railties", "~> 4.1.0" gem "actionpack", "~> 4.1.0" gem "activemodel", "~> 4.1.0" gemspec :path => "../" jbuilder-2.3.1/gemfiles/rails_4_2.gemfile 0000644 0000041 0000041 00000000371 12556325572 020265 0 ustar www-data www-data # This file was generated by Appraisal source "https://rubygems.org" gem "rake" gem "mocha", :require => false gem "appraisal" gem "pry" gem "railties", "~> 4.2.0" gem "actionpack", "~> 4.2.0" gem "activemodel", "~> 4.2.0" gemspec :path => "../" jbuilder-2.3.1/gemfiles/rails_3_0.gemfile 0000644 0000041 0000041 00000000411 12556325572 020255 0 ustar www-data www-data # This file was generated by Appraisal source "https://rubygems.org" gem "rake" gem "mocha", :require => false gem "appraisal" gem "pry" gem "test-unit" gem "railties", "~> 3.0.0" gem "actionpack", "~> 3.0.0" gem "activemodel", "~> 3.0.0" gemspec :path => "../" jbuilder-2.3.1/gemfiles/rails_3_2.gemfile 0000644 0000041 0000041 00000000411 12556325572 020257 0 ustar www-data www-data # This file was generated by Appraisal source "https://rubygems.org" gem "rake" gem "mocha", :require => false gem "appraisal" gem "pry" gem "test-unit" gem "railties", "~> 3.2.0" gem "actionpack", "~> 3.2.0" gem "activemodel", "~> 3.2.0" gemspec :path => "../" jbuilder-2.3.1/gemfiles/rails_4_0.gemfile 0000644 0000041 0000041 00000000371 12556325572 020263 0 ustar www-data www-data # This file was generated by Appraisal source "https://rubygems.org" gem "rake" gem "mocha", :require => false gem "appraisal" gem "pry" gem "railties", "~> 4.0.0" gem "actionpack", "~> 4.0.0" gem "activemodel", "~> 4.0.0" gemspec :path => "../" jbuilder-2.3.1/gemfiles/rails_edge.gemfile 0000644 0000041 0000041 00000000343 12556325572 020604 0 ustar www-data www-data # This file was generated by Appraisal source "https://rubygems.org" gem "rake" gem "mocha", :require => false gem "appraisal" gem "rails", :github => "rails/rails" gem "arel", :github => "rails/arel" gemspec :path => "../" jbuilder-2.3.1/gemfiles/rails_3_1.gemfile 0000644 0000041 0000041 00000000411 12556325572 020256 0 ustar www-data www-data # This file was generated by Appraisal source "https://rubygems.org" gem "rake" gem "mocha", :require => false gem "appraisal" gem "pry" gem "test-unit" gem "railties", "~> 3.1.0" gem "actionpack", "~> 3.1.0" gem "activemodel", "~> 3.1.0" gemspec :path => "../" jbuilder-2.3.1/metadata.yml 0000644 0000041 0000041 00000006150 12556325572 015666 0 ustar www-data www-data --- !ruby/object:Gem::Specification name: jbuilder version: !ruby/object:Gem::Version version: 2.3.1 platform: ruby authors: - David Heinemeier Hansson - Pavel Pravosud autorequire: bindir: bin cert_chain: [] date: 2015-07-06 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: activesupport requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 3.0.0 - - "<" - !ruby/object:Gem::Version version: '5' type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 3.0.0 - - "<" - !ruby/object:Gem::Version version: '5' - !ruby/object:Gem::Dependency name: multi_json requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '1.2' type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '1.2' description: email: - david@37signals.com - pavel@pravosud.com executables: [] extensions: [] extra_rdoc_files: [] files: - ".gitignore" - ".travis.yml" - Appraisals - CHANGELOG.md - Gemfile - MIT-LICENSE - README.md - Rakefile - gemfiles/rails_3_0.gemfile - gemfiles/rails_3_1.gemfile - gemfiles/rails_3_2.gemfile - gemfiles/rails_4_0.gemfile - gemfiles/rails_4_1.gemfile - gemfiles/rails_4_2.gemfile - gemfiles/rails_edge.gemfile - jbuilder.gemspec - lib/generators/rails/jbuilder_generator.rb - lib/generators/rails/scaffold_controller_generator.rb - lib/generators/rails/templates/api_controller.rb - lib/generators/rails/templates/controller.rb - lib/generators/rails/templates/index.json.jbuilder - lib/generators/rails/templates/show.json.jbuilder - lib/jbuilder.rb - lib/jbuilder/blank.rb - lib/jbuilder/dependency_tracker.rb - lib/jbuilder/errors.rb - lib/jbuilder/jbuilder.rb - lib/jbuilder/jbuilder_template.rb - lib/jbuilder/key_formatter.rb - lib/jbuilder/railtie.rb - test/jbuilder_dependency_tracker_test.rb - test/jbuilder_generator_test.rb - test/jbuilder_template_test.rb - test/jbuilder_test.rb - test/scaffold_api_controller_generator_test.rb - test/scaffold_controller_generator_test.rb - test/test_helper.rb homepage: https://github.com/rails/jbuilder licenses: - MIT metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 1.9.3 required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.4.8 signing_key: specification_version: 4 summary: Create JSON structures via a Builder-style DSL test_files: - test/jbuilder_dependency_tracker_test.rb - test/jbuilder_generator_test.rb - test/jbuilder_template_test.rb - test/jbuilder_test.rb - test/scaffold_api_controller_generator_test.rb - test/scaffold_controller_generator_test.rb - test/test_helper.rb jbuilder-2.3.1/test/ 0000755 0000041 0000041 00000000000 12556325572 014340 5 ustar www-data www-data jbuilder-2.3.1/test/jbuilder_template_test.rb 0000644 0000041 0000041 00000023041 12556325572 021417 0 ustar www-data www-data require "test_helper" require "mocha/setup" require "active_model" require "action_view" require "action_view/testing/resolvers" require "active_support/cache" require "jbuilder/jbuilder_template" BLOG_POST_PARTIAL = <<-JBUILDER json.extract! blog_post, :id, :body json.author do first_name, last_name = blog_post.author_name.split(nil, 2) json.first_name first_name json.last_name last_name end JBUILDER COLLECTION_PARTIAL = <<-JBUILDER json.extract! collection, :id, :name JBUILDER RACER_PARTIAL = <<-JBUILDER json.extract! racer, :id, :name JBUILDER class Racer extend ActiveModel::Naming include ActiveModel::Conversion def initialize(id, name) @id, @name = id, name end attr_reader :id, :name end BlogPost = Struct.new(:id, :body, :author_name) Collection = Struct.new(:id, :name) blog_authors = [ "David Heinemeier Hansson", "Pavel Pravosud" ].cycle BLOG_POST_COLLECTION = Array.new(10){ |i| BlogPost.new(i+1, "post body #{i+1}", blog_authors.next) } COLLECTION_COLLECTION = Array.new(5){ |i| Collection.new(i+1, "collection #{i+1}") } ActionView::Template.register_template_handler :jbuilder, JbuilderHandler PARTIALS = { "_partial.json.jbuilder" => "foo ||= 'hello'; json.content foo", "_blog_post.json.jbuilder" => BLOG_POST_PARTIAL, "racers/_racer.json.jbuilder" => RACER_PARTIAL, "_collection.json.jbuilder" => COLLECTION_PARTIAL } module Rails def self.cache @cache ||= ActiveSupport::Cache::MemoryStore.new end end class JbuilderTemplateTest < ActionView::TestCase setup do @context = self Rails.cache.clear end def jbuild(source) @rendered = [] partials = PARTIALS.clone partials["test.json.jbuilder"] = source resolver = ActionView::FixtureResolver.new(partials) lookup_context.view_paths = [resolver] template = ActionView::Template.new(source, "test", JbuilderHandler, virtual_path: "test") json = template.render(self, {}).strip MultiJson.load(json) end def undef_context_methods(*names) self.class_eval do names.each do |name| undef_method name.to_sym if method_defined?(name.to_sym) end end end def assert_collection_rendered(result, context = nil) result = result.fetch(context) if context assert_equal 10, result.length assert_equal Array, result.class assert_equal "post body 5", result[4]["body"] assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"] assert_equal "Pavel", result[5]["author"]["first_name"] end test "rendering" do result = jbuild(<<-JBUILDER) json.content "hello" JBUILDER assert_equal "hello", result["content"] end test "key_format! with parameter" do result = jbuild(<<-JBUILDER) json.key_format! camelize: [:lower] json.camel_style "for JS" JBUILDER assert_equal ["camelStyle"], result.keys end test "key_format! propagates to child elements" do result = jbuild(<<-JBUILDER) json.key_format! :upcase json.level1 "one" json.level2 do json.value "two" end JBUILDER assert_equal "one", result["LEVEL1"] assert_equal "two", result["LEVEL2"]["VALUE"] end test "partial! renders partial" do result = jbuild(<<-JBUILDER) json.partial! "partial" JBUILDER assert_equal "hello", result["content"] end test "partial! + locals via :locals option" do result = jbuild(<<-JBUILDER) json.partial! "partial", locals: { foo: "howdy" } JBUILDER assert_equal "howdy", result["content"] end test "partial! + locals without :locals key" do result = jbuild(<<-JBUILDER) json.partial! "partial", foo: "goodbye" JBUILDER assert_equal "goodbye", result["content"] end test "partial! renders collections" do result = jbuild(<<-JBUILDER) json.partial! "blog_post", collection: BLOG_POST_COLLECTION, as: :blog_post JBUILDER assert_collection_rendered result end test "partial! renders collections when as argument is a string" do result = jbuild(<<-JBUILDER) json.partial! "blog_post", collection: BLOG_POST_COLLECTION, as: "blog_post" JBUILDER assert_collection_rendered result end test "partial! renders collections as collections" do result = jbuild(<<-JBUILDER) json.partial! "collection", collection: COLLECTION_COLLECTION, as: :collection JBUILDER assert_equal 5, result.length end test "partial! renders as empty array for nil-collection" do result = jbuild(<<-JBUILDER) json.partial! "blog_post", collection: nil, as: :blog_post JBUILDER assert_equal [], result end test "partial! renders collection (alt. syntax)" do result = jbuild(<<-JBUILDER) json.partial! partial: "blog_post", collection: BLOG_POST_COLLECTION, as: :blog_post JBUILDER assert_collection_rendered result end test "partial! renders as empty array for nil-collection (alt. syntax)" do result = jbuild(<<-JBUILDER) json.partial! partial: "blog_post", collection: nil, as: :blog_post JBUILDER assert_equal [], result end test "render array of partials" do result = jbuild(<<-JBUILDER) json.array! BLOG_POST_COLLECTION, partial: "blog_post", as: :blog_post JBUILDER assert_collection_rendered result end test "render array of partials as empty array with nil-collection" do result = jbuild(<<-JBUILDER) json.array! nil, partial: "blog_post", as: :blog_post JBUILDER assert_equal [], result end test "render array of partials as a value" do result = jbuild(<<-JBUILDER) json.posts BLOG_POST_COLLECTION, partial: "blog_post", as: :blog_post JBUILDER assert_collection_rendered result, "posts" end test "render as empty array if partials as a nil value" do result = jbuild <<-JBUILDER json.posts nil, partial: "blog_post", as: :blog_post JBUILDER assert_equal [], result["posts"] end test "cache an empty block" do undef_context_methods :fragment_name_with_digest, :cache_fragment_name jbuild <<-JBUILDER json.cache! "nothing" do end JBUILDER result = nil assert_nothing_raised do result = jbuild(<<-JBUILDER) json.foo "bar" json.cache! "nothing" do end JBUILDER end assert_equal "bar", result["foo"] end test "fragment caching a JSON object" do undef_context_methods :fragment_name_with_digest, :cache_fragment_name jbuild <<-JBUILDER json.cache! "cachekey" do json.name "Cache" end JBUILDER result = jbuild(<<-JBUILDER) json.cache! "cachekey" do json.name "Miss" end JBUILDER assert_equal "Cache", result["name"] end test "conditionally fragment caching a JSON object" do undef_context_methods :fragment_name_with_digest, :cache_fragment_name jbuild <<-JBUILDER json.cache_if! true, "cachekey" do json.test1 "Cache" end json.cache_if! false, "cachekey" do json.test2 "Cache" end JBUILDER result = jbuild(<<-JBUILDER) json.cache_if! true, "cachekey" do json.test1 "Miss" end json.cache_if! false, "cachekey" do json.test2 "Miss" end JBUILDER assert_equal "Cache", result["test1"] assert_equal "Miss", result["test2"] end test "fragment caching deserializes an array" do undef_context_methods :fragment_name_with_digest, :cache_fragment_name jbuild <<-JBUILDER json.cache! "cachekey" do json.array! %w[a b c] end JBUILDER result = jbuild(<<-JBUILDER) json.cache! "cachekey" do json.array! %w[1 2 3] end JBUILDER assert_equal %w[a b c], result end test "fragment caching works with previous version of cache digests" do undef_context_methods :cache_fragment_name @context.expects :fragment_name_with_digest jbuild <<-JBUILDER json.cache! "cachekey" do json.name "Cache" end JBUILDER end test "fragment caching works with current cache digests" do undef_context_methods :fragment_name_with_digest @context.expects :cache_fragment_name ActiveSupport::Cache.expects :expand_cache_key jbuild <<-JBUILDER json.cache! "cachekey" do json.name "Cache" end JBUILDER end test "current cache digest option accepts options" do undef_context_methods :fragment_name_with_digest @context.expects(:cache_fragment_name).with("cachekey", skip_digest: true) ActiveSupport::Cache.expects :expand_cache_key jbuild <<-JBUILDER json.cache! "cachekey", skip_digest: true do json.name "Cache" end JBUILDER end test "does not perform caching when controller.perform_caching is false" do controller.perform_caching = false jbuild <<-JBUILDER json.cache! "cachekey" do json.name "Cache" end JBUILDER assert_equal Rails.cache.inspect[/entries=(\d+)/, 1], "0" end test "invokes templates via params via set!" do @post = BLOG_POST_COLLECTION.first result = jbuild(<<-JBUILDER) json.post @post, partial: "blog_post", as: :blog_post JBUILDER assert_equal 1, result["post"]["id"] assert_equal "post body 1", result["post"]["body"] assert_equal "David", result["post"]["author"]["first_name"] end test "invokes templates implicitly for ActiveModel objects" do @racer = Racer.new(123, "Chris Harris") result = jbuild(<<-JBUILDER) json.partial! @racer JBUILDER assert_equal %w[id name], result.keys assert_equal 123, result["id"] assert_equal "Chris Harris", result["name"] end end jbuilder-2.3.1/test/jbuilder_test.rb 0000644 0000041 0000041 00000037725 12556325572 017542 0 ustar www-data www-data require 'test_helper' require 'active_support/inflector' require 'jbuilder' def jbuild(*args, &block) Jbuilder.new(*args, &block).attributes! end Comment = Struct.new(:content, :id) class NonEnumerable def initialize(collection) @collection = collection end delegate :map, :count, to: :@collection end class VeryBasicWrapper < BasicObject def initialize(thing) @thing = thing end def method_missing(name, *args, &block) @thing.send name, *args, &block end end # This is not Struct, because structs are Enumerable class Person attr_reader :name, :age def initialize(name, age) @name, @age = name, age end end class RelationMock include Enumerable def each(&block) [Person.new('Bob', 30), Person.new('Frank', 50)].each(&block) end def empty? false end end class JbuilderTest < ActiveSupport::TestCase setup do Jbuilder.send :class_variable_set, '@@key_formatter', nil end test 'single key' do result = jbuild do |json| json.content 'hello' end assert_equal 'hello', result['content'] end test 'single key with false value' do result = jbuild do |json| json.content false end assert_equal false, result['content'] end test 'single key with nil value' do result = jbuild do |json| json.content nil end assert result.has_key?('content') assert_equal nil, result['content'] end test 'multiple keys' do result = jbuild do |json| json.title 'hello' json.content 'world' end assert_equal 'hello', result['title'] assert_equal 'world', result['content'] end test 'extracting from object' do person = Struct.new(:name, :age).new('David', 32) result = jbuild do |json| json.extract! person, :name, :age end assert_equal 'David', result['name'] assert_equal 32, result['age'] end test 'extracting from object using call style for 1.9' do person = Struct.new(:name, :age).new('David', 32) result = jbuild do |json| json.(person, :name, :age) end assert_equal 'David', result['name'] assert_equal 32, result['age'] end test 'extracting from hash' do person = {:name => 'Jim', :age => 34} result = jbuild do |json| json.extract! person, :name, :age end assert_equal 'Jim', result['name'] assert_equal 34, result['age'] end test 'nesting single child with block' do result = jbuild do |json| json.author do json.name 'David' json.age 32 end end assert_equal 'David', result['author']['name'] assert_equal 32, result['author']['age'] end test 'empty block handling' do result = jbuild do |json| json.foo 'bar' json.author do end end assert_equal 'bar', result['foo'] assert !result.key?('author') end test 'blocks are additive' do result = jbuild do |json| json.author do json.name 'David' end json.author do json.age 32 end end assert_equal 'David', result['author']['name'] assert_equal 32, result['author']['age'] end test 'support merge! method' do result = jbuild do |json| json.merge! 'foo' => 'bar' end assert_equal 'bar', result['foo'] end test 'support merge! method in a block' do result = jbuild do |json| json.author do json.merge! 'name' => 'Pavel' end end assert_equal 'Pavel', result['author']['name'] end test 'blocks are additive via extract syntax' do person = Person.new('Pavel', 27) result = jbuild do |json| json.author person, :age json.author person, :name end assert_equal 'Pavel', result['author']['name'] assert_equal 27, result['author']['age'] end test 'arrays are additive' do result = jbuild do |json| json.array! %w[foo] json.array! %w[bar] end assert_equal %w[foo bar], result end test 'nesting multiple children with block' do result = jbuild do |json| json.comments do json.child! { json.content 'hello' } json.child! { json.content 'world' } end end assert_equal 'hello', result['comments'].first['content'] assert_equal 'world', result['comments'].second['content'] end test 'nesting single child with inline extract' do person = Person.new('David', 32) result = jbuild do |json| json.author person, :name, :age end assert_equal 'David', result['author']['name'] assert_equal 32, result['author']['age'] end test 'nesting multiple children from array' do comments = [ Comment.new('hello', 1), Comment.new('world', 2) ] result = jbuild do |json| json.comments comments, :content end assert_equal ['content'], result['comments'].first.keys assert_equal 'hello', result['comments'].first['content'] assert_equal 'world', result['comments'].second['content'] end test 'nesting multiple children from array when child array is empty' do comments = [] result = jbuild do |json| json.name 'Parent' json.comments comments, :content end assert_equal 'Parent', result['name'] assert_equal [], result['comments'] end test 'nesting multiple children from array with inline loop' do comments = [ Comment.new('hello', 1), Comment.new('world', 2) ] result = jbuild do |json| json.comments comments do |comment| json.content comment.content end end assert_equal ['content'], result['comments'].first.keys assert_equal 'hello', result['comments'].first['content'] assert_equal 'world', result['comments'].second['content'] end test 'handles nil-collections as empty arrays' do result = jbuild do |json| json.comments nil do |comment| json.content comment.content end end assert_equal [], result['comments'] end test 'nesting multiple children from a non-Enumerable that responds to #map' do comments = NonEnumerable.new([ Comment.new('hello', 1), Comment.new('world', 2) ]) result = jbuild do |json| json.comments comments, :content end assert_equal ['content'], result['comments'].first.keys assert_equal 'hello', result['comments'].first['content'] assert_equal 'world', result['comments'].second['content'] end test 'nesting multiple chilren from a non-Enumerable that responds to #map with inline loop' do comments = NonEnumerable.new([ Comment.new('hello', 1), Comment.new('world', 2) ]) result = jbuild do |json| json.comments comments do |comment| json.content comment.content end end assert_equal ['content'], result['comments'].first.keys assert_equal 'hello', result['comments'].first['content'] assert_equal 'world', result['comments'].second['content'] end test 'array! casts array-like objects to array before merging' do wrapped_array = VeryBasicWrapper.new(%w[foo bar]) result = jbuild do |json| json.array! wrapped_array end assert_equal %w[foo bar], result end test 'nesting multiple children from array with inline loop on root' do comments = [ Comment.new('hello', 1), Comment.new('world', 2) ] result = jbuild do |json| json.call(comments) do |comment| json.content comment.content end end assert_equal 'hello', result.first['content'] assert_equal 'world', result.second['content'] end test 'array nested inside nested hash' do result = jbuild do |json| json.author do json.name 'David' json.age 32 json.comments do json.child! { json.content 'hello' } json.child! { json.content 'world' } end end end assert_equal 'hello', result['author']['comments'].first['content'] assert_equal 'world', result['author']['comments'].second['content'] end test 'array nested inside array' do result = jbuild do |json| json.comments do json.child! do json.authors do json.child! do json.name 'david' end end end end end assert_equal 'david', result['comments'].first['authors'].first['name'] end test 'directly set an array nested in another array' do data = [ { :department => 'QA', :not_in_json => 'hello', :names => ['John', 'David'] } ] result = jbuild do |json| json.array! data do |object| json.department object[:department] json.names do json.array! object[:names] end end end assert_equal 'David', result[0]['names'].last assert !result[0].key?('not_in_json') end test 'nested jbuilder objects' do to_nest = Jbuilder.new{ |json| json.nested_value 'Nested Test' } result = jbuild do |json| json.value 'Test' json.nested to_nest end expected = {'value' => 'Test', 'nested' => {'nested_value' => 'Nested Test'}} assert_equal expected, result end test 'nested jbuilder object via set!' do to_nest = Jbuilder.new{ |json| json.nested_value 'Nested Test' } result = jbuild do |json| json.value 'Test' json.set! :nested, to_nest end expected = {'value' => 'Test', 'nested' => {'nested_value' => 'Nested Test'}} assert_equal expected, result end test 'top-level array' do comments = [ Comment.new('hello', 1), Comment.new('world', 2) ] result = jbuild do |json| json.array! comments do |comment| json.content comment.content end end assert_equal 'hello', result.first['content'] assert_equal 'world', result.second['content'] end test 'it allows using next in array block to skip value' do comments = [ Comment.new('hello', 1), Comment.new('skip', 2), Comment.new('world', 3) ] result = jbuild do |json| json.array! comments do |comment| next if comment.id == 2 json.content comment.content end end assert_equal 2, result.length assert_equal 'hello', result.first['content'] assert_equal 'world', result.second['content'] end test 'extract attributes directly from array' do comments = [ Comment.new('hello', 1), Comment.new('world', 2) ] result = jbuild do |json| json.array! comments, :content, :id end assert_equal 'hello', result.first['content'] assert_equal 1, result.first['id'] assert_equal 'world', result.second['content'] assert_equal 2, result.second['id'] end test 'empty top-level array' do comments = [] result = jbuild do |json| json.array! comments do |comment| json.content comment.content end end assert_equal [], result end test 'dynamically set a key/value' do result = jbuild do |json| json.set! :each, 'stuff' end assert_equal 'stuff', result['each'] end test 'dynamically set a key/nested child with block' do result = jbuild do |json| json.set! :author do json.name 'David' json.age 32 end end assert_equal 'David', result['author']['name'] assert_equal 32, result['author']['age'] end test 'dynamically sets a collection' do comments = [ Comment.new('hello', 1), Comment.new('world', 2) ] result = jbuild do |json| json.set! :comments, comments, :content end assert_equal ['content'], result['comments'].first.keys assert_equal 'hello', result['comments'].first['content'] assert_equal 'world', result['comments'].second['content'] end test 'query like object' do result = jbuild do |json| json.relations RelationMock.new, :name, :age end assert_equal 2, result['relations'].length assert_equal 'Bob', result['relations'][0]['name'] assert_equal 50, result['relations'][1]['age'] end test 'initialize via options hash' do jbuilder = Jbuilder.new(key_formatter: 1, ignore_nil: 2) assert_equal 1, jbuilder.instance_eval{ @key_formatter } assert_equal 2, jbuilder.instance_eval{ @ignore_nil } end test 'key_format! with parameter' do result = jbuild do |json| json.key_format! camelize: [:lower] json.camel_style 'for JS' end assert_equal ['camelStyle'], result.keys end test 'key_format! with parameter not as an array' do result = jbuild do |json| json.key_format! :camelize => :lower json.camel_style 'for JS' end assert_equal ['camelStyle'], result.keys end test 'key_format! propagates to child elements' do result = jbuild do |json| json.key_format! :upcase json.level1 'one' json.level2 do json.value 'two' end end assert_equal 'one', result['LEVEL1'] assert_equal 'two', result['LEVEL2']['VALUE'] end test 'key_format! resets after child element' do result = jbuild do |json| json.level2 do json.key_format! :upcase json.value 'two' end json.level1 'one' end assert_equal 'two', result['level2']['VALUE'] assert_equal 'one', result['level1'] end test 'key_format! with no parameter' do result = jbuild do |json| json.key_format! :upcase json.lower 'Value' end assert_equal ['LOWER'], result.keys end test 'key_format! with multiple steps' do result = jbuild do |json| json.key_format! :upcase, :pluralize json.pill 'foo' end assert_equal ['PILLs'], result.keys end test 'key_format! with lambda/proc' do result = jbuild do |json| json.key_format! ->(key){ key + ' and friends' } json.oats 'foo' end assert_equal ['oats and friends'], result.keys end test 'default key_format!' do Jbuilder.key_format camelize: :lower result = jbuild{ |json| json.camel_style 'for JS' } assert_equal ['camelStyle'], result.keys end test 'do not use default key formatter directly' do Jbuilder.key_format jbuild{ |json| json.key 'value' } formatter = Jbuilder.send(:class_variable_get, '@@key_formatter') cache = formatter.instance_variable_get('@cache') assert_empty cache end test 'ignore_nil! without a parameter' do result = jbuild do |json| json.ignore_nil! json.test nil end assert_empty result.keys end test 'ignore_nil! with parameter' do result = jbuild do |json| json.ignore_nil! true json.name 'Bob' json.dne nil end assert_equal ['name'], result.keys result = jbuild do |json| json.ignore_nil! false json.name 'Bob' json.dne nil end assert_equal ['name', 'dne'], result.keys end test 'default ignore_nil!' do Jbuilder.ignore_nil result = jbuild do |json| json.name 'Bob' json.dne nil end assert_equal ['name'], result.keys Jbuilder.send(:class_variable_set, '@@ignore_nil', false) end test 'nil!' do result = jbuild do |json| json.key 'value' json.nil! end assert_nil result end test 'null!' do result = jbuild do |json| json.key 'value' json.null! end assert_nil result end test 'null! in a block' do result = jbuild do |json| json.author do json.name 'David' end json.author do json.null! end end assert result.key?('author') assert_nil result['author'] end test 'empty attributes respond to empty?' do attributes = Jbuilder.new.attributes! assert attributes.empty? assert attributes.blank? assert !attributes.present? end test 'throws ArrayError when trying to add a key to an array' do assert_raise Jbuilder::ArrayError do jbuild do |json| json.array! %w[foo bar] json.fizz "buzz" end end end test 'throws NullError when trying to add properties to null' do assert_raise Jbuilder::NullError do jbuild do |json| json.null! json.foo 'bar' end end end test 'throws NullError when trying to add properties to null using block syntax' do assert_raise Jbuilder::NullError do jbuild do |json| json.author do json.null! end json.author do json.name "Pavel" end end end end end jbuilder-2.3.1/test/scaffold_controller_generator_test.rb 0000644 0000041 0000041 00000004260 12556325572 024020 0 ustar www-data www-data require 'test_helper' require 'rails/generators/test_case' require 'generators/rails/scaffold_controller_generator' class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase tests Rails::Generators::ScaffoldControllerGenerator arguments %w(Post title body:text) destination File.expand_path('../tmp', __FILE__) setup :prepare_destination test 'controller content' do run_generator assert_file 'app/controllers/posts_controller.rb' do |content| assert_instance_method :index, content do |m| assert_match /@posts = Post\.all/, m end assert_instance_method :show, content do |m| assert m.blank? end assert_instance_method :new, content do |m| assert_match /@post = Post\.new/, m end assert_instance_method :edit, content do |m| assert m.blank? end assert_instance_method :create, content do |m| assert_match /@post = Post\.new\(post_params\)/, m assert_match /@post\.save/, m assert_match /format\.html \{ redirect_to @post, notice: 'Post was successfully created\.' \}/, m assert_match /format\.json \{ render :show, status: :created, location: @post \}/, m assert_match /format\.html \{ render :new \}/, m assert_match /format\.json \{ render json: @post\.errors, status: :unprocessable_entity \}/, m end assert_instance_method :update, content do |m| assert_match /format\.html \{ redirect_to @post, notice: 'Post was successfully updated\.' \}/, m assert_match /format\.json \{ render :show, status: :ok, location: @post \}/, m assert_match /format\.html \{ render :edit \}/, m assert_match /format\.json \{ render json: @post.errors, status: :unprocessable_entity \}/, m end assert_instance_method :destroy, content do |m| assert_match /@post\.destroy/, m assert_match /format\.html \{ redirect_to posts_url, notice: 'Post was successfully destroyed\.' \}/, m assert_match /format\.json \{ head :no_content \}/, m end assert_match(/def post_params/, content) assert_match(/params\.require\(:post\)\.permit\(:title, :body\)/, content) end end end jbuilder-2.3.1/test/jbuilder_dependency_tracker_test.rb 0000644 0000041 0000041 00000004050 12556325572 023434 0 ustar www-data www-data require 'test_helper' require 'jbuilder/dependency_tracker' class FakeTemplate attr_reader :source, :handler def initialize(source, handler = :jbuilder) @source, @handler = source, handler end end class JbuilderDependencyTrackerTest < ActiveSupport::TestCase def make_tracker(name, source) template = FakeTemplate.new(source) Jbuilder::DependencyTracker.new(name, template) end def track_dependencies(source) make_tracker('jbuilder_template', source).dependencies end test 'detects dependency via direct partial! call' do dependencies = track_dependencies <<-RUBY json.partial! 'path/to/partial', foo: bar json.partial! 'path/to/another/partial', :fizz => buzz RUBY assert_equal %w[path/to/partial path/to/another/partial], dependencies end test 'detects dependency via direct partial! call with parens' do dependencies = track_dependencies <<-RUBY json.partial!("path/to/partial") RUBY assert_equal %w[path/to/partial], dependencies end test 'detects partial with options (1.9 style)' do dependencies = track_dependencies <<-RUBY json.partial! hello: 'world', partial: 'path/to/partial', foo: :bar RUBY assert_equal %w[path/to/partial], dependencies end test 'detects partial with options (1.8 style)' do dependencies = track_dependencies <<-RUBY json.partial! :hello => 'world', :partial => 'path/to/partial', :foo => :bar RUBY assert_equal %w[path/to/partial], dependencies end test 'detects partial in indirect collecton calls' do dependencies = track_dependencies <<-RUBY json.comments @post.comments, partial: 'comments/comment', as: :comment RUBY assert_equal %w[comments/comment], dependencies end test 'detects explicit depedency' do dependencies = track_dependencies <<-RUBY # Template Dependency: path/to/partial json.foo 'bar' RUBY assert_equal %w[path/to/partial], dependencies end end jbuilder-2.3.1/test/test_helper.rb 0000644 0000041 0000041 00000000414 12556325572 017202 0 ustar www-data www-data require "bundler/setup" require "active_support" require "rails/version" if Rails::VERSION::STRING > "4.0" require "active_support/testing/autorun" else require "test/unit" end if ActiveSupport.respond_to?(:test_order=) ActiveSupport.test_order = :random end jbuilder-2.3.1/test/jbuilder_generator_test.rb 0000644 0000041 0000041 00000001762 12556325572 021600 0 ustar www-data www-data require 'test_helper' require 'rails/generators/test_case' require 'generators/rails/jbuilder_generator' class JbuilderGeneratorTest < Rails::Generators::TestCase tests Rails::Generators::JbuilderGenerator arguments %w(Post title body:text password:digest) destination File.expand_path('../tmp', __FILE__) setup :prepare_destination test 'views are generated' do run_generator %w(index show).each do |view| assert_file "app/views/posts/#{view}.json.jbuilder" end end test 'index content' do run_generator assert_file 'app/views/posts/index.json.jbuilder' do |content| assert_match /json\.array!\(@posts\) do \|post\|/, content assert_match /json\.extract! post, :id, :title, :body/, content assert_match /json\.url post_url\(post, format: :json\)/, content end assert_file 'app/views/posts/show.json.jbuilder' do |content| assert_match /json\.extract! @post, :id, :title, :body, :created_at, :updated_at/, content end end end jbuilder-2.3.1/test/scaffold_api_controller_generator_test.rb 0000644 0000041 0000041 00000003033 12556325572 024646 0 ustar www-data www-data require 'test_helper' require 'rails/generators/test_case' require 'generators/rails/scaffold_controller_generator' if Rails::VERSION::MAJOR > 4 class ScaffoldApiControllerGeneratorTest < Rails::Generators::TestCase tests Rails::Generators::ScaffoldControllerGenerator arguments %w(Post title body:text --api) destination File.expand_path('../tmp', __FILE__) setup :prepare_destination test 'controller content' do run_generator assert_file 'app/controllers/posts_controller.rb' do |content| assert_instance_method :index, content do |m| assert_match /@posts = Post\.all/, m end assert_instance_method :show, content do |m| assert m.blank? end assert_instance_method :create, content do |m| assert_match /@post = Post\.new\(post_params\)/, m assert_match /@post\.save/, m assert_match /render :show, status: :created, location: @post/, m assert_match /render json: @post\.errors, status: :unprocessable_entity/, m end assert_instance_method :update, content do |m| assert_match /render :show, status: :ok, location: @post/, m assert_match /render json: @post.errors, status: :unprocessable_entity/, m end assert_instance_method :destroy, content do |m| assert_match /@post\.destroy/, m end assert_match(/def post_params/, content) assert_match(/params\.require\(:post\)\.permit\(:title, :body\)/, content) end end end end jbuilder-2.3.1/.gitignore 0000644 0000041 0000041 00000000063 12556325572 015350 0 ustar www-data www-data tmp gemfiles/*.lock Gemfile.lock .ruby-version pkg jbuilder-2.3.1/jbuilder.gemspec 0000644 0000041 0000041 00000001113 12556325572 016522 0 ustar www-data www-data Gem::Specification.new do |s| s.name = 'jbuilder' s.version = '2.3.1' s.authors = ['David Heinemeier Hansson', 'Pavel Pravosud'] s.email = ['david@37signals.com', 'pavel@pravosud.com'] s.summary = 'Create JSON structures via a Builder-style DSL' s.homepage = 'https://github.com/rails/jbuilder' s.license = 'MIT' s.required_ruby_version = '>= 1.9.3' s.add_dependency 'activesupport', '>= 3.0.0', '< 5' s.add_dependency 'multi_json', '~> 1.2' s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- test/*`.split("\n") end jbuilder-2.3.1/Appraisals 0000644 0000041 0000041 00000001611 12556325572 015402 0 ustar www-data www-data appraise "rails-3-0" do gem "test-unit" gem "railties", "~> 3.0.0" gem "actionpack", "~> 3.0.0" gem "activemodel", "~> 3.0.0" end appraise "rails-3-1" do gem "test-unit" gem "railties", "~> 3.1.0" gem "actionpack", "~> 3.1.0" gem "activemodel", "~> 3.1.0" end appraise "rails-3-2" do gem "test-unit" gem "railties", "~> 3.2.0" gem "actionpack", "~> 3.2.0" gem "activemodel", "~> 3.2.0" end appraise "rails-4-0" do gem "railties", "~> 4.0.0" gem "actionpack", "~> 4.0.0" gem "activemodel", "~> 4.0.0" end appraise "rails-4-1" do gem "railties", "~> 4.1.0" gem "actionpack", "~> 4.1.0" gem "activemodel", "~> 4.1.0" end appraise "rails-4-2" do gem "railties", "~> 4.2.0" gem "actionpack", "~> 4.2.0" gem "activemodel", "~> 4.2.0" end appraise "rails-edge" do gem "rails", github: "rails/rails" gem "arel", github: "rails/arel" end jbuilder-2.3.1/CHANGELOG.md 0000644 0000041 0000041 00000021632 12556325572 015176 0 ustar www-data www-data # Changelog 2.3.1 ----- * [Explicitly require ostruct to prevent NameError](https://github.com/rails/jbuilder/pull/281) 2.3.0 ----- * [Add new in-place partial invocation support](https://github.com/rails/jbuilder/commit/1feda7ee605c136e59fb4de970f4674de518e6de) * [Add implicit partial rendering for AM::Models](https://github.com/rails/jbuilder/commit/4d5bf7d0ea92765adb7be36834e84f9855a061df) * [Generate API controller if Rails API option is enabled](https://github.com/rails/jbuilder/commit/db68f6bd327cf42b47ef22d455fb5721a8c2cf5f) * [JBuilder's templates have less priority than app templates](https://github.com/rails/jbuilder/commit/7c1a5f25603ec1f4e51fba3dbba9db23726a5d69) * [Add AC::Helpers module to jbuilder for api only apps](https://github.com/rails/jbuilder/commit/7cf1d1eb7d125caf38309b5427952030011c1aa0) 2.2.16 ------ * [Fix NoMethodError around `api_only` in railtie](https://github.com/rails/jbuilder/commit/b08d1da10b14720b46d383b2917e336060fd9ffa) 2.2.14 ------ * [Make Jbuilder compatible with Rails API](https://github.com/rails/jbuilder/commit/29c0014a9c954c990075d42c45c66075260e924b) 2.2.13 ------ * Several peformance optimizations: [#260](https://github.com/rails/jbuilder/pull/260) & [#261](https://github.com/rails/jbuilder/pull/261) 2.2.12 ------ * [Replace explici block calls with yield for performance](https://github.com/rails/jbuilder/commit/3184f941276ad03a071cf977133d1a32302afa47) 2.2.11 ------ * Generate the templates for Rails 5+ [#258](https://github.com/rails/jbuilder/pull/258) [@amatsuda](https://github.com/amatsuda) 2.2.10 ------ * Add Jbuilder::Blank#empty? to tell if attributes are empty [#257](https://github.com/rails/jbuilder/pull/257) [@a2ikm](https://github.com/a2ikm) 2.2.9 ----- * Support `partial!` call with `locals` option in `JbuilderTemplate` [#251](https://github.com/rails/jbuilder/pull/251) 2.2.8 ----- * [Raise ArrayError when trying to add key to an array](https://github.com/rails/jbuilder/commit/869e4be1ad165ce986d8fca78311bdd3ed166087) 2.2.7 ----- * [Make Blank object serializable with Marshal](https://github.com/rails/jbuilder/commit/7083f28d8b665aa60d0d1b1927ae88bb5c6290ba) 2.2.6 ----- * [Make sure dependency tracker loads after template handler](https://github.com/rails/jbuilder/commit/3ba404b1207b557e14771c90b8832bc01ae67a42) 2.2.5 ----- * [Refactor merge block behavior to raise error for unexpected values](https://github.com/rails/jbuilder/commit/4503162fb26f53f613fc83ac081fd244748b6fe9) 2.2.4 ----- * [Typecast locals hash key during collection render](https://github.com/rails/jbuilder/commit/a6b0c8651a08e01cb53eee38e211c65423f275f7) 2.2.3 ----- * [Move template handler registration into railtie](https://github.com/rails/jbuilder/commit/c8acc5cea6da2a79b7b345adc301cb5ff2517647) * [Do not capture the block where it is possible](https://github.com/rails/jbuilder/commit/973b382c3924cb59fc0e4e25266b18e74d41d646) 2.2.2 ----- * [Fix `Jbuilder#merge!` inside block](https://github.com/rails/jbuilder/commit/a7b328552eb0d36315f75bff813bea7eecf8c1d7) 2.2.1 ----- * [Fix empty block handling](https://github.com/rails/jbuilder/commit/972a11141403269e9b17b45b0c95f8a9788245ee) 2.2.0 ----- * [Allow to skip `array!` iterations by calling `next`](https://github.com/rails/jbuilder/commit/81a63308fb9d5002519dd871f829ccc58067251a) 2.1.2 ----- * [Cast array-like objects to array before merging](https://github.com/rails/jbuilder/commit/7b8c8a1cb09b7f3dd26e5643ebbd6b2ec67185db) 2.1.1 ----- * [Remove unused file](https://github.com/rails/jbuilder/commit/e49e1047976fac93b8242ab212c7b1a463b70809) 2.1.0 ----- * [Blocks and their extract! shortcuts are additive by default](https://github.com/rails/jbuilder/commit/a49390736c5f6e2d7a31111df6531bc28dba9fb1) 2.0.8 ----- * [Eliminate circular dependencies](https://github.com/rails/jbuilder/commit/0879484dc74e7be93b695f66e3708ba48cdb1be3) * [Support cache key generation for complex objects](https://github.com/rails/jbuilder/commit/ca9622cca30c1112dd4408fcb2e658849abe1dd5) * [Remove JbuilderProxy class](https://github.com/rails/jbuilder/commit/5877482fc7da3224e42d4f72a1386f7a3a08173b) * [Move KeyFormatter into a separate file](https://github.com/rails/jbuilder/commit/13fee8464ff53ce853030114283c03c135c052b6) * [Move NullError into a separate file](https://github.com/rails/jbuilder/commit/13fee8464ff53ce853030114283c03c135c052b6) 2.0.7 ----- * [Add destroy notice to scaffold generator](https://github.com/rails/jbuilder/commit/8448e86f8cdfa0f517bd59576947875775a1d43c) 2.0.6 ----- * [Use render short form in controller generator](https://github.com/rails/jbuilder/commit/acf37320a7cea7fcc70c791bc94bd5f46b8349ff) 2.0.5 ----- * [Fix edgecase when json is defined as a method](https://github.com/rails/jbuilder/commit/ca711a0c0a5760e26258ce2d93c14bef8fff0ead) 2.0.4 ----- * [Add cache_if! to conditionally cache JSON fragments](https://github.com/rails/jbuilder/commit/14a5afd8a2c939a6fd710d355a194c114db96eb2) 2.0.3 ----- * [Pass options when calling cache_fragment_name](https://github.com/rails/jbuilder/commit/07c2cc7486fe9ef423d7bc821b83f6d485f330e0) 2.0.2 ----- * [Fix Dependency Tracking fail to detect single-quoted partial correctly](https://github.com/rails/jbuilder/commit/448679a6d3098eb34d137f782a05f1767711991a) * [Prevent Dependency Tracker constants leaking into global namespace](https://github.com/rails/jbuilder/commit/3544b288b63f504f46fa8aafd1d17ee198d77536) 2.0.1 ----- * [Dependency tracking support for Rails 3 with cache_digest gem](https://github.com/rails/jbuilder/commit/6b471d7a38118e8f7645abec21955ef793401daf) 2.0.0 ----- * [Respond to PUT/PATCH API request with :ok](https://github.com/rails/jbuilder/commit/9dbce9c12181e89f8f472ac23c764ffe8438040a) * [Remove Ruby 1.8 support](https://github.com/rails/jbuilder/commit/d53fff42d91f33d662eafc2561c4236687ecf6c9) * [Remove deprecated two argument block call](https://github.com/rails/jbuilder/commit/07a35ee7e79ae4b06dba9dbff5c4e07c1e627218) * [Make Jbuilder object initialize with single hash](https://github.com/rails/jbuilder/commit/38bf551db0189327aaa90b9be010c0d1b792c007) * [Track template dependencies](https://github.com/rails/jbuilder/commit/8e73cea39f60da1384afd687cc8e5e399630d8cc) * [Expose merge! method](https://github.com/rails/jbuilder/commit/0e2eb47f6f3c01add06a1a59b37cdda8baf24f29) 1.5.3 ----- * [Generators add `:id` column by default](https://github.com/rails/jbuilder/commit/0b52b86773e48ac2ce35d4155c7b70ad8b3e8937) 1.5.2 ----- * [Nil-collection should be treated as empty array](https://github.com/rails/jbuilder/commit/2f700bb00ab663c6b7fcb28d2967aeb989bd43c7) 1.5.1 ----- * [Expose template lookup options](https://github.com/rails/jbuilder/commit/404c18dee1af96ac6d8052a04062629ef1db2945) 1.5.0 ----- * [Do not perform any caching when `controller.perform_caching` is false](https://github.com/rails/jbuilder/commit/94633facde1ac43580f8cd5e13ae9cc83e1da8f4) * [Add partial collection rendering](https://github.com/rails/jbuilder/commit/e8c10fc885e41b18178aaf4dcbc176961c928d76) * [Deprecate extract! calling private methods](https://github.com/rails/jbuilder/commit/b9e19536c2105d7f2e813006bbcb8ca5730d28a3) * [Add array of partials rendering](https://github.com/rails/jbuilder/commit/7d7311071720548047f98f14ad013c560b8d9c3a) 1.4.2 ----- * [Require MIME dependency explicitly](https://github.com/rails/jbuilder/commit/b1ed5ac4f08b056f8839b4b19b43562e81e02a59) 1.4.1 ----- * [Removed deprecated positioned arguments initializer support](https://github.com/rails/jbuilder/commit/6e03e0452073eeda77e6dfe66aa31e5ec67a3531) * [Deprecate two-arguments block calling](https://github.com/rails/jbuilder/commit/2b10bb058bb12bc782cbcc16f6ec67b489e5ed43) 1.4.0 ----- * [Add quick collection attribute extraction](https://github.com/rails/jbuilder/commit/c2b966cf653ea4264fbb008b8cc6ce5359ebe40a) * [Block has priority over attributes extraction](https://github.com/rails/jbuilder/commit/77c24766362c02769d81dac000b1879a9e4d4a00) * [Meaningfull error messages when adding properties to null](https://github.com/rails/jbuilder/commit/e26764602e34b3772e57e730763d512e59489e3b) * [Do not enforce template format, enforce handlers instead](https://github.com/rails/jbuilder/commit/72576755224b15da45e50cbea877679800ab1398) 1.3.0 ----- * [Add nil! method for nil JSON](https://github.com/rails/jbuilder/commit/822a906f68664f61a1209336bb681077692c8475) 1.2.1 ----- * [Added explicit dependency for MultiJson](https://github.com/rails/jbuilder/commit/4d58eacb6cd613679fb243484ff73a79bbbff2d2 1.2.0 ----- * Multiple documentation improvements and internal refactoring * [Fixes fragment caching to work with latest digests](https://github.com/rails/jbuilder/commit/da937d6b8732124074c612abb7ff38868d1d96c0) 1.0.2 ----- * [Support non-Enumerable collections](https://github.com/rails/jbuilder/commit/4c20c59bf8131a1e419bb4ebf84f2b6bdcb6b0cf) * [Ensure that the default URL is in json format](https://github.com/rails/jbuilder/commit/0b46782fb7b8c34a3c96afa801fe27a5a97118a4) 1.0.0 ----- * Adopt Semantic Versioning * Add rails generators jbuilder-2.3.1/README.md 0000644 0000041 0000041 00000015155 12556325572 014647 0 ustar www-data www-data # Jbuilder [][travis] [][gem] [][codeclimate] [][gemnasium] [travis]: https://travis-ci.org/rails/jbuilder [gem]: https://rubygems.org/gems/jbuilder [codeclimate]: https://codeclimate.com/github/rails/jbuilder [gemnasium]: https://gemnasium.com/rails/jbuilder Jbuilder gives you a simple DSL for declaring JSON structures that beats massaging giant hash structures. This is particularly helpful when the generation process is fraught with conditionals and loops. Here's a simple example: ``` ruby # app/views/message/show.json.jbuilder json.content format_content(@message.content) json.(@message, :created_at, :updated_at) json.author do json.name @message.creator.name.familiar json.email_address @message.creator.email_address_with_name json.url url_for(@message.creator, format: :json) end if current_user.admin? json.visitors calculate_visitors(@message) end json.comments @message.comments, :content, :created_at json.attachments @message.attachments do |attachment| json.filename attachment.filename json.url url_for(attachment) end ``` This will build the following structure: ``` javascript { "content": "
This is serious monkey business
", "created_at": "2011-10-29T20:45:28-05:00", "updated_at": "2011-10-29T20:45:28-05:00", "author": { "name": "David H.", "email_address": "'David Heinemeier Hansson'