Rails route disambiguation - ruby-on-rails

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?

Related

NoMethodError (undefined method `product_url'

I have the following error when debugging my first project on rails:
NoMethodError (undefined method `product_url' for #
Did you mean? products_url):
app/controllers/products_controller.rb:13:in `create'
class ProductsController < ApplicationController
def show
#product = Product.find(params[:id])
end
def new
end
def create
#product = Product.new(product_params)
#product.save
redirect_to #product
end
private
def product_params
params.require(:product).permit(:title, :price, :count)
end
end
----------config/routes.rb------
Rails.application.routes.draw do
get 'welcome/index'
resource :products
root 'welcome#index'
end
----------rake routes----------
Prefix Verb URI Pattern Controller#Action
welcome_index GET /welcome/index(.:format) welcome#index
new_products GET /products/new(.:format) products#new
edit_products GET /products/edit(.:format) products#edit
products GET /products(.:format) products#show
PATCH /products(.:format) products#update
PUT /products(.:format) products#update
DELETE /products(.:format) products#destroy
POST /products(.:format)
You need to initialise #product. It can be done like:
before_action :set_document, only: [:show, :edit, :update, :destroy]
def set_document
#document = Document.find(params[:id])
end
You can scaffold the Controller with
rails g scaffold_controller Document
to see exactly how rails is generating classes for a model.
In your routes.rb it should be
resources: products

ActiveRecord::RecordNotFound in Api::V1::PostsController#show

I am trying to follow Rails Todo API Part 1 from egghead.io https://egghead.io/lessons/angularjs-rails-todo-api-part-1
I am trying to access localhost:3000/api/v1/posts and the page should show the json response of:
[]
but instead I get the error:
ActiveRecord::RecordNotFound in Api::V1::PostsController#show
Couldn't find Post without an ID
def show
respond_with(Post.find(params[:id])) <----- error is here
end
I also tried adding a record which should return the json response of that record but I get the same error. What am I doing wrong?
I have completed the controller and routes as follows:
app/controllers/api/v1/posts_controller.rb
module Api
module V1
class PostsController < ApplicationController
skip_before_filter :verify_authenticity_token
respond_to :json
def index
respond_with(Post.all.order("id DESC"))
end
def show
respond_with(Post.find(params[:id]))
end
def create
#post = Post.new(post_params)
if #post.save
respond_to do |format|
format.json {render :json => #post}
end
end
end
def update
#post = Post.find(params[:id])
if #post.update(post_params)
respond_to do |format|
format.json {render :json => #post}
end
end
end
def destroy
respond_with Post.destroy(params[:id])
end
private
def post_params
params.require(:post).permit(:content)
end
end
end
end
config/routes.rb
WhatRattlesMyCage::Application.routes.draw do
namespace :api, defaults: {format: :json} do
namespace :v1 do
resource :posts
end
end
end
rake routes:
Prefix Verb URI Pattern Controller#Action
api_v1_posts POST /api/v1/posts(.:format) api/v1/posts#create {:format=>:json}
new_api_v1_posts GET /api/v1/posts/new(.:format) api/v1/posts#new {:format=>:json}
edit_api_v1_posts GET /api/v1/posts/edit(.:format) api/v1/posts#edit {:format=>:json}
GET /api/v1/posts(.:format) api/v1/posts#show {:format=>:json}
PATCH /api/v1/posts(.:format) api/v1/posts#update {:format=>:json}
PUT /api/v1/posts(.:format) api/v1/posts#update {:format=>:json}
DELETE /api/v1/posts(.:format) api/v1/posts#destroy {:format=>:json}
Make it resources :posts in your routes.rb
As it is you have malformed routes and the show method is being called instead of the index method

Why do I need to specify :location=>some_url(#object) in respond_with in the case of POST

I am implementing a RESTful API using RoR. Here my UsersController:
class ApplicationController < ActionController::API
[...]
end
module Api
module V1
class UsersController < ApplicationController
respond_to :json
def create
#user = User.new(user_params)
#user.save
respond_with #user, :location => api_v1_user_url(#user)
end
def show
#user = User.find(params[:id])
respond_with #user
end
end
end
end
If I omit the #user param from :location => api_v1_user_url(#user) in UsersController#create i.e. I have it like so:
respond_with #user, :location => api_v1_user_url
I get the following error:
ActionController::UrlGenerationError in Api::V1::UsersController#create
No route matches {:action=>"show", :controller=>"api/v1/users", :format=>"json"} missing required keys: [:id]
I just added the #user param to api_v1_user_url on a hunch after I saw this error and it works.
My question is what is going on here? I do not understand why I need to pass #user when most of the examples I've seen do not involve passing the object #user to the :location attribute.
The output of rake routes is a follows:
$ rake routes
Ignoring bcrypt-3.1.7 because its extensions are not built. Try: gem pristine bcrypt-3.1.7
Prefix Verb URI Pattern Controller#Action
api_v1_users GET /api/v1/users(.:format) api/v1/users#index {:format=>"json"}
POST /api/v1/users(.:format) api/v1/users#create {:format=>"json"}
new_api_v1_user GET /api/v1/users/new(.:format) api/v1/users#new {:format=>"json"}
edit_api_v1_user GET /api/v1/users/:id/edit(.:format) api/v1/users#edit {:format=>"json"}
api_v1_user GET /api/v1/users/:id(.:format) api/v1/users#show {:format=>"json"}
PATCH /api/v1/users/:id(.:format) api/v1/users#update {:format=>"json"}
PUT /api/v1/users/:id(.:format) api/v1/users#update {:format=>"json"}
DELETE /api/v1/users/:id(.:format) api/v1/users#destroy {:format=>"json"}
static_index GET /static/index(.:format) static#index
root GET / static#index
Another place I've seen this (just to name another one):
Embracing REST with mind, body and soul
The reason being is that api_v1_user_url or api_v1_user_path are for a single instance and you need to pass the id of that user it should look for and render. Hence why you got the error you go.
In the examples you probably saw api_v1_users_url or api_v1_users_path which renders all the users. Notice the users_ vs user_

no route matches - rails 4.0

I have a route set up as such:
get 'password reset' => 'password_resets#edit', :as => 'password_reset'
resources :password_resets
I have a controller as such:
class PasswordResetsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email])
if user
user.send_password_reset
redirect_to root_url, :notice => 'Email has been sent. Please follow instructions to reset your password.'
else
redirect_to password_resets_path
flash[:error] = 'Sorry but we do not know that email.'
end
end
def edit
#user = User.find_by_password_reset_token!(params[:id])
end
end
I then sent an email off and used letter_opener to view its contents in browser:
No route matches {:controller=>"password_resets", :action=>"edit", :format=>"lYoa1Rh6yfwL2olfwkODnQ"} missing required keys: [:id]
I then did rake routes
password_resets GET /password_resets(.:format) password_resets#index
POST /password_resets(.:format) password_resets#create
new_password_reset GET /password_resets/new(.:format) password_resets#new
edit_password_reset GET /password_resets/:id/edit(.:format) password_resets#edit
GET /password_resets/:id(.:format) password_resets#show
PATCH /password_resets/:id(.:format) password_resets#update
PUT /password_resets/:id(.:format) password_resets#update
DELETE /password_resets/:id(.:format) password_resets#destroy
Why am I getting this error? all my mailer tests are passing ... but trying this in browser means that eaither my mailer tests are lying or something is wrong.
If I try doing a link like:
link_to "Some where", edit_password_reset_url(#user.password_reset_token)
The browser works but the tests fail ... with the same error message.
try
link_to "Some where", edit_password_reset_url(id: #user.password_reset_token)
If user.password_reset_token = lYoa1Rh6yfwL2olfwkODnQ
You should send ID of this password table to the edit action.

Routing error in Rails 3.1

I am certainly losing my head/sleep over this.
This is my questions_controller.rb
class QuestionsController < ApplicationController
# GET /questions
# GET /questions.json
def index
#questions = Question.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #questions }
end
end
This is my applications_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
end
This is my rake routes:
questions GET /questions(.:format) questions#index
POST /questions(.:format) questions#create
new_question GET /questions/new(.:format) questions#new
edit_question GET /questions/:id/edit(.:format) questions#edit
question GET /questions/:id(.:format) questions#show
PUT /questions/:id(.:format) questions#update
DELETE /questions/:id(.:format) questions#destroy
home_index GET /home/index(.:format) home#index
This is my routes.rb
App::Application.routes.draw do
resources :questions
end
Error on going to http://0.0.0.0:3000/questions
uninitialized constant QuestionsController
What might be the error?
This kind of errors sometimes happen when there is a syntax error in one of files. Restart your dev server and look up for errors in its output.
Especially check line
format.html # index.html.erb
I don't think it can be written this way.
Can you make sure the controller filename is in correctly plural form?
app/controllers/questions_controller.rb
Thanks.

Resources