0

I'm working through Ryan Bates' Railscast #124: Beta Invitations. I've got all the code in place, but I haven't been able to actually get things working. When I try to send an invite email, I get this message.

    Routing Error       
    No route matches [POST] "/invitations"

If I pluralize the resource's name in Routes.rb, I get a different routing error.

    Routing Error
    uninitialized constant InvitationsController

What am I doing wrong?

Here's my Routes.rb file.

  resources :users, :invitation
  resources :sessions, :only => [:new, :create, :destroy]

  match '/hunts', :to => 'hunts#index'

  match '/signup/',  :to => 'users#new'
  match '/signin',  :to => 'sessions#new'
  match '/signout', :to => 'sessions#destroy'
  match '/contact', :to => 'pages#contact'
  match '/about',   :to => 'pages#about' 
  match '/help',    :to => 'pages#help'

  root :to => "pages#home"
  match ':controller(/:action(/:id(.:format)))'
end

And my Invitation Controller.

class InvitationController < ApplicationController

  def new
    @invitation = Invitation.new
  end

  def create
    @invitation = Invitation.new(params[:invitation])
    @invitation.sender = current_user
    if @invitation.save
      if logged_in?
        Mailer.deliver_invitation(@invitation, signup_url(@invitation.token))
        flash[:notice] = "Thank you, invitation sent."
        redirect_to root_path
      else
        flash[:notice] = "Thank you, we will notify when we are ready."
        redirect_to root_path
      end
    else
      render :action => 'new'
    end
  end

end

Update: Here's the info requested. Views/invitation/html.erb

    <%= form_for @invitation do |f| %>
      <p>
        <%= f.label :recipient_email, "Friend's email address" %><br />
        <%= f.text_field :recipient_email %>
      </p>
      <p><%= f.submit "Invite!" %></p>
    <% end %>
tereško
  • 56,151
  • 24
  • 92
  • 147
Ben Downey
  • 2,213
  • 4
  • 30
  • 53

2 Answers2

2

rake routes is a very useful tool which you can use to see all the routes defined for your application.

You have added resources :invitation which defines the following routes

invitation_index GET    /invitation(.:format)          invitation#index
                 POST   /invitation(.:format)          invitation#create
  new_invitation GET    /invitation/new(.:format)      invitation#new
 edit_invitation GET    /invitation/:id/edit(.:format) invitation#edit
      invitation GET    /invitation/:id(.:format)      invitation#show
                 PUT    /invitation/:id(.:format)      invitation#update
                 DELETE /invitation/:id(.:format)      invitation#destroy

Note that you are calling the InvitationController's actions.

So nothing is wrong with your route -> controller mapping.

You are just posting to a non-existent route. When you pluralize the route's name, you end up having a non-existent controller (InvitationsController).

Just change the URL you're posting to and you're good to go.

shime
  • 8,005
  • 1
  • 27
  • 45
  • So what's the most RESTful thing to do here? Pluralize the Invitation controller or change the URL I'm posting to? – Ben Downey Apr 08 '12 at 00:05
  • 2
    I would go for a plural name of the controller. It's definitely more RESTful. The common pattern in rails community is - if you're in doubt, follow the convention - since one of the rails mantras is "Convention over configuration". Your singular routes have a better chance of blowing up. Check [this](http://stackoverflow.com/questions/646951/singular-or-plural-controller-and-helper-names-in-rails) out. – shime Apr 08 '12 at 02:05
  • Beautiful. Thanks for the link! – Ben Downey Apr 08 '12 at 03:13
0

Try to use the plural when you call resources in your config/routes.rb:

resources :users, :invitations

This happens because you pass an instance of the Invitation model (@invitation) to this helper, it pluralize the class name to know where to submit.
Moreover, since @invitation is not yet saved in the DB (@invitation.new_record? returns true) then form_for set the form's method to "POST".

This information means the POST request to 'invitations' is processed by "invitations#create" (The create method of the InvitationsController class). It's convention over configuration, if you want to access invitations in a RESTful way and use resources in your config/routes.rb things must be named in a certain way to work out of the box (or you could simply override the "action" attribute of your form using some of the form helpers options).

BTW if you want to make things in a different manner you should read the Rails Guide to Routing and see if some option can help you to define your invitations routing rules, and have a look at the REST chapter of the Getting Started Rails Guide.

UPDATE: I missed the sentence "If I pluralize the resource's name in Routes.rb, I get a different routing error."

BTW, the problem is your controller class name is "InvitationController" while the form generated by the form_for helper submit to "/invitations".

Michael Durrant
  • 84,444
  • 83
  • 284
  • 429
Aldo 'xoen' Giambelluca
  • 9,881
  • 7
  • 28
  • 39