Rename a custom member route named helper in Rails 3 - ruby-on-rails-3

I have routes listed as follows
resources :jobs do
resources :invoices, :only => [:show] do
get 'submit_invoice', :on => :member
end
end
So the middle route creates a url like /jobs/:job_id/invoices/:id/submit_invoice which is exactly what I want. However rails assigns the name submit_invoice_job_invoice to the path which is ugly and horrible to type.
How can I make the name just submit_invoice so that I can have submit_invoice_path and submit_invoice_url?

The answer should be:
get "/jobs/:job_id/invoices/:id/submit_invoice" => "invoices#submit_invoice",
:as => "submit_invoice"

resources :jobs do
resources :invoices, :only => [:show] do
get 'submit_invoice', :on => :member, :as => 'submit_invoice'
end
end
Use :as => 'routename' and invoke it as routename_path.
:)

Related

Rails 3.1 How do I create an API route for "me" that points to the user resource

I have a set of API routes in rails as follows
namespace "api" do
namespace "v1" do
resources :users do
resources :posts
resources :likes
...
end
end
end
So far, so good. I can GET /api/v1/users/fred_flintstone and retrieve all of the information for that user.
What I would like to do now is add the concept of "me" (ala facebook) such that if the user is authenticated (fred_flintstone), I can also do the following
GET /api/v1/me
GET /api/v1/me/posts
...
I require both sets of routes. So I want to achieve the same results either using GET /api/v1/me/posts OR GET /api/v1/users/fred_flintstone/posts.
I've been through the route tutorial and have googled so a pointer would be as much appreciated as a direct answer.
EDIT:
What I've done that has worked is pretty hacky. I've created a second set of entries in the routes table using a scope:
scope "/api/v1/me", :defaults => {:format => 'json'}, :as => 'me' do
resources :posts, :controller => 'api/v1/users/posts'
resources :likes, :controller => 'api/v1/users/likes'
...
end
And then I added a set_user method that tests for the presence of params[:user_id]. I'm really looking for a way to DRY this up.
What about leaving the routes the way they are in your post, and just solving this inside the controller?
Heres a before_filter that you could apply to all of the routes you have which pull a User from a :user_id.
# Set the #user variable from the current url;
# Either by looking up params[:user_id] or
# by assigning current_user if params[:user_id] = 'me'
def user_from_user_id
if params[:user_id] == 'me' && current_user
#user = current_user
else
#user = User.find_by_user_id params[:user_id]
end
raise ActiveRecord::RecordNotFound unless #user
end
Then in your controller functions you can just use the #user variable without having to worry about whether the user passed a user_id, or me.
Hope that helps! :)
EDIT:
Lemme take another shot, given your comments.
How about a function that lists all the resources you wish to access via both the standard routes and the /me route. Then you can just use the function in both the namespaces you require.
routes.rb
# Resources for users, and for "/me/resource"
def user_resources
resources :posts
resources :likes
...
end
namespace 'api' do
namespace 'v1' do
resources :users do
user_resources
end
end
end
scope '/api/v1/:user_id', :constraints => { :user_id => 'me' },
:defaults => {:format => 'json'}, :as => 'me' do
user_resources
end
# We're still missing the plain "/me" route, for getting
# and updating, so hand code those in
match '/api/v1/:id' => 'users#show', :via => :get,
:constraints => { :id => 'me' }
match '/api/v1/:id' => 'users#update', :via => :put,
:constraints => { :id => 'me' }

link_to different behavior from rails2 to rails3

In rails2, I was able to have code like this:
link_to(user.company.name, user.company)
which would map to:
/companies/id
but in rails 3, this same line of code throws a error stating:
undefined method `user_companies_path'
The obvious fix is to do something like:
link_to(user.company.name, company_path(user.company))
But I was wondering if anyone could explain the reason behind the change? The logic seemed a lot cleaner.
EDIT: Adding samples of my routes
In rails2, my routes looked like:
map.resources :users, :except => :edit, :member => { :details => :get }
map.resources :companies, :except => :edit, :member => { :details => :get }
In rails3, my routes are:
resources :users, :except => :edit do
member do
get :details
end
end
resources :companies, :except => :edit do
member do
get :details
end
end
The short answer is that the Rails 3 routing API bases your application on resources which is why these RESTful routes are being used, and also means that it does things like support constraints.
In Rails 2, you'd do:
resources :cars do
resource :models
member do
post :year
end
collection do
get :details
end
end
In Rails 3, you'd do:
map.resources :cars, :member => {:year => :post}, :collection => {:details => :get} do |cars|
cars.resource :model
end
You also have the :as key available which means you can then use named route helpers anywhere that url_for is available (i.e. controllers, mailers etc.)

Adding methods to REST rails

I want to add more methods to my rest.
Here is my routes.rb file:
resources :boards, :except => [:new, :create] do
get 'customize', :on => :member
get 'change_template', :on => :member
get 'all_walls', :on => :member
end
I am getting them in the following format:
change_template_board GET /boards/:id/change_template(.:format) {:action=>"change_template", :controller=>"boards"}
But I want them in this format:
/boards/:board_id/change_template/:id(.:format)
How can I do that?
I'm copying the first answer from this question. In your routes.rb, you can add a new route dooit to resource fifi by adding this to your routes.rb file:
resources :fifi do
member do
get :dooit
end
end
This will create the route dooit_fifi along with the standard fifi, fifi_index, new_fifi, and edit_fifi routes.
If you want to restrict the routes created, you can do something like this:
resources :fifi, only: [:show, :create, :destroy] do
member do
get :dooit
end
end
which will produce only the routes dooit_fifi, fifi, and fifi_index.

Rails 3: What does this route do?

Looking for a little helping understanding how this route would work?
New route:
resources :artists do
resources :users
end
entire routes
resources :artists do
resources :users
end
match 'auth/:provider/callback' => 'authentications#create'
resources :authentications
devise_for :admins
match '/admin' => 'RailsAdmin/Main#index'
devise_for :users, :controllers => {:registrations => 'registrations'} do
match '/users/change_password', :to => 'registrations#change_password'
match '/users/edit_account', :to => 'registrations#edit_account'
end
resources :posts do
member do
get :likers
end
collection do
get :search
end
end
resources :relationships, :only => [:create, :destroy]
resources :appreciations, :only => [:create, :destroy]
match '/a_json/:id', :to => 'artists#index'
match '/s_json/:id', :to => 'stores#index'
match '/contact', :to => 'pages#contact'
match '/about', :to => 'pages#about'
match '/help', :to => 'pages#help'
match '/blog', :to => 'pages#blog'
resources :users do
member do
get :following, :followers, :likes
end
end
# This is a legacy wild controller route that's not recommended for RESTful applications.
# Note: This route will make all actions in every controller accessible via GET requests.
# match ':controller(/:action(/:id(.:format)))'
match '/:id' => 'users#show', :constraints => {:id => /[^\/]+/}, :as => :global_user
root :to => "pages#home"
end
This would create nested routes, allowing you to use URLs like /artists/5/users/45, which would call UsersController#show with a parameter artist_id which was 5, and a parameter id which was 45. All of the other usual RESTful routes are also created "nested" under a single artist.
Rails actually has a tool for showing you what routes have been generated: just run rake routes to take a peek.

Help migrating routes to rails 3 format

I am trying to figure out changing this routes.rb to the new rails 3 syntax but it's proving to be quite difficult... I know most of the sutff is simply removing the map.
but some of these routes I cant figure out what they were supposed to do in rails 2 to begin with... so if someone could help me get this to work without deprecation warnings I'd appreciate it'. Please Help.
MyProject::Application.routes.draw do |map|
map.resources :grading_levels
map.resources :class_timings
map.resources :subjects
map.resources :attendances
map.resources :employee_attendances
map.resources :attendance_reports
map.feed 'courses/manage_course', :controller => 'courses' ,:action=>'manage_course'
map.feed 'courses/manage_batches', :controller => 'courses' ,:action=>'manage_batches'
map.resources :courses, :has_many => :batches
map.resources :batches do |batch|
batch.resources :exam_groups
batch.resources :additional_exam_groups
batch.resources :elective_groups, :as => :electives
end
map.resources :exam_groups do |exam_group|
exam_group.resources :exams, :member => { :save_scores => :post }
end
map.resources :additional_exam_groups do |additional_exam_group|
additional_exam_group.resources :additional_exams , :member => { :save_additional_scores => :post }
end
map.root :controller => 'users', :action => 'login'
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id/:id2'
map.connect ':controller/:action/:id.:format'
end
resources :grading_levels
resources :class_timings
resources :subjects
resources :attendances
resources :employee_attendances
resources :attendance_reports
match 'courses/manage_course' => 'courses#manage_course', :as => :feed
match 'courses/manage_batches' => 'courses#manage_batches', :as => :feed
resources :courses
resources :batches do
resources :exam_groups
resources :additional_exam_groups
resources :elective_groups
end
resources :exam_groups do
resources :exams do
member do
post :save_scores
end
end
end
resources :additional_exam_groups do
resources :additional_exams do
member do
post :save_additional_scores
end
end
end
match '/' => 'users#login'
match '/:controller(/:action(/:id))'
match ':controller/:action/:id/:id2' => '#index'