My routes has resources :home, but rspec is saying routes not defined? - ruby-on-rails

My homecontroller has:
def about()
end
And I have a rspec test that does GET 'about' and it fails saying that there is no route that matches.
doesn't this map all actions in the controller:
resources :home
or do I have to explicitly state each action in the home controller?

resources :home sets up the default RESTful routes - index, show, new, create, edit, update, and destroy. Any additional routes have to be specified. It looks like you're adding a simple collection route, so you'd specify it like this:
resources :home
collection do
get 'about'
end
end
This will give your the route '/home/about'. I assume this is Rails 3. If you're in Rails 2.x, do it like so:
map.resources :home, :collection => {:about => :get}
And from the command line, you can always see what routes you have available with this command:
rake routes
I hope this helps!
EDIT: If you want a default route, you can add this:
match ':controller(/:action(/:id))'
This is a default route that will match any generic requests.
FULL ARTICLE: Routing in Rails 3 is its own beast. There have been a lot of questions about it lately, so I've created a very detailed article with code samples to help others:
Routing in Ruby on Rails 3
I created a companion Rails 3 app that can be downloaded to play around with, as well:
https://github.com/kconrails/rails3_routing
If you have any questions, please hit up my site and ask. Thanks!

resources will give you the 7 CRUD methods for a controller, if you want additional actions, you need to do something like the following:
resources :homes do
collection do
match "about" => "homes#about", :as => "about"
end
end
Then you'll also have an additional about_homes_path/url helper available.

Related

Having difficulty defining Rails route

I'm new to rails and I'm trying to create a new route to perform an action.
Currently I have the following defined in my routes
match 'books/scrape_data' => 'books#scrape_data', :via => :get
and the following action
def scrape_data
#books = Book.all
#books.each do |book|
# do stuff
end
redirect_to :action => 'list'
end
But the route seems to go to the show action with :id 'scrape_data'.
Can anyone point my in the right direction?
It sounds like you must also have a route definition such as resources :books that appears before the route you listed in your question. Since routes are parsed top-down, the books#show route is intercepting your route and bucketing scrape_data into the id. Run bundle exec rake routes to see the order of the routes defined.
The easy fix is to move your route up above resources :books. But it'd actually be more correct to get rid of your custom route and add it to the resources block like this:
resources :books do
get 'scrape_data', on: :collection
end
After this, do another bundle exec rake routes and see if that's what you wanted.
Excuse the "answer", but I don't have the rep to comment.
My go to resource for all things routing related is Routing from the outside in
Run bundle exec rake routes to see your routes and how they're nested. Then you'll see whether your params are matching up (common mistake with nested routes).
You can also view all of your routes by going to:
http://localhost:3000/rails/info/routes
which can be pretty helpful instead of having to kill your server and use the console.

In RoR, do I have to specify every controller method as a route by hand?

What I'm wondering, in this case where I want to create a few web service type controllers, is if there is a way to "export" what method is allowed to be called from the controller. I'm still very new to RoR, and its routes feature, but in the end, is it expected that a fully functional RoR application just has hundreds of routes? Not every controller method I'm creating falls into a "resource" category.
Rails routes come in several varieties – RESTful routes are merely the ones that happen to provide native support for Rails resources. Remember that event resource routes can be modified to have member and collection routes:
# routes.rb
resources :products do
member do
get 'short' #=> products/:product_id/short/:id
post 'toggle' #=> products/:product_id/toggle/:id
end
collection do
get 'sold' #=> products/sold
end
end
You can also nest resource routes within other resource routes:
# routes.rb
resources :products do
resources :comments #=> RESTful routes patterned as products/:product_id/comments/:id/:action
resources :sales do
get 'recent', :on => :collection
end
end
Another handy feature is named routing. The following route is not resourceful:
# routes.rb
match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase # Creates route path akin to purchase_path(:id)
Namespaced routes can be very helpful for organization and readability:
# routes.rb
namespace :admin do
resources :products #=> RESTful routes patterned as admin/products/:product_id/:action
end
So, basically, there's a route for everything you want to do, whether it's RESTful/resourceful or not. But yes, you need to write a route for every action you want exposed to your app.
Using the routes.rb file, you can create routes or pattern matching for routes, as well as parameterized routes, and nested routes. You should read more about this here.
You can also give routes their own method name such as my_new_route_path. If you really wanted to, you could just hardcode routes into your HTML. Please don't do this.
Every controller action needs routes that map to it.

Rails activation route

I am learning rails and routing has me wanting to jump off the roof.
I am confused on how to go about routing my activation at this point.
I have the following currently in my user routing:
resources :users, only: [:new,:create,:show]. Now I want a route to Users#activate like this www.app.com/users/activate/:a_long_token. Now I know I can just simply do a match '/activate/:auth_token', to: 'users#activate but I am not sure whether this is convention. I was reading this guide on user authentication but it seems its routing is rails 2. Can I do something to add the route mentioned above by simply adding something to the resource itself. By that I mean doing something like (I know this won't work)
resource :users do
member do
get :activate
end
end
rails3 guide
http://guides.rubyonrails.org/
http://guides.rubyonrails.org/routing.html
resources :users do
collection do
get "activate/:a_long_token" => "users#activate", as: :activate
end
end
rake routes outputs this
activate_users GET /users/activate/:a_long_token(.:format) users#activate

Custom actions in rails controller with restful actions?

I'm having some trouble with using creating my own actions inside a controller I generated using the scaffold.
I understand everything maps to the restful actions but I'm building a user controller where users can login/logout, etc but when I created the action and declared it in the routes.rb I get this error when I visit users/login
Couldn't find User with id=login
It tries to use login as a ID parameter instead of using it as an action.
Routes.rb
match 'users/login' => 'users#login'
I think I'm doing something wrong with the routes so if anybody could help me that would be great.
Thanks
I assume your routes.rb looks like this:
resources :users
match 'users/login' => 'users#login'
The problem is that Rails uses the first route that matches. From the documentation:
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.
So either define your custom route before resources :users:
match 'users/login' => 'users#login'
resources :users
…or use this syntax for adding more RESTful actions:
resources :users do
collection do
match 'login'
end
end
To see the existing routes (and their order) run rake routes from the command line.

How do you check the URL Helpers for a Model Resource in Rails?

I'm currently following the Shovell tutorial in the Simply Rails 2 book. On page 168, it mentions URL Helpers for the Story Resource:
stories_path /stories
new_story_path /stories/new
story_path(#story) /stories/1
edit_story_path(#story) /stories/1/edit
The above is then used in the controller:
def create
#story = Story.new(params[:story])
#story.save
redirect_to stories_path
end
My routes.rb:
ActionController::Routing::Routes.draw do |map|
map.resources :stories
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
It looks like stories_path is the url name to /stories. Is that explicitly defined somewhere within my app, I can't seem to grep for that keyword. If not, is there a way that I can check the mapping above from the Rails console or somewhere else? In Django, url names are usually explicitly defined in urls.py, I just can't figure out how the above is being generated. Any documentation and pointers will help.
To get a list of the mapped routes:
rake routes
What map.resources :stories is doing is mapping your RESTful actions (index, show, edit etc.) from the stories_controller.rb to named routes that you can then use for simplicity.
routes.rb includes helpful tips on defining custom routes and it may be worth spending a little bit of time looking at resources in the API to get a better understanding:
http://api.rubyonrails.org/classes/ActionController/Resources.html#M000522
I think checking out the Rails Guides on Routing will help you a lot to understand what's going on
In short, by using the
map.resources :stories
the Router will automatically generate some useful (and RESTful) routes. Their path will take the model name (remember in Rails there is the Convention over Configuration motto), and, by default, will generate routes for all the REST actions.
This routes are available through your controller, views, etc.
If you want to check out which routes are generated from your mappings, you can use the "rake routes" command.
Now, given that, you can also write explicit URLs on your routes.rb file for actions or events that don't quite comply with the REST paradigm.
For that, you can use
map.connect "/some_kind_of_address", :controller => :pages, :action => "something_else"
Or
map.home "/home", :controller => :pages, :action => "home"
The last one will gave you both home_path and home_url routes you can use in your code.

Resources