jbuilder 1.5.3 → 2.11.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/workflows/ruby.yml +108 -0
- data/.gitignore +4 -1
- data/Appraisals +25 -0
- data/CONTRIBUTING.md +106 -0
- data/Gemfile +4 -5
- data/MIT-LICENSE +2 -2
- data/README.md +182 -40
- data/Rakefile +15 -10
- data/gemfiles/rails_5_0.gemfile +10 -0
- data/gemfiles/rails_5_1.gemfile +10 -0
- data/gemfiles/rails_5_2.gemfile +10 -0
- data/gemfiles/rails_6_0.gemfile +10 -0
- data/gemfiles/rails_6_1.gemfile +10 -0
- data/gemfiles/rails_head.gemfile +10 -0
- data/jbuilder.gemspec +25 -8
- data/lib/generators/rails/jbuilder_generator.rb +13 -2
- data/lib/generators/rails/scaffold_controller_generator.rb +9 -3
- data/lib/generators/rails/templates/api_controller.rb +63 -0
- data/lib/generators/rails/templates/controller.rb +18 -22
- data/lib/generators/rails/templates/index.json.jbuilder +1 -4
- data/lib/generators/rails/templates/partial.json.jbuilder +16 -0
- data/lib/generators/rails/templates/show.json.jbuilder +1 -1
- data/lib/jbuilder/blank.rb +11 -0
- data/lib/jbuilder/collection_renderer.rb +109 -0
- data/lib/jbuilder/dependency_tracker.rb +61 -0
- data/lib/jbuilder/errors.rb +24 -0
- data/lib/jbuilder/jbuilder.rb +7 -0
- data/lib/jbuilder/jbuilder_template.rb +228 -67
- data/lib/jbuilder/key_formatter.rb +34 -0
- data/lib/jbuilder/railtie.rb +31 -6
- data/lib/jbuilder.rb +144 -137
- data/test/jbuilder_dependency_tracker_test.rb +72 -0
- data/test/jbuilder_generator_test.rb +31 -4
- data/test/jbuilder_template_test.rb +319 -163
- data/test/jbuilder_test.rb +613 -298
- data/test/scaffold_api_controller_generator_test.rb +70 -0
- data/test/scaffold_controller_generator_test.rb +62 -19
- data/test/test_helper.rb +36 -0
- metadata +47 -22
- data/.travis.yml +0 -38
- data/Gemfile.old +0 -7
    
        data/jbuilder.gemspec
    CHANGED
    
    | @@ -1,14 +1,31 @@ | |
| 1 1 | 
             
            Gem::Specification.new do |s|
         | 
| 2 | 
            -
              s.name | 
| 3 | 
            -
              s.version | 
| 4 | 
            -
              s. | 
| 5 | 
            -
              s.email | 
| 6 | 
            -
              s.summary | 
| 7 | 
            -
              s. | 
| 2 | 
            +
              s.name     = 'jbuilder'
         | 
| 3 | 
            +
              s.version  = '2.11.5'
         | 
| 4 | 
            +
              s.authors  = 'David Heinemeier Hansson'
         | 
| 5 | 
            +
              s.email    = 'david@basecamp.com'
         | 
| 6 | 
            +
              s.summary  = 'Create JSON structures via a Builder-style DSL'
         | 
| 7 | 
            +
              s.homepage = 'https://github.com/rails/jbuilder'
         | 
| 8 | 
            +
              s.license  = 'MIT'
         | 
| 8 9 |  | 
| 9 | 
            -
              s. | 
| 10 | 
            -
             | 
| 10 | 
            +
              s.required_ruby_version = '>= 2.2.2'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              s.add_dependency 'activesupport', '>= 5.0.0'
         | 
| 13 | 
            +
              s.add_dependency 'actionview', '>= 5.0.0'
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              if RUBY_ENGINE == 'rbx'
         | 
| 16 | 
            +
                s.add_development_dependency('racc')
         | 
| 17 | 
            +
                s.add_development_dependency('json')
         | 
| 18 | 
            +
                s.add_development_dependency('rubysl')
         | 
| 19 | 
            +
              end
         | 
| 11 20 |  | 
| 12 21 | 
             
              s.files         = `git ls-files`.split("\n")
         | 
| 13 22 | 
             
              s.test_files    = `git ls-files -- test/*`.split("\n")
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              s.metadata = {
         | 
| 25 | 
            +
                "bug_tracker_uri"       => "https://github.com/rails/jbuilder/issues",
         | 
| 26 | 
            +
                "changelog_uri"         => "https://github.com/rails/jbuilder/releases/tag/v#{s.version}",
         | 
| 27 | 
            +
                "mailing_list_uri"      => "https://discuss.rubyonrails.org/c/rubyonrails-talk",
         | 
| 28 | 
            +
                "source_code_uri"       => "https://github.com/rails/jbuilder/tree/v#{s.version}",
         | 
| 29 | 
            +
                "rubygems_mfa_required" => "true",
         | 
| 30 | 
            +
              }
         | 
| 14 31 | 
             
            end
         | 
| @@ -10,6 +10,8 @@ module Rails | |
| 10 10 |  | 
| 11 11 | 
             
                  argument :attributes, type: :array, default: [], banner: 'field:type field:type'
         | 
| 12 12 |  | 
| 13 | 
            +
                  class_option :timestamps, type: :boolean, default: true
         | 
| 14 | 
            +
             | 
| 13 15 | 
             
                  def create_root_folder
         | 
| 14 16 | 
             
                    path = File.join('app/views', controller_file_path)
         | 
| 15 17 | 
             
                    empty_directory path unless File.directory?(path)
         | 
| @@ -20,6 +22,7 @@ module Rails | |
| 20 22 | 
             
                      filename = filename_with_extensions(view)
         | 
| 21 23 | 
             
                      template filename, File.join('app/views', controller_file_path, filename)
         | 
| 22 24 | 
             
                    end
         | 
| 25 | 
            +
                    template filename_with_extensions('partial'), File.join('app/views', controller_file_path, filename_with_extensions("_#{singular_table_name}"))
         | 
| 23 26 | 
             
                  end
         | 
| 24 27 |  | 
| 25 28 |  | 
| @@ -32,8 +35,12 @@ module Rails | |
| 32 35 | 
             
                      [name, :json, :jbuilder] * '.'
         | 
| 33 36 | 
             
                    end
         | 
| 34 37 |  | 
| 35 | 
            -
                    def  | 
| 36 | 
            -
                       | 
| 38 | 
            +
                    def full_attributes_list
         | 
| 39 | 
            +
                      if options[:timestamps]
         | 
| 40 | 
            +
                        attributes_list(attributes_names + %w(created_at updated_at))
         | 
| 41 | 
            +
                      else
         | 
| 42 | 
            +
                        attributes_list(attributes_names)
         | 
| 43 | 
            +
                      end
         | 
| 37 44 | 
             
                    end
         | 
| 38 45 |  | 
| 39 46 | 
             
                    def attributes_list(attributes = attributes_names)
         | 
| @@ -43,6 +50,10 @@ module Rails | |
| 43 50 |  | 
| 44 51 | 
             
                      attributes.map { |a| ":#{a}"} * ', '
         | 
| 45 52 | 
             
                    end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                    def virtual_attributes
         | 
| 55 | 
            +
                      attributes.select {|name| name.respond_to?(:virtual?) && name.virtual? }
         | 
| 56 | 
            +
                    end
         | 
| 46 57 | 
             
                end
         | 
| 47 58 | 
             
              end
         | 
| 48 59 | 
             
            end
         | 
| @@ -4,9 +4,15 @@ require 'rails/generators/rails/scaffold_controller/scaffold_controller_generato | |
| 4 4 | 
             
            module Rails
         | 
| 5 5 | 
             
              module Generators
         | 
| 6 6 | 
             
                class ScaffoldControllerGenerator
         | 
| 7 | 
            -
                   | 
| 7 | 
            +
                  source_paths << File.expand_path('../templates', __FILE__)
         | 
| 8 8 |  | 
| 9 | 
            -
                  hook_for :jbuilder, default: true
         | 
| 9 | 
            +
                  hook_for :jbuilder, type: :boolean, default: true
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  private
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    def permitted_params
         | 
| 14 | 
            +
                      attributes_names.map { |name| ":#{name}" }.join(', ')
         | 
| 15 | 
            +
                    end unless private_method_defined? :permitted_params
         | 
| 10 16 | 
             
                end
         | 
| 11 17 | 
             
              end
         | 
| 12 | 
            -
            end
         | 
| 18 | 
            +
            end
         | 
| @@ -0,0 +1,63 @@ | |
| 1 | 
            +
            <% if namespaced? -%>
         | 
| 2 | 
            +
            require_dependency "<%= namespaced_path %>/application_controller"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            <% end -%>
         | 
| 5 | 
            +
            <% module_namespacing do -%>
         | 
| 6 | 
            +
            class <%= controller_class_name %>Controller < ApplicationController
         | 
| 7 | 
            +
              before_action :set_<%= singular_table_name %>, only: %i[ show update destroy ]
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              # GET <%= route_url %>
         | 
| 10 | 
            +
              # GET <%= route_url %>.json
         | 
| 11 | 
            +
              def index
         | 
| 12 | 
            +
                @<%= plural_table_name %> = <%= orm_class.all(class_name) %>
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              # GET <%= route_url %>/1
         | 
| 16 | 
            +
              # GET <%= route_url %>/1.json
         | 
| 17 | 
            +
              def show
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              # POST <%= route_url %>
         | 
| 21 | 
            +
              # POST <%= route_url %>.json
         | 
| 22 | 
            +
              def create
         | 
| 23 | 
            +
                @<%= singular_table_name %> = <%= orm_class.build(class_name, "#{singular_table_name}_params") %>
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                if @<%= orm_instance.save %>
         | 
| 26 | 
            +
                  render :show, status: :created, location: <%= "@#{singular_table_name}" %>
         | 
| 27 | 
            +
                else
         | 
| 28 | 
            +
                  render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              # PATCH/PUT <%= route_url %>/1
         | 
| 33 | 
            +
              # PATCH/PUT <%= route_url %>/1.json
         | 
| 34 | 
            +
              def update
         | 
| 35 | 
            +
                if @<%= orm_instance.update("#{singular_table_name}_params") %>
         | 
| 36 | 
            +
                  render :show, status: :ok, location: <%= "@#{singular_table_name}" %>
         | 
| 37 | 
            +
                else
         | 
| 38 | 
            +
                  render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              # DELETE <%= route_url %>/1
         | 
| 43 | 
            +
              # DELETE <%= route_url %>/1.json
         | 
| 44 | 
            +
              def destroy
         | 
| 45 | 
            +
                @<%= orm_instance.destroy %>
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              private
         | 
| 49 | 
            +
                # Use callbacks to share common setup or constraints between actions.
         | 
| 50 | 
            +
                def set_<%= singular_table_name %>
         | 
| 51 | 
            +
                  @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                # Only allow a list of trusted parameters through.
         | 
| 55 | 
            +
                def <%= "#{singular_table_name}_params" %>
         | 
| 56 | 
            +
                  <%- if attributes_names.empty? -%>
         | 
| 57 | 
            +
                  params.fetch(<%= ":#{singular_table_name}" %>, {})
         | 
| 58 | 
            +
                  <%- else -%>
         | 
| 59 | 
            +
                  params.require(<%= ":#{singular_table_name}" %>).permit(<%= permitted_params %>)
         | 
| 60 | 
            +
                  <%- end -%>
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
            end
         | 
| 63 | 
            +
            <% end -%>
         | 
| @@ -1,19 +1,17 @@ | |
| 1 1 | 
             
            <% if namespaced? -%>
         | 
| 2 | 
            -
            require_dependency "<%=  | 
| 2 | 
            +
            require_dependency "<%= namespaced_path %>/application_controller"
         | 
| 3 3 |  | 
| 4 4 | 
             
            <% end -%>
         | 
| 5 5 | 
             
            <% module_namespacing do -%>
         | 
| 6 6 | 
             
            class <%= controller_class_name %>Controller < ApplicationController
         | 
| 7 | 
            -
              before_action :set_<%= singular_table_name %>, only: [ | 
| 7 | 
            +
              before_action :set_<%= singular_table_name %>, only: %i[ show edit update destroy ]
         | 
| 8 8 |  | 
| 9 | 
            -
              # GET <%= route_url %>
         | 
| 10 | 
            -
              # GET <%= route_url %>.json
         | 
| 9 | 
            +
              # GET <%= route_url %> or <%= route_url %>.json
         | 
| 11 10 | 
             
              def index
         | 
| 12 11 | 
             
                @<%= plural_table_name %> = <%= orm_class.all(class_name) %>
         | 
| 13 12 | 
             
              end
         | 
| 14 13 |  | 
| 15 | 
            -
              # GET <%= route_url %>/1
         | 
| 16 | 
            -
              # GET <%= route_url %>/1.json
         | 
| 14 | 
            +
              # GET <%= route_url %>/1 or <%= route_url %>/1.json
         | 
| 17 15 | 
             
              def show
         | 
| 18 16 | 
             
              end
         | 
| 19 17 |  | 
| @@ -26,42 +24,40 @@ class <%= controller_class_name %>Controller < ApplicationController | |
| 26 24 | 
             
              def edit
         | 
| 27 25 | 
             
              end
         | 
| 28 26 |  | 
| 29 | 
            -
              # POST <%= route_url %>
         | 
| 30 | 
            -
              # POST <%= route_url %>.json
         | 
| 27 | 
            +
              # POST <%= route_url %> or <%= route_url %>.json
         | 
| 31 28 | 
             
              def create
         | 
| 32 29 | 
             
                @<%= singular_table_name %> = <%= orm_class.build(class_name, "#{singular_table_name}_params") %>
         | 
| 33 30 |  | 
| 34 31 | 
             
                respond_to do |format|
         | 
| 35 32 | 
             
                  if @<%= orm_instance.save %>
         | 
| 36 | 
            -
                    format.html { redirect_to  | 
| 37 | 
            -
                    format.json { render  | 
| 33 | 
            +
                    format.html { redirect_to <%= show_helper %>, notice: <%= %("#{human_name} was successfully created.") %> }
         | 
| 34 | 
            +
                    format.json { render :show, status: :created, location: <%= "@#{singular_table_name}" %> }
         | 
| 38 35 | 
             
                  else
         | 
| 39 | 
            -
                    format.html { render  | 
| 36 | 
            +
                    format.html { render :new, status: :unprocessable_entity }
         | 
| 40 37 | 
             
                    format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity }
         | 
| 41 38 | 
             
                  end
         | 
| 42 39 | 
             
                end
         | 
| 43 40 | 
             
              end
         | 
| 44 41 |  | 
| 45 | 
            -
              # PATCH/PUT <%= route_url %>/1
         | 
| 46 | 
            -
              # PATCH/PUT <%= route_url %>/1.json
         | 
| 42 | 
            +
              # PATCH/PUT <%= route_url %>/1 or <%= route_url %>/1.json
         | 
| 47 43 | 
             
              def update
         | 
| 48 44 | 
             
                respond_to do |format|
         | 
| 49 45 | 
             
                  if @<%= orm_instance.update("#{singular_table_name}_params") %>
         | 
| 50 | 
            -
                    format.html { redirect_to  | 
| 51 | 
            -
                    format.json {  | 
| 46 | 
            +
                    format.html { redirect_to <%= show_helper %>, notice: <%= %("#{human_name} was successfully updated.") %> }
         | 
| 47 | 
            +
                    format.json { render :show, status: :ok, location: <%= "@#{singular_table_name}" %> }
         | 
| 52 48 | 
             
                  else
         | 
| 53 | 
            -
                    format.html { render  | 
| 49 | 
            +
                    format.html { render :edit, status: :unprocessable_entity }
         | 
| 54 50 | 
             
                    format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity }
         | 
| 55 51 | 
             
                  end
         | 
| 56 52 | 
             
                end
         | 
| 57 53 | 
             
              end
         | 
| 58 54 |  | 
| 59 | 
            -
              # DELETE <%= route_url %>/1
         | 
| 60 | 
            -
              # DELETE <%= route_url %>/1.json
         | 
| 55 | 
            +
              # DELETE <%= route_url %>/1 or <%= route_url %>/1.json
         | 
| 61 56 | 
             
              def destroy
         | 
| 62 57 | 
             
                @<%= orm_instance.destroy %>
         | 
| 58 | 
            +
             | 
| 63 59 | 
             
                respond_to do |format|
         | 
| 64 | 
            -
                  format.html { redirect_to <%= index_helper %>_url }
         | 
| 60 | 
            +
                  format.html { redirect_to <%= index_helper %>_url, notice: <%= %("#{human_name} was successfully destroyed.") %> }
         | 
| 65 61 | 
             
                  format.json { head :no_content }
         | 
| 66 62 | 
             
                end
         | 
| 67 63 | 
             
              end
         | 
| @@ -72,12 +68,12 @@ class <%= controller_class_name %>Controller < ApplicationController | |
| 72 68 | 
             
                  @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
         | 
| 73 69 | 
             
                end
         | 
| 74 70 |  | 
| 75 | 
            -
                #  | 
| 71 | 
            +
                # Only allow a list of trusted parameters through.
         | 
| 76 72 | 
             
                def <%= "#{singular_table_name}_params" %>
         | 
| 77 73 | 
             
                  <%- if attributes_names.empty? -%>
         | 
| 78 | 
            -
                  params | 
| 74 | 
            +
                  params.fetch(<%= ":#{singular_table_name}" %>, {})
         | 
| 79 75 | 
             
                  <%- else -%>
         | 
| 80 | 
            -
                  params.require(<%= ":#{singular_table_name}" %>).permit(<%=  | 
| 76 | 
            +
                  params.require(<%= ":#{singular_table_name}" %>).permit(<%= permitted_params %>)
         | 
| 81 77 | 
             
                  <%- end -%>
         | 
| 82 78 | 
             
                end
         | 
| 83 79 | 
             
            end
         | 
| @@ -1,4 +1 @@ | |
| 1 | 
            -
            json.array! | 
| 2 | 
            -
              json.extract! <%= singular_table_name %>, <%= attributes_list %>
         | 
| 3 | 
            -
              json.url <%= singular_table_name %>_url(<%= singular_table_name %>, format: :json)
         | 
| 4 | 
            -
            end
         | 
| 1 | 
            +
            json.array! @<%= plural_table_name %>, partial: "<%= plural_table_name %>/<%= singular_table_name %>", as: :<%= singular_table_name %>
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            json.extract! <%= singular_table_name %>, <%= full_attributes_list %>
         | 
| 2 | 
            +
            json.url <%= singular_table_name %>_url(<%= singular_table_name %>, format: :json)
         | 
| 3 | 
            +
            <%- virtual_attributes.each do |attribute| -%>
         | 
| 4 | 
            +
            <%- if attribute.type == :rich_text -%>
         | 
| 5 | 
            +
            json.<%= attribute.name %> <%= singular_table_name %>.<%= attribute.name %>.to_s
         | 
| 6 | 
            +
            <%- elsif attribute.type == :attachment -%>
         | 
| 7 | 
            +
            json.<%= attribute.name %> url_for(<%= singular_table_name %>.<%= attribute.name %>)
         | 
| 8 | 
            +
            <%- elsif attribute.type == :attachments -%>
         | 
| 9 | 
            +
            json.<%= attribute.name %> do
         | 
| 10 | 
            +
              json.array!(<%= singular_table_name %>.<%= attribute.name %>) do |<%= attribute.singular_name %>|
         | 
| 11 | 
            +
                json.id <%= attribute.singular_name %>.id
         | 
| 12 | 
            +
                json.url url_for(<%= attribute.singular_name %>)
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| 15 | 
            +
            <%- end -%>
         | 
| 16 | 
            +
            <%- end -%>
         | 
| @@ -1 +1 @@ | |
| 1 | 
            -
            json. | 
| 1 | 
            +
            json.partial! "<%= plural_table_name %>/<%= singular_table_name %>", <%= singular_table_name %>: @<%= singular_table_name %>
         | 
| @@ -0,0 +1,109 @@ | |
| 1 | 
            +
            require 'delegate'
         | 
| 2 | 
            +
            require 'active_support/concern'
         | 
| 3 | 
            +
            require 'action_view'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            begin
         | 
| 6 | 
            +
              require 'action_view/renderer/collection_renderer'
         | 
| 7 | 
            +
            rescue LoadError
         | 
| 8 | 
            +
              require 'action_view/renderer/partial_renderer'
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            class Jbuilder
         | 
| 12 | 
            +
              module CollectionRenderable # :nodoc:
         | 
| 13 | 
            +
                extend ActiveSupport::Concern
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                class_methods do
         | 
| 16 | 
            +
                  def supported?
         | 
| 17 | 
            +
                    superclass.private_method_defined?(:build_rendered_template) && self.superclass.private_method_defined?(:build_rendered_collection)
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                private
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def build_rendered_template(content, template, layout = nil)
         | 
| 24 | 
            +
                  super(content || json.attributes!, template)
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def build_rendered_collection(templates, _spacer)
         | 
| 28 | 
            +
                  json.merge!(templates.map(&:body))
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def json
         | 
| 32 | 
            +
                  @options[:locals].fetch(:json)
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                class ScopedIterator < ::SimpleDelegator # :nodoc:
         | 
| 36 | 
            +
                  include Enumerable
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  def initialize(obj, scope)
         | 
| 39 | 
            +
                    super(obj)
         | 
| 40 | 
            +
                    @scope = scope
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  # Rails 6.0 support:
         | 
| 44 | 
            +
                  def each
         | 
| 45 | 
            +
                    return enum_for(:each) unless block_given?
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                    __getobj__.each do |object|
         | 
| 48 | 
            +
                      @scope.call { yield(object) }
         | 
| 49 | 
            +
                    end
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  # Rails 6.1 support:
         | 
| 53 | 
            +
                  def each_with_info
         | 
| 54 | 
            +
                    return enum_for(:each_with_info) unless block_given?
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    __getobj__.each_with_info do |object, info|
         | 
| 57 | 
            +
                      @scope.call { yield(object, info) }
         | 
| 58 | 
            +
                    end
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                private_constant :ScopedIterator
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
              if defined?(::ActionView::CollectionRenderer)
         | 
| 66 | 
            +
                # Rails 6.1 support:
         | 
| 67 | 
            +
                class CollectionRenderer < ::ActionView::CollectionRenderer # :nodoc:
         | 
| 68 | 
            +
                  include CollectionRenderable
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  def initialize(lookup_context, options, &scope)
         | 
| 71 | 
            +
                    super(lookup_context, options)
         | 
| 72 | 
            +
                    @scope = scope
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                  private
         | 
| 76 | 
            +
                    def collection_with_template(view, template, layout, collection)
         | 
| 77 | 
            +
                      super(view, template, layout, ScopedIterator.new(collection, @scope))
         | 
| 78 | 
            +
                    end
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
              else
         | 
| 81 | 
            +
                # Rails 6.0 support:
         | 
| 82 | 
            +
                class CollectionRenderer < ::ActionView::PartialRenderer # :nodoc:
         | 
| 83 | 
            +
                  include CollectionRenderable
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  def initialize(lookup_context, options, &scope)
         | 
| 86 | 
            +
                    super(lookup_context)
         | 
| 87 | 
            +
                    @options = options
         | 
| 88 | 
            +
                    @scope = scope
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  def render_collection_with_partial(collection, partial, context, block)
         | 
| 92 | 
            +
                    render(context, @options.merge(collection: collection, partial: partial), block)
         | 
| 93 | 
            +
                  end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                  private
         | 
| 96 | 
            +
                    def collection_without_template(view)
         | 
| 97 | 
            +
                      @collection = ScopedIterator.new(@collection, @scope)
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                      super(view)
         | 
| 100 | 
            +
                    end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                    def collection_with_template(view, template)
         | 
| 103 | 
            +
                      @collection = ScopedIterator.new(@collection, @scope)
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                      super(view, template)
         | 
| 106 | 
            +
                    end
         | 
| 107 | 
            +
                end
         | 
| 108 | 
            +
              end
         | 
| 109 | 
            +
            end
         | 
| @@ -0,0 +1,61 @@ | |
| 1 | 
            +
            require 'jbuilder/jbuilder'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            dependency_tracker = false
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            begin
         | 
| 6 | 
            +
              require 'action_view'
         | 
| 7 | 
            +
              require 'action_view/dependency_tracker'
         | 
| 8 | 
            +
              dependency_tracker = ::ActionView::DependencyTracker
         | 
| 9 | 
            +
            rescue LoadError
         | 
| 10 | 
            +
              begin
         | 
| 11 | 
            +
                require 'cache_digests'
         | 
| 12 | 
            +
                dependency_tracker = ::CacheDigests::DependencyTracker
         | 
| 13 | 
            +
              rescue LoadError
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
            end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            if dependency_tracker
         | 
| 18 | 
            +
              class Jbuilder
         | 
| 19 | 
            +
                module DependencyTrackerMethods
         | 
| 20 | 
            +
                  # Matches:
         | 
| 21 | 
            +
                  #   json.partial! "messages/message"
         | 
| 22 | 
            +
                  #   json.partial!('messages/message')
         | 
| 23 | 
            +
                  #
         | 
| 24 | 
            +
                  DIRECT_RENDERS = /
         | 
| 25 | 
            +
                    \w+\.partial!     # json.partial!
         | 
| 26 | 
            +
                    \(?\s*            # optional parenthesis
         | 
| 27 | 
            +
                    (['"])([^'"]+)\1  # quoted value
         | 
| 28 | 
            +
                  /x
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  # Matches:
         | 
| 31 | 
            +
                  #   json.partial! partial: "comments/comment"
         | 
| 32 | 
            +
                  #   json.comments @post.comments, partial: "comments/comment", as: :comment
         | 
| 33 | 
            +
                  #   json.array! @posts, partial: "posts/post", as: :post
         | 
| 34 | 
            +
                  #   = render partial: "account"
         | 
| 35 | 
            +
                  #
         | 
| 36 | 
            +
                  INDIRECT_RENDERS = /
         | 
| 37 | 
            +
                    (?::partial\s*=>|partial:)  # partial: or :partial =>
         | 
| 38 | 
            +
                    \s*                         # optional whitespace
         | 
| 39 | 
            +
                    (['"])([^'"]+)\1            # quoted value
         | 
| 40 | 
            +
                  /x
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  def dependencies
         | 
| 43 | 
            +
                    direct_dependencies + indirect_dependencies + explicit_dependencies
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  private
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  def direct_dependencies
         | 
| 49 | 
            +
                    source.scan(DIRECT_RENDERS).map(&:second)
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  def indirect_dependencies
         | 
| 53 | 
            +
                    source.scan(INDIRECT_RENDERS).map(&:second)
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              ::Jbuilder::DependencyTracker = Class.new(dependency_tracker::ERBTracker)
         | 
| 59 | 
            +
              ::Jbuilder::DependencyTracker.send :include, ::Jbuilder::DependencyTrackerMethods
         | 
| 60 | 
            +
              dependency_tracker.register_tracker :jbuilder, ::Jbuilder::DependencyTracker
         | 
| 61 | 
            +
            end
         | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            require 'jbuilder/jbuilder'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class Jbuilder
         | 
| 4 | 
            +
              class NullError < ::NoMethodError
         | 
| 5 | 
            +
                def self.build(key)
         | 
| 6 | 
            +
                  message = "Failed to add #{key.to_s.inspect} property to null object"
         | 
| 7 | 
            +
                  new(message)
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              class ArrayError < ::StandardError
         | 
| 12 | 
            +
                def self.build(key)
         | 
| 13 | 
            +
                  message = "Failed to add #{key.to_s.inspect} property to an array"
         | 
| 14 | 
            +
                  new(message)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              class MergeError < ::StandardError
         | 
| 19 | 
            +
                def self.build(current_value, updates)
         | 
| 20 | 
            +
                  message = "Can't merge #{updates.inspect} into #{current_value.inspect}"
         | 
| 21 | 
            +
                  new(message)
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
            end
         |