Adding methods to REST rails - ruby-on-rails-3

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.

Related

Overriding SessionsControllers is not loggin in

I want to add OpenID authentication in my web. To do that I have follow several tutorials and used several plugins and gems and finally I manage to do something with devise_openid_authenticatable gem. I also have normal login/password authentication, Facebook authentication and Twitter authentication. Those three work perfectly.
Now I'm trying to override Devise's Session Controller , but when I do it, the normal login/password stops working. The error I get is:
ActiveRecord::RecordNotFound in Sessions#create
Couldn't find User without an ID
The rest of the authentication forms work OK, even the sign up works perfect. It's only the login/password authentication method...
I use Rails 3.0.1, Ruby 1.8.9 and Devise 1.4.9
routes.rb
MAWeb::Application.routes.draw do
[...]
devise_for :admins
devise_for :users, :controllers => {:registrations => 'registrations', :sessions => 'sessions'}
match '/users/openid' => 'users#openid_sign_in'
match 'openid/sign_in' => 'openid#sign_in', :as => :openid_sign_in
get 'openid/create'
match '/auth/:provider/callback' => 'authentications#create'
match '/auth/failure' => 'authentications#failure'
resources :subscription_contact_datas
resources :subscription_preferences do
collection do
post :create_with_params
end
member do
get 'delete_tag'
end
get 'fill_event_id', :on => :member
end
resources :event_states
resources :subscription_profiles do
collection do
put :update_profiles
end
end
resources :event_criteria_options
resources :subscriptions do
collection do
get :options_for_event_criteria
end
end
resources :event_criterias
resources :categories
resources :user_infos do
member do
get 'edit'
end
end
resources :events
resources :users do
member do
get 'showUserActivity'
end
end
resources :admins
resources :subscriptions_from_poi
root :to => "home#index"
namespace :user do
root :to => "users#index"
end
namespace :admin do
root :to => "admins#index"
end
*registrations controller's override works perfectly
EDIT: Added the most of the routes. The ones I omited are not important in my opinion.

Rename a custom member route named helper in 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.
:)

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.)

How to tweak nested route

I have routes like this:
namespace :admin do
resources :users, :only => :index do
resources :skills, :only => :index
end
end
resources :skills
In this case I got:
admin_user_skills GET /admin/users/:user_id/skills(.:format)
{:action=>"index", :controller=>"admin/skills"}
How to change nested route in order to point to SkillsController instead of Admin::SkillsController? I'd like to have this:
admin_user_skills GET /admin/users/:user_id/skills(.:format)
{:action=>"index", :controller=>"skills"}
Interesting thing - if we have no Admin::SkillsController, it will use SkillsController automatically, but only in development.
Using namespace in routes implies to have special directory for "namespaced" controllers, admin in your case. But if you use scope instead you have what you need:
scope '/admin' do
resources :users, :only => :index do
resources :skills, :only => :index
end
end

Refactor: Having a nested resource where the parent fails

I have the following resources setup:
resources :sites do
resources :documents
# more nested here
end
resources :documents do
resources :notes, :except => [:show, :new, :edit]
end
I want the notes controller to have the document context. The problem is, the document controller itself depends on the site context. So the /document urls that are created from the above all throw a 500 error. I could adjust the controller code to handle this, but i wonder if there's a way to not create the /document urls, just: /document/#id/notes
For any one else that may have this problem You can restrict the routes you don't want by using :except just the way #agmcleod has for the :notes. So to restrict the document urls would either be:
resources :sites do
resources :documents, :except => [:index, :show, :new, :create, :edit, :update, :destroy]
# more nested here
end
or
resources :documents, :except => [:index, :show, :new, :create, :edit, :update, :destroy] do
resource :notes, :except => [:show, :new, :edit]
end
You can remove any of the actions as necessary.