我在非用户模型的视图中写了一个表单,允许访问者登录。我想先看看这是否有效。所以我让动作“索引”进行测试。
<%form_tag(:controller=>"users",:action=>"index") do %>
Name: <%=text_field_tag "name" %><br>
Password: <%=password_field_tag "password" %><br>
<%=submit_tag "Login" %>
<% end -%>
令人惊讶的是,rails路由将页面定向到“新”视图,而浏览器导航栏仍显示:
http://0.0.0.0:3000/users
当我刷新页面时,它会显示正常的“索引”页面。
为什么会这样?
更令人毛骨悚然的是,当我将上面代码中的:action
更改为:action=>"new"
时,屏幕显示“路由错误”。当我刷新它时,它呈现正常的“新”视图。
users_controller.rb
如下:
class UsersController < ApplicationController
def index
@users=User.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @users }
end
end
def show
@user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @user }
end
end
def login
flash[:notice]="Hello";
end
def new
end
def create
@user = User.new(params[:project])
respond_to do |format|
if @user.save
format.html { redirect_to(@user, :notice => 'user was successfully created.') }
format.xml { render :xml => @user, :status => :created, :location => @user }
else
format.html { render :action => "new" }
format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
end
end
end
end
我的routes.rb如下:
Testdrive::Application.routes.draw do
resources :users do
member do
post 'login'
end
end
resources :cars
答案 0 :(得分:5)
Apneadiving的答案是正确的,但我认为澄清一些事情很重要:
您想让用户访问哪个页面?听起来您希望用户访问索引页面(您对用户登陆新页面感到惊讶)。
首先:您应该了解您所做的HTTP请求类型与控制器指向浏览器的位置之间的关系。见http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions
您的表单基本上是向/users
网址提交POST请求。 Controller始终将POSTS路由到此地址以进行CREATE操作。因此,正如Apneadiving所解释的那样,你发送的post params不是CREATE所期望的,所以保存失败并且你被重定向到users/new
现在,我在您指定的表单中看到::controller => 'users', :action => 'index'
。所以,这就是我看到你希望人们登陆索引页面的地方。但是,您需要了解的是,Rails表单助手不会神奇地链接到控制器层。
第二:知道Rails中的信息流基本上是单向的:来自模型的东西可以转到控制器,但不是其他方式。来自控制器的东西可以进入视图,但不是其他方式。
控制器可以从用户接收的唯一内容是HTTP请求。当您使用表单标记帮助程序时,您只是使用快捷方式来定义HTML action
元素的method
和form
属性。见http://www.w3.org/TR/html401/interact/forms.html#h-17.13
因此,即使您指定了:action => 'index'
,您的表单仍然会发送POST请求(默认情况下会形成POST)。控制器不知道你是否意味着该人要求点击索引操作,它只知道它在/users
网址上收到了POST而不是GET。因此,它将请求路由到CREATE操作。
这就是REST的全部内容。
解决方案:
您需要使用尚未预定义的操作。在您的路线中,当您放置时,您似乎尝试这样做:
resources :users do
member do
post 'login'
end
end
此代码将正确接受对users/123/login
的POST请求。
但是,因为您在用户集合的MEMBER而不是COLLECTION本身上指定了此项,所以您必须提供特定的USER_ID才能使该请求正确处理。因为您正在使用此操作进行登录,所以这不是您所需要的。见http://guides.rubyonrails.org/routing.html#nested-resources
您需要做的是为COLLECTION指定此路线(即:users/login
):
resources :users do
collection do
post 'login'
end
end
然后,在表单中,将表单标记更改为:controller => 'users', :action => 'login'
。
最后,在您的控制器中,您需要指定登录操作。在这种情况下,它可以很简单:
def login
redirect_to users_path
end
所有这一切都将收到POST并重定向到索引。但是,如果您希望表单中的params粘贴,则需要在LOGIN操作中处理它们。重定向后,它们不会持续存在并可用于您的INDEX操作。
我希望这能为你解决问题。祝你好运!
答案 1 :(得分:2)
你的问题出在你的routes.rb上。看看here。这个例子很清楚:
resources :photos do
member do
get 'preview'
end
end
描述:“这将通过GET识别/ photos / 1 / preview”。
因此,请回到您的代码:post login
行不会导致您打算到达目的地。
相反,帖子请求会定向到“创建”视图,因为这是您通过键入resources :users
所要求的内容(请参阅here)。
因为没有正确保存,它会重定向到“新”视图,因为:
else
format.html { render :action => "new" }
那么解决方案是什么?以下是一些曲目:
params[:project]
创建你的新用户。