I am new to ruby and while creating a sample application found out an issue that whenever I go to http://127.0.0.1:3000/people/index by default show action is executed and index is taken as a parameter. This is server log:
Started GET "/people/index" for
127.0.0.1 at 2010-12-23 18:43:01 +0500 Processing by PeopleController#show as
HTML Parameters: {"id"=>"index"}
I have this in my route file:
root :to => "people#index"
resources :people
match ':controller(/:action(/:id(.:format)))'
What is going on here and how can I fix the issue?
The route
resources :people
creates "sub"-routes
get '/people' => 'people#index'
get '/people/new' => 'people#new'
post '/people' => 'people#create'
get '/people/:id' => 'people#show'
get '/people/:id/edit' => 'people#edit'
put '/people/:id' => 'people#update'
delete '/people/:id' => 'people#destroy'
Actually, all of these sub-routes include (.:format) at the end of the recognized path.
The path /people/index would be recognized by the route /people/:id, mapping to the action #show.
The path /people would be recognized by the route /people, mapping to the action #index.
Use the URL helpers people_path and people_url for the /people route.
To get Rails to travel backward in time to before it espoused REST and to understand /people/index, do this:
resources :people do
get :index => 'people#index'
end
You might want to watch this Railscast episode.
A couple things to keep in mind when working with your routes:
rake routes dumps the map of URLs to your controllers
When providing backwards compatibility, redirect the user to the correct path
I personally have yet to upgrade my app to Rails 3, and I'll be dragging my feet until I really need to do it (just got it out the door not too long ago). In Rails 2.x you had resource routes, but if you kept the default controller/action/id route it would fall through and resolve. It appears that is no longer the case in Rails 3. Essentially your resource routes handle all URLs in that resource namespace (/people in your case).
To provide backwards compatibility, I would add a redirect route to resolve that incompatibility.
match "/people/index", :to => redirect("/people")
The main reason for that is to prevent users from saving an incorrect URL for their personal links--while allowing legacy users to still be able to get where they meant to go.
Edit: New answer, removed pointing out the typo in the question.
Related
get '/:company' => 'organizations#show', as: 'company_home'
I have this route, this is a way so that different companies registered to my application will login. As I have overridden all the devise related things. This is working fine until I have realized that for every route, this is getting applied
When I hit
get 'employee_dashboard' => 'dashboard#show'
The Parameters: {"company"=>"employee_dashboard"} are going to organizations#show
But I want it to hit dashboard#show how to get around with this?
Move the wildcard route after
get 'employee_dashboard' => 'dashboard#show'
or at the end of route file
get '/:company' => 'organizations#show', as: 'company_home'
so this route will be used only if no other route matches
I'm making a website for a class and I'm trying to implement a friend request function with a model called 'Users' and a join model called 'Relationships'. I have a button on the user#show page that should add a friend by using the create method in the Relationships controller. Here is the code for the button:
<%= link_to "Add as Friend", relationships_path(:friend_id => #user), method: :post %>
When I press the link, however, it tries to access the index method instead. After looking in the console, it looks like the link is sending a GET request, which routes to the index method, instead of a POST request, which routes to the create method. Can someone explain why this error is occurring and how I can fix it?
Edit: As requested, here is what I have in my routes:
Rails.application.routes.draw do
resources :interests
get 'interests/create'
get 'interests/destroy'
get 'home/index'
get 'sessions/create'
get 'sessions/destroy'
resources :users
resources :relationships
resources :subscriptions
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
# root 'welcome#index'
root 'home#index'
get "/auth/:provider/callback" => "sessions#create"
get "/signout" => "sessions#destroy", :as => :signout
Using a link_to helper indicates to Rails that you'd like to produce an a tag in your HTML. No element of the HTML specification regarding a tags allows for producing POST requests. Because Rails understands the utility of allowing for POST and DELETE requests to be issued using links, however, it provides those options in the link_to helper. It's implementation, though, must use JavaScript under the hood in order to appropriately function.
Check that jquery-ujs is installed, and that your asset pipeline is working correctly in order to use the helper in this way.
You may also evaluate whether using a form_for and a button is better, since that will automatically POST.
I'm pretty sure you are matching the wrong route. Run rake routes and see the route that links to the Relationships#create.
Using 'url' instead of 'path' with the route helper solved the problem for me. So instead of 'relationships_path' use 'relationships_url'.
I am someone who has always liked sinatra better than rails, and has never had to do a large enough scale project that rails was required (all the sources I have read say that rails is better for larger scale projects) and now I do have to do a large scale project. I have gotten very confused with the url structure of rails. What I am trying to do is the rails equivalent of this:
get "/" do
erb :index
end
get "/home" do
erb :dashboard
end
get "/home/profile" do
erb :profile
end
get "/home/friends" do
erb :friends
end
In the first one I understand that I should put in app/routes.rb I should put root home#index and in the home controller I should put def index end.
In the second one, I understand that I should do the same except replacing index with home.
But for the third and forth ones I have no idea what to do.
Also, is the a RESTful way to do the first two?
You probably want something like this
root 'home#index'
get 'home' => 'home#dashboard'
get 'home/profile' => 'home#profile'
get 'home/friends' => 'home#friends'
remember to use the command rake routes to see all your routes, where they lead and what their names are (if they have any)
I never understood what RESTful means, so someone else will have to answer that part of your question.
K M Rakibul Islam has shown you what can be called a "resourceful" way to do routes (because it uses the keyword resources) but it looks like you're just doing the static pages at this stage, so it's not necessary.
The simplest way to do routes is with this formula:
method url => controller::action, as: route_name
where method can be get, post, patch or delete so you can have different actions linked to the same URL depending on the method the request uses.
Putting a name on the route is optional, but it gives you a clean way to use the route in your views (route_name_path)
When you start making models then you'll find that using the resources keyword comes in handy. Read about it.
You can have this:
resources :home do
collection do
get :profile
end
collection do
get :friends
end
end
end
This will give you routes like this:
profile_home_index GET /home/profile(.:format) home#profile
friends_home_index GET /home/friends(.:format) home#friends
The standard way of declaring the root path:
root 'home#index'
And for the 2nd one, you have to do:
get 'home' => 'home#dashboard'
which will give you this route:
GET /home(.:format) home#dashboard
One route can be defined in many ways that works. But, Rails has conventions that should be followed while defining routes in your Rails app.
I would highly recommend you to take a look at the Rails Routing Guide
After running rails generate controller home index in my Rails application, I see this line in routes.rb
get "home/index"
What does this line do? When I removed it, I didn't observe any difference it makes.
see the Rails Routing page for more info but...
It adds, to the routing table, an entry to direct a GET request of the form
http://localhost:3000/home/index
To the HomeController#index action, which will render a response and display the results to the user.
It is a shorthand notation for
match 'home/index' => 'home#index', :via => :get
To see what other routes your application has available, run the following from a terminal while inside your projects directory
rake routes
This irritates me right now, and I've been at it for more than an hour. Maybe one of you has an idea.
I've defined the following routes in routes.rb:
resources :ads do
member do
post :preview_revision
get :revise
end
collection do
get :search
post :preview
end
end
When I run rake routes, the preview_revision route is shown correctly:
preview_revision_ad POST /ads/:id/preview_revision(.:format) {:action=>"preview_revision", :controller=>"ads"}
However, when I make a POST request to /ads/145/preview_revision, I get the following error:
Started POST "/ads/145/preview_revision" for 127.0.0.1 at Mon Nov 15 17:45:51 +0100 2010
ActionController::RoutingError (No route matches "/ads/145/preview_revision"):
Rendered /Library/Ruby/Gems/1.8/gems/actionpack-3.0.1/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.2ms)
The id (145) exists, yes.
The action and the controller (action: preview_revision, controller: ads) exist as well.
All the other routes work perfectly fine
I've tried restarting the server several times
I double-checked that it's actually a POST request, that the ID is correct, I really don't know what to do anymore.
Rails version is 3.0.1
--- UPDATE ---
I tried changing the method from POST to PUT, and now it works. Apparently POST routes on member level are not working, or not allowed.
Still, I want to know why. I do know that POST is for creating a member, so a POST request on a member makes no sense, but I didn't find this mentioned anywhere in the Rails guides, and why would rake routes display the route, if it doesn't actually work? Is that a bug?
--- UPDATE 2 ---
The Rails Routing guide (Edge version) specifically says:
2.9.1 Adding Member Routes
To add a member route, just add a
member block into the resource block:
resources :photos
do member do
get 'preview'
end
end
This will recognize /photos/1/preview
with GET, and route to the preview
action of PhotosController. It will
also create the preview_photo_url and
preview_photo_path helpers.
Within the block of member routes,
each route name specifies the HTTP
verb that it will recognize. You can
use get, put, post, or delete here. If
you don’t have multiple member routes,
you can also pass :on to a route,
eliminating the block [...]
So is the POST on member possible or not possible? Am I missing something? Just to be clear, I don't wanna use it anymore, but still, it bugs me not knowing why it doesn't work.
The best thing to do, if you find a bug in actively maintained open-source software, is:
to submit a bug report to the project's bug tracker isolating the problem as much as possible and with as much detail as possible, and, optionally,
to include a patch that fixes the bug if you can.
The bug tracker for Rails is at rails.lighthouseapp.com.
---edit---
The bug tracker for Rails is now at github.com/rails/rails/issues.
That should be working. I've created a blank app with 3.0.1 and added those routes and it worked.
Have you tried passing the :on param? Something like:
resources :ads do
post :preview_revision, :on => :member
get :revise, :on => :member
get :search, :on => :collection
post :preview, :on => :collection
end