0

I have a remote form in my Rails 4 application for my Artists model. I have another form for my Shows, and the Shows form has a link that can be clicked if the user wishes to add a new Artist to the database from inside the Shows form. Clicking that link sends a GET request to /artists/new and the ArtistsController assigns @artist a new Artist and then renders new.js.erb, which hides the link to add a new Artist and renders the form for a new Artist in its place.

The form is rendered fine, and when I click submit a POST request is sent and it is routed to the create method in my ArtistsController The server then sends a response back that is in my create.js.erb file, but that response is interpreted by the browser as html. Instead of executing the JavaScript that is in create.js.erb it just displays the code in the browser.

Here is my Shows form

= form_for @show, html: {role: 'form'} do |f|
  - if @show.errors.any?
    #error_explanation
      %h2= "#{pluralize(@show.errors.count, "error")} prohibited this venue from being saved:"
      %ul
        - @show.errors.full_messages.each do |msg|
          %li= msg

  .row
    = f.label :venue_id
    = f.collection_select :venue_id, Venue.all, :id, :name, class: 'form-control'
  .row
    .col-sm-6
      = link_to 'New Artist', new_artist_path, id: :new_artist_link, remote: true
  .row.row-centered
    .col-sm-6
      .form-group
        = f.label :date
        = f.date_select :show_date, order: [:day, :month, :year], class: 'form-control'
    .col-sm-6
      .form-group
        = f.label :doors_open
        = f.time_select :doors_open, class: 'form-control'
  .row.row-centered
    .col-sm-6
      .form-group
        = f.label :dinner_starts
        = f.time_select :dinner_starts, class: 'form-control'
    .col-sm-6
      .form-group
        = f.label :show_starts
        = f.time_select :show_starts, class: 'form-control'
  .row.row-centered
    .col-sm-6
      .form-group
        = f.label :dinner_ends
        = f.time_select :dinner_ends, class: 'form-control'
    .col-sm-6
      .form-group
        = f.label :show_ends
        = f.time_select :show_ends, class: 'form-control'

  .form-group
    = f.submit 'Save Show', class: 'btn btn-default'

Here is my Artists form

= form_for(@artist, remote: true, authenticity_token: true, format: :js) do |f|
  - if @artist.errors.any?
    #error_explanation
      %h2= "#{pluralize(@artist.errors.count, "error")} prohibited this artist from being saved:"
      %ul
        - @artist.errors.full_messages.each do |msg|
          %li= msg

  .field
    = f.label :name
    = f.text_field :name
  .actions
    = f.submit 'Submit'

Here is my ArtistsController new and create methods

  def new
    @artist = Artist.new

    respond_to do |format|
      format.js
    end
  end

  def create
    @artist = Artist.new(artist_params)

    if @artist.save
      respond_to do |format|
        format.js
        end
      end
    end

Here is my new.js.erb

$('#new_artist_link').hide().after("<%= j render 'form' %>");

My create.js.erb. I had actual code in here, but removed it, and just replaced it with this until I can figure out the problem.

$('h1').hide();

I spent all day yesterday trying to figure this out and am totally baffled.

EDIT: Writing the following jQuery in my new.js.erb and adding post 'artists/create to my routes allowed me to post the data, the problem was that the accept header of the post was not accepting JavaScript. Is there a way to not have to write the entire ajax request and to just modify the existing one to accept javascript?

Updated create.js.erb

$('#new_artist_link').hide().after("<%= j render 'form' %>");
$('#new_artist_link').remove();
$('#new_artist').submit(function() {

    var url = "/artists/create"; // the script where you handle the form input.

    $.ajax({
        type: "POST",
        url: url,
        data: $("#new_artist").serialize(), // serializes the form's elements.
        accepts: 'application/javascript'
    });

    return false; // avoid to execute the actual submit of the form.
});
ThomYorkkke
  • 2,061
  • 3
  • 18
  • 26
  • Is this an ajax request? If so where is ajax code? – charlietfl Feb 27 '15 at 15:54
  • http://stackoverflow.com/questions/4227775/rails-form-for-remote-true-is-not-calling-js-method seem to point to the same issue. I would also check the generated HTML tag for the form to see if data-remote="true" is there. – Mingsheng Feb 27 '15 at 16:49
  • @charlietfl As far as I understand it, Rails should use ujs to generate the ajax code because I put remote: true, right? – ThomYorkkke Feb 27 '15 at 18:50
  • I don't know much about rails, but even if it is generated by rails the browser still has to be sent the code to run. Seeing that would help – charlietfl Feb 27 '15 at 18:52
  • @Mingsheng Okay, that helped. Thanks! It turned out I had to modify the accepts header to take javascript. I included an edit in my post showing what I had to do - is there a simpler way to do this that is rails-native and doesn't involve the jQuery? – ThomYorkkke Feb 27 '15 at 19:14
  • You probably should add the answer to this question instead since u got it figured out. Likely might help someone else in the future who didn't manage to find the other post. Not sure about the other issue though. Glad it helped. – Mingsheng Feb 27 '15 at 19:19
  • I'm having the same problem. I'm totally baffled why Rails isn't working like it used to. I've been programming Rails and remote forms for over 8 years and these have always "just worked". This seems like an issue that should be submitted to the Rails Core team or the `jquery-rails` team. Adding "remote: true" should be all you need to do here - the framework should set the Accept headers properly, IMHO. – danielricecodes Apr 29 '17 at 15:00

1 Answers1

0

I figured out the problem - my POST accept header did not include text/javascript, so I had to add the following to my new.js.erb

$('#new_artist').submit(function() {

    var url = "/artists/create"; // the script where you handle the form input.

    $.ajax({
        type: "POST",
        url: url,
        data: $("#new_artist").serialize(), // serializes the form's elements.
        accepts: 'application/javascript'
    });

    return false; // avoid to execute the actual submit of the form.
});

I also had to add post 'artists/create' to my routes.rb

ThomYorkkke
  • 2,061
  • 3
  • 18
  • 26