如何获取使用无效数据提交的rails表单以重新填充用户输入的字段

时间:2013-09-01 21:05:35

标签: ruby-on-rails ruby-on-rails-3 devise

我正在努力构建rails 3 + devise,用户注册页面。这将是一个额外的页面,不会取代现有的设计注册页面。此页面将包含用户信息和结算信息。

我正在尝试提交表单,如果表单字段没有保存,请让重新加载的页面包含用户以前输入的数据。这是一个片段:

<%= form_for(User.new, :url => '/pricing/sign_up') do |f| %>
    <%= f.label :email %>
    <%= f.email_field :email %>
<% end %>

当表单提交无效数据时。当视图重新渲染时,输入的现有电子邮件不会保留。如何使现有用户的输入保持不变,以帮助用户快速纠正错误并提交有效表单?

由于

3 个答案:

答案 0 :(得分:6)

关键是让form_for使用正确的对象。所以,而不是

<%= form_for(User.new, :url => '/pricing/sign_up') do |f| %>

你应该使用一个实例变量来包含这个对象,比如这个

<%= form_for(@user, :url => '/pricing/sign_up') do |f| %>

控制器操作如下所示:

# Note: this may need to be an `edit` method instead?
def new
  @user = User.new
end

# Note: this may need to be an `update` method instead?
def create
  @user = User.new(params[:user])
  if @user.save
    # Do something... Usually a redirect with success message.
  else
    render :new
  end
end

这个create方法正在做的是用表单中的params填充@user对象。然后调用@user.save将在后台调用@user.valid?,如果没有返回错误,则记录将保存到数据库中。但这部分是关键。如果@user.valid?确实导致错误,则会填充@user上的错误集合。然后,在render :new完成并重新呈现您的用户表单后,表单将能够通过访问@user.errors集合来吐出错误消息。否则,就像以前那样,你总是在表单中有一个User.new对象,它永远不会有任何错误,因为它之前从未用于尝试记录验证。

如何在表单中显示错误是一个偏好问题,稍微超出了本问题的范围。以下是指南:http://guides.rubyonrails.org/active_record_validations.html#displaying-validation-errors-in-views

答案 1 :(得分:3)

我认为这是因为您的form_for声明,您在每次通话时都在创建新的User实例。

如果您将User.new移动到控制器并在new操作失败时呈现create操作,那么您应该会看到用户在表单字段中输入了值。

以下内容应该有效:

# app/controllers/users_controller.rb

def new
  @user = User.new
end

def create
  @user = User.new(params[:user])

  respond_to do |format|
    if @user.save 
      ...
    else 
      format.html { render :new }
    end
  end
end

然后在你看来:

<%= form_for(@user, :url => '/pricing/sign_up') do |f| %>
  <%= f.label :email %>
  <%= f.email_field :email %>
<% end %>

答案 2 :(得分:2)

表单字段的值由您传递给form_for的模型驱动,因此在您的情况下,它们将始终为空,因为您传递的是全新的用户对象。

您应该使用在控制器中设置的实例变量;在new操作中,这将是一个新的User模型,但在create操作中,它将是一个通过表单设置属性的模型:

# app/controllers/users_controller.rb
def new
  @user = User.new
end

def create
  @user = user.create(user_params)

  if @user.save
    redirect_to user_path(@user)
  else
    render :new
  end
end

然后是以下形式:

<%= form_for(@user, :url => '/pricing/sign_up') do |f| %>
  <%= f.label :email %>
  <%= f.email_field :email %>
<% end %>