Where is this "posts_path" variable defined? - ruby-on-rails

I'm following this tutorial (seems good) for Rails. After I run
ruby script/generate scaffold Post
then this link works in one of the erb files:
<%= link_to "My Blog", posts_path %>
WHY? I've looked for "posts_path" in the whole app and it's nowhere to be found. On the other hand, this
<%= link_to "My Blog", home_path %>
does not work, and it's also a Controller.
Where is the posts_path defined?

posts_path is a named route you get for free from the route that was added by script/generate scaffold. See routes.rb you should see something like this:
map.resources :posts
See the API docs for information on what other named routes you get for free.
Also you can run rake routes and see what all your routes.rb is giving you.
If you want a home_path named route add a line like this to your routes.rb:
map.home '/home', :controller => "home", :action => "index"

I believe that "posts_path" is created dynamically by Rails at runtime. Look at your routes.rb file - Home is probably not defined the same way as Posts. It has nothing to do with you controllers, it's dependent on the route definition.

map.root :controller => "home" would be a shorter way of writing the path to your home directory. This will use / has the home, and not /home. If you still want to use /home (and home_path), map.home 'home', :controller => "home" will do the same thing.
There's a great guide written by Mike Gunderloy about everything there is to know about routing.

Related

Rails app gets unnecessarily RESTFUL with links

I've got an app where the links work fine when I'm on the homepage, but when I'm on a page belonging to a resource such as "users", some links get a little weird.
When I'm on the homepage and I click the link for the "About" page, I'm taken there directly. But if I'm on the page for users/index and I hover over the link for the "About" page, it shows the destination as being "users/about."
Here's what my routes file looks like.
RobotimusApp::Application.routes.draw do
resources :users
root to: "pages#home"
match '/about', to:'pages#about'
match '/guides', to:'pages#guides'
end
Here's what my nav bar looks like
%ul.nav
%li
=link_to 'Home', root_url
%li
=link_to 'About', 'about'
- if user_signed_in?
%li
= link_to('My Sites', user_path(current_user))
Welp, the issue lies in this line:
=link_to 'About', 'about'
Instead of passing in a routed path like about_path, we pass in the string 'about'. When link_to receives a string as its URL parameter, it doesn't run it through the router or anything; it assumes that that's the URL you want to go to. (After all, about_path and the like return strings.)
So, you end up with something like this in the HTML:
About
Here, about is a relative URL, so from the path /users it will go to /users/about.
You could just use a preceding slash to make it an absolute path:
= link_to 'About', '/about'
But it's not particularly Rails-y to hard-code our URLs when we can use routes instead. You're probably going for something like this:
= link_to 'About', about_pages_path
(Is about_pages the route name? It probably should be. You can always name it with an as parameter.)
If you run rake routes in a terminal you'll get a list of all the routes available.
think the link for your about page should be
= link_to 'About', about_pages_path

Rails 3 namespaced routes: how to link *from* a namespace back to the global namespace? [REVISED]

I have a common layout file, used site-wide. It contains links like:
<%= link_to("Home", { :controller => :home, :action => :index }) %>
And other common links in the header/footer etc.
All of my controllers are simply under the app/controllers/ directory. But I've added a namespace for admins (to ban users etc):
namespace :admin do
resources :users
end
My admin namespace isn't any different in look & feel, so it uses the same layout as the rest of the site. Which is causing some issues, since all of my link_to and url_for calls are being mis-interpreted as, say:
<%= link_to("Home", { :controller => "admin/home", :action => :index }) %>
Which crashes the app, as no such route exists. Do I have to go through all of my templates used by the layout and change the controller portion of the link_to with a leading slash, or is there a better way to make all of my top-level routes functional even under the admin namespace? I link out of the admin namespace into the top-level namespace for lots of things, so it would be good if I didn't really have to give any special consideration to my link_to calls.
In summary, when under a namespaced controller, do you have to prefix all :controller parameters in link_to with a leading slash in order to break out of the namespace?
Defining the forums route on the routing and using the forums_path instead of the :controller/:action hash should be enough and cleaner.
config/routes.rb:
match '/forums' => 'forums#index', :as => :forums
Views:
<li class="menuitem"><%= link_to("Forums", forums_path()) %></li>

Using "news_path" for a :news resource doesn't work with `No route matches {:action=>"show", :controller=>"admin/news"} missing required keys: [:id]'

I am implementing an admin subdomain and have googled to try and find the answer to this, however I have not found another instance.
My routes look like this for the subdomain section:
constraints :subdomain => 'admin' do
scope :module => "admin" do
resources :news, :events
match 'news', :to => 'news#index', :as => 'news'
root :to => "dashboard#index"
end
end
Events works fine, but for some reason in order for news to work I need to add a specific route to match it. It may help to show the partial where the error is generated (admin/shared/menu):
<ul>
<li><%= link_to 'Home', root_path, :class => "#{current_class?(root_path)}" %></li>
<li><%= link_to 'News', news_path, :class => "#{current_class?(news_path)}" %></li>
<li><%= link_to 'Events', events_path, :class => "#{current_class?(events_path)}" %></li>
<div class="clearboth"></div>
</ul>
And then the error if I was to remove the match route:
No route matches {:action=>"show", :controller=>"admin/news"} missing required keys: [:id]
I just don't have a clue why, any thoughts?
I found that this is an issue with rails in that the naming convention news should not be used due to plural issues, news -> new so therefore I had to rename everything to articles instead. Oversight on my part, a tad stupid.
The reason Rails gets confused is because "news" is used for both the singular and plural. news'.singularize gives news; and news.pluralize also gives news (Wikipedia has a longer description of this phenomenon; there are other words that do the same).
Rails will generate a news_path route (plural, for the index action) and a news_path route (singular, for the show action).
The singular route expects a News instance; it appears that the show action is defined later, and overwrites the index action, resulting in the strange behaviour.
The solution is simple: use the news_index_path if you want the index action. I haven't encountered any other issues, and am still using the News model.
ActiveAdmin fixed this issue in the same way.
If you really don't want to use News, then you can suffix it with Item, Entry, Object, or a similar word. This will leave you with a NewsItem model with news_item_path and news_items_path.

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.

rails redirect_to problem

I am developing a rails app and have a question.
In my routes.rb:
map.connect 'admin', :controller => "/admin/users", :action => "index"
So when I go to "http://mydomain.com/admin", it redirects to "http://mydomain.com/admin/users/index".
However, the address remains as "http://mydomain.com/admin".
Thus, links in the page are wrong because they are created based on "http://mydomain.com/admin".
What's the solution to this problem?
Sam
try this:
map.connect 'admin/:action/:id', :controller => 'admin/users'
Your code is not redirecting the browser it's just setting up /admin and /admin/users to trigger the same action.
You could try:
map.connect 'admin', :controller => "/admin/users", :action => "redirect_to_index"
Then in your controller write:
def redirect_to_index
redirect_to :action => :index
end
This will send a redirect to the browser, causing it to display the correct URL.
Hopefully there is a better method that only involves routes.rb. This site might be helpful -> redirect-routing-plugin-for-rails
Make sure any same-domain links on the page start with a /, and use the full path. Generally you should use Rails route methods to generate your links when possible. Same goes for using the image_tag and stylesheet_link_tag helpers.
So if you have a link to "privacy.html", change it to "/privacy.html" and you should be all good no matter where in the route structure you are. This is extra nice when you start extracting your view code out to re-usable partials.
Use link_to and button_to (in UrlHelper)

Resources