Reputation: 1073
I have a form for the same controller and action on two different pages and want the validation on the model to apply in both locations but I cant seem to get the render/redirect to work for both.
The default controller:
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
This works when a new job is added, but if it fails it will always redirect back to the jobs/new
route.
I have tried using the redirect_back method but this does not show the validation and current values are lost. I have had a play with looking at the referrer path and trying to extract the controller and method and re-render that but I have not had much success.
I would like to avoid having to add custom logic for each route and dont want a new action for each page I want to be able to create a job on.
Upvotes: 0
Views: 87
Reputation: 1073
So I used Ryan's suggestion and set up a JS response. Posting here for future readers.
Controller:
# 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
View:
# 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()
I am still not certain that this is the right way of doing this but it works quite nicely and much better than a simple js alert.
Upvotes: 0
Reputation: 4053
The way I usually do this is by submitting the form via JavaScript
. That way, if it fails, I can just render an alert()
with whatever error message there is. The values are still there (as I haven't left the page). If it succeeds, I just issue a window.location
to the next page I want to go.
To do that, add the remote: true
option to your form_for
/form_tag
. Then in your controller:
if @job.save
render js: "window.location = 'new/path/after/save'"
else
render js: "alert(\"#{@job.errors.full_messages.first}\")"
end
Upvotes: 1