2

I'm following these two tutorials altogether,

and implementing a simple comment system in Rails. However, I got a problem with handling the submit. I implemented a simple AJAX POST request to send my form data (as state). It looks like this:

var CommentForm = React.createClass({
    handleChange: function(e) {
    var name, obj;
    name = e.target.name;
    return this.setState((
      obj = {},
      obj["" + name] = e.target.value,
      obj
    ));
  },
    handleSubmit: function(e) {
        e.preventDefault();
        var author = React.findDOMNode(this.refs.author).value.trim();
        var text   = React.findDOMNode(this.refs.text).value.trim();
        if(!text || !author) {
            return;
        }
        $.post(this.props.postUrl, {comment: this.state}, null, "application/json");
        React.findDOMNode(this.refs.author).value = '';
        React.findDOMNode(this.refs.text).value = '';
    },
    render: function() {
        return (
            <form className="commentForm" onSubmit={this.handleSubmit}>
        <input type="text" placeholder="Your name" ref="author" name="author" onChange={this.handleChange} />
        <input type="text" placeholder="Say something..." ref="text" name="text" onChange={this.handleChange} />
        <input type="submit" value="Post" />
      </form>
        );
    }
});

As I examined the console, It looks like it is passing to the right route and the right params, except no authenticity_token param. Here is a screen shot of what is in the console.

enter image description here

In the first link that I've provided, it is said that jquery_ujs handles generating and passing an authenticity token to Ajax POST. However, this is not true in my case. What am I missing?

Edit: I've got a few answers that would fix my problem. However, I'm still curios about what makes the difference between my code and the code at this tutorial?

3 Answers 3

1

This is because you are missing in your render method to pass an authenticity_token. Either you disable the authenticity check (not recommended), or you deliver your rendered form with an authenticity token.

In this case i would recommend to use Gon for clean passing of controller variables to JS: https://github.com/gazay/gon

When you installed it:

In your controller method:

gon.authenticity_token = form_authenticity_token

In your react class:

<form className="commentForm" onSubmit={this.handleSubmit}>
    <input type="hidden" name="authenticity_token" value={gon.authenticity_token}  />
    <input type="text" placeholder="Your name" ref="author" name="author" onChange={this.handleChange} />
    <input type="text" placeholder="Say something..." ref="text" name="text" onChange={this.handleChange} />
    <input type="submit" value="Post" />
</form>
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the solution! I was not considering to disable the check, too. But I still wonder what makes this difference between his tutorial and my code?
I just checked his tutorial, he didn't paste his ApplicationController, so i can't tell if he has protect_from_forgery activated or not, at least in his own controllers he doesn't use it
Yep, thought about it too, but he explicitly says that: "If you have used other JS frameworks along with Rails (for example, AngularJS) to build similar features, you might have run into problems because your POST requests don't include the CSRF token required by Rails, so, why didn't we run into this same issue? Easy, because we are using jQuery to interact with our backend, and Rails' jquery_ujs unobtrusive driver will include the CSRF token on every AJAX request for us. Cool!" That is what confuses me. Just sent him an email.
I see, i didn't come up to that section, but i'm wondering if it's related to github.com/rails/jquery-ujs/blob/master/src/rails.js#L70 - can you confirm that your ajax call is sending the request header X-CSRF-Token?
Because you could have forgot to include apidock.com/rails/ActionView/Helpers/CsrfHelper/csrf_meta_tags in your layout, that would explain the missing value to include in the request headers.
1

You could add the authenticity_token attribute to your AJAX POST:

you could replace this line:

$.post(this.props.postUrl, {comment: this.state}, null, "application/json");

with this:

$.post(this.props.postUrl, {
    comment: this.state,
    authenticity_token: $('meta[name=csrf-token]').attr('content')
  }, null, "application/json");

Comments

0

Solved. Removed the line

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

from application.html.erb. It turns out that it was shadowing the jquery_rails while making an AJAX request.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.