Trouble in Rails 3 Adding Restful Routes to Namespaced Resources - ruby-on-rails-3

I am trying to add a route to a controller that has been set as a resource in the 'admin' namespace like this:
namespace :admin do
resources :books do
collection do
post :process_new
end
end
end
I have added an action int the Admin::BooksController for process_new, but whenever I try to access this action using the url: .../admin/books/process_new I get the following error:
Couldn't find Book with ID=process_new
It looks like it's routing to the show action and trying to use process_new as the id. Can someone shed some light on what I may be doing wrong?
**Edit:
I changed my redirects to use the helper functions and it seems to be working.

Add get :process_new to your resources :books routes:
namespace :admin do
resources :books do
collection do
get :process_new
post :process_new
end
end
end

Related

how can I make a simple route on rails and can I use it for an ajax form?

Ive been trying to create a simple route on rails, following this instructions
http://guides.rubyonrails.org/routing.html
my problem is that when I want to enter to my method I get a weird error.
I have a controler user and on my routes I wrote something like this
resources :users do
match "/custom/" => "user#custom"
end
So, at my controller I add this code
def custom
#user = User.find(params[:user_id])
end
but when I try to enter doing localhost:3000/users/1/custom I get an error like
uninitialized constant UserController
doing rake routes I can see
user_custom /users/:user_id/custom(.:format) user#custom
Any idea how to solve this problem?
I want this route to submit a form... is it possible to use this route (if i make it run) for use ajax? I want to submit a form.
Thanks
Change your route to:
resources :users do
match "/custom/" => "users#custom"
end
You should avoid the use of match though, since it will be deprecated in Rails 4. Try this instead
resources :users do
get :custom, on: :member
end
get is the verb, :custom the route and on: :member means that you are looking for a /users/:id/custom route instead of a /users/custom one. If you are looking for the latter, do this:
resources :users do
get :custom, on: :collection
end
Another way to do it is like this, which I prefer:
resources :users do
get 'custom', on: :collection
end
That gives you a route of /users/custom. If you were do use on: :member, then it would give you a route of /users/:id/custom.
You can also use a block for defining multiple custom actions for collections or members.
For example:
resources :users do
collection do
get 'custom'
post 'some_other_method'
end
member do
get 'some_action'
end
end

How to use a custom action in Rails' controller, called by a nested route

I want to add a custom action named "campaign" acting in a similar fashion like REST's "new" in the same controller, but it's purpose is different, so I wanted to separate them. Because, this campaign form will have some additional fields. One other alternative would be a passing an extra parameter to "new" action and render different templates for regular "new" action and custom "campaign". But, I wanna figure out why it didn't work out.
So, I come up with the following route ("messages" is the controller having both "new" and "campaign" actions):
get 'users/:user_id/messages/campaign', as: :campaign_user_message
or
resources :users do
resources: messages do
member do
get 'campaign'
end
end
end
At the console output, I'm getting ActiverRecord:RecordNotFound since it does this:
Started GET "/users/1/messages/campaign" for 127.0.0.1 at 2012-12-22 00:14:38 -0800
Processing by MessagesController#show as HTML
Parameters: {"user_id"=>"1", "id"=>"campaign"}
I'm calling the action in this way:
link_to campaign_user_message_path(#user)
if you want to have route such as "/users/1/messages/campaign" you should write smth like that:
resources :users do
resources :messages do
collection do
get 'campaign'
end
end
end
If you write in your way(with member do ... end) you code will generate url "/users/:user_id/messages/:id/campaign". and you should pass #user and #message:
link_to campaign_user_message_path(#user, #message)
I've did something like this overcome to the mentioned issue:
resources :users do
get 'messages/new_campaign' => 'messages#new_campaign'
post 'messages/create_campaign' => 'messages#create_campaign'
end
So, I can use the url helper "user_messages_new_campaign" to GET the action /users/:user_id/messages/new_campaign"

Nested Routing for Single Table Inheritance model rails 3.1

I created a Single table inheritance model in my model file and am having difficulty with the routing. When I use :as in my resource, it renames my named path.
Model file:
class Account < ActiveRecord::Base
belongs_to :user
end
class AdvertiserAccount < Account
end
class PublisherAccount < Account
end
Routes.rb
resources :advertiser_accounts, :as => "accounts" do
resources :campaigns
end
I used :as in my routes because it is a single table inheritance and I want to pass the account_id and not the advertiser_account_id. My link is http://127.0.0.1:3000/advertiser_accounts/1/campaigns
/advertiser_accounts/:account_id/campaigns/:id(.:format)
However, using :as renames my named path from advertiser_account_campaigns to account_campaigns. My route looks like
account_campaigns GET /advertiser_accounts/:account_id/campaigns(.:format) campaigns#index
So when I create a new item using form_for, I would get "undefined method `advertiser_account_campaigns_path'"
Edited: current hacked solution
A hack around way that I am using is to duplicate the code in the routes file. Anyone have suggestions?
resources :advertiser_accounts, :as => "accounts" do
resources :campaigns
end
resources :advertiser_accounts do
resources :campaigns
end
If you run "rake routes" with your setup you'll see this:
account_campaigns GET /advertiser_accounts/:account_id/campaigns(.:format) campaigns#index
POST /advertiser_accounts/:account_id/campaigns(.:format) campaigns#create
new_account_campaign GET /advertiser_accounts/:account_id/campaigns/new(.:format) campaigns#new
edit_account_campaign GET /advertiser_accounts/:account_id/campaigns/:id/edit(.:format) campaigns#edit
account_campaign GET /advertiser_accounts/:account_id/campaigns/:id(.:format) campaigns#show
PUT /advertiser_accounts/:account_id/campaigns/:id(.:format) campaigns#update
DELETE /advertiser_accounts/:account_id/campaigns/:id(.:format) campaigns#destroy
accounts GET /advertiser_accounts(.:format) advertiser_accounts#index
POST /advertiser_accounts(.:format) advertiser_accounts#create
new_account GET /advertiser_accounts/new(.:format) advertiser_accounts#new
edit_account GET /advertiser_accounts/:id/edit(.:format) advertiser_accounts#edit
account GET /advertiser_accounts/:id(.:format) advertiser_accounts#show
PUT /advertiser_accounts/:id(.:format) advertiser_accounts#update
DELETE /advertiser_accounts/:id(.:format) advertiser_accounts#destroy
So you should use "account_campaingns_path" in this setup, the ":as" actually changes the calls in the code not the paths in the url. If you want to change the paths you should use ":path =>" rather than ":as =>".
The Rails guide on routing also shows some examples with ":as" and ":path" and the resulting paths and helpers, you'll need to search a bit because think they only use in in examples explaining other cases.
Edit: rereading your question, I think you may also want to look at member routes, I'm not sure if that's what you want to mean with it being a single inheritance and not wanting to pass the advertiser_account's ':account_id'?

Match of routes in the collection

I define each actions in my controller this way (in routes.rb):
resources :home do
collection do
get "home/index"
get "home/about_me"
get "home/contact"
end
end
If I would use a match for the action about_me, I have to use
resources :home do
collection do
get "home/index"
get "home/about_me"
get "home/contact"
end
end
match 'about-me' => 'home#about_me'
Exist any way, how to add match rule direct into a collection? I mean something like this:
resources :home do
collection do
get "home/index"
get "home/about_me", match => "about-me"
get "home/contact"
end
end
And I have one question yet - when I use in the routes.rb the second block of code, so when I set the URL address about-me, so the address works fine, but when I type there home/about_me, so I get the error
Unknown action: The action 'show' could not be found for HomeController.
What caused this error?
I think the problem here is that your routes have the home/ prefix when they are nested inside resources :home. Try this:
resources :home do
collection do
get :index
get :about_me
get :contact
end
end
Also, when you have trouble setting your routes, type rake routes in your console. This will generate the routes of your app and the corresponding paths and controllers.
EDIT: Here's the answer to your other question.
resources :home do
collection do
get 'about_me' => 'about-me'
end
end

Defining a route for a method in rails 3

I'm new to Rails and currently using Rails 3, so please bear with me. I have a basic app, with a basic scaffolded controller/model e.g Contacts.
Amongst the methods for Show/Edit etc.. i have added a method called newcontacts (i have also added a newcontacts.html.erb), which will eventually show the last 5 contacts imported , but at the moment i am using the same code one would find in the basic Index method of a controller (i intend to filter the data at a later point), the method in the controller is -
def newcontacts
#contacts = Contact.all
respond_to do |format|
format.html # index.html.erb
end
end
I can access localhost:3000/contacts which displays the index method action from the contact controller, but when i try and access this method (newcontacts) using localhost:3000/contacts/newcontacts it returns the error
Couldn't find Contact with id=newcontacts
I have looked at the routes.rb file as i believe this is what needs editing, and have added the following line to routes.rb
match 'newcontacts', :to => 'contacts#newcontacts'
but this only works when i call localhost:3000/newcontacts.
So my question is, how do i get the url localhost:3000/contacts/newcontacts to work?
Any help would be great.
I think what you're trying to do is add another RESTful action.
resources :contacts do
# This will map to /contacts/newcontacts
get 'newcontacts', :on => :collection # Or (not and; use only one of these)...
# This will map to /contacts/:id/newcontacts
get 'newcontacts', :on => :member # ... if you want to pass in a contact id.
end
Try this in your routes.rb file:
resources :contacts do
member do
put 'newcontacts'
end
end
That will add in a new action for the contacts controller.