routes.rb and controller - ruby-on-rails

Sorry, I thought I understood this, but now I have to re-evaluate my understanding of routes.rb. Hoping you could help.
A browser request goes to the Application Controller and the Controller tells what to show, right? - what erb file, database stuff, whatever...
In my routes.rb file I have:
root :to => 'static_pages#FAQ'
Until lately I thought what was happening was: routes.rb is looking at my static_pages_controller.rb file, looking at the FAQ method, and then seeing what to do. If there's nothing in the FAQ method - as is the case - then Rails does its magic and goes to my FAQ.html.erb in my View, the closest thing.
But even if I change the name of:
def FAQ
end
in my controller, or delete the static_pages_controller.rb altogether, it still goes to my FAQ.html.erb file. So does routes.rb not even look at controllers? Does it go straight to 'View' files? Thanks for any help.

static page are served first so that is why FAQ.html.erb is always served.
Also "A browser request goes to the Application Controller and the Controller tells what to show, right? - what erb file, database stuff, whatever..."
I think of it this way: The request first goes through routing, then to the controller for the resource in question, the controller being inherited from application_controller, will then query the model as needed, calculating variables as needed which it then uses in comiling the View page, which are compilation, gets sent as HTML.

Your ideas are essentially correct; Rails will attempt to render the static_page's controller's FAQ method, which implicitly renders the "FAQ" view, if no view (or other output) is explicitly rendered by the action.
What you're missing is that Rails will fill in the blanks if any one of the controller/action pieces is missing. All you need to do is define the view and Rails will assume that you're simply not bothering to define an empty action.

Starting a method name with a capital letter seems like a very bad idea in ruby, because ruby will treat any identifiers that start with a capital letter as a constant. The very first thing I would do personally is change 'FAQ' to 'faq' in my routes and controller code. If you really want to have 'FAQ' capitalized in the browser url, you can probably accomplish that via something like:
root :to => static_pages#faq, :as => 'FAQ'
To check that your method is getting called, use the logger:
def faq
Rails.logger.warn "faq method did get called after all"
end

Related

what determines controller action ruby rails

at https://www.codecademy.com/en/courses/learn-rails/lessons/start/exercises/start-views, the controll action is described as 'pages#home':
Well done! Now when a user visits http://localhost:8000/welcome, the route
get 'welcome' => 'pages#home'
will tell Rails to send this request to the Pages controller's home action.
but when I made the controller I did rails generate controller Pages which is uppercase.
pages_controller.rb:
class PagesController < ApplicationController
def home
end
end
Is the pages part of pages#home determined by the first part of pages_controller.rb, ignoring the _controller.rb end?
What happens if I change pages_controller.rb to renamedpages_controller.rb but leave the class name as PagesController?
thank you
Action Controller is the C in MVC. After routing has determined which controller to use for a request, your controller is responsible for making sense of the request and producing the appropriate output. Luckily, Action Controller does most of the groundwork for you and uses smart conventions to make this as straightforward as possible.
Controller Naming Convention
The naming convention of controllers in Rails favors pluralization of the last word in the controller's name, although it is not strictly required (e.g. ApplicationController). For example, ClientsController is preferable to ClientController, SiteAdminsController is preferable to SiteAdminController or SitesAdminsController, and so on.
Following this convention will allow you to use the default route generators (e.g. resources, etc) without needing to qualify each :path or :controller, and keeps URL and path helpers' usage consistent throughout your application. See Rails Guides.
When a request is made like: http://localhost:8000/welcome, it matches a route in the routes.rb file where the route is mapped to a controller and an action.
In your routes file, you have:
get 'welcome' => 'pages#home'
get 'welcome' part matches with the url .../welcome and map this request to pages#home where pages is the controller name and home is an action (a method defined in pages_controller). This is Rails convention to name the controllers like this: ControllerName_controller.rb. So, basically pages is your controller's name and the last _controllers is common to each and every controller in your Rails application.
What happens next is, this action of the controller do some work and talk to the model/database and build the required variables/data that will be passed to a view. According to Rails convention, there has to be a matching view file like: home.html.erb which will render the response to the browser.
There are other ways to render different partials and views in different ways, but if you follow the Rails convention, then it becomes very easy to understand and work with different Models, Views and Controllers in Rails. This is called: Convention Over Configuration.
When you follow the Rails convention for naming things, Rails does a lot of work and configuration for you for free to make your life easier.
When you have get 'welcome' => 'pages#home' in your routes file, then when a request: /welcome comes, it maps to pages_controller and it will look for the pages_controller.rb file under the app/controller/. If you rename this to something else, then the program will not find it as it expected and will throw you an error and your request will not be completed.
Your controller's name has to match with the class name of that controller, This is also a Rails convention. If you change any one of them, then you will get an error and your request will fail.
Yes. and #home is the "action" in PagesController
You get a uninitialized constant PagesController error
So, your controllers should always be in the form NameController defined in name_controller.rb, and actions as public methods in NameController.

Rails routing issue, can't figure out the link path

Let me fair from the outset, and tell you that I've 'solved' the problem I'm describing. But a solution that you don't understand is not really a solution, now is it?
I have a resource, Newsbites. I have an index page for Newsbites. All my CRUD actions work fine.
I created a separate index (frontindex.html.erb) that acts as the front page of my website to show the newest Newsbites. The formatting is different from my normal index so readers get a larger photo, more of the text of the article(more ads too:).
In my routing table, I have the following statements:
resources :newsbites
get 'newsbites/frontindex'
root 'newsbites#frontindex'
Rake routes show the following:
newsbites_frontindex GET /newsbites/frontindex(.:format) newsbites#frontindex
If I load my website from the root (localhost:3000), it works great. There is a separate menu page that is rendered at the top, and it loads fine. I can click on all links, except the 'Home' link, and they work fine.
The 'Home' link is:
<%= link_to 'Home', newsbites_frontindex_path %>
When I click on the linked, I get the following error:
Couldn't find Newsbite with 'id'=frontindex
The error points to the 'show' action of my Newbites controller. Here are the frontindex and show def from the controller. They appear exactly as I'm posting them:
def frontindex
#newsbites = Newsbite.all
end
def show
#newsbite = Newsbite.find(params[:id])
end
I don't get it. Why is the show action being called by newbites_frontindex_path when there is both a def and views that match? Now, I can get around this by simply pointing home to root_path. But that doesn't help me understand. What if this was not the root of the site?
Any help would be greatly appreciated.
Actually I'm very surprised your code worked at all. A route must define two things
Some sort of regex against which the URL of the user is matched (newsbites/frontindex is different than newsbites/backindex)
What do you want to do for a given URL ? You want to point to a controller action
Rails won't usually "guess" what that action is. Or maybe, he was still able to "guess" that you wanted to use the newsbites controller, but it didn't guess the action right this time :(.
You should declare the root like this, which is what you did
root 'controller#action'
For the rest, there are two ways you can declare it. I prefer the second one
resources :newsbites
get 'newsbites/frontindex', to: 'newsbites#frontindex'
resources :newsbites do
# stuff added here will have the context of the `newsbites` controller already
get 'frontindex', on: :collection # the name of the action is inferred to be `frontindex`
end
The on: :collection, means that 'frontindex' is an action that concerns ALL the newsbites, so the URL generated will be newsbites/frontindex.
On the other hand get 'custom_action', on: :member, means that the custom_action targets a specific item, the URL generated would look like newsbites/:id/custom_action
EDIT : Rails also generate path_helpers based on the route declaration
get 'test', to: 'newsbites#frontindex'
get 'test/something', to: 'newsbites#frontindex'
resources :newsbites do
get 'frontindex', on: :collection
get 'custom_action', on: :member
Will generate path helpers
test_path
test_something_path
# CRUD helpers : new/edit/show/delete, etc. helpers
frontindex_newsbites_path
custom_actions_newsbite_path(ID) # without s !
You can always override this by adding an as: option
get 'custom_action', on: :member, as: 'something_cool'
# => something_cool_newsbites_path
Rails routes thinks that frontindex is an id. That's what the error message says. So it goes to GET newsbite/:id which maps to show.
You need to find a way let Rails routes know that frontindex is not an id.
On a side note: The order in which you define routes matters. The first one matched will be used. If you have GET newsbite/:id and GET newsbite/frontindex then the one that appears first will be matched. In your case this is the first one.
Maybe try to change the order.

Ruby on Rails 4 Routing/Views/Path

I have 2 questions:
I have a controller called homepage. I have a view called samplegraph in my homepage's view directory. I want to get the routing working correctly such that www.homepage.com/samplegraph takes me to the samplegraph page.
As far as I can tell, the route for it in routes.rb should be something like this:
GET 'homepage/samplegraph' => 'homepage#showgraph1'
If I'm understanding rails routing correctly, this statement routes GET requests to homepage/samplegraph to the homepage controller's showgraph1 action. At this point I'm not particularly sure what the showgraph1 action should be in order to render the view page(samplegraph). At the moment the action is simply empty. I don't really know what to put here.
Second question:
Also, while I was researching rails routing, I was looking into resource based routing. For my purposes, I don't need most of the stuff generated by that. One thing I am interested in is that invoking resource based routing automatically generates Paths for you via helpers(I think?).
How would I generate a Path for my route, such that I'd be able to use a link_to method to link various parts of the application together? Any help/comments would be greatly appreciated.
Firstly, if you want to get 'samplegraph' page rendered by hitting 'www.homepage.com/samplegraph', you will need to update your route.
Replace
get 'homepage/samplegraph' => 'homepage#showgraph1'
with
get '/samplegraph' => 'homepage#showgraph1'
Now in showgraph1 action of your homepage controller, you will need to render samplegraph view page at last line of the action.
render 'samplegraph'
As of you second question, just hit rake routes on your terminal from your app directory. It will show all routes with helpers which you can use with link_to. You will need to append _path to those routes while using with link_to
Like #RAJ said first of all you need to change your route to
get '/samplegraph' => 'homepage#showgraph1'
At this point I'm not particularly sure what the showgraph1 action should be in order to render the view page(samplegraph)
Rails doesn't care if your action is empty or not, it'll still render your actions view even if it's empty. Since your action is named showgraph1 so it'll make rails look for showgraph1.html.erb with path views/homepage/showgraph1.html.erb
To change this behavior you need to use render 'samplegraph' in your action
One thing I am interested in is that invoking resource based routing automatically generates Paths for you via helpers(I think?)
Rails generate path and url helpers for each route and it doesn't depend on how your routes are defined but you can customize your helper methods by specifying as: option
get 'homepage/samplegraph' => 'homepage#showgraph1', as: 'showgraph'
This will make your helper methods showgraph_path and showgraph_url

How to add a view in rails

I am quite new to rails but i have searched a lot how to do this but it doesnt seem to work for me. Im trying to create a new view called request for my model called steppy_steps, so i created a new file in the views directory called request.html.rb, added this to my routes, match '/request' => 'pages#request', also tried get "steppy_tests/home", and lastly added (def request, end), to my Steppy_Tests_Controller.rb but when i check the url it gives me an error:Couldn't find SteppyTest with id=home
I cant figure out what to do any help would be great! Thanks in advance.
You should read up on the MVC programming pattern (which is what Rails is based on)
In order to make a view, you need to have the controller and model aspects in place too. I think you're doing this already, but to help you understand more, I'll outline below:
Views : Controller Actions
If you want to show a view from the steppy_steps controller, you need to first have a controller action set up to handle the request. You'd normally use a self-named controller for this (controller name steppy_steps), and have various actions for that
In your routes, you'll then "capture" the request to your steppy_steps controller like this:
#config/routes.rb
resources :steppy_steps
This will create a set of RESTful routes, which you can then translate into your controller, like this:
#app/controllers/steppy_steps_controller.rb
def index
#Index code
end
def show
#Show code
end
This will allow you to create a views directory which can contain the views for /views/steppy_steps/show.html.erb and /views/steppy_steps/index.html.erb
Routes Are Super Important
The error you're getting is caused by you sending /home to your view
The problem here is that if you're using a route which has an in-built id param (the show action routes have this), then Rails will look for the extra params after the URL
To fix this, you'll have to provide more of your code, but I also believe you'd be better understanding the fundamentals of Rails a little more
Adding Routes
You can add routes & views as you wish
If you're looking to add a requests route / view, I'd do this:
#config/routes.rb
resources :steppy_steps do
collection do
get :requests
end
end
This will allow you to create /steppy_steps/requests

URL redirect in Rails 2

In my rails application, for some reason, I have to redirect my URL in to desired URL.
This is how my config setting the routes.rb.
map.connect 'sample/:action/:id.:format', :controller => 'test'
It redirects well when the url is http://example.com/sample. It goes Test controller index method.
When the url is http://example.com/sample/displayname?id=10, it goes to Test controller and searches for displayname method. Obviously it wasn't there, so I got the "undefined" error message.Here I want even though the URL is (http://example.com/sample/displayname?id=10) it quite enough to go Test controller's index method.
Also in the Address Bar I want to URL masking . If I hit http://example.com/sample/ it should redirect & in address Bar http://example.com/test.
How can i do this with Rails-2 application (Rails version 2.3.9)?
First, I don't recommend doing this. It's going against the conventions of how things are done in rails, and that tends to lead to pain.
(As for what I do recommend? Just structure your urls differently. If you do things the way rails makes easy, then you'll have fun using it. Otherwise, your life will be full of pain and suffering.)
BUT, if you really want to, it looks like you can't do regular expression routes in rails. I thought you could, but I see no signs that you can. What you can do, however, is...
def method_missing
index
end
Put that in the controller you want to have this behavior. It'll do what you want, but it also might hide other errors. In any case, don't say I didn't warn you. This seems like a bad idea...
As for the redirect, a before_filter in the test controller will do that.
before_filter :redirect_if_wrong_path
def redirect_if_wrong_path
if request.path =~ /\/sample/
redirect_to request.path.sub('/sample', '/test')
end
end

Resources