Hi, I just ran into this ActionController::RoutingError and just
wanted to check if someone can confirm this as a bug in the Rails 3
beta gem.
config/routes.rb contains:
get ‘login’ => ‘session#new’
post ‘login’ => ‘session#create’, :as => :login
GET /login works fine:
Started GET “/login” for 127.0.0.1 at 2010-02-20 17:45:49
SQL (0.3ms) SET SQL_AUTO_IS_NULL=0
Processing by SessionController#new as HTML
Rendered session/new.html.haml within layouts/application.html.haml
(77.9ms)
Completed in 85ms (Views: 84.1ms | ActiveRecord: 0.2ms) with 200
However POST /login gives the following error:
Started POST “/login” for 127.0.0.1 at 2010-02-20 17:45:58
SQL (0.3ms) SET SQL_AUTO_IS_NULL=0
ActionController::RoutingError (No route matches “/login”):
rake routes returns the expected urls:
login POST /login
{:controller=>“session”, :action=>“create”}
GET /login
{:controller=>“session”, :action=>“new”}
Hi, I just ran into this ActionController::RoutingError and just
wanted to check if someone can confirm this as a bug in the Rails 3
beta gem.
config/routes.rb contains:
get ‘login’ => ‘session#new’
post ‘login’ => ‘session#create’, :as => :login
Daniel, can you post the complete route? The ‘get’ and ‘post’ HTTP
verbs
should exist within a member or collection block of a resource block.
For
example,
resources :posts do
collection do
get :search
end
end
or
resources :posts do
get :search, :on => :collection
end
Note: both of the examples are equivalent.
Next, your routes look ambiguous meaning that you could have easily
implemented this as follows:
match ‘login’ => “user_sessions#lnew”, :as => :login
match ‘login’ => “user_sessions#destroy”, :as => :logout
ah the last bit of the previous message should have not been in there,
but should have been in this message.
Changing the Session class to:
class Session < ActiveRecord::Base
end
and adding a table to the database (which is not the goal here just a
workaround for figuring out what’s going on here) makes the everything
work correctly with:
form_for(Session.new, :url => login_path)
This clearly shouldn’t be related but this is what I have so far…
Ok what is really happening here is that for_for(Session.new, :url =>
login_path) includes a hidden input field setting _method to put which
correctly complains about a routing error since no route is defined
for PUT /login
Remaining question to me is why does form_for set the method to PUT
which means for every object not responding to new_record? it will
automatically set the method to PUT
since the options are reverse merged later with the provided options
this can be avoided by setting explicit :html => { :method => :post }
in form_for - not sure though if this is entended behavior…
If someone has some inside view comments would be appreciated…
not quite the routes you are providing are not equivalent to what I
wanted to archive and they are the only routes in the routing file for
this test. What I want is:
GET /login should be resolved to session#new
POST /login should be resolved to session#create
possible ways of doing so are according to the action_dispatch/
routing.rb file
get ‘login’ => ‘session#new’
post ‘login’ => ‘session#create’, :as => :login
or when using match
match ‘login’ => ‘session#new’, :via => :get
match ‘login’ => ‘session#create’, :via => :post
the above two examples are equivalent since get and post just add
the :via => :method to the options and call match
Yes, this is correct and expected, the question to me is rather if it
is expected behavior to assume an update operation if the object
doesn’t respond to :new_record?
Yes, this is correct and expected, the question to me is rather if it
is expected behavior to assume an update operation if the object
doesn’t respond to :new_record?
Yes, this is expected because AR instance is either new (i.e. hasn’t
been
saved) or
not new (i.e. has been saved). One can easily test this in the Rails
console.
Ok but I’m not using an ActiveRecord instance here. I just temporarily
made Session inherit from ActiveRecord::Base for testing purpose. And
the attr_accessors didn’t override anything since the table I created
only contained an id attribute.
Session class inherits from ActiveRecord::Base. Thus, if you create an
instance(s) of
Session, then each instance is a type of ActiveRecord::Base.
The idea here was to just create a normal class (not inheriting from
ActiveRecord) and to only use the validations module. The session is
not going to be stored in the database.
Ok but I’m not using an ActiveRecord instance here. I just temporarily
made Session inherit from ActiveRecord::Base for testing purpose. And
the attr_accessors didn’t override anything since the table I created
only contained an id attribute.
The idea here was to just create a normal class (not inheriting from
ActiveRecord) and to only use the validations module. The session is
not going to be stored in the database.
The original implementation of Session was:
class Session
include ActiveModel::Validations
attr_accessor :login, :password, :id
end
Maybe I should make clear that I changed the Session implementation
back to its original state after finding what caused the PUT method
being attached. Looks like you were still assuming my Session inherits
from ActiveRecord::Base. It was just for testing purpose to see if it
works correctly with an ActiveRecord model.
I know how to add validations to it etc. (not included in this post to
keep the examples lean) the point I’m trying to make here is the
dependency of form_for on the :new_record? method.
What are you trying to prove here?
I’m not using ActiveRecord and my Session class IS NOT inheriting from
ActiveRecord::Base either
I’m trying to prove to you that ActiveModel works without
ActiveRecord::Base. It
works so much so I’m building ActiveRecord style interface to work with
Maglev.
Next, in your initial e-mail to the mailing list, you mentioned that
there
was a possible
bug in Rails 3 routing. What does this have to do with the possible bug
in
routing?