Routing error rails 3 - ruby-on-rails-3

I have a Rails 2.3.5 app with many controllers, models etc. which I'm trying to upgrade to Rails 3.2.21. I'm having some troubles with my routes. I tried to follow the Rails 3 new routing format but it doesn't seem to work. I'm getting two problems (which I guess all indicate one fundamental issue with my routing):
In the root ('/') I'm getting the generic "Welcome abroad" Rails
page. My routes (see below) have defined routing for root.
For some controllers I get No route matches [GET] "/study" message. My route shows this route, but for some reason doesn't define the GET method.
Here's my config/routes.rb code:
Myapp::Application.routes.draw do
root :to => 'study#index'
match 'login' => 'login', :protocol => 'https://'
resources :study_maps do
get :clone, :on => :member
end
# Route report create actions to the report controller
match 'report/create', :as => 'report'
match ':controller(/:action(/:id))(.:format)'
end
If I'm running rake routes I'm getting:
root / study#index
login /login(.:format) login#login {:protocol=>"https://"}
clone_study_map GET /study_maps/:id/clone(.:format) study_maps#clone
study_maps GET /study_maps(.:format) study_maps#index
POST /study_maps(.:format) study_maps#create
new_study_map GET /study_maps/new(.:format) study_maps#new
edit_study_map GET /study_maps/:id/edit(.:format) study_maps#edit
study_map GET /study_maps/:id(.:format) study_maps#show
PUT /study_maps/:id(.:format) study_maps#update
DELETE /study_maps/:id(.:format) study_maps#destroy
report /report/create(.:format) report#create
/:controller(/:action(/:id))(.:format) :controller#:action
Here's my StudyController#index code:
require 'myapp/studymgr'
require 'project_user'
require_dependency 'myapp/controller_extensions/report_manager'
class StudyController < ApplicationController
include PaginatorController
before_filter(:authenticate, :except => [:todo])
before_filter(:authorize,
:only => [:update, :destroy, :edit, :prune, :select_experiments ])
def index
#tags = Stag.find(:all).collect { |stag| stag.tag }
...
#include_ext = true
end
end
Can someone advise on what I'm missing?

Finally found a solution - my views had .rhtml extension. I found that this format is no longer supported under Rails 3 (What is the difference Between .erb , .rhtml and .html.erb?), so I changed all views extensions to .html.erb and then the routes worked with no need to specify explicit resource for each controller, just using the generic route: match ':controller(/:action(/:id))'.
As for the issue in the root route (#1 above), where I always got the Rails "Welcome abroad" page, despite having explicit route in my routes.rb, turns out I had to remove public/index.html which is loaded for root by Rails, and then my view was loaded.

Related

ruby on rails - routes error porting from 3.x to 4.x

i've started porting one of my apps from rails 3.x to rails 4.x....
when i start the app in development, i receive a route definition related error:
=> Booting WEBrick
=> Rails 4.2.5 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
Exiting
/home/francesco/.rvm/gems/ruby-2.2.2#Best-i-gest_v2/gems/actionpack-4.2.5/lib/action_dispatch/routing/route_set.rb:549:in `add_route': Invalid route name, already in use: 'app_settings' (ArgumentError)
You may have defined two routes with the same name using the `:as` option, or you may be overriding a route already defined by a resource with the same naming. For the latter, you can restrict the routes created with `resources` as explained here:
http://guides.rubyonrails.org/routing.html#restricting-the-routes-created
.....
here part of my routes.rb file containing the routes marked as double defined:
.....
get 'app_settings' => 'admin/app_settings#index', :as => 'app_settings'
put 'app_settings' => 'admin/app_settings#index', :as => 'app_settings'
post 'app_settings' => 'admin/app_settings#index', :as => 'app_settings'
post 'app_settings/upload' => 'admin/app_settings#upload_logo', :as => 'app_settings/upload'
.....
i've defined these routes because i'm going to manage all actions related to application setting using the 'index' action only (the app has a single db record storing all settings, this record is automatically created at the first time the user will load page, then updated when it saves) as you can see here:
# only one record here! it will store all the application settings
def index
# manages all the controller actions inside the index...
if request.get?
# this is a get request... returns the first settings record or a new one if none exists!
#app_settings = !AppSettings.all.first.nil? ? AppSettings.all.first : AppSettings.new
elsif request.post?
# this is a post request, the settings record will be created
#app_settings = AppSettings.new(params[:app_settings])
#app_settings.save
elsif request.put?
# this will update the existing app_settings record
#app_settings = AppSettings.find_by_id(params[:app_settings][:id].to_i)
#app_settings.update_attributes(params[:app_settings])
end
# renders the index page
render "index"
end
i'm looking for a way to correct the routes.rb file (keeping my controller and view as is!!) or an alternative way to manage this issue!!
waiting your suggestions,
many thanks in advance for your time,
francesco
Seems like you have way too much logic in one method. I'm fairly sure even in rails 3 that wasn't acceptable.
What about using rest route ( resources as described in the rails routing guide )
resources :app_settings, only: [:index, :update, :create]
This will create three routes for index (geT), update (patch), create (post).
Your controller will now look like this:
def index
#app_settings = !AppSettings.all.first.nil? ? AppSettings.all.first : AppSettings.new
end
def create
#app_settings = AppSettings.new(params[:app_settings])
#app_settings.save
end
def update
#app_settings = AppSettings.find_by_id(params[:app_settings][:id].to_i)
#app_settings.update_attributes(params[:app_settings])
end
There will also be no need to use render 'index' ... rails will automatically look for /app/app_settings/index.html.erb
ok guys,
i've solved...
many thanks to Alexandre and Ryan who guided me in solving this issue.....
well,
Alexandre sure you're right!! too much logic inside a single action so...
here is the new version of my files:
routes.rb:
....
post 'app_settings/upload' => 'admin/app_settings#upload_logo', :as => 'app_settings/upload'
# site admin area
namespace :admin do
resources :app_settings, only: [:index, :update, :create]
resources :users
......
end
.....
as you can see, i've inserted app_settings route inside the admin namespace ..
app_settings_controller.rb:
# app_settings security settings - used for declarative authorization
filter_access_to [:index, :create, :update], :require => :manage
filter_access_to :upload_logo, :require => :manage
# app_settings index method (this replaces the show method so all actions will be managed in the index view page)
def index
# this is a get request... returns the first settings record or a new one if none exists!
#app_settings = !AppSettings.first.nil? ? AppSettings.first : AppSettings.new(id: 1)
#app_settings.save
end
# app_settings create method
def create
# this is a post request, the settings record will be created
#app_settings = AppSettings.new(app_settings_params)
#app_settings.save
# renders the index page
render "index"
end
# app_settings update method
def update
# this will update the existing app_settings record
#app_settings = AppSettings.find_by_id(params[:app_settings][:id].to_i)
#app_settings.update_attributes(app_settings_params)
# renders the index page
render "index"
end
......
as you can see, i've implemented your solution keeping the index view as only view used by the app, just for not changing too much inside the app....
i've fixed the declarative_authorization section accordingly with the modifications you've suggested and simplified the creation of the new record as Ryan suggested but adding a little extra (i've specified the record id and then saved the record itself) all to prevent another issue in my view where the form_for is declared as follows:
<!-- application settings edit form -->
<%= form_for [:admin, #app_settings] do |app_sett| %>
.....
.....
<% end %>
so many thanks again to you all!!
hoping to continue learning from you all the times i read a page of this site!!
regards,
francesco

Devise routing, problems customising Devise routes

After customising Devise routes, I have some issues with the routing.
Currently setup (but failing):
/me/account loads Devise::Registration#edit form
/me/account/:what routes to account_controller#edit
My routes (shortcut):
devise_for :users do
...
end
devise_scope :user do
scope "/me/account" do
get "/" => "users/registrations#edit", :as => :my_account
get "/:what" => "accounts#edit", :as => :my_account_edit
end
end
resources :accounts, :only => [:edit, :update]
Rake routes output:
activate_account GET /reactivate(.:format) users#reactivate
my_account GET /me/account(.:format) users/registrations#edit
my_account_edit GET /me/account/:what(.:format) accounts#edit
cancel GET /me/account/cancel(.:format) users/registrations#cancel
DELETE /me/account(.:format) users/registrations#destroy
edit_account GET /accounts/:id/edit(.:format) accounts#edit
account PATCH /accounts/:id(.:format) accounts#update
PUT /accounts/:id(.:format) accounts#update
Account
Since /me/account is actually showing registrations#edit ( Devise ) and all the /me/account/helpme are custom form fields
This has issues:
No notices shown on /me/account on update or failure
On failure the form is not repopulated with earlier filled in form values
Its not updating the form
/me/account/helpme goes , on form submit , to /accounts/1 ( the current user id ) and throws error
No route matches {:action=>"edit", :controller=>"accounts", :id=>"1", :what=>nil} missing required keys: [:what]
These issues are totally driving me insane. Anyone can provide me some suggestions to fix (one or more ) of these routing issues?
About form submit error.
You need to override url in your form to submit to:
<%= form_for #resource, url: my_account_edit(what: params[:what]) do |f| %>
This should be done in your views or in devise-generated views.
If you didn't generated devise views, then, just run in terminal:
rails g devise:views
EDIT
And you should tell us how your form in views looks like, and how controller handles updates of custom fields.

Issue with nested resources in routing in Rails

I'm trying to set up a nested resource in my routes config but I just can't work out where the problem lies.
Here is the relevant code from my routes config
resources :positions, :only => [:new,:create,:edit,:update,:destroy]
resources :etkh_profiles, :path => "members", :only => [:new,:create,:show,:index] do
resources :positions
collection do
post 'search'
end
end
It works when I try '/positions/new' but when I try 'members/positions/new' I get this error
No route matches [GET] "/members/positions/new"
Any ideas?
Thanks for your help.
The URL you need to use is more like /members/:memberid/positions/new since you've specified that positions are contained inside an etkh_profile. You can check this by running rake routes.

Ruby on Rails 3 nested routes: wrong action route

I have two models: team and project
routes.rb
resources :teams do
resource :projects
end
And two questions!
1- According to http://guides.rubyonrails.org/routing.html, I expect to get teams/:team_id/projects/:id path. However, this is not the case.
rake routes
team_projects POST /teams/:team_id/projects(.:format) projects#create
new_team_projects GET /teams/:team_id/projects/new(.:format) projects#new
edit_team_projects GET /teams/:team_id/projects/edit(.:format) projects#edit
GET /teams/:team_id/projects(.:format) projects#show
PUT /teams/:team_id/projects(.:format) projects#update
DELETE /teams/:team_id/projects(.:format) projects#destroy
so I had to name route to get it working
match 'teams/:team_id/projects/:id' => 'projects#show', :via => [:get], :as => :show_project
so how can take advantage of rails helper methods instead of naming them?
2- In project show action view, the debugger throws these parameters for me:
action: show
controller: projects
team_id: '1'
which is fine. but when I click on "new_team_projects_path" url, it redirects me to the same view and the debugger throws these parameters:
controller: projects
action: show
team_id: '1'
id: new
It doesn't redirect me to the new action, but it took "new" as an ID! why?
You need to use
resources :teams do
resources :projects
end
Note the plural! resource produces a singular route without id.
won't be relevant anymore with the first fix.

Ruby on Rails Tutorial, Chapter 11, Exercise 7 - Breaks my rspec tests

I'm working through Michael Hartl's excellent tutorial on Rails, but I am having trouble with exercise 7 in Chapter 11.
This exercise is:
Add a nested route so that
/users/1/microposts shows all the
microposts for user 1. (You will also
have to add a Microposts controller
index action and corresponding view.)
I've done this successfully by changing my routes.rb file to read:
resources :users do
resources :microposts, :only => [:create, :destroy]
end
I am able to successfully call /users/1/microposts from a browser. However, most of the tests in microposts_controller_spec.rb are now broken. I receive the "no route matches" error when running autotest. For instance, the first test, which simply reads:
it "should deny access to 'create'" do
post :create
response.should redirect_to(signin_path)
end
now produces the following error:
1) MicropostsController access
control should deny access to 'create'
Failure/Error: post :create
No route matches {:controller=>"microposts",
:action=>"create"}
When I check rake routes
, I find this entry:
user_microposts POST /users/:user_id/microposts(.:format) {:action=>"create", :controller=>"microposts"}
which suggests the route does exist.
Has anyone else run into this issue while completing the tutorial? Is there a change I need to make in the spec file once I introduce nested routes? Does Rspec work with nested routes?
thanks
Because this is a nested route you will need to pass the user_id through:
some_user = way_of_creating_a_user_goes_here
post :create, :user_id => some_user.id
RSpec will attempt to go to the /microposts route without this parameter.