Search code examples
ruby-on-railsrespond-to

Modifying respond_to in Rails 3


Here is the premise:

I have a model called Rules, which has a corresponding controller and view. I'd like the user to be able to create a new rule from their Dashboard, which has a separate view and controller.

The dashboard has three tabs called "Rules", "Rulesets, and "Games." Each tab has its own partial, so for Rules I'm using the _rules.erb partial which looks like this

<div id="dashboard-rules" class="dashboard-panel ui-nav-panel">
  <%= button_to'Create A Rule', '#', id: "create-rule-btn", class: "btn btn-primary" %>

  <div id="create-rule-form-container">
  </div>

...

</div>

Using jQuery, I'm loading the contents of the New Rules page which is controlled by the Rules controller, like this...

$('#create-rule-btn').click (e) ->
    e.preventDefault()
    $('#create-rule-form-container').load('/rules/new.html .form-horizontal')

This loads just the form from rules/new.html. My problem is that when I click the "Save Rule" button, it redirects to the /rules URL. And then either displays errors or says "Rule Saved Successfully." I'd like for it not to redirect and have the errors show in the dashboard...again, not redirect to /rules URL.

This is my Rules create action, which I think needs to be modified, I'm just not sure how:

def create
  @rule = Rule.new(params[:rule])

  respond_to do |format|
    if @rule.save
      format.html { redirect_to @rule, notice: 'Rule was successfully created.' }
      format.json { render json: @rule, status: :created, location: @rule }
    else
      format.html { redirect_to :controler => "dashboard"}
      format.json { render json: @rule.errors, status: :unprocessable_entity }
    end
  end
end

I know I have to fiddle with how respond_to is working, I just don't know how.


Solution

  • Remember that you need to set all variable you set in your dashboard in the create action in order for the following to work. This is because you're rendering the same template as the dashboard so you need to set the variables again.

    if @rule.save
      format.html { redirect_to dashboard_path, notice: 'Rule was successfully created.' }
      format.json { render json: @rule, status: :created, location: @rule }
    else
      # initialize the variables needed on the dashboard here
      format.html { render template: 'dashboard/index' }
      format.json { render json: @rule.errors, status: :unprocessable_entity }
    end
    

    One more solution is to submit the form via ajax and just refresh the page when the rule is saved.

    UPDATE: quick js solution

    in the form that creates the rules, add the following

    form_for @rule, html: { remote: true } do |f|
    

    This will submit the form via ajax. In your controller, add a format.js line after each format.json

    format.json { ... }
    format.js
    

    then create a app/views/rules/create.js.erb (or haml) file. In the file, you can add any js you want so add the following

    <% if @rule.errors.any? %>
      # add js here to append the errors in the page
    <% else %>
      window.location.reload
    <% end %>