Reactの公式チュートリアルでのエラーについてです。

発生エラー

コメントを送信した時に以下のエラーが発生しました。

jquery.min.js:4 POST http://localhost:3000/comments.json 405 (Method Not Allowed)
comments.json error Method Not Allowed

問題はコンポーネントに渡すurlでした。

// エラー
ReactDOM.render(
  <CommentBox url="comments.json" pollInterval={2000} />,
  document.getElementById('content')
);

server.rbではドキュメントルートがpublicに指定されているので、comments.jsonを問い合わせるとは/public/commnts.jsonを取得するということです。/public/comment.jsonが置いてあれば、表示に問題はなく送信だけエラーが出ます。

// 正常
ReactDOM.render(
  <CommentBox url="/api/comments" pollInterval={2000} />,
  document.getElementById('content')
);

server.rbに合わせるならurlcomments.jsonから/api/commentsに変更して、server.rbと同じディレクトリにcomments.jsonを置きましょう。その理由を知るためにserver.rbを見てみます。

Rubyのserverファイル

server.mount_proc '/api/comments' do |req, res|
  comments = JSON.parse(File.read('./comments.json', encoding: 'UTF-8'))

  if req.request_method == 'POST'
    # Assume it's well formed
    comment = { id: (Time.now.to_f * 1000).to_i }
    req.query.each do |key, value|
      comment[key] = value.force_encoding('UTF-8') unless key == 'id'
    end
    comments << comment
    File.write(
      './comments.json',
      JSON.pretty_generate(comments, indent: '    '),
      encoding: 'UTF-8'
    )
  end
  # ...
end

Rubyの場合はWEBrickを使って実装されています。mount_proc/api/commentsにアクセスされた場合に、./comments.jsonを読み込むようにしています。この時、server.rbがあるパスからの相対パスとなります。/public/comments.jsonは読み込まれません。

var CommentBox = React.createClass({
  // ...
  handleCommentSubmit: function(comment) {
    var comments = this.state.data;
    var newComments = comments.concat([comment]);
    this.setState({data: newComments});
    $.ajax({
      url :this.props.url,
      dataType: 'json',
      type: 'POST',
      data: comment,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        this.setState({data: comments});
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  // ...
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        <CommentList data={this.state.data} />
        <CommentForm onCommentSubmit={this.handleCommentSubmit} />
      </div>
    );
  }
});

javascriptでコメントを送信時にはAPIを叩いているだけで保存しているわけではありません。comments.jsonを叩いても内容が取得できるだけです。これが最初のエラーが発生する理由でした。