Rick Rick - 3 months ago 10
Ruby Question

Rails POST method from two separate pages

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.

Answer

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.

Comments