Search code examples
ruby-on-railsrubyurl-routingnested-routes

Nested routes redirecting to create action with wrong route


I've created nested routes for a model called Userfolder. The routes are mapped like this:

Rake Routes

userfolder_userfolders POST   /userfolders/:userfolder_id/userfolders(.:format)     userfolders#create
new_userfolder_userfolder GET    /userfolders/:userfolder_id/userfolders/new(.:format) userfolders#new

Which is exactly the way I want it. But when I create a new Userfolder, Rails is redirecting the create action to "/userfolders" and not "/userfolders/:userfolder_id/userfolders". It is still following the initial Rails scaffolding routes.

Is there a way to change this? Or have I missed out on something entirely?

EDIT 1: Here is my Userfolder controller code.

class UserfoldersController < ApplicationController


before_action :set_userfolder, only: [:show, :edit, :update, :destroy]
  before_action :set_parentfolder, except: [:show, :edit, :update, :destroy, :index]

  # GET /userfolders
  # GET /userfolders.json
  def index
    if Userfolder.first.nil?
      Userfolder.create(:name => 'root', :parent_id => 0)
    end
    redirect_to Userfolder.first
  end

  # GET /userfolders/1
  # GET /userfolders/1.json
  def show
  end

  # GET /userfolders/:userfolder_id/userfolders/new(.:format)
  def new
    @userfolder = @parentfolder.children.build
  end

  # GET /userfolders/1/edit
  def edit
  end

  # POST /userfolders/:userfolder_id/userfolders
  def create
    @userfolder = @parentfolder.children.build(userfolder_params)

    respond_to do |format|
      if @userfolder.save
        format.html { redirect_to userfolder_path(@parentfolder.id), notice: 'Userfolder was successfully created.' }
      else
        render :action => 'new'
      end
    end
  end

  # PATCH/PUT /userfolders/1
  # PATCH/PUT /userfolders/1.json
  def update
    respond_to do |format|
      if @userfolder.update(userfolder_params)
        format.html { redirect_to @userfolder, notice: 'Userfolder was successfully updated.' }
      else
        render :action => 'edit'
      end
    end
  end

  # DELETE /userfolders/1
  # DELETE /userfolders/1.json
  def destroy
    parent_folder = @userfolder.parent
    @userfolder.destroy
    respond_to do |format|
      format.html { redirect_to parent_folder, notice: 'Userfolder was successfully destroyed.' }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_userfolder
      @userfolder = Userfolder.find(params[:id])
    end

    def set_parentfolder
      @parentfolder = Userfolder.find(params[:userfolder_id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def userfolder_params
      params.require(:userfolder).permit(:name, :parent_id)
    end
end

This is my routes.rb file:

Rails.application.routes.draw do
  resources :userfiles

  # The priority is based upon order of creation: first created -> highest priority.
  # See how all your routes lay out with "rake routes".

  # You can have the root of your site routed with "root"
  root 'userfolders#index'

  resources :userfolders, :shallow => true, :except => [:new, :create] do
    resources :userfolders, :only => [:new, :create]
  end

EDIT 2: This is the console output: Console


Solution

  • So the issue was with the _form.html.erb like I suspected.

    This is the create controller:

      def create
    @userfolder = @parentfolder.children.build(userfolder_params)
    
    respond_to do |format|
      if @userfolder.save
        format.html { redirect_to @parentfolder, notice: 'Userfolder was successfully created.' }
      else
        render :action => 'new'
      end
     end
    end
    

    And here is the _form.html.erb:

        <%= form_for([@parentfolder, @userfolder]) do |f| %>
      <% if @userfolder.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(@userfolder.errors.count, "error") %> prohibited this userfolder from being saved:</h2>
    
          <ul>
          <% @userfolder.errors.full_messages.each do |message| %>
            <li><%= message %></li>
          <% end %>
          </ul>
        </div>
      <% end %>
    
      <div class="field">
        <%= f.label :name %><br>
        <%= f.text_field :name %>
      </div>
      <div class="field">
        <%= f.label :parent_id %><br>
        <%= f.number_field :parent_id %>
      </div>
      <div class="actions">
        <%= f.submit %>
      </div>
    <% end %>
    

    By adding the <%= form_for([@parentfolder, @userfolder]) do |f| %>, I'm telling Rails to redirect to /userfolders/:userfolder_id/userfolders. Instead of redirecting to /userfolders.