Nikola Stojaković
Nikola Stojaković

Reputation: 2305

New route returns me to the index page

[Update] Code is little canged because I realized that I need more generation pictures for one school (one for each generation) so associations are different now.

I have a School model with GenerationPicture:

class School < ActiveRecord::Base

  belongs_to :city
  has_many :sclasses
  has_many :users, through: :sclasses
  has_many :generation_pictures

  validates :name, presence: true
  validates :icon_url, length: { maximum: 100 }

end

class GenerationPicture < ActiveRecord::Base

  validates :generation, presence: true, numericality: { only_integer: true }, uniqueness: true

  has_attached_file :image, styles: { large: "600x600", medium: "300x300>", thumb: "150x150" }, default_url: "/images/:style/missing.png"
  validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/

  belongs_to :school

end

This is my generation_pictures controller:

class GenerationPicturesController < ApplicationController

    def new
        find_city
        find_school

        @generation_picture = @school.generation_pictures.new
    end

    def create
        find_city
        find_school

        @generation_picture = @school.generation_pictures.new(generation_picture_params)

        if @generation_picture.save
            redirect_to generation_picture_path(@generation_picture)
        else
            render "new"
        end
    end

    def edit
        find_city
        find_school
        find_generation_picture
    end

    def update
        find_city
        find_school
        find_generation_picture

        if @generation_picture.update(generation_picture_params)
            redirect_to generation_picture_path(@generation_picture)
        else
            render "edit"
        end
    end

    private

    def generation_picture_params
        params.require(:generation_picture).permit(:generation, :image)
    end

    def find_city
        @city = City.find(params[:city_id])
    end

    def find_school
        @school = School.find(params[:school_id])
    end

    def find_generation_picture
        @generation_picture = @school.generation_pictures.find(params[:id])
    end

end

When I try to access the page for new picture I'm returned to the index page and console shows no errors.

Here are routes:

Rails.application.routes.draw do

  root 'welcome#index'

  # prevedene rute
  get "/pocetna"          => "welcome#index", as: "index"
  get "/korpa"            => "carts#new", as: "new_cart"
  get "/poslato"          => "carts#success", as: "success"

  resources :sessions, only: [:new, :create, :destroy]

  get "/prijava"   => "sessions#new", as: "login"
  post "/prijava"  => "sessions#create"
  get "/odjava"    => "sessions#destroy", as: "logout"
  delete "/odjava" => "sessions#destroy"

  #resources :users do
  #  resources :photos
  #end

  # Gradovi
  get "/gradovi" => "welcome#index", as: "cities"
  get "/gradovi/novi" =>  "cities#new", as: "new_city"
  post "/gradovi" => "cities#create"
  get "/gradovi/:id" => "cities#show", as: "city"
  get "/gradovi/:id/uredi" => "cities#edit", as: "edit_city"
  patch "/gradovi/:id" => "cities#update"

  # Škole
  get "/gradovi/:city_id" => "schools#index", as: "schools"
  get "/gradovi/:city_id/nova-skola" => "schools#new", as: "new_school"
  post "/gradovi/:city_id/" => "schools#create"
  get "/gradovi/:city_id/skola/:id" => "schools#show", as: "school"
  get "/gradovi/:city_id/skola/:id/uredi" => "schools#edit", as: "edit_school"
  patch "/gradovi/:city_id/skola/:id" => "schools#update"

  # Tabloi
  get "/gradovi/:city_id/skola/:school_id/tablo/novi" => "generation_pictures#new", as: "new_generation_picture"
  post "/gradovi/:city_id/skola/:school_id" => "generation_pictures#create"
  get "/gradovi/:city_id/skola/:school_id/tablo/:id" => "generation_pictures#show", as: "generation_picture"
  get "/gradovi/:city_id/skola/:school_id/tablo/:id/uredi" => "generation_pictures#edit", as: "edit_generation_picture"
  patch "/gradovi/:city_id/skola/:school_id" => "generation_pictures#update"

  # Razredi
  get "/gradovi/:city_id/skola/:school_id" => "sclasses#index", as: "sclasses"
  post "/gradovi/:city_id/skola/:school_id" => "sclasses#create"
  get "/gradovi/:city_id/skola/:school_id/razred/dodaj" => "sclasses#new", as: "new_sclass"
  get "/gradovi/:city_id/skola/:school_id/razred/:id" => "sclasses#show", as: "sclass"
  get "/gradovi/:city_id/skola/:school_id/razred/:id/uredi" => "sclasses#edit", as: "edit_sclass"
  patch "/gradovi/:city_id/skola/:school_id/razred/:id" => "sclasses#update"

  # Učenici
  get "/gradovi/:city_id/skola/:school_id/razred/:sclass_id" => "users#index", as: "users"
  post "/gradovi/:city_id/skola/:school_id/razred/:sclass_id" => "users#create"
  get "/gradovi/:city_id/skola/:school_id/razred/:sclass_id/ucenik/dodaj" => "users#new", as: "new_user"
  get "/gradovi/:city_id/skola/:school_id/razred/:sclass_id/ucenik/:id" => "users#show", as: "user"
  get "/gradovi/:city_id/skola/:school_id/razred/:sclass_id/ucenik/:id/uredi" => "users#edit", as: "edit_user"
  patch "/gradovi/:city_id/skola/:school_id/razred/:sclass_id/ucenik/:id" => "users#update"
  delete "/gradovi/:city_id/skola/:school_id/razred/:sclass_id/ucenik/:id" => "users#destroy"

  resources :city
  resources :carts

end

This is the form partial:

<% if controller.action_name == "edit" %>

    <%= form_for [@city, @school, @generation_picture], url: generation_picture_path(@city, @school, @generation_picture), html: { multipart: true } do |f| %>

        <% if @generation_picture.errors.any? %>
            <div class="alert alert-danger">
                <ul>
                    <% @generation_picture.errors.full_messages.each do |msg| %>
                        <li><%= msg %></li>
                    <% end %>
                </ul>
            </div>
        <% end %>

        <%= f.label "Fotografija:" %>
        <%= f.file_field :image, class: "input-field" %>

        <%= f.label "Generacija:" %>
        <%= f.text_field :generation, class: "input-field" %>

        <%= f.submit "Pošalji", class: "btn btn-default" %>

    <% end %>

<% else %>

    <%= form_for @generation_picture, url: school_path(@city, @school), html: { multipart: true } do |f| %>

        <% if @generation_picture.errors.any? %>
            <div class="errors alert alert-danger">
                <ul>
                    <% @generation_picture.errors.full_messages.each do |msg| %>
                        <li><%= msg %></li>
                    <% end %>
                </ul>
            </div>
        <% end %>

        <%= f.label "Fotografija:" %>
        <%= f.file_field :image, class: "input-field" %>

        <%= f.label "Generacija:" %>
        <%= f.text_field :generation, class: "input-field" %>

        <%= f.submit "Pošalji", class: "btn btn-default" %>

    <% end %>

<% end %>

[Update] Rake routes output

new_generation_picture GET    /gradovi/:city_id/skola/:school_id/tablo/novi(.:format)                         generation_pictures#new
                        POST   /gradovi/:city_id/skola/:school_id(.:format)                                    generation_pictures#create
     generation_picture GET    /gradovi/:city_id/skola/:school_id/tablo/:id(.:format)                          generation_pictures#show
edit_generation_picture GET    /gradovi/:city_id/skola/:school_id/tablo/:id/uredi(.:format)                    generation_pictures#edit
                        PATCH  /gradovi/:city_id/skola/:school_id(.:format)                                    generation_pictures#update

            schools GET    /gradovi/:city_id(.:format)                                                     schools#index
         new_school GET    /gradovi/:city_id/nova-skola(.:format)                                          schools#new
                    POST   /gradovi/:city_id(.:format)                                                     schools#create
             school GET    /gradovi/:city_id/skola/:id(.:format)                                           schools#show
        edit_school GET    /gradovi/:city_id/skola/:id/uredi(.:format)                                     schools#edit
                    PATCH  /gradovi/:city_id/skola/:id(.:format)                                           schools#update

[Update 2] Current routes

Rails.application.routes.draw do

  root 'welcome#index'

  get "/korpa"            => "carts#new", as: "new_cart"
  get "/poslato"          => "carts#success", as: "success"

  resources :sessions, only: [:new, :create, :destroy]

  get "/prijava"   => "sessions#new", as: "login"
  post "/prijava"  => "sessions#create"
  get "/odjava"    => "sessions#destroy", as: "logout"
  delete "/odjava" => "sessions#destroy"

  scope(path_names: { new: 'novi', edit: 'uredi' }) do
    resources :cities, path: 'gradovi', except: [:index, :destroy] do
      scope(path_names: { new: 'nova-skola', edit: 'uredi' }) do
        resources :schools, path: 'skola', except: [:index, :destroy], shallow: true do
          scope(path_names: { new: 'dodaj', edit: 'uredi'}) do
            resources :sclasses, path: 'razred', except: [:destroy] #, shallow: true
            scope(path_names: { new: 'dodaj', edit: 'uredi'}) do
              resources :users, path: 'ucenik'
            end
          end
          scope(path_names: { new: 'novi', edit: 'uredi'}) do
            resources :generation_pictures, path: 'tablo', except: [:index, :destroy]
          end
        end
      end
    end
  end

  resources :carts, except: [:new] # defined at top

end

Upvotes: 0

Views: 71

Answers (1)

Eric
Eric

Reputation: 2549

You have a lot of routes overriding others, such as:

get "/gradovi/:id" => "cities#show", as: "city"
# vs.
get "/gradovi/:city_id" => "schools#index", as: "schools"

and

post "/gradovi/:city_id/skola/:school_id" => "generation_pictures#create"
# vs.
post "/gradovi/:city_id/skola/:school_id" => "sclasses#create"    

and

get "/gradovi/:city_id/skola/:school_id/razred/:id" => "sclasses#show", as: "sclass"
# vs
get "/gradovi/:city_id/skola/:school_id/razred/:sclass_id" => "users#index", as: "users"

Rails can't tell whether a number is supposed to be :id or :city_id, it just sees a number. Likewise, configuring the same URL to go to multiple controller actions will result in disappointing behavior.

I think a good first step is to simplify your route definitions with nested resources and translated paths.

Rails.application.routes.draw do

  root 'welcome#index'

  # prevedene rute
  #
  # another duplicate of root_path:
  # get "/pocetna"          => "welcome#index", as: "index"
  get "/korpa"            => "carts#new", as: "new_cart"
  get "/poslato"          => "carts#success", as: "success"


  get "/prijava"   => "sessions#new", as: "login"
  post "/prijava"  => "sessions#create"
  get "/odjava"    => "sessions#destroy", as: "logout"
  delete "/odjava" => "sessions#destroy"

  # Gradovi
  scope(path_names: { new: 'novi', edit: 'uredi' }) do
    resources :cities, path: 'gradovi', except: [:index, :destroy] do
      # don't create multiple routes to 'welcome#index', 
      # use root_url or root_path
      # get '/gradovi', to: 'welcome#index', as: 'cities', on: :collection

      # Škole
      scope(path_names: { new: 'nova-skola', edit: 'uredi' }) do
        # use root_url here for 'welcome#index', too
        resources :schools, path: 'skola', except: [:index, :destroy] do
        # Tabloi
        scope(path_names: { new: 'novi', edit: 'uredi'}) do
          resources :generation_pictures, path: 'tablo', except: [:index, :destroy]
        end
        # Razredi
        scope(path_names: { new: 'dodaj', edit: 'uredi'}) do
          resources :sclasses, path: 'razred', except: [:destroy]
          # Učenici
          scope(path_names: { new: 'dodaj', edit: 'uredi'}) do
            resources :users, path: 'ucenik'
          end
        end
      end
    end
  end

  # You already have `resources :cities` as 'gradovi' above:    
  # resources :city
  resources :carts, except: [:new] # defined at top

end

This is going to change your route helper names that you're using elsewhere in your code, but your routes should be much cleaner now. You should also look into the shallow routing keyword, because nesting this many deep just to get to your users (for example), is not a great style.

There's no reason why getting a list of students for a class has to include the city in the URL, and nobody wants to type new_city_school_sclass_user_path(@city, @school, @sclass), so organize your urls better. It doesn't affect your associations or any app functionality, just the route names and URLs. I suggest putting shallow: true on schools:

scope(path_names: { new: 'novi', edit: 'uredi' }) do
# Gradovi
  resources :cities, path: 'gradovi', except: [:index, :destroy] do
    # don't create multiple routes to 'welcome#index', 
    # use root_url or root_path
    # get '/gradovi', to: 'welcome#index', as: 'cities', on: :collection

    # Škole
    scope(path_names: { new: 'nova-skola', edit: 'uredi' }) do
      # use root_url here for 'welcome#index', too
      resources :schools, path: 'skola', except: [:index, :destroy], shallow: true do
        # Razredi
        scope(path_names: { new: 'dodaj', edit: 'uredi'}) do
          resources :sclasses, path: 'razred', except: [:destroy] #, shallow: true
          # Učenici
          scope(path_names: { new: 'dodaj', edit: 'uredi'}) do
            resources :users, path: 'ucenik'
          end
        end
        # Tabloi
        scope(path_names: { new: 'novi', edit: 'uredi'}) do
          resources :generation_pictures, path: 'tablo', except: [:index, :destroy]
        end
      end
    end
  end
end

Which gives you a list of routes like this:

                         root GET    /                                            welcome#index
                     new_cart GET    /korpa(.:format)                             carts#new
                      success GET    /poslato(.:format)                           carts#success
                        login GET    /prijava(.:format)                           sessions#new
                      prijava POST   /prijava(.:format)                           sessions#create
                       logout GET    /odjava(.:format)                            sessions#destroy
                       odjava DELETE /odjava(.:format)                            sessions#destroy
                 sclass_users GET    /razred/:sclass_id/ucenik(.:format)          users#index
                              POST   /razred/:sclass_id/ucenik(.:format)          users#create
              new_sclass_user GET    /razred/:sclass_id/ucenik/dodaj(.:format)    users#new
                    edit_user GET    /ucenik/:id/uredi(.:format)                  users#edit
                         user GET    /ucenik/:id(.:format)                        users#show
                              PATCH  /ucenik/:id(.:format)                        users#update
                              PUT    /ucenik/:id(.:format)                        users#update
                              DELETE /ucenik/:id(.:format)                        users#destroy
              school_sclasses GET    /skola/:school_id/razred(.:format)           sclasses#index
                              POST   /skola/:school_id/razred(.:format)           sclasses#create
            new_school_sclass GET    /skola/:school_id/razred/dodaj(.:format)     sclasses#new
                  edit_sclass GET    /razred/:id/uredi(.:format)                  sclasses#edit
                       sclass GET    /razred/:id(.:format)                        sclasses#show
                              PATCH  /razred/:id(.:format)                        sclasses#update
                              PUT    /razred/:id(.:format)                        sclasses#update
   school_generation_pictures POST   /skola/:school_id/tablo(.:format)            generation_pictures#create
new_school_generation_picture GET    /skola/:school_id/tablo/novi(.:format)       generation_pictures#new
      edit_generation_picture GET    /tablo/:id/uredi(.:format)                   generation_pictures#edit
           generation_picture GET    /tablo/:id(.:format)                         generation_pictures#show
                              PATCH  /tablo/:id(.:format)                         generation_pictures#update
                              PUT    /tablo/:id(.:format)                         generation_pictures#update
                 city_schools GET    /gradovi/:city_id/skola(.:format)            schools#index
                              POST   /gradovi/:city_id/skola(.:format)            schools#create
              new_city_school GET    /gradovi/:city_id/skola/nova-skola(.:format) schools#new
                  edit_school GET    /skola/:id/uredi(.:format)                   schools#edit
                       school GET    /skola/:id(.:format)                         schools#show
                              PATCH  /skola/:id(.:format)                         schools#update
                              PUT    /skola/:id(.:format)                         schools#update
                       cities POST   /gradovi(.:format)                           cities#create
                     new_city GET    /gradovi/novi(.:format)                      cities#new
                    edit_city GET    /gradovi/:id/uredi(.:format)                 cities#edit
                         city GET    /gradovi/:id(.:format)                       cities#show
                              PATCH  /gradovi/:id(.:format)                       cities#update
                              PUT    /gradovi/:id(.:format)                       cities#update
                        carts GET    /carts(.:format)                             carts#index
                              POST   /carts(.:format)                             carts#create
                    edit_cart GET    /carts/:id/edit(.:format)                    carts#edit
                         cart GET    /carts/:id(.:format)                         carts#show
                              PATCH  /carts/:id(.:format)                         carts#update
                              PUT    /carts/:id(.:format)                         carts#update
                              DELETE /carts/:id(.:format)                         carts#destroy

Upvotes: 1

Related Questions