Rails 3アプリでページ固有のJavaScriptを追加する最良の方法は?


159

Rails 3には、かなりクールないくつかの控えめなJavaScriptがあります。

しかし、私は特定のページに追加のJavaScriptを含めるための最良の方法は何かと思っていました。

たとえば、以前に行った可能性がある場合:

<%= f.radio_button :rating, 'positive', :onclick => "$('some_div').show();" %>

次のようにして、目立たなくすることができます

<%= f.radio_button :rating, 'positive' %>

# then in some other file
$('user_rating_positive').click(function() {
  $('some_div').show();
}

だから私は私の質問がそのJavaScriptをどこに/どのように含めるかだと思いますか?application.jsこのJavaScriptはこの1つのビューにのみ適用できるため、ファイルをいっぱいにしたくありません。どういうわけか各ページのカスタムJavaScriptファイルを含めるか、ヘッダーが検索するインスタンス変数に貼り付けますか?



これがどのように機能し、何が最善であるかを完全に理解したい場合は、railsapps.github.io/rails-javascript-include-external.htmlをお読みください。これは、このトピックに関して私が見た中で最高のドキュメントです。Railsだけでなく、Web開発に携わるすべての人にとって、すばらしい読み物です。そのため、レールのように物事を行うのが最善です。私は今後の質問にUnholy Railsを必ず使用します。ワオ。
DutGRIFF 2014年

2
@KateGregoryの方が新しい。
Ciro Santilli郝海东冠状病六四事件法轮功

回答:


153

私がしたいのは、ビューごとのJavascriptをcontent_for :headブロックに含めてyieldから、アプリケーションレイアウトのそのブロックに含めることです。例えば

それがかなり短い場合:

<% content_for :head do %>
  <script type="text/javascript">
    $(function() {
      $('user_rating_positve').click(function() {
        $('some_div').show();
      }
    });
  </script>
<% end %>

または、長い場合は、次のようになります。

<% content_for :head do %>
  <script type="text/javascript">
    <%= render :partial => "my_view_javascript"
  </script>
<% end %>

次に、レイアウトファイルで

<head>
  ...
  <%= yield :head %>
</head>

40
なぜ使用しないの<%= javascript_include_tag "my_javascipt_file" %> ですか?
AJP 2011

5
@AJP私はそれが資産パイプラインの目的を打ち負かすと思います
lulalala

2
@lulalalaしかし、答えのコードはとにかくそれをしませんか?
AJP 2012年

8
@AJPそれは厄介ですが、それはあなたの答えよりも1つ少ないHTTPリクエストを行う必要があります。
lulalala 2012年

4
私はこの記事を気に入りましたrailsapps.github.com/rails-javascript-include-external.html
Ziggy

103

JavaScriptを1つのページだけに含めたい場合は、もちろんインラインでページに含めることができますが、JavaScriptをグループ化してアセットパイプラインや縮小されたjsなどを利用したい場合は、そうすることができ、追加のサイトの特定のコントローラー/ビュー/セクションにのみ適用されるグループにjsを分割することにより、特定のページにのみ組み合わされて読み込まれるjsアセット。

アセット内のjsをフォルダーごとに個別のマニフェストファイルとともにフォルダーに移動します。したがって、バックエンドでのみ使用される管理jsライブラリがある場合は、次のようにします。

  • 資産
    • javascripts
      • 管理者
        • ... js
      • admin.js(管理者グループのマニフェスト)
      • application.js(アプリグローバルグループのマニフェスト)
      • グローバル
        • ... js

既存のapplication.js

//= require jquery
//= require jquery_ujs
//= require_tree ./global // requires all js files in global folder

新しいadmin.jsマニフェストファイル

//= require_tree ./admin // requires all js files in admin folder

config / production.rbを編集して、この新しいjsマニフェストがロードされていることを確認してください

config.assets.precompile += %w( admin.js )

次に、ページレイアウトを調整して、ページヘッドに追加のjsを含めることができるようにします。

<%= content_for :header %>   

次に、この特定のjsグループ(および通常のアプリケーショングループ)や、ページ固有のjs、cssなどを含めるビューで、次のようにします。

<% content_for :header do %>
  <%= javascript_include_tag 'admin' %>  
<% end %>

もちろん、cssを使用して同じことを行い、サイトの特定の領域にのみ適用するために同様の方法でグループ化することができます。


すべてのマニフェストを同じ場所に保持する場合は、そのフォルダー内のすべてをプリコンパイルするようにRailsに指示できます。そうすれば、production.rbを1回編集するだけで済み、追加した内容を追跡する必要がなくなります。
2012年

あなたがそれを行うことができることを知りませんでした-それであなたはあなたのマニフェストと個々のjsグループを含む「マニフェスト」フォルダーを持つことができましたか?これを試してみるかもしれません。私は彼らがあなたがすべてのjsをどこにでもインポートされた1つの大きなファイルに単にグロブすることを想定しているように思われるので、彼らがデフォルトでもう少し健全な設定を持っていればいいのに
ケニーグラント

奇妙なことに、を使用するとSprockets :: FileNotFoundエラーが発生しますが、Rails 3.2.12 //= require_tree ./globalを使用するとエラーが発生しません//= require_directory ./global
QIX

2
最終的に多くのスクリプトタグが作成されるようです。アセットパイプラインの目標はスクリプトタグを1つだけにすることだと思いましたか。ページ固有になるようにJavaScriptを記述します。
ジギー

1
分かったと思う。ただし、追加のスクリプトタグを回避することは、ページの読み込み時間にとって非常に重要です。
Ziggy

12

これらの答えは私にトンを助けました!誰かがもう少し欲しいなら...

  1. プリコンパイルしたい場合は、JavaScriptをマニフェストに入れる必要があります。ただし、以降のすべてのjavascriptファイルが必要な場合はapplication.js.coffee、別のページに移動するたびにすべてのjavacsriptsがロードされ、ページ固有のJavaScriptを実行する目的が無効になります。

したがって、speciifc.jsすべてのページ固有のJavaScriptファイルを必要とする独自のマニフェストファイル(など)を作成する必要があります。また、require_treeから変更application.js

app / assets / javascripts / application.js

//= require jquery
//= require jquery_ujs
//= require_tree ./global

app / assets / javascripts / specific.js

//= require_tree ./specific

次に、environments/production.rbこのマニフェストをconfigオプションを使用してプリコンパイル済みリストに追加します。

config.assets.precompile += %w( specific.js )

できた!常に読み込まれる必要があるすべての共有 JavaScriptはapp/assets/javascripts/globalフォルダに配置され、ページ固有のJavaScript はに配置されますapp/assets/javascripts/specific。次のようなビューからページ固有のJavaScriptを呼び出すだけです。

<%= javascript_include_tag "specific/whatever.js" %> //.jsはオプションです。

これで十分ですが、私javascript_include_tag params[:controller]も活用したいと思いました。コントローラーを作成すると、app/assets/javascripts他の人が述べたように、関連するcoffeescriptファイルが生成されます。本当にコントローラー固有の JavaScriptがあり、ユーザーが特定のコントローラービューに到達したときにのみ読み込まれます。

そこで別のマニフェストを作成しました controller-specific.js

app / assets / javascripts / controller-specific.js

//= require_directory .

これには、コントローラーに関連付けられたすべての自動生成されたコーヒースクリプトが含まれます。また、それをプリコンパイル済みリストに追加する必要があります。

config.assets.precompile += %w( specific.js controller-specific.js )


詳細な回答をありがとうございました。この行はどこに置くべきですか javascript_include_tag params[:controller]。現在、私のapplication.html.erbにはこの行がありjavascript_include_tag 'application'ます。これを別の行に置き換えますか?
simha 2013

1
また、この行<%= javascript_include_tag "specific/whatever.js" %>content_for :headerブロックに入れるべきですか?
simha 2013

1
をいじる必要があるのは私には奇妙ですconfig.assets.precompile。すべてがapp/assets/javascripts/*.js自動的にプリコンパイルされていませんか?
AlexChaffee 2014

@AlexChaffee自動的に使用できるファイルはapplication.cssおよびのみですapplication.js。他のファイルは、他のファイルに含めるか、を使用してリストする必要がありますconfig.assets.precompile続きを読む
Sung Cho

マニフェスト宣言は移動されました。Rails 4.2.0を実行しています。#:とproduction.rbファイルでこのコメントを発見したconfig.assets.precompileconfig.assets.versionのconfig /初期化子/ assets.rbに移動してきた
素っ気

11

私は以下を好む...

application_helper.rbファイル内

def include_javascript (file)
    s = " <script type=\"text/javascript\">" + render(:file => file) + "</script>"
    content_for(:head, raw(s))
end

次に、特定のビュー(この例ではapp / views / books / index.html.erb)

<% include_javascript 'books/index.js' %>

...私のために働くようです。


9

アセットパイプラインや複雑な回避策を使用して、必要なページ固有のJavaScript(同情)を取得したくない場合は、上記の回答と同じように達成できるが、コードが少ない、最も単純で最も堅牢な方法は、使用する:

<%= javascript_include_tag "my_javascipt_file" %>

注:これには、includeタグごとに、使用する回答よりも1つ多くのhttpリクエストが必要です。 content_for :head


javascript_include_tagまさに私が探していたものでした、AJPは乾杯しました
トムマッケンジー

「my_javascipt_file」はどこに置きますか?アセット/ JavaScriptで?しかし、もしそうなら、それ//= require .はapplication.js ので自動的に取得されませんか?
qix 2013年

@Linusはい、//= require .そのスクリプトをサイトの任意のページに取り込みます。そのため、Kenny Grant(use //= require_tree ./global)またはbjgが提案するようなことを行う必要があります。
AJP 2013年

1
これは私にとってはるかに簡単な方法でした。application.jsに変更//= require_tree .//= require_directory .、assets \ javascriptsにサブディレクトリを作成しました。あなたが行を追加することで、あなたのJSをプリコンパイルする設定\初期化子\ assets.rbに新しいディレクトリを含める必要があること注:Rails.application.config.assets.precompile += %w( new_dir/js_file.js )
Jonesy


3

私の理解では、アセットパイプラインは、すべてのjsを1つの(縮小された)ファイルにまとめることにより、ページの読み込み時間を短縮することを目的としています。これは一見不快に思えるかもしれませんが、実際にはCやRubyなどの一般的な言語にすでに存在する機能です。「include」タグのようなものは、ファイルが複数含まれるのを防ぎ、プログラマーがコードを編成するのを助けることを意図しています。Cでプログラムを作成してコンパイルすると、実行中のプログラムのすべての部分にそのすべてのコードが存在しますが、メソッドがメモリにロードされるのは、そのコードが使用されている場合のみです。ある意味で、コンパイルされたプログラムには、コードが適切にモジュール化されていることを保証するものは何も含まれていません。このようにプログラムを作成することでコードをモジュール化し、オペレーティングシステムは、特定の場所に必要なオブジェクトとメソッドのみをメモリに読み込みます。「メソッド固有のインクルード」などもあるのでしょうか?Railsアプリが落ち着いている場合、これは本質的にあなたが求めているものです。

ページ上のHTML要素の動作を強化するようにJavaScriptを記述した場合、それらの関数は設計上「ページ固有」です。コンテキストに関係なく実行されるように記述した複雑なコードがある場合は、とにかくそのコードをhtml要素にバインドすることを検討してください(Garber-Irishメソッドで説明されているように、bodyタグを使用できます)。関数が条件付きで実行される場合、パフォーマンスはおそらくこれらすべての余分なスクリプトタグよりも小さくなります。

rails apps projectで説明されているように、私はpaloma gem の使用を考えています。次に、パロマコールバックにページ固有の関数を含めることで、JavaScriptをページ固有にすることができます。

Paloma.callbacks['users']['new'] = function(params){
    // This will only run after executing users/new action
    alert('Hello New Sexy User');
}; 

あなたはレールを使用しているので、あなたは宝石が好きだということを知っています:)


3

Railsを非常に優れたものにする重要な機能を失うため、アセットパイプラインの外でJSまたはCSSファイルをロードしないでください。そして、あなたは別の宝石を必要としません。私はできるだけ少ない宝石を使用することを信じており、ここでは宝石を使用する必要はありません。

必要なものは「コントローラ固有のJavascript」として知られています(「アクション固有のJavascriptは下部に含まれています」。これにより、特定のコントローラ用の特定のJavaScriptファイルをロードできます。Javascriptをビューに接続しようとすることは一種です。 。逆方向であり、MVC設計パターンに従っていない。それをコントローラーまたはコントローラー内のアクションに関連付けたい場合。

残念ながら、何らかの理由で、Rails開発者はデフォルトで、すべてのページがアセットディレクトリにあるすべてのJSファイルをロードすることにしました。彼らがデフォルトで「コントローラー固有のJavaScript」を有効にする代わりにこれを行うことに決めた理由は、私には決してわかりません。これは、デフォルトで次のコード行を含むapplication.jsファイルを介して行われます。

//= require_tree .

これはディレクティブと呼ばれます。これは、sprocketsがassets / javascriptsディレクトリにあるすべてのJSファイルをロードするために使用するものです。デフォルトでは、sprocketsはapplication.jsとapplication.cssを自動的にロードし、require_treeディレクティブはそれぞれのディレクトリにあるすべてのJSとCoffeeファイルをロードします。

注:足場を作成するとき(足場を作成していない場合は、今から始めるのがよいでしょう)、Rails は、その足場のコントローラー用のコーヒーファイルを自動的に生成します。コーヒーファイルではなく標準のJSファイルを生成する場合は、Gemfileでデフォルトで有効になっているコーヒーgemを削除すると、代わりにスキャフォールドがJSファイルを作成します。

「コントローラ固有のJavaScript」を有効にする最初のステップは、application.jsファイルからrequire_treeコードを削除することです。それでもグローバルJSファイルが必要な場合は、assets / javascriptsディレクトリ内のフォルダに変更してください。IE:

//= require_tree ./global

ステップ2: config / initializers / assets.rbファイルに移動し、以下を追加します。

%w( controllerone controllertwo controllerthree ).each do |controller|
  Rails.application.config.assets.precompile += ["#{controller}.js", "#{controller}.css"]
end

必要なコントローラ名を挿入します。

ステップ3: application.html.erbファイルのjavascript_include_tagをこれで置き換えます(params [:controller]の部分に注意してください:

<%= javascript_include_tag 'application', params[:controller], 'data-turbolinks-track': 'reload' %>

サーバーとビオラを再起動してください!足場で生成されたJSファイルは、そのコントローラーが呼び出されたときにのみロードされます。

コントローラの特定のACTIONに特定のJSファイルをロードする必要があります。IE / articles / new?代わりにこれを行ってください:

application.html.erb

<%= javascript_include_tag "#{controller_name}/#{action_name}" if AppName::Application.assets.find_asset("#{controller_name}/#{action_name}") %>

config / initializers / assets.rb

config.assets.precompile += %w(*/*)

次に、assets / javascriptsフォルダーにコントローラーと同じ名前の新しいフォルダーを追加し、内部にアクションと同じ名前のjsファイルを置きます。次に、その特定のアクションでロードします。


1

わかりましたので、おそらくこれはこれまでで最悪の回避策のようですが、.jsファイルをレンダリングするだけのコントローラーメソッドを作成します

コントローラ

def get_script
   render :file => 'app/assessts/javascripts/' + params[:name] + '.js'
end
def get_page
   @script = '/' + params[:script_name] + '.js?body=1'
   render page
end

見る

%script{:src => @script, :type => "text/javascript"}

何らかの理由でこれを行いたくない場合は、お知らせください。


1

JSを追加するための推奨される方法はフッターにあるため、次の方法で行うことができます。

show.html.erb:

<% content_for :footer_js do %>
   This content will show up in the footer section
<% end %>

layouts / application.html.erb

<%= yield :footer_js %>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.