Rails 3 Routing Question - ruby-on-rails

Why in Rails 3 do you have to uncomment match ':controller(/:action(/:id(.:format)))' (as seen in this Hello World article) to make the index method of the hello controller be called when you go to http://localhost:3000/hello? Can somebody please explain why we have to do this in Rails 3 but not Rails 2, and is this a normal thing for Rails 3 or is it some kind of hack?

That particular match is sort of a catch-all for any requests that haven't already been defined.
Ideally you should be using Resource Routing, but that matcher still exists as legacy support.
It's commented out by default because Rails assumes that if a user attempts to access a route that you didn't explicitly define, it should cause a 404 error instead of a 500 error, which is what would happen if I tried to access http://localhost:3000/hello with that matcher enabled, because there's no 'hello' controller.

Related

Rails Tutorial- cannot get rails to recognize route

I am new to programming in general, someone referred me to railstutorial.org.
Specs: I am working on a cloud9 IDE, as suggested in the tutorial.
Information: I am on 1.3 of the rails tutorial, which is setting the root route.
The problem was initially my route did not effect the server launch (root page was still ruby default, not to 'application#hello'). Here are the files that the tutorial said to edit.
routes.rb
Rails.application.routes.draw do
root to: 'application#hello'
end
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
def hello
render text: "Hello, world!"
end
end
There are a lot of comments that were defaulted into the files that I left out.
I have followed the instructions precisely. After I first had trouble, I thought I may have made an installation error, so I deleted my IDE and restarted, paying extreme attention to detail, especially versions.
I have tried $ rake routes, and my understanding it gives the message:
You don't have any routes defined!
That leads me to believe that the problem is the routes.rb file. I have tried changing the syntax to:
root to: 'application#hello'
I don't know a whole lot, such as how it would work using application, so I also tried:
root 'ApplicationController#hello'
and
root to: 'ApplicationController#hello'
These all result in the no routes defined message. I have no idea what is going on.
Thanks for any input or help!
You could try root 'application#hello' in your routes. Also, when starting out simple things like forgetting to save the file before trying things out on the browser can slip by; restarting the server takes care of a surprising number of foibles.
The rails documentation can also provide you a bit more information beyond the tutorial.
You probably want to move that action outside of the ApplicationController to another controller, but if you really insist, you can put this into your routes.rb:
get '/hello', to: 'application#hello', as: :hello
If you want the page to be the root, I would recommend creating a StaticPagesController and defining hello there, instead of putting it inside ApplicationController.
Here's what you can do:
Run rails g controller static_pages
Inside your StaticPagesController.rb, copy and paste your hello method that was inside ApplicationController.
Change the routes.rb to root 'static_pages#hello.
and you should have your desired result.
I've followed the same tutorial and I can say that the materials covered in the first two chapters are quite complicated at first if you are new to programming. It's only after you've done the entire tutorial that it will become clear to you how this routing thing (or any other details in these chapters for that matter) actually works.
However, since this idea of routing is very important, it's not a bad idea to understand how it works even if you are at an early stage in the tutorial.
The way you can create a route in rails is that you first specify a proper HTTP verb (GET, POST, PATCH, DELETE) with an appropriate path, the name of a controller, followed by a hash sign (#) and the name of an action defined in the controller.
Here controller is just a ruby class and an action a ruby method. (Since the basic principle of ruby on rails is "convention over configuration", it's important to get used to the terminology like controller, action, routing etc...)
When you say
get '/hello' => "application#hello"
(yes, you can use => in place of to:) as takeriho suggests, what happens is that a GET request to a URL of the type /hello(/ being "root path" as in www.example.com/(note the / at the end)) will get routed to the action, or method, named hello defined in a controller, or a class, named ApplicationController.
If you take a look at application_controller.rb, you can see that a method hello is defined within a class ApplicationController.
class ApplicationController < ActionController::Base
.....
def hello
render text: "Hello, world!"
end
end
Now if you want to specify a root route, which is your original question, you can just do root followed by the name of a controller, a hash sign (#), and the name of a class. So the code
root "application#hello"
means that a request to a url of the form /, or a root_path as it's called in rails convention, will get routed to the action (or method) named hello defined in a controller (or a class) named ApplicationController. You could accomplish the same result by doing
get '/' => "application#hello", as: :root
(you can name a route by adding as: :custom_name) but rails is smart enough to know that the two are equivalent. The task is made easier by following the rails conventions.
If you are completely new to Rails, I highly suggest you check out the Rails courses in Pragmatic Studio before going through the Ruby on Rails Tutorial which, as the author suggests, is not for a complete beginner. This approach worked perfectly for me. The rails courses offered by Pragmatic Studio assumes you have no prior knowledge about programming, and explains the basics in a manner much clearer than I did in this answer.
Happy coding :)

How to namespace routes in Rails 4 to set up Forem?

I've been trying to set up Forem (a Rails 4 forum engine) using a guide and original docs.
Most things work, but I'm getting route errors. In my application.erb I have this route in a link_to:
topic_path(u)
The guide recommends that I preface this with my application name so my routes won't conflict with Forem's routes, so I did that as so:
H2le.topic_path(u)
(H2le is the application name set in application.rb)
However, this errors out:
"undefined method `topic_path' for H2le:Module"
Am I not setting the application name properly?
The problem was my being a Ruby newb and the guide I was following perhaps not being super explicit. It recommended to namespace the links like:
main_app.path
And I interpreted main_app to be a placeholder for my app name. Well, wrong. main_app is a built-in helper function, so it should literally just say main_app. I fixed this, and everything worked.

Dynamic Sitemap Errors

I'm trying to get dynamic_sitemaps gem to work with my site, but the readme is very technical and a bit over my head at the moment.
I'm running into errors when trying to generate the sitemap for this bit of code.
# You can have multiple sitemaps like the above – just make sure their names are different.
# Automatically link to all pages using the routes specified
# using "resources :pages" in config/routes.rb. This will also
# automatically set <lastmod> to the date and time in page.updated_at:
#
sitemap_for :offers
It's returning the below error
ArgumentError: The collection given to sitemap_for must respond to
find_each. This is for performance. Use Model.scoped to get an ActiveRecord relation that responds to find_each.
I'm looking to have the sitemap contain all my offer posts etc.
Any help is greatly appreciated!
If your model's name is Offer, try
sitemap_for Offer.all
(note: #scoped is deprecated, so #all seems to be the better option going forward)

Rails - duplicate routes - upgrade from 3.2 to 4.2

I've just upgraded my rails app from rails 3.2.21 to 4.2.0,
After fixed some error I have somes duplicates routes problems.
`add_route': Invalid route name, already in use: 'contact'
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....
but ... yes, I have some route pointing on the same controller action, but this is the way I want it. How can I tell rails 4 to no take care of this, or theres is a way to not touch my routes?
thanls !
The router in rails 4.0 detects whether a route name has been used before whereas previously it would've just overwritten them. This is even listed on github.
Fix:
Just make sure you are not using same helper method name for two routes in as: option

Rails: how do you access RESTful helpers?

I'm trying to work through this guide to Rails routing, but I got stuck in section 3.3:
Creating a RESTful route will also make available a pile of helpers within your application
and then they list some helpers like photos_url, photos_path, etc.
My questions:
Where can I find the complete list of helpers that is "made available?"
Is there a way to call the helpers in the console? I created an app, then opened up the console with script/console. I tried to call one of the helpers on the console like this:
>> entries_url
But got:
NameError: undefined local variable or method `entries_url' for #<Object:0x349a4>
from (irb):8
You have several questions in there, most of which have already been answered by people below.
The answer to one that wasn't fully addressed however, is: yes you can use the script/console to see where your routes go. Just type in app.[route_helper] and it will respond with the path. For example app.users_path will return /users/
So for your example type app.entries_url for the full URL - or app.entries_path for its relative path within the console.
rake routes at the command line should get you that list.
I think this may be what you are looking for ... http://topfunky.com/clients/peepcode/REST-cheatsheet.pdf
You can access other helpers in the console by prepending "helper."; ie. helper.progress_box (assuming #progress_box exists of course)
From memory, you can't call url/path helpers from the console for some reason.

Resources