2019-12-14に更新

【Rails】Bootstrapを導入したらAjaxが機能しなくなっていたお話

参考にしたサイト

はじめに

1.起こったこと

Railsアプリで、Ajax(jQuery)を使用した機能を作っていてしばらく上手く動いていたのですが、Bootstrapを導入してjavascript周りをいじってから機能しなくなっていました。

2.解決策

とても簡単なことで、HTMLファイルのheadタグ内に記述すべきjQuery CDNscriptタグ)の位置が間違っていたのが原因でした。
さらにこのjQuery CDNscriptタグ)とjavascript_include_tagの順番がこの通りになっていることが大事なようです。(参考リンク1

app/views/layouts/application.html.erb

<head>
    ・
    ・
    ・
  <!-- Optional JavaScript -->
  <!-- jQuery first, then Popper.js, then Bootstrap JS -->
  <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>

3.解説・補足

bootstrapを導入する際に、bodyタグの一番下にjQuery CDNscriptタグ)を移動してしまっていたのが原因のようです。
記述する位置には気をつけましょう!

修正のためやってみたこと

  • Javascriptファイルが読み込まれているか確かめる

このAjaxを使用している部分は「フォーム入力時にプルダウンでテンプレートを選択 → 選択されたテンプレートの中身がフォームに自動入力される」という機能なのですが、
まずはjavascriptが正常に読み込まれていないのかと思い、
試しに「プルダウンを選択した時に選択されたテンプレートがアラートで表示される」ように、呼び出されるjavascriptにalert(template_id)を記述してみたところ、しっかりとアラートが出てきました。
javascriptは機能しているようです。

  • Ajax(jQuery)が機能しているか確かめる

次に、Ajaxで渡されるはずのtemplatesコントローラーのget_bodyアクションが処理されているかを調べました。適当な行にraise params.inspectと入れることで、その箇所でエラーが発生するはずです。
ところがプルダウンリストを選択してもエラーは発生せず、フォームにも何も反映されません。
Ajaxが機能せず、目的のコントローラーのアクションに渡っていないことがわかりました。
javascriptは読み込まれていても、Ajaxが動作しない。
つまりjQueryの読み込みが上手くいってなさそうで、調べてみると(参考リンク1)にたどり着いた経緯です。

用語

  • jQuery CDN

という単語が出てきましたが、(参考リンク2)によると、
jQueryを使うには、jQuery本体をダウンロードして読み込む方法と、CDNを経由して使う方法の2種類があるようです。後者の方が、jQueryをダウンロードする必要がなく、今回のようにHTMLファイルのheadタグ内に以下のようなsqriptタグを貼り付けるだけでjQueryが動作するようになります。

  <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
  • SDN

これが概念としてまだイマイチ理解できませんでした。
宿題とします。

MEMO

参考までに該当部分のコードを晒しておきます。
(色々余計なコードもそのままにしていると思うので、初心者の方は参考にしないでください…)

app/views/layouts/application.html.erb

<head>
  <!-- Required meta tags -->
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

  <title>Workdiary</title>
  <%= csrf_meta_tags %>
  <%= csp_meta_tag %>


  <!-- Optional JavaScript -->
  <!-- jQuery first, then Popper.js, then Bootstrap JS -->
  <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>

app/assets/javascripts/application/js

function changeTemplate(val){
  var template_id = val;

  // alert(template_id)

  $.ajax({
    url: "/templates/get_body",
    type: "GET",
    data: {
      template_id: template_id
    }
  })
}

app/controllers/concerns/templates_controller.rb

  def get_body
    template = Template.find(params[:template_id])
    @template_body = template.body
    respond_to do |format|
      format.js
    end
  end
ツイッターでシェア
みんなに共有、忘れないようにメモ

Massa

北海道でアプリ制作に取り組んでるノンプログラマな農夫。仕事や日常生活で感じる小さな不便を解消すべく趣味と実益を兼ねて遊んでます ■Python・GAS + LINE bot

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント