嵌入表单而不会破坏内置的Rails验证

时间:2019-04-27 10:28:50

标签: ruby-on-rails

我正在尝试创建一个可重用的评论资源,可以将其添加到其他资源中,以便他们可以发表评论。我可以使用以下命令相对轻松地实现此目标:

IE:views / blog / index.html.erb

# blog here...
<%= render partial: 'comments/form', locals: { comment: Comment.new } %>
<%= render @comments %>

controllers / comments_controller.rb

def create
  @comment = Comment.new(comment_params)

  respond_to do |format|
    if @comment.save
      format.html { redirect_to @comment, notice: 'Comment was successfully created.' }
      format.json { render :show, status: :created, location: @comment }       
    else
      format.html { render :new }
      format.json { render json: @comment.errors, status: :unprocessable_entity }
    end
end
...

views / comment / _form.html.erb

<%= bootstrap_form_with(model: comment, local: true) do |form| %>
  <%= form.text_area :message, rows: 5 %>
  <%= form.submit class: 'btn btn-secondary float-right' %>
<% end %>

这有效,但是无论我如何配置表单,表单验证均不起作用。

我尝试配置表单的方式:

解决方案1 ​​

<%= form_with(model: comment, local: false) do |form| %>

此解决方案有效,但是本机Rails表单验证失败,并且不会显示验证错误。

解决方案2

<%= form_with(model: comment, format: 'json') do |form| %>

再一次表单验证不起作用,需要我自己用javascript进行连接(我宁愿使用开箱即用的功能)

解决方案3:

<%= form_with(model: comment, local: true) do |form| %>

此方法有效,但是当存在验证问题时(并在那里成功验证),它会将我重定向到原始页面之外,并重定向到/ comments / new。

我发现以“轨道方式”做事有很多好处。我的问题是在不同资源视图中嵌入资源表单并仍然获得不错的内置Rails验证的正式Rails方法是什么?

处理此问题的官方方法是什么?

2 个答案:

答案 0 :(得分:2)

local:true模式的验证不起作用,因为您每次都将新的空对象传递给表单。您需要传递一个保存失败的对象(因此设置了errors)。

'Rails-way'是简单的CRUD,您在其中使用相同的控制器来呈现和处理表单,并且一旦使用共享表单破坏了表单(您的注释控制器显然就不知道如何呈现页面表单了) ),则可以使用javascript(或使用远程表单)进行操作。

对于后者-确保在注释create操作中正确呈现错误消息

答案 1 :(得分:0)

正如@Vasfed所说,您正在打破 Rails-way ,因此您需要在控制器上做更多的工作:

def index
  @comment = Comment.new # You need this to remove it from the partial render
  @comments = Comments.all
end

def create
  @comment = Comment.new(comment_params)

  respond_to do |format|
    if @comment.save
      format.html { redirect_to @comment, notice: 'Comment was successfully created.' }
      format.json { render :show, status: :created, location: @comment }       
    else
      format.html do
        @comments = Comments.all # DRY this with a private method and use it in index
        render :index
      end
      format.json { render json: @comment.errors, status: :unprocessable_entity }
    end
end

您认为不需要设置locals[:comment],因为您可以直接在表单中使用@comment,但可以保留以下内容:

<%= render 'comments/form', comment: @comment %>
<%= render @comments %>

对不起,如果我(可能)忘记了一些东西。我没有测试。