Unable to find cause of an update statement - ruby-on-rails

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

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.

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? %>

Rails route disambiguation

Rails version: 5.2.3
Ruby version:2.0.4
In the below I am using concerns with post to overcome size limitations imposed on gets. It ends up clashing with #show and I can't figure out how to disambiguate them.
routes.rb
require 'sidekiq/web'
Rails.application.routes.draw do
concern :with_datatable do
post 'datatable', on: :collection
end
resources :organizations, concerns: [:with_datatable]
mount Sidekiq::Web, at: "/ninjas"
end
my routes are as follows:
datatable_organizations POST /organizations/datatable(.:format) organizations#datatable
organizations GET /organizations(.:format) organizations#index
POST /organizations(.:format) organizations#create
new_organization GET /organizations/new(.:format) organizations#new
edit_organization GET /organizations/:id/edit(.:format) organizations#edit {:id=>/[0-9]+/}
organization GET /organizations/:id(.:format) organizations#show {:id=>/[0-9]+/}
PATCH /organizations/:id(.:format) organizations#update {:id=>/[0-9]+/}
PUT /organizations/:id(.:format) organizations#update {:id=>/[0-9]+/}
DELETE /organizations/:id(.:format) organizations#destroy {:id=>/[0-9]+/}
sidekiq_web /ninjas Sidekiq::Web
rails_service_blob GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs#show
rails_blob_representation GET /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#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
Navigating to the route, /organizations/datatable.json produces this error:
OrganizationsController#show is missing a template for this request format and variant.
It thinks /organizations/datatable.json is a match for /organizations/:id/show despite having a clear route for /organizations/datatable(.:format)
Here's my controller:
class OrganizationsController < ApplicationController
def index
#title = "Organizations"
#page_description = "Organization data warehouse"
#page_icon = "institution"
#organization = Organization.new
#load = {data_table: true}
respond_to do |format|
format.html
format.json { render json: OrganizationDatatable.new(params) }
end
end
def datatable
respond_to do |format|
format.json { render json: OrganizationDatatable.new(params) }
end
end
def get_raw_records
Organization.all
end
def create
end
def edit
end
def destroy
end
def show
end
def update
end
def new
end
end
full error text:
ActionController::UnknownFormat - OrganizationsController#show is missing a template for this request format and variant.
request.formats: ["text/html"]
request.variant: []
NOTE! For XHR/Ajax or API requests, this action would normally respond with 204 No Content: an empty white screen. Since you're loading it in a web browser, we assume that you expected to actually render a template, not nothing, so we're showing an error to be extra-clear. If you expect 204 No Content, carry on. That's what you'll get from an XHR or API request. Give it a shot.
What am I missing here?

I am getting a No route matches error while trying to reroute to a new page?

I am new to ruby on rails , I was making a basic app that lets you display posts, after which we can access a new page where a user can enter new posts.
But the problem now is , upon clicking the submit button I get this error
No route matches {:action=>"show", :controller=>"posts"} missing required keys: [:id]
This is the content inside my post controller
class PostsController < ApplicationController
def index
#posts = Post.all
end
def show
#post = Post.find(params[:id])
end
def new
#post =Post.new
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to post_path,:notice=>"success"
else
render "new"
end
end
def edit
end
def update
end
def destroy
end
private
def post_params
params.require(:post).permit(:Title, :Content)
end
end
after this i tried to reload to check if there was an update at all , but all i got was empty entries
rake route command displays
nevin#NevinSunny:~/Workspace/Rails/Test1/blog$ rake routes
Prefix Verb URI Pattern Controller#Action
posts GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
new_post GET /posts/new(.:format) posts#new
edit_post GET /posts/:id/edit(.:format) posts#edit
post GET /posts/:id(.:format) posts#show
PATCH /posts/:id(.:format) posts#update
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
Change your create action:
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post, :notice => "success"
else
render "new"
end
end
Edit:
In response to your comment:
def create
#post = Post.new(post_params)
if #post.save
redirect_to posts_path, :notice=>"success"
else
render "new"
end
end
This is simple, When you say:
redirect_to post_path
you need to pass ID, as the error indicates:
redirect_to post_path(#post)
alternatively follow convention:
redirect_to #post

Ruby On Rails Routing Error (was previously working)

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.

Resources