¿La mejor manera de agregar JavaScript específico de página en una aplicación Rails 3?


Rails 3 tiene un poco de JavaScript discreto que es bastante genial.

Pero me preguntaba cuál es la mejor manera de incluir JavaScript adicional para una página en particular.

Por ejemplo, donde podría haber hecho anteriormente:

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

Ahora podemos hacerlo discreto con algo como

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

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

Así que supongo que mi pregunta es dónde/cómo incluir ese JavaScript? No quiero llenar el archivo application.js porque este JavaScript solo es aplicable a esta vista. Debería incluir un archivo JavaScript personalizado para cada página de alguna manera, o pegarlo en una variable de instancia que el encabezado busca?

Author: Xufox, 2010-08-09

10 answers

Lo que me gusta hacer es incluir el Javascript per-view en un bloque content_for :head y luego yield a ese bloque en el diseño de su aplicación. Por ejemplo

Si es bastante corto entonces:

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

O, si es más largo, entonces:

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

Luego, en su archivo de diseño

<head>
  ...
  <%= yield :head %>
</head>
 148
Author: bjg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-29 18:57:53

Si desea incluir javascript solo en una página, puede incluirlo en la página en línea, por supuesto, sin embargo, si desea agrupar su javascript y aprovechar la canalización de activos, js minificado, etc., es posible hacerlo y tener activos js adicionales que se combinan y solo se cargan en páginas específicas dividiendo su js en grupos que solo se aplican en ciertos controladores/vistas/secciones del sitio.

Mueva su js en assets a carpetas, con un archivo de manifiesto separado para cada uno, así que si tienes una biblioteca js admin que solo se usa en el backend, puedes hacer esto:

  • activos
    • javascripts
      • admin
        • ...js
      • admin.js (manifiesto para grupo de administración)
      • solicitud.js (manifiesto para el grupo global de aplicaciones)
      • global
        • ...js

En la aplicación existente.js

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

En un nuevo administrador.manifiesto de js file

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

Asegúrese de que este nuevo manifiesto js se cargue editando config/production.rb

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

Luego ajuste el diseño de su página para que pueda incluir algunos js adicionales para el encabezado de la página:

<%= content_for :header %>   

Luego, en las vistas donde desea incluir este grupo js específico (así como el grupo de aplicaciones normal) y/o cualquier js, css, etc. específico de la página:

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

Por supuesto, puede hacer lo mismo con css y agruparlo de una manera similar para aplicarlo solo a ciertas áreas de la sitio.

 102
Author: Kenny Grant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-22 12:34:04

Prefiero lo siguiente...

En su application_helper.rb file

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

Y luego en tu vista particular (app/views/books/index.HTML.erb en este ejemplo)

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

... parece funcionar para mí.

 11
Author: cailinanne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-17 18:41:26

¡Estas respuestas me ayudaron muchísimo! Si alguien quiere un poco más...

  1. Necesitas poner los javascript en los manifiestos si los quieres precompilados. Sin embargo, si necesita cada archivo javascript de application.js.coffee, todos los scripts javac se cargarán cada vez que navegue a una página diferente, y el propósito de hacer javascripts específicos de la página será derrotado.

Por lo tanto, necesita crear su propio archivo de manifiesto (por ejemplo, speciifc.js) que requerirá todos los archivos javascript específicos de la página. También, modifíquese require_tree de application.js

App / assets / javascripts / application.js

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

App / assets / javascripts / specific.js

//= require_tree ./specific

Luego en su environments/production.rb agregue este manifiesto a la lista precompilada con la opción config,

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

Hecho! Todos los javascripts compartidos que siempre deben cargarse se colocarán en la carpeta app/assets/javascripts/global, y los javascripts page-spcific en app/assets/javascripts/specific. Usted puede simplemente llama a los javascript específicos de la página desde la vista como

<%= javascript_include_tag "specific/whatever.js" %> //.js es opcional.

Esto es suficiente, pero yo quería hacer un uso de javascript_include_tag params[:controller] también. Al crear controladores, se genera un archivo coffeescript asociado en app/assets/javascripts como otras personas mencionadas. Existen realmente scripts java específicos del controlador, que se cargan solo cuando el usuario alcanza la vista del controlador específica.

Así que creé otro manifiesto controller-specific.js

App/assets/javascripts / controller-specific.js

//= require_directory .

Esto incluirá todos los coffeescripts generados automáticamente asociados con los controladores. Además, debe agregarlo a la lista precompilada.

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

 11
Author: Maximus S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-12 03:10:10

Si no desea utilizar la canalización de activos o las soluciones complejas para obtener ese javascript específico de página necesario (simpatizo), la forma más simple y robusta, que logra lo mismo que las respuestas anteriores pero con menos código es solo usar:

<%= javascript_include_tag "my_javascipt_file" %>

Nota: esto requiere una solicitud http más por etiqueta include que las respuestas que usan content_for :head

 9
Author: AJP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:30

Echa un vistazo a la gema pluggable_js. Usted puede encontrar esta solución más fácil de usar.

 7
Author: peresleguine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-25 12:58:58

Entiendo que la canalización de activos está destinada a disminuir el tiempo de carga de la página al triturar todos sus js juntos en un archivo (minificado). Si bien esto puede parecer repugnante en la superficie, en realidad es una característica que ya existe en lenguajes populares como C y Ruby. Cosas como las etiquetas" include " están destinadas a evitar la inclusión múltiple de un archivo y a ayudar a los programadores a organizar su código. Cuando escribes y compilas un programa en C, todo ese código está presente en cada parte de tu ejecución programa, pero los métodos solo se cargan en la memoria cuando se está utilizando ese código. En cierto sentido, un programa compilado no incluye nada que garantice que el código sea muy modular. Hacemos el código modular escribiendo nuestros programas de esa manera, y el sistema operativo solo carga en memoria los objetos y métodos que necesitamos para una localidad dada. ¿Existe siquiera algo como la "inclusión específica del método"? Si tu aplicación rails es restful, esto es esencialmente lo que estás pidiendo.

Si escriba su javascript para que aumente el comportamiento de los elementos HTML en la página, entonces esas funciones son 'específicas de la página' por diseño. Si hay algún código complicado que haya escrito de tal manera que se ejecute independientemente de su contexto, tal vez considere vincular ese código a un elemento html de todos modos (podría usar la etiqueta body, como se describe en el método Garber-Irish). Si una función se ejecuta condicionalmente, el rendimiento probablemente será menor que todos esos scripts adicionales Tags.

Estoy pensando en usar la gema paloma, como se describe en el proyecto rails apps. Luego puede hacer que su javascript sea específico de la página incluyendo funciones específicas de la página en una devolución de llamada de paloma:

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

Usas rails, así que sé que te encantan las gemas:)

 3
Author: Ziggy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-29 22:08:39

No debería cargar sus archivos JS o CSS fuera de la canalización de activos porque pierde características importantes que hacen que Rails sea tan grande. Y no necesitas otra joya. Creo en el uso de la menor cantidad de gemas posible, y el uso de una gema no es necesario aquí.

Lo que desea se conoce como "Javascript Específico del Controlador" ("Javascript específico de la acción se incluye en la parte inferior). Esto le permite cargar un archivo JavaScript específico para un CONTROLADOR específico. Tratando de conectar su Javascript a una vista es una especie de... hacia atrás y no sigue el patrón de diseño MVC. Desea asociarlo con sus Controladores o acciones dentro de sus Controladores.

Desafortunadamente, por cualquier razón, los desarrolladores de Rails decidieron que, por defecto, cada página cargará cada archivo JS ubicado en su directorio de activos. Nunca sabré por qué decidieron hacer esto en lugar de habilitar "Javascript específico del Controlador" por defecto. Esto se hace a través de la aplicación.archivo js, que incluye el siguiente línea de código por defecto:

//= require_tree .

Esto se conoce como una directiva. Es lo que sprockets usa para cargar cada archivo JS en el directorio assets / javascripts. De forma predeterminada, los piñones cargan automáticamente la aplicación.js and application.css, y la directiva require_tree carga cada archivo JS y Coffee en sus respectivos directorios.

NOTA: Cuando haces scaffold (si no eres scaffolding, ahora es un buen momento para empezar), Rails genera automáticamente café archivo para usted, para el controlador de ese andamio. Si desea que genere un archivo estándar JS en lugar de un archivo coffee , elimine la gema coffee que está habilitada por defecto en su Gemfile , y su scaffold creará archivos JS en su lugar.

Ok, entonces el primer paso para habilitar "Javascript Específico del Controlador" es eliminar el código require_tree de su aplicación.js, O cambiarlo a una carpeta dentro de su directorio assets / javascripts si aún necesita archivos JS globales. I. E.:

//= require_tree ./global

Paso 2: Entra en tu config/initializers/assets.archivo rb, y agregue lo siguiente:

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

Inserte los nombres de controlador que desee.

Paso 3: Reemplaza el javascript_include_tag en tu aplicación.HTML.archivo erb con esto (tenga en cuenta la parte params [: controller]:

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

Reinicia tu servidor y viola! El archivo JS que se generó con su scaffold ahora solo se carga cuando se llama a ese controlador.

¿Necesita cargar un archivo JS específico sobre una ACCIÓN específica en su controlador , es decir /articles/new? Haga esto en su lugar:

solicitud.HTML.erb :

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

config/inicializadores/activos.rb :

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

Luego agregue una nueva carpeta con el mismo nombre que su controlador en su carpeta assets/javascripts y coloque su archivo js con el mismo nombre que su acción dentro. Luego cargarlo en que acción específica.

 3
Author: Erick Maynard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-03 03:50:21

Ok así que tal vez esto es como el peor trabajo alrededor nunca, pero creat un método de controlador que acaba de renderizar el .js file

Controlador

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

Ver

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

Si por alguna razón no queremos hacer esto, házmelo saber.

 1
Author: Bill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-15 22:00:05

La forma preferida de agregar JS es en footer, por lo que puede hacerlo de esta manera:

Mostrar.HTML.erb:

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

Diseños / aplicación.HTML.erb

<%= yield :footer_js %>
 1
Author: Syed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-22 08:21:46