Home > database >  Rails routing not providing the index and using it as the show for nested resources
Rails routing not providing the index and using it as the show for nested resources

Time:12-02

I had this tutorial working for a different exercise, but now I'm putting the actual work into practice and can't figure out what I'm now doing wrong.
https://www.digitalocean.com/community/tutorials/how-to-create-nested-resources-for-a-ruby-on-rails-application

Here's my Product Categories model

class ProductCategory < ApplicationRecord
    has_many :products
end

my Product model:

class Product < ApplicationRecord
  belongs_to :product_category
end

My routes.rb:

Rails.application.routes.draw do
  root 'product_categories#index'
  resources :product_categories do
    resource :products
  end
end

The actual routes output for rails routes:

% rails routes
                                  Prefix Verb   URI Pattern                                                                                       Controller#Action
                                    root GET    /                                                                                                 product_categories#index
           new_product_category_products GET    /product_categories/:product_category_id/products/new(.:format)                                   products#new
          edit_product_category_products GET    /product_categories/:product_category_id/products/edit(.:format)                                  products#edit
               product_category_products GET    /product_categories/:product_category_id/products(.:format)                                       products#show
                                         PATCH  /product_categories/:product_category_id/products(.:format)                                       products#update
                                         PUT    /product_categories/:product_category_id/products(.:format)                                       products#update
                                         DELETE /product_categories/:product_category_id/products(.:format)                                       products#destroy
                                         POST   /product_categories/:product_category_id/products(.:format)                                       products#create
                      product_categories GET    /product_categories(.:format)                                                                     product_categories#index
                                         POST   /product_categories(.:format)                                                                     product_categories#create
                    new_product_category GET    /product_categories/new(.:format)                                                                 product_categories#new
                   edit_product_category GET    /product_categories/:id/edit(.:format)                                                            product_categories#edit
                        product_category GET    /product_categories/:id(.:format)                                                                 product_categories#show
                                         PATCH  /product_categories/:id(.:format)                                                                 product_categories#update
                                         PUT    /product_categories/:id(.:format)                                                                 product_categories#update
                                         DELETE /product_categories/:id(.:format)                                                                 product_categories#destroy
           rails_postmark_inbound_emails POST   /rails/action_mailbox/postmark/inbound_emails(.:format)                                           action_mailbox/ingresses/postmark/inbound_emails#create
              rails_relay_inbound_emails POST   /rails/action_mailbox/relay/inbound_emails(.:format)                                              action_mailbox/ingresses/relay/inbound_emails#create
           rails_sendgrid_inbound_emails POST   /rails/action_mailbox/sendgrid/inbound_emails(.:format)                                           action_mailbox/ingresses/sendgrid/inbound_emails#create
     rails_mandrill_inbound_health_check GET    /rails/action_mailbox/mandrill/inbound_emails(.:format)                                           action_mailbox/ingresses/mandrill/inbound_emails#health_check
           rails_mandrill_inbound_emails POST   /rails/action_mailbox/mandrill/inbound_emails(.:format)                                           action_mailbox/ingresses/mandrill/inbound_emails#create
            rails_mailgun_inbound_emails POST   /rails/action_mailbox/mailgun/inbound_emails/mime(.:format)                                       action_mailbox/ingresses/mailgun/inbound_emails#create
          rails_conductor_inbound_emails GET    /rails/conductor/action_mailbox/inbound_emails(.:format)                                          rails/conductor/action_mailbox/inbound_emails#index
                                         POST   /rails/conductor/action_mailbox/inbound_emails(.:format)                                          rails/conductor/action_mailbox/inbound_emails#create
       new_rails_conductor_inbound_email GET    /rails/conductor/action_mailbox/inbound_emails/new(.:format)                                      rails/conductor/action_mailbox/inbound_emails#new
      edit_rails_conductor_inbound_email GET    /rails/conductor/action_mailbox/inbound_emails/:id/edit(.:format)                                 rails/conductor/action_mailbox/inbound_emails#edit
           rails_conductor_inbound_email GET    /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                                      rails/conductor/action_mailbox/inbound_emails#show
                                         PATCH  /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                                      rails/conductor/action_mailbox/inbound_emails#update
                                         PUT    /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                                      rails/conductor/action_mailbox/inbound_emails#update
                                         DELETE /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                                      rails/conductor/action_mailbox/inbound_emails#destroy
new_rails_conductor_inbound_email_source GET    /rails/conductor/action_mailbox/inbound_emails/sources/new(.:format)                              rails/conductor/action_mailbox/inbound_emails/sources#new
   rails_conductor_inbound_email_sources POST   /rails/conductor/action_mailbox/inbound_emails/sources(.:format)                                  rails/conductor/action_mailbox/inbound_emails/sources#create
   rails_conductor_inbound_email_reroute POST   /rails/conductor/action_mailbox/:inbound_email_id/reroute(.:format)                               rails/conductor/action_mailbox/reroutes#create
                      rails_service_blob GET    /rails/active_storage/blobs/redirect/:signed_id/*filename(.:format)                               active_storage/blobs/redirect#show
                rails_service_blob_proxy GET    /rails/active_storage/blobs/proxy/:signed_id/*filename(.:format)                                  active_storage/blobs/proxy#show
                                         GET    /rails/active_storage/blobs/:signed_id/*filename(.:format)                                        active_storage/blobs/redirect#show
               rails_blob_representation GET    /rails/active_storage/representations/redirect/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations/redirect#show
         rails_blob_representation_proxy GET    /rails/active_storage/representations/proxy/:signed_blob_id/:variation_key/*filename(.:format)    active_storage/representations/proxy#show
                                         GET    /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format)          active_storage/representations/redirect#show
                      rails_disk_service GET    /rails/active_storage/disk/:encoded_key/*filename(.:format)                                       active_storage/disk#show
               update_rails_disk_service PUT    /rails/active_storage/disk/:encoded_token(.:format)                                               active_storage/disk#update
                    rails_direct_uploads POST   /rails/active_storage/direct_uploads(.:format)                                                    active_storage/direct_uploads#create

The ProductCategoriesController:

class ProductCategoriesController < ApplicationController
    before_action :set_product_category, except: [:index, :new, :create]

    def index
        @categories = ProductCategory.all
    end

    def show
    end

    def new
        @category = ProductCategory.new
    end

    def create
        @category = ProductCategory.new(category_params)

        respond_to do |format|
            if @category.save
                format.html { redirect_to root_path }
            else
                format.html { render :edit, status: :unprocessable_entity }
            end
        end
    end

    private
        def set_product_category
            @product_category = ProductCategory.find(params[:id])
            @name = @product_category.name
        end

        def category_params
            params.require(:product_category).permit(:name)
        end


end

and finally, the ProductsController:

class ProductsController < ApplicationController
    before_action :get_product_category
    before_action :set_product, except: [:index, :new, :create]

    def index
        @products = @product_category.products
    end

    def show
    end

    def new
        @product = @product_category.products.build
    end

    def edit
    end

    def create
        @product = @product_category.products.build(product_params)

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

    def update
        respond_to do |format|
            if @product.update(product_params)
                format.html { redirect_to @product, notice: "Product was successfully updated." }
                format.json { render :show, status: :ok, location: @product }
            else
                format.html { render :edit, status: :unprocessable_entity }
                format.json { render json: @product.errors, status: :unprocessable_entity }
            end
        end
    end

    def destroy
        @product.destroy
        respond_to do |format|
            format.html { redirect_to products_url, notice: "Product was successfully destroyed." }
            format.json { head :no_content }
        end
    end
    

    private
        def get_product_category
            @product_category = ProductCategory.find(params[:product_category_id])
        end

        def set_product
            @product = @product_category.products.find(params[:id])
            
        end

        def product_params
            params.require(:product).permit(:name, :description, :product_type)
        end
end

So when you create a new product, it should redirect to the product's show page, but instead I get the error it and find Product without an ID. I do see in the routes that while a show is being generated, an index route is not.

Any help would be appreciated. Thanks.

CodePudding user response:

You have a typo in your routes file:

    resource :products

should be

    resources :products

(Note the missing 's'.) Once you correct this, you should see that the correct routes are generated by Rails and things work more as you expect.

  • Related