Rails - 如何在共享表单上显示验证错误

时间:2017-03-12 10:29:54

标签: ruby-on-rails simple-form

我正在制作一个可在多个页面中重复使用的表单。用户可以发送包含此表单的电子邮件,并将其自身保存的消息保存在数据库中。

我在此表单上有两个简单的验证,错误在这个表单中得到了很好的显示:

<%= simple_form_for @message do |f| %>
    <%= f.input :email, error: "E-mail can't be empty" %>
    <%= f.input :text, error: "Text can't be empty" %>
    <%= f.button :submit %>
<% end %>

如果我希望我的表单可以在多个页面上重用,而不是将其更改为:

<%= simple_form_for Message.new do |f| %>
    <%= f.input :email, error: "E-mail can't be empty" %>
    <%= f.input :text, error: "Text can't be empty" %>
    <%= f.button :submit %>
<% end %>

表单和验证仍然适用于此表单,但它不显示错误。我希望有人可以帮助我。

2 个答案:

答案 0 :(得分:1)

一种可能的解决方案是在ApplicationController中创建一个创建@message变量的方法,然后在显示表单所需的每个操作上调用它。

class ApplicationController < ActionController::Base
  # ..
  def load_message_for_form
    if params[:message]
      @message = Message.new(message_params)
    else
      @message = Message.new
    end
  end

  def message_params
    params.require(:message).permit(:email, :text) # add what you need
  end
end

然后在你需要表格的行动中

class UsersController < ApplicationController
  before_action :load_message_for_form, only: [:index, :new] #change this to suit your needs
end

编辑: 虽然这个解决方案确实很有效,但是应该注意不要过度使用它,因为ApplicationController很快就会被这样的东西所笼罩。但对于简单的情况,没关系。

答案 1 :(得分:1)

问题是,验证后需要无效对象才能显示错误。

使用共享表单通常意味着您希望能够在任何您喜欢的地方显示用于创建某个模型实例的表单。
这就是你的第二种形式的好处。
这就是你使用Message.new

的原因

现在,如果某些验证失败,您的控制器需要使用此无效实例重新显示表单 这只能通过表单的第一个变体来完成。

那你如何重新显示正确的形式呢?

  • 在保存时出现错误时显示正常的“新”视图。这会将您的新对象从最初嵌入的contenxt中剔除,但可能是一个很好的方法

  • 使用AJAX处理共享表单的提交,并使用控制器的响应替换共享表单,如果成功则为“OK”,如果出现错误,则表单的第一个变体。

第二种意思是:

<%= simple_form_for Message.new, remote: true do |f| %>
  <%= f.input :email, error: "E-mail can't be empty" %>
  <%= f.input :text, error: "Text can't be empty" %>
  <%= f.button :submit %>
<% end %>

然后你需要一个用于create动作的js处理程序,它取代了以下形式:app / views / messages / new.js.erb

$('.new_message').html('<%= escape_javascript render partial: 'form' %>');

成功:app / views / messages / create.js.erb:

$('.new_message').html('Got your message!');

在您的控制器中,您需要处理js请求:

  def create
    @message = Message.new(message_params)

    respond_to do |format|
      if @message.save
        format.html { redirect_to @message, notice: 'Message was successfully created.' }
        format.js 
      else
        format.html { render :new }
        format.js { render :new }
      end
    end
  end

这会将所有代码留在消息的上下文中 您不要污染ApplicationController和其他要包含共享表单的控制器。