我在两个不同的页面上有一个相同控制器和操作的表单,并希望模型上的验证适用于这两个位置,但我似乎无法使渲染/重定向适用于两者。
默认控制器:
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方法,但这并没有显示验证,当前值丢失了。我有一个看看引用路径并试图提取控制器和方法并重新渲染它的游戏,但我没有取得多大成功。
我希望避免为每条路线添加自定义逻辑,并且不希望为我希望能够创建作业的每个页面添加新操作。
答案 0 :(得分:1)
我通常这样做的方法是通过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
答案 1 :(得分:0)
所以我使用了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警报工作得更好,更好。