Rails Custom Route Gets Confused on :id - ruby-on-rails

I am trying to setup a custom route. However whenever I hit the beverage_locations/new page, it tries to send 'new' in the url as the :location_id in the index path.
route.rb
controller 'beverage_locations' do
get 'beverage_locations/:location_id' => 'beverage_locations#index'
get 'beverage_locations/new' => 'beverage_locations#new'
end
error
ActiveRecord::RecordNotFound in BeverageLocationsController#index
Couldn't find Location with id=new
any idea how to fix this?
Thanks!

Rails routes are matched in the order they are specified, so if you
have a resources :photos above a get 'photos/poll' the show action’s
route for the resources line will be matched before the get line. To
fix this, move the get line above the resources line so that it is
matched first.
From http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions
A demo:
# beverage_locations_controller.rb
class BeverageLocationsController < ApplicationController
def index
render :text => params[:location_id]
end
def new
render :text => 'New method'
end
end
# config/routes.rb
Forfun::Application.routes.draw do
controller 'beverage_locations' do
get 'beverage_locations/new' => 'beverage_locations#new'
get 'beverage_locations/:location_id' => 'beverage_locations#index'
end
end
# http://localhost:3000/beverage_locations/1234 => 1234
# http://localhost:3000/beverage_locations/new => New method

You need to swap the order of the routes so that the new action has preference:
controller 'beverage_locations' do
get 'beverage_locations/new' => 'beverage_locations#new'
get 'beverage_locations/:location_id' => 'beverage_locations#index'
end

Related

Rails: Have I over-engineered this quiz and results page?

Recently I've been trying to get a quiz page directing to a results page (and, with thanks to StanBoyet, I think I've finally managed it).
I have a User model and controller, and log in (using Devise) is all working fine. I have a QuizAnswers model and controller and all the tables present on the database. I also have a ResultsController.
Here is my routes.rb (note the resources):
Rails.application.routes.draw do
devise_for :users
root :to => 'home#index'
get "elearning" => "home#elearning"
get "howitworks" => "home#howitworks"
get "leadershipstyles" => "home#leadershipstyles"
get "whattypeofleader" => "quizzes#new"
get "showmetheskills" => "home#showmetheskills"
get "safeguarding" => "home#safeguarding"
get "toolsforthejob" => "home#toolsforthejob"
get "whatnext" => "home#whatnext"
get "congratulations" => "home#congratulations"
get "teamwork" => "home#teamwork"
get "facilitation" => "home#facilitation"
get "planning" => "home#planning"
get "communication" => "home#communication"
resources :quizzes
resources :results
resources :quiz_answers
resources :users do
resources :posts
end
end
In my quiz form, I pass form_for #quiz_answers (made accessible by the QuizAnswers#new action):
def new
#user = current_user
#quiz_answer = current_user.quiz_answers.build
end
(I have also tried, as an alternative, #quiz_answer = QuizAnswer.new)
When I click submit, the QuizAnswers#create action is triggered, which looks like this:
def create
redirect_to results_path
end
Which (rake routes tells me) points to results#index (ResultsController#index action) which I have set up like this:
def index
# in order to access all the results in our view...
#results = QuizAnswer.find(current_user.id)
end
When I click submit though, I'm getting the error:
Couldn't find QuizAnswer with 'id'=35
I have two questions:
How do I set up my new QuizAnswers with a reference to the id of the current_user? (QuizAnswers has a user_id attribute, as well as the usual id attribute).
Secondly, is this all horribly over-engineered or is this just 'the Rails way'? (If I'm doing it wrong, feel free to explain how I should do it 'right').
This line is very strange:
#results = QuizAnswer.find(current_user.id)
You need to change it to
#results = QuizAnswer.where(user_id: current_user.id)
#or
#results = current_user.quiz_answers

Ruby on Rails: /articles/:id not matching /articles/1

I'm brand new to Ruby on Rails, and am working through the tutorial http://edgeguides.rubyonrails.org/getting_started.html
I started by setting up an 'articles' route, and have the following routes when running 'rake routes':
'article GET /articles/:id (.:format) articles#show'
So, I see that there is a path, /articles/:id, which should map to articles#show. however, when I hit the url: /articles/1, I get the following error:
"Unknown action
the action '1' could not be found in the ArticlesController"
I'm just not at all sure whats happening here. Show is defined in my articles_controller.rb:
class ArticlesController < ApplicationController
def new
end
def create
#article = Article.new(params[:article])
#article.save
redirect_to #article
end
def show
#article = Article.find(params[:id])
end
def index
#articles = Article.all
end
private
def article_params
params.require(:article).permit(:title,:text)
end
end
anyone have ideas?
Update: added Routes.rb
RailsStarter::Application.routes.draw do
# The priority is based upon order of creation:
# first created -> highest priority.
# Sample of regular route:
# match 'products/:id' => 'catalog#view'
# Keep in mind you can assign values other than :controller and :action
# Sample of named route:
# match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
# This route can be invoked with purchase_url(:id => product.id)
get ':controller(/:action(/:id))'
root :to => 'say#hello'
# Sample resource route (maps HTTP verbs to controller actions automatically):
resources :articles
end
Remove the get ':controller(/:action(/:id))' from the routes.rb file
You should probably remove (or update) the root route as well, as say#hello is from the intro lesson.

Rails path gives me no route matches, but I don't understand why

so I have a very simple I think layout. My config routes is:
resources :webcomics
match '/webcomics/first' => 'webcomics#first', :as => :first
match '/webcomics/random' => 'webcomics#random', :as => :random
match '/webcomics/latest' => 'webcomics#latest', :as => :latest
Controller:
def show
#webcomic = Webcomic.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #webcomic }
end
end
def first
#webcomic = Webcomic.order("created_at ASC").first
respond_to do |format|
format.html { render 'show'}
format.json { render json: #webcomic }
end
end
navigation bar:
<%= link_to first_webcomics_path, :rel => "tooltip", :title => "first comic" do %>
formatting in here
<% end %>
when I click on this link, it sends me to the right path /webcomics/first, BUT it gives me the error
Routing Error
No route matches {:action=>"edit", :controller=>"webcomics"}
I am breaking my head how is it going to 'EDIT', and no matter this message is totally wrong, I do have edit, but why does it try to go to action edit.
def edit
#webcomic = Webcomic.find(params[:id])
end
Results of rake routes:
first_webcomics GET /webcomics/first(.:format) webcomics#first
latest_webcomics GET /webcomics/latest(.:format) webcomics#latest
random_webcomics GET /webcomics/random(.:format) webcomics#random
webcomics GET /webcomics(.:format) webcomics#index
POST /webcomics(.:format) webcomics#create
new_webcomic GET /webcomics/new(.:format) webcomics#new
edit_webcomic GET /webcomics/:id/edit(.:format) webcomics#edit
webcomic GET /webcomics/:id(.:format) webcomics#show
PUT /webcomics/:id(.:format) webcomics#update
DELETE /webcomics/:id(.:format) webcomics#destroy
root / webcomics#index
Routing is in order; put the matches above the resources.
That said, I'd consider adding those routes as RESTful actions instead:
resources :webcomics
collection do
get 'first'
get 'random'
get 'latest'
end
end
IMO this is a bit cleaner, and happens to fit reasonably well.
The issue is because of your edit link in the show template. Edit links require an object to
edit:
<%= link_to "edit", edit_webcomic_path(#webcomic) %>
Put those three match rules above the resources line like that:
match '/webcomics/first' => 'webcomics#first', :as => :first
match '/webcomics/random' => 'webcomics#random', :as => :random
match '/webcomics/latest' => 'webcomics#latest', :as => :latest
resources :webcomics
The reason is explained in Ruby Guides: Routing:
Rails routes are matched in the order they are specified, so if you
have a resources :photos above a get 'photos/poll' the show action’s
route for the resources line will be matched before the get line. To
fix this, move the get line above the resources line so that it is
matched first.

How do I add a route which maps to a slug url generated by the stringex gem in ruby on rails 3.1?

It seems simple, in my model I have:
class CustomerAccount < ActiveRecord::Base
acts_as_url :name
def to_param
url # or whatever you set :url_attribute to
end
end
And in my controller, I have:
class CustomerAccountsController < ApplicationController
def show # dashboard for account, set as current account
#account = CustomerAccount.find_by_url params[:id]
no_permission_redirect if !#account.has_valid_user?(current_user)
set_current_account(#account)
#latest_contacts = Contact.latest_contacts(current_account)
end
end
What's currently in the routes.rb is:
resources :customer_accounts, :path => :customer_accounts.url do
member do
get 'disabled'
post 'update_billing'
end
end
That gives me the following error when I try to generate data via rake db:seed, or at least I assume the entry in routes is what's doing it.
undefined method `url' for :customer_accounts:Symbol
So what do I need to do to get the route set up? What I'd like is http://0.0.0.0/customeraccountname to map to the view for the customer account page.
UPDATE:
Here is the code that ended up working in routes.rb, which I discovered after looking at the examples in the answer below:
resources :customer_accounts, :path => '/:id' do
root :action => "show"
member do
get 'disabled'
post 'update_billing'
end
end
If you want to set it up so you have a route like you show, do this:
get '/:id', :to => "customer_accounts#show"
If you want the disabled and update_billing actions underneath this:
get '/:id/disabled', :to => "customer_accounts#disabled"
post '/:id/update_billing', :to => "customer_accounts#update_billing"
Alternatively (and much neater):
scope '/:id' do
controller "customer_accounts" do
root :action => "show"
get 'disabled'
get 'update_billing'
end
end

Rails 3 add GET action to RESTful controller

I have a controller with the 7 RESTful actions plus an additional 'current' action, which returns the first active foo record:
class FooController < ApplicationController
def current
#user = User.find(params[:user_id])
#foo = #user.foos.where(:active => true).first
#use the Show View
respond_to do |format|
format.html { render :template => '/foos/show' }
end
end
#RESTful actions
...
end
The Foo Model :belongs_to the User Model and the User Model :has_many Foos.
If I structure the routes as such:
resources :users do
resources :foos do
member do
get :current
end
end
end
The resulting route is '/users/:user_id/foos/:id'. I don't want to specify the foo :id, obviously.
I've also tried:
map.current_user_foo '/users/:user_id/current_foo', :controller => 'foos', :action => 'current'
resources :users do
resources :foos
end
The resulting route is more like I would expect: '/users/:user_id/current_foo'.
When I try to use this route, I get an error that reads:
ActiveRecord::RecordNotFound in FoosController#current
Couldn't find Foo without an ID
edit
When I move the current action to the application controller, everything works as expected. The named route must be conflicting with the resource routing.
/edit
What am I missing? Is there a better approach for the routing?
I think you want to define current on the collection, not the member (the member is what is adding the :id).
try this.
resources :users do
resources :foos do
collection do
get :current
end
end
end
Which should give you a route like this:
current_user_foos GET /users/:user_id/foos/current(.:format) {:controller=>"foos", :action=>"current"}
Also map isn't used anymore in the RC, it will give you a deprecation warning.

Resources