Rails 3 nested resources route error - ruby-on-rails

I'm not being able to redirect the user to the page I want after he creates a new "service" resource.
Here's the routes.rb:
resources :wsps do
resources :services
end
The html form:
<%= form_for([#wsp,#service]) do |f| %>
Services_controller.rb:
def new
#wsp = current_wsp
#service = #wsp.services.build
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #service }
end
end
def create
#wsp = current_wsp
#service = #wsp.services.build(params[:service])
if #service.save
redirect_to wsp_service_path
end
end
The wsp_service_path goes to /wsps/1/services and the error:
No route matches {:action=>"destroy", :controller=>"services"}
What am I doing wrong? Why cant't I use "wsp_service_path"?
Thank you.

You can use wsp_service_path (while you should be use wsp_service_url since you are in a controller). All you are missing is arguments. wsp_service_path (or _url) are going to expect two arguments: a wsp and a service. Once you provide those two, it works.
redirect_to wsp_service_url(#wsp, #service)

Related

No route match even when route is defined

I have just started working in rails.
I have a controller that redirects to another controller to send an email for emailid verification.
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
redirect_to :controller => 'verify', :action => 'sendmail'
else
format.html { render :new }
end
and this is the route in routes file
resources :verify
but still the program is returning an error
No route matches {:action=>"sendmail", :controller=>"verify"}
This is the code of the controller to which I am redirecting
def sendmail
# type = 1 for email and 2 for reseting password
randomNumber=rand()
verification[:value]=BCrypt::Password.create(randomNumber, :cost => 1)
verification[:type] = 1
if verification.save
Usermail.registered(#verification).deliver
end
I think Verify (singular) as a controller name won't easily be mapped by resources, instead just add a custom match
get '/verify/sendmail', to: 'verify#sendmail', as: :verification_mail
Then do
redirect_to verification_mail_path

How do I define a custom URL for a form confirmation page?

I am creating a basic product landing page with Rails in which users can enter their email address to be notified when the product launches. (Yes, there are services/gems etc that could do this for me, but I am new to programming and want to build it myself to learn rails.)
On successful submit of the form, I would like to redirect to a custom '/thanks' page in which I thank users for their interest in the product (and also encourage them to complete a short survey.)
Currently, successful submits are displayed at "/invites/:id/" eg "invites/3" which I do not want since it exposes the number of invites that have been submitted. I would like to instead redirect all successful submits to a "/thanks" page.
I have attempted to research "rails custom URLs" but have not been able to find anything that works. The closest I was able to find was this Stackoverflow post on how to redirect with custom routes but did not fully understand the solution being recommended. I have also tried reading the Rails Guide on Routes but am new to this and did not see anything that I understood to allow for creating a custom URL.
I have placed my thanks message which I would like displayed on successful form submit in "views/invites/show.html.haml"
My Routes file
resources :invites
root :to => 'invites#new'
I tried inserting in routes.rb:
post "/:thanks" => "invites#show", :as => :thanks
But I don't know if this would work or how I would tell the controller to redirect to :thanks
My controller (basically vanilla rails, only relevant actions included here):
def show
#invite = Invite.find(params[:id])
show_path = "/thanks"
respond_to do |format|
format.html # show.html.erb
format.json { render json: #invite }
end
end
# GET /invites/new
# GET /invites/new.json
def new
#invite = Invite.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #invite }
end
end
# POST /invites
# POST /invites.json
def create
#invite = Invite.new(params[:invite])
respond_to do |format|
if #invite.save
format.html { redirect_to #invite }
#format.js { render :action => 'create_success' }
format.json { render json: #invite, status: :created, location: #invite }
else
format.html { render action: "new" }
#format.js { render :action => 'create_fail' }
format.json { render json: #invite.errors, status: :unprocessable_entity }
end
end
end
It would seem as if creating a standard URL for displaying a confirmation would be relatively straightforward. Any advice on how to achieve this would be appreciated.
I guess you want to redirect after your create action, which is executed when the form is submitted.
Just add redirect_to in the following way:
def create
#invite = Invite.new(params[:invite])
if #invite.save
...
redirect_to '/thanks'
else
...
redirect_to new_invite_path # if you want to return to the form submission page on error
end
end
I omitted some of the code for brevity.
In your routes add:
get '/thanks', to: "invites#thanks"
Add the thanks action to your invites controller:
def thanks
# something here if needed
end
And create a thanks.html.erb page in app/views/invites.
I would do get "/thanks" => "invites#thanks" in routes.rb and then add this in your controller:
def thanks
end
Then add a file app/views/invites/thanks.html.erb with your thank-you content.
You could create a route like this:
resources :invites do
collection do
get 'thanks'
end
end
This will also create a path helper called thanks_invites_path.
It will be at the invites/thanks path, but if you want it to be on/thanks, you could just do as Jason mentioned:
get "/thanks" => "invites#thanks", :as => :thanks
The as part will generate a helper to access that page: thanks_path.
You would need a extra action in the controller called thanks, and put whatever info you need inside, and also you will need a additional view called thanks.html.erb
Since you want everybody to go to that page after a successful submit, in your create action you would have:
format.html { redirect_to thanks_invites_path} (or thanks_path), what ever you choose, when you name the route you can check it with rake routes if it's okay, and whatever rake routes says, just add _path at the end.

Rails issue with "route matching"

I'm getting the following error when loading this URL: localhost:3000/groups/5/post/new
No route matches [GET] "/groups/5/post/new"
I am trying to create a new "post" for a specific group. Here is my Post controllers "new" action:
def new
#group = Group.find(params[:group_id])
#post = Post.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #post }
end
end
I have my routes orginized as so:
resources :groups do
resources :posts do
resources :comments
end
end
Does anyone see anything that may be causing this?
Thank you.
localhost:3000/groups/5/post/new
Should be
localhost:3000/groups/5/posts/new
Using that nested resource, shouldn't the path be?: /groups/5/posts/new (note the plural posts)

Rails 3.1/Mongoid - How to find model by name rather than id in routes

Edit: i am using Mongoid/MongoDB for my database, meaning I don't get the normal Active Record tools I think.
I have a simple Rails 3.1 app with a model Page. I would like to match '/:customURL' to the Page#show action for the Page with the relevant :customURL. How should I change the controller and routes? Keep in mind that there are a few routes from '/SOMETHING' that I want to keep. For instance '/pages' should still go to my Page#index action not try to find a page with customURL of 'pages'.
current controller:
def show
#page = Page.find(params[:id])
#title = #page.title
respond_to do |format|
format.html # show.html.erb
format.json { render json: #page }
end
end
routes:
resources :pages do
resources :feeds
end
get "pages/index"
get "pages/show"
get "pages/new"
root :to => "pages#index"
Thanks a million.
Assuming that your Page has a customURL attribute from its database table. In your controller:
def show
#page = Page.first(:conditions => {:customURL => params[:customURL]})
#title = #page.title
respond_to do |format|
format.html # show.html.erb
format.json { render json: #page }
end
end
In your routes
resources :pages, :except => :show do
resources :feeds
end
# Anything you want to match before the custom URLs needs to go above the next route definition
get "/:customURL" => "pages#show"
root :to => "pages#index"

Confused about Ruby on Rails REST Routing

I am really confused about Ruby on Rails REST routing. Even though I have specified that after the success it should go to the confirm action it goes to the show action and pass the ID=confirm.
def create
#article = Article.new(params[:article])
respond_to do |format|
if #article.save
format.html { redirect_to :action => "confirm" }
else
format.html { render :action => "new" }
end
end
end
The error I get is the following:
ActiveRecord::RecordNotFound in ArticlesController#show
Couldn't find Article with ID=confirm
Rails.root: /Projects/highoncoding
Application Trace | Framework Trace | Full Trace
app/controllers/articles_controller.rb:31:in `show'
UPDATE 1:
Here is my Route.rb file:
resources :articles
get "articles/confirm"
# config/routes.rb
MyApp::Application.routes.draw do
resources :articles do
member do
get 'confirm'
end
end
end
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def create
#article = Article.new(params[:article])
respond_to do |format|
if #article.save
# use a named route here
format.html { redirect_to confirm_article_url(#article) }
else
format.html { render :action => "new" }
end
end
end
end
you'll need to add the route so it looks like
match 'articles/confirm/', :controller => 'article', :action => 'confirm'
resources :articles
you need to have the :id in there or it will think that confirm is an id which is why you are seeing the error ID=confirm. make sure also that this is the first route. (at least before the resources for the articles controller.
You should probably add the confirm route directly in your routes file.
match 'articles/confirm' => 'articles#confirm'
resources only work for create/update/destroy/etc.

Resources