Rails POST 来自两个单独页面的方法

Rails POST method from two separate pages

我在两个不同的页面上有一个用于相同控制器和操作的表单,我希望对模型的验证适用于两个位置,但我似乎无法让 render/redirect 对这两个页面都起作用。

默认控制器:

def create
  @job = Job.new(job_params)

  if @job.save
    redirect_back fallback_location: jobs_path, flash: { success: 'New job was added.' }
  else
    render :new
  end
end

这在添加新作业时有效,但如果失败,它将始终重定向回 jobs/new 路由。

我试过使用 redirect_back 方法,但这并没有显示验证结果,当前值也丢失了。我玩过查看引用路径并尝试提取控制器和方法并重新呈现的游戏,但我没有取得太大成功。

我想避免必须为每个路由添加自定义逻辑,并且不想为我希望能够在其上创建作业的每个页面执行新操作。

我通常这样做的方式是通过 JavaScript 提交表格。这样,如果它失败了,我可以只渲染一个 alert() 和任何错误消息。这些值仍然存在(因为我没有离开页面)。如果成功,我只需发出一个 window.location 到我想去的下一页。

为此,请将 remote: true 选项添加到 form_for/form_tag。然后在你的控制器中:

if @job.save
  render js: "window.location = 'new/path/after/save'"
else
  render js: "alert(\"#{@job.errors.full_messages.first}\")"
end

所以我使用了 Ryan 的建议并设置了一个 JS 响应。在这里发布给未来的读者。

控制器:

# app/controllers/jobs_controller.rb
def create
  @job = Job.new(job_params)

  if @job.save
    redirect_back fallback_location: jobs_path, flash: { success: 'New job was added.' }
  else
    respond_to do |format|
      format.html { render :new }
      format.js
    end
  end
end

查看:

# app/views/jobs/create.js.erb
var errors = <%= raw @job.errors.to_json %>;
validation.parseErrors('job', errors);

JS:

# app/assets/javascripts/client_validation/client_validation.coffee
@validation =
  parseErrors: (model, errors)->
    validation.clearErrors()
    for field, errorList of errors
      $field = $ "\##{model}_#{field}"
      $field.closest('.form-group').addClass 'has-danger'
      for error in errorList
        $field.after "<div class='form-control-feedback'>#{field} #{error}</div>"
  clearErrors: ->
    $('.has-danger').removeClass 'has-danger'
    $('.form-control-feedback').remove()

我仍然不确定这是正确的方法,但它工作得很好,比简单的 js 警报要好得多。