Ruby On Rails Routing Error (was previously working) - ruby-on-rails

So I'm working on a project and I want to create new subcategory. The link was working but I'm not getting the following error:
No route matches {:action=>"show", :controller=>"subcategories"}
The project is fairly new so my routes file is very simple:
Mrprice::Application.routes.draw do
get "admin/index" => 'admin#index'
resources :products
resources :subcategories
resources :categories
root to: 'store#index', as: 'root'
end
In my view:
<%= link_to 'New Subcategory', new_subcategory_path %>
I'm sure there's a typo somewhere or else the solution is very simple but I can't for the life of me figure it out.
I hope I've given enough information and that someone here knows what the problem is!
edit: subcategories_controller.rb (relevant methods)
def show
#subcategory = Subcategory.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #subcategory }
end
end
def new
#subcategory = Subcategory.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #subcategory }
end
end
def create
#subcategory = Subcategory.new(params[:subcategory])
respond_to do |format|
if #subcategory.save
format.html { redirect_to #subcategory, notice: 'Subcategory was successfully created.' }
format.json { render json: #subcategory, status: :created, location: #subcategory }
else
format.html { render action: "new" }
format.json { render json: #subcategory.errors, status: :unprocessable_entity }
end
end
end
rake routes gives:
admin_index GET /admin/index(.:format) admin#index
products GET /products(.:format) products#index
POST /products(.:format) products#create
new_product GET /products/new(.:format) products#new
edit_product GET /products/:id/edit(.:format) products#edit
product GET /products/:id(.:format) products#show
PUT /products/:id(.:format) products#update
DELETE /products/:id(.:format) products#destroy
subcategories GET /subcategories(.:format) subcategories#index
POST /subcategories(.:format) subcategories#creat
new_subcategory GET /subcategories/new(.:format) subcategories#new
edit_subcategory GET /subcategories/:id/edit(.:format) subcategories#edit
subcategory GET /subcategories/:id(.:format) subcategories#show
PUT /subcategories/:id(.:format) subcategories#updat
DELETE /subcategories/:id(.:format) subcategories#destr
categories GET /categories(.:format) categories#index
POST /categories(.:format) categories#create
new_category GET /categories/new(.:format) categories#new
edit_category GET /categories/:id/edit(.:format) categories#edit
category GET /categories/:id(.:format) categories#show
PUT /categories/:id(.:format) categories#update
DELETE /categories/:id(.:format) categories#destroy
root / store#index
note: not sure how to fix the formatting - I already tried a code block

Okay so I finally figured it out!
The problem was a routing error on the new subcategory form.
I had:
<%= link_to "Subcategories Home", subcategories_index_path %>
I know this was incorrect so I changed it to:
<%= link_to "Subcategories Home", subcategories_url %>
Mostly I just went through Rails Routing from the Outside In with a fine toothed comb until I figured out the correct way to route back to subcategories#index.

Related

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

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.
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.

how can redirect to project stage in rails by their project id

Currently after creating project stage page redirects to stage index but i want page to be redirected to project show page by their project id how can i do that in rails?
def create
#project = Project.find(params[:project_id])
#stage = #project.stages.build(stage_params)
respond_to do |format|
if #stage.save
format.html { redirect_to project_stages_path, notice: 'Stage was successfully created.' }
format.json { render :show, status: :created, location: #stage }
else
format.html { render :new }
format.json { render json: #stage.errors, status: :unprocessable_entity }
end
end
end
routes.rb
resources :projects do
resources :stages
end
rake routes
project_stages GET /projects/:project_id/stages(.:format) stages#index
POST /projects/:project_id/stages(.:format) stages#create
new_project_stage GET /projects/:project_id/stages/new(.:format) stages#new
edit_project_stage GET /projects/:project_id/stages/:id/edit(.:format) stages#edit
project_stage GET /projects/:project_id/stages/:id(.:format) stages#show
PATCH /projects/:project_id/stages/:id(.:format) stages#update
PUT /projects/:project_id/stages/:id(.:format) stages#update
DELETE /projects/:project_id/stages/:id(.:format) stages#destroy
projects GET /projects(.:format) projects#index
POST /projects(.:format) projects#create
new_project GET /projects/new(.:format) projects#new
edit_project GET /projects/:id/edit(.:format) projects#edit
project GET /projects/:id(.:format) projects#show
PATCH /projects/:id(.:format) projects#update
PUT /projects/:id(.:format) projects#update
DELETE /projects/:id(.:format) projects#destroy
Normally, use: redirect_to project_path(#project)
And you can even use: redirect_to #project
Details in https://api.rubyonrails.org/classes/ActionController/Redirecting.html
Change redirect_to
redirect_to project_path(#project)
Hope that helps!

undefined method `errors' for nil:NilClass in rails

i have created project scaffold and stage scaffold.i have a rendered a button on show page of the project to that open a form of stages. but i am getting no method error. i want to pass project_id to stage created. i have one to many association between project and stage.
error
projects_controller.rb
def index
#projects = current_user.projects.all.paginate(page: params[:page], per_page: 15)
end
def show
#project=Project.find(params[:id])
#stages = Stage.all
end
stages_controller.rb
def index
#stages = Stage.all
end
def show
end
def new
#stages = Stage.new
#project = Project.find(params[:project_id])
end
def create
#project = Project.find(params[:project_id])
#stage = #project.stages.build(stages_params)
respond_to do |format|
if #stage.save
format.html { redirect_to #stage, notice: 'Stage was successfully created.' }
format.json { render :show, status: :created, location: #stage }
else
format.html { render :new }
format.json { render json: #stage.errors, status: :unprocessable_entity }
end
end
routes.rb
resources :projects do
resources :stages
end
model project.rb
has_many :stages
rake routes
Prefix Verb URI Pattern Controller#Action
tasks GET /tasks(.:format) tasks#index
POST /tasks(.:format) tasks#create
new_task GET /tasks/new(.:format) tasks#new
edit_task GET /tasks/:id/edit(.:format) tasks#edit
task GET /tasks/:id(.:format) tasks#show
PATCH /tasks/:id(.:format) tasks#update
PUT /tasks/:id(.:format) tasks#update
DELETE /tasks/:id(.:format) tasks#destroy
project_stages GET /projects/:project_id/stages(.:format) stages#index
POST /projects/:project_id/stages(.:format) stages#create
new_project_stage GET /projects/:project_id/stages/new(.:format) stages#new
edit_project_stage GET /projects/:project_id/stages/:id/edit(.:format) stages#edit
project_stage GET /projects/:project_id/stages/:id(.:format) stages#show
PATCH /projects/:project_id/stages/:id(.:format) stages#update
PUT /projects/:project_id/stages/:id(.:format) stages#update
DELETE /projects/:project_id/stages/:id(.:format) stages#destroy
projects GET /projects(.:format) projects#index
POST /projects(.:format) projects#create
new_project GET /projects/new(.:format) projects#new
edit_project GET /projects/:id/edit(.:format) projects#edit
project GET /projects/:id(.:format) projects#show
PATCH /projects/:id(.:format) projects#update
PUT /projects/:id(.:format) projects#update
DELETE /projects/:id(.:format) projects#destroy
project show.html.erb
<%= link_to "Add Stage", new_project_stage_url(#project), :class=>"button primary small" %>
updated error
You are using nested routes but in form_with you have not specified that. Try to change the form_with like this:
form_with(model: stage, url: [#project, stage])
Source: https://stackoverflow.com/a/46919792/4207394
You will have to check the variable names, i.e., the stage variable should have the new Stage object and #project variable should have the Project object or else please change the names accordingly.
I think you have an arror because in your new method you are setting a variable called #stages
def new
#stages = Stage.new
#project = Project.find(params[:project_id])
end
but in your view you are using a variable called #stage.
Just change #stages into #stage in your controller method #new and you might be good to go like so :
def new
#stage = Stage.new
#project = Project.find(params[:project_id])
end
And in you view :
<% if #stage.errors.any? %>

Unable to find cause of an update statement

I am able to retrieve the record from GET request, but fail to update the record using PATCH request. Any suggestion on how debug this issue?
def show
#product = Product.find(params[:id])
render json: { status: :ok, message: 'Find the product ', data: #product }
end
def update
#product = Product.find(params[:id])
if #product.update(product_params)
render json: { status: :ok, message: 'Product updated!!! ', data: #product }
else
render json: { status: :error, message: 'Product not available!!!', data: #product }
end
end
private
def product_params
params.require(:product).permit(:title, :price, :count)
end
Curl requests:
curl -i -X GET 'localhost:3000/products/1'
{"status":"ok","message":"Find the product ","data":{"id":1,"title":"cell phone","price":"999","count":"99","created_at":"2019-01-19T16:12:09.717Z","updated_at":"2019-01-21T09:01:56.056Z"}}
curl -i -X PATCH 'localhost:3000/products/1' -d '{"product":{ "title": "t", "price": "1.23", "count": "3"}}'
{"status":"error","message":"Product not available!!!","data":{"id":1,"title":"t","price":"1.23","count":"3","created_at":"2019-01-19T16:12:09.717Z","updated_at":"2019-01-21T09:01:56.056Z"}}
Prefix Verb URI Pattern Controller#Action
welcome_index GET /welcome/index(.:format) welcome#index
product_purchase GET /products/:product_id/purchase(.:format) products#purchase
products GET /products(.:format) products#index
POST /products(.:format) products#create
new_product GET /products/new(.:format) products#new
edit_product GET /products/:id/edit(.:format) products#edit
product GET /products/:id(.:format) products#show
PATCH /products/:id(.:format) products#update
PUT /products/:id(.:format) products#update
DELETE /products/:id(.:format) products#destroy
root GET /
You are using product in the GET and products in the PATCH request. Check your routes file if you have defined the correct route.
Also based on your curl responses, it seems the product was updated. But the status and the message is from the else block. Try using update! to check for any errors

Ruby on Rails: Routing error

I am having trouble deleting and showing user records.
Here is my routes.rb
FinalApp::Application.routes.draw do
resources :users
devise_for :users, :controllers => { :registrations => 'admin' }
resources :projects
match "search" => "projects#search", :as => :search
root :to => 'projects#index'
end
Here is my admin controller:
class AdminController < ApplicationController
def index
#users = User.all
respond_to do |format|
format.html # index.html.erb
format.json { render :json => #users }
end
end
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# GET /users/1
# GET /users/1.json
def show
#user = User.find(params[:id])
#user_user_id = params[:id]
respond_to do |format|
format.html # show.html.erb
format.json { render json: #user }
end
end
# GET /users/new
# GET /users/new.json
def new
#user = User.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #user }
end
end
# GET /users/1/edit
def edit
#user = User.find(params[:id])
end
# POST /users
# POST /users.json
# PUT /users/1
# PUT /users/1.json
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
end
Here is my view:
<%= stylesheet_link_tag "admin" %>
<body>
<div id ="title1">Admin</div>
<div class ="menu"></div>
<div id ="section3">
<table id = "mytable">
<table border = "1">
<tr>
<th>Username </th>
<th>Email</th>
<th>First Name</th>
<th>Last Name</th>
<th>Admin?</th>
<th></th>
<th></th>
<th></th>
</tr>
<%= link_to "New User", admin_new_path %><br />
<% #users.each do |t| %>
<tr>
<td><%= t.username %></td>
<td><%= t.email %></td>
<td><%= t.firstname %></td>
<td><%= t.lastname %></td>
<td><%= t.admin %></td>
<td><%= link_to 'Show', t %></td>
<td> <%= button_to "Delete", t, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table></br>
</body>
</html>
I can display the User database, but when I go to delete a record. I get this error No route matches [DELETE] "/users/11". I am new to rails so please remember this when trying to help. Thanks in advance.
Edit: here are my routes =>
admin_index GET /admin(.:format) admin#index
POST /admin(.:format) admin#create
new_admin GET /admin/new(.:format) admin#new
edit_admin GET /admin/:id/edit(.:format) admin#edit
admin GET /admin/:id(.:format) admin#show
PUT /admin/:id(.:format) admin#update
DELETE /admin/:id(.:format) admin#destroy
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) admin#cancel
user_registration POST /users(.:format) admin#create
new_user_registration GET /users/sign_up(.:format) admin#new
edit_user_registration GET /users/edit(.:format) admin#edit
PUT /users(.:format) admin#update
DELETE /users(.:format) admin#destroy
projects GET /projects(.:format) projects#index
POST /projects(.:format) projects#create
new_project GET /projects/new(.:format) projects#new
edit_project GET /projects/:id/edit(.:format) projects#edit
project GET /projects/:id(.:format) projects#show
PUT /projects/:id(.:format) projects#update
DELETE /projects/:id(.:format) projects#destroy
search /search(.:format) projects#search
root / projects#index
EDIT2: This is how my routes.rb file should have looked. Using rake routes I was able to change the paths to fix my problem.
FinalApp::Application.routes.draw do
# website home
root :to => 'projects#index'
# devise sessions (NB does not use admin/users controller)
devise_for :users, :controllers => { :registrations => 'users' }
# normal controllers
resources :users
resources :projects
# custom routes
match "search" => "projects#search", :as => :search
end
You should add resources :users to your routes.rb. In any case, you can always check rake routes in your console to see the available routes.
On a side note, the way you define you admin routes are not completely correct. Not everything is a get. For example, creating an admin would be a post. The easiest way is just to use something like resources :admins.
You have ended up with two routes leading to admin#destroy:
DELETE /users(.:format) admin#destroy
DELETE /admin/:id(.:format) admin#destroy
and yet you have no route which matches /users/xx, just a route which matches DELETE /users with an optional format bit. You have a route which matches /admin/11 so if you tried that it would work, however I would try to simplify things a bit.
Do you actually need to specify a controller on the devise resources? What exactly do you want to override there, as you have ended up with a load of routes (like cancel) which lead nowhere and some which clash...
Try a simpler routes definition (NB this requires renaming your AdminController UsersController instead, I would follow this convention as it will make your life easier, and match your other urls, so you end up with users/1 etc, not admin/1)
FinalApp::Application.routes.draw do
# website home
root :to => 'projects#index'
# devise sessions (NB does not use admin/users controller)
devise_for :users
# normal controllers
resources :users
resources :projects
# custom routes
match "search" => "projects#search", :as => :search
end
Then do rake routes to make sure you understand where the routes are pointing. You need a route which says (NB the :id bit):
DELETE /users/:id(.:format) users#destroy
or if you prefer an admin controller (and are willing to sort out the custom routes)
DELETE /admin/:id(.:format) admin#destroy
Perhaps before diving into this though you could read through the rails routing guide as it might clear a few things up for you:
http://guides.rubyonrails.org/routing.html
This appears to be a pretty standard use of Devise with your only notable difference being the name of your Controller. Therefore, the only thing you should need for devise routing is:
devise_for :users, :controllers => { :registrations => 'admin' }
Also, delete all of your "get 'admin/*'" entries. Not every HTTP method is a GET when you're working in a REST environment. Here is one article that discusses REST methods.

Resources