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 警报要好得多。
我在两个不同的页面上有一个用于相同控制器和操作的表单,我希望对模型的验证适用于两个位置,但我似乎无法让 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 警报要好得多。