Search code examples
ruby-on-railsrubyscaffolding

Where does `respond_to do |format|` come from when scaffolding a Rails controller?


When doing rails generate scaffold Banana, bananas_controller.rb has the following code:

  # POST /bananas or /bananas.json
  def create
    @banana = Banana.new(banana_params)

    respond_to do |format|
      if @banana.save
        format.html { redirect_to banana_url(@banana), notice: "Banana was successfully created." }
        format.json { render :show, status: :created, location: @banana }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @banana.errors, status: :unprocessable_entity }
      end
    end
  end

But when I look at the railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt template in the Rails codebase, the create method is only defined like so:

  # POST <%= route_url %>
  def create
    @<%= singular_table_name %> = <%= orm_class.build(class_name, "#{singular_table_name}_params") %>

    if @<%= orm_instance.save %>
      redirect_to <%= redirect_resource_name %>, notice: <%= %("#{human_name} was successfully created.") %>
    else
      render :new, status: :unprocessable_entity
    end
  end

There is no mention of respond_to do |format| whatsoever. Where in the Rails codebase is respond_to do |format| added? I grepped the whole project to no avail.


Solution

  • Jbuilder overrides the default controller.rb template and adds respond_to block as well as a hook to generate .json.jbuilder views:

    $ ag "format.json" `bundle show --paths`
    
    /home/alex/.rbenv/versions/3.3.0/lib/ruby/gems/3.3.0/gems/actionpack-7.1.3.3/lib/action_controller/api.rb
    82:  #         format.json { render json: posts }
    
    /home/alex/.rbenv/versions/3.3.0/lib/ruby/gems/3.3.0/gems/jbuilder-2.12.0/lib/generators/rails/templates/controller.rb
    34:        format.json { render :show, status: :created, location: <%= "@#{singular_table_name}" %> }
    37:        format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity }
    47:        format.json { render :show, status: :ok, location: <%= "@#{singular_table_name}" %> }
    50:        format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity }
    61:      format.json { head :no_content }
    

    https://github.com/rails/jbuilder/blob/v2.12.0/lib/generators/rails/templates/controller.rb#L31-L38