ActiveRecord RecordNotFound Error - ruby-on-rails

I created a CRUD using the scaffold .
rails g scaffold intermediate_level/memory_game
And then I created the method Play, but when I call the method play an error is returned.
http://localhost:3000/intermediate_level/memory_game/play?id=1
Couldn't find IntermediateLevel::MemoryGame with 'id'=play
# Use callbacks to share common setup or constraints between actions.
def set_intermediate_level_memory_game
#intermediate_level_memory_game = IntermediateLevel::MemoryGame.find(params[:id])
end
def play {
#intermediate_level_memory_game = IntermediateLevel::MemoryGame.find(params[:id])
}
My routes.file
namespace :intermediate_level do
resources :memory_game
get 'memory_game/play'
end

Your custom get 'memory_game/play should come before resources :memory_game. Rails evaluates routes in the order in which they are listed in the routes.rb file, with the routes closest to the top of the file receiving the highest priority.

With your given routes information:
namespace :intermediate_level do
resources :memory_game
get 'memory_game/play'
end
You have these two routes:
GET /intermediate_level/memory_game/:id(.:format) intermediate_level/memory_game#show
and
GET /intermediate_level/memory_game/play(.:format) intermediate_level/memory_game#play
When you make this request:
http://localhost:3000/intermediate_level/memory_game/play?id=1
it is matched by both of those routes and as you defined: resources :memory_game before get 'memory_game/play' in your routes.rb file, so the first one (GET /intermediate_level/memory_game/:id) comes into action as that has higher priority, (because Routes have priority defined by the order of appearance of the routes in the config/routes.rb file) and then it tries to find the memory game with id param which in that case is play but fails to do so (as you don't have any memory game where id=play) and fails with the error message:
Couldn't find IntermediateLevel::MemoryGame with 'id'=play
One quick way to get around this issue is to reorder your routes like this:
namespace :intermediate_level do
get 'memory_game/play'
resources :memory_game
end
Then, your request url http://localhost:3000/intermediate_level/memory_game/play?id=1 will be served by GET /intermediate_level/memory_game/play(.:format) intermediate_level/memory_game#play route which is what you want.

Related

Rails - using namespace controllers to organize files

I am trying to learn about namespacing.
I've asked a few questions on this topic previously, but I'm not understanding what is going on.
I have made a folder in my controller's folder called 'features'. In it, I have saved a file called app_roles_controller.rb.
The first line of that controller is:
class Features::AppRolesController < ApplicationController
The purpose of the features folder is so I can organise my files better (that's it).
In my routes.rb, I have tried:
resources :app_roles, :namespace => "features", :controller => "app_roles"
I have also tried:
namespace :features do
resources :app_roles
end
I have a model (top level) called app_role.rb and I have a views folder saved as views/features/app_roles which then has the index, show etc files in it. The table in my schema is called 'app_roles".
When I rake routes for app_roles, I get:
Paths Containing (app_role):
app_roles_path GET /app_roles(.:format)
app_roles#index {:namespace=>"features"}
POST /app_roles(.:format)
app_roles#create {:namespace=>"features"}
new_app_role_path GET /app_roles/new(.:format)
app_roles#new {:namespace=>"features"}
edit_app_role_path GET /app_roles/:id/edit(.:format)
app_roles#edit {:namespace=>"features"}
app_role_path GET /app_roles/:id(.:format)
app_roles#show {:namespace=>"features"}
PATCH /app_roles/:id(.:format)
app_roles#update {:namespace=>"features"}
PUT /app_roles/:id(.:format)
app_roles#update {:namespace=>"features"}
DELETE /app_roles/:id(.:format)
app_roles#destroy {:namespace=>"features"}
I can't understand what it is that I'm doing wrong.
When I try:
http://localhost:3000/app_roles#index
I get an error that says:
uninitialized constant AppRolesController
When I try:
http://localhost:3000/features/app_roles#index
I get an error that says:
No route matches [GET] "/features/app_roles"
I'm looking for a plain English explanation of how to set this up. I've tried the programming ruby book (several times over).
Please, can you help me understand what needs to happen to introduce organisational files in my rails app?
It looks like your other attempt was actually correct. As outlined in the Rails documentation, if you want to generate routes for the resource app_roles under the namespace features you can add the following to your routes.rb file:
namespace :features do
resources :app_roles
end
Now, you run rake routes you will see the following:
Prefix Verb URI Pattern Controller#Action
features_app_roles GET /features/app_roles(.:format) features/app_roles#index
POST /features/app_roles(.:format) features/app_roles#create
new_features_app_role GET /features/app_roles/new(.:format) features/app_roles#new
edit_features_app_role GET /features/app_roles/:id/edit(.:format) features/app_roles#edit
features_app_role GET /features/app_roles/:id(.:format) features/app_roles#show
PATCH /features/app_roles/:id(.:format) features/app_roles#update
PUT /features/app_roles/:id(.:format) features/app_roles#update
DELETE /features/app_roles/:id(.:format) features/app_roles#destroy
The first line for example means that if you make a GET request to /features/app_roles it will be routed to the index action in the features/app_roles controller.
In other words, if you visit http://localhost:3000/features/app_roles it will route the request to index action that is located in app/controllers/features/app_roles_controller.rb which it expects to have the class Features::AppRolesController.
So your app/controllers/features/app_roles_controller.rb file should look something like this:
class Features::AppRolesController < ApplicationController
def index
end
end

Why does order matter in Rails routes.rb when using resources?

I receive an error when my route is listed as such:
resources :coupons
get 'coupons/redeem_coupon', to: 'coupons#redeem_coupon', as: 'redeem_coupon'
The error is:
ActiveRecord::RecordNotFound - Couldn't find Coupon with 'id'=redeem_coupon:
When I reverse the order to:
get 'coupons/redeem_coupon', to: 'coupons#redeem_coupon', as: 'redeem_coupon'
resources :coupons
It works fine. I understand that resources creates these routes
GET /coupons
GET /coupons/new
POST /coupons
GET /coupons/:id
GET /coupons/:id/edit
PATCH/PUT /coupons/:id
DELETE /coupons/:id
Is listing my custom route first, more specific or overriding the other route? Why does the order matter?
The error you're getting is because rails tries to match routes starting from the top down. If you're trying to add a custom route to an existing resource, the easier way is to do this. collection is if you want to use it on the group, member is if you want to add a custom route to an individual resource.
resources :coupons do
collection do
get 'redeem_coupon'
end
end
By listing your custom route first, you are overriding the other route. When rails gets a request, it simply starts from the top of your routes.rb file and goes with whichever route matches first.

ActiveRecord::RecordNotFound in ContactsController#create Couldn't find Company without an ID error

When i try to submit at localhost:3000/companies/1/contacts/new i get the error Couldn't find Company without an ID https://gist.github.com/overhang/f8c20d2d2c851cdee7b1 any clue?
I reckon it might be a problem with routes.rb
Remove the following lines from routes.rb
# config/routes.rb
# get "companies/index"
# get "companies/new"
# get "companies/show"
# get "companies/create"
# get "companies/edit"
Notice that RESTful controller actions like edit and show require a specific Company passed in order for the correct company to be looked up. These get routes don't allow for that. Instead, you should be utilizing the resource routes you've already created:
# config/routes.rb
resources :companies
The non-resourceful routes are impeding the execution of the resourceful ones. Removing them should fix your problem.

Rails route parent ID name and CanCan issue

I'm trying to get a simple route working
/agenda_items/5/feed
To do this, I have the following route setup
resources :agenda_items do
member do
get "/feed", to: "comments#feed"
end
end
In each of my controllers, I'm using CanCan to handle the authentication and it works fine, however on this one action I'm having an issue, which I'm pretty sure is down to railsnaming generation. When I runrake routes`, the route above is produced as
feed_agenda_item /agenda_items/:id/feed(.:format) agenda_items/:id#feed
As far as I can tell, CanCan is expecting the :id parameter, to actually be :agenda_item_id so as a result, my parent resource isn't being loaded.
Is there any way I can get rails to change this so that CanCan will work without me having to manually load and authorize the resource, or is there a way I can get CanCan to change what it's looking for on certain actions?
The problem is that your routes are wrong. You try to create a member action for agenda items which routes to the comments controller. If you want a feed of all the commments from a single agenda item you should do something like this:
resources :agenda_items do
resources :comments do
collection do
get :feed
end
end
end
You should now get the following when running rake routes:
feed_agenda_item_comments /agenda_items/:agenda_item_id/feed(.:format) comments#feed

Can't find a row in my table sqlite3 table

I'm trying to set up a simple edit feature for an object in one of my tables. Here is my current code which I've seen online and in books but it doesn't work
def edit
#fire_chief = FireChief.find(params[:id])
end
All I have to do is figure out how to edit a specific Fire Chief in list view and I can keep programming, but I'm stuck.
The error I'm recieving is "Couldn't find FireChief without an ID"
If I use this little snippet of code it finds the edit form fine
def edit
#fire_chief = FireChief.last
end
But it always pulls up the last entry to be edited. I need it to pull the entry that i click...might be the 1st, 3rd, or 5th, etc. I know a lot of this is redundant, but I just want to be clear on what I'm trying to do.
This is my routes file:
resource :timesheet do
resource :command_officer
resources :fire_chief
resources :fire_fighters
resource :safety_officer
resources :emts
resources :hazmat_specialists
resources :command_vehicles
resources :engines
resources :emergency_supports
resources :hazmat_units
resources :field_units
resources :pumpers
resources :tankers
resources :rescue_units
end
end
I just changed the resource :fire_chief to be plural, so now its this resources :fire_chief
But I'm getting this error now:
Routing Error
uninitialized constant FireChiefController
To get an id or any other data you need from params you have to pass the data inside the url like this example:
/firechief/2/edit
This way your edit method will know the id and the method will work. You can set this manually inside your routes, making a route like this:
get "/firechief/:firechief_id/edit" => "firechiefs#edit", as => :edit_firechief
Or if you are using resources inside your routes, it shall work by default.
If you actually does not want to pass any data inside your url, you could implement a session based solution. Create a method to store the id of the firechief inside a controller that fits your needs, or just add this line if you want to create the session inside a method (like firechief#create) you already has:
session[:firechief] = #here you add the id of the firechief you want to store
Now on your controller you can do this:
def edit
#fire_chief = FireChief.find(session[:firechief])
end

Resources