example - ¿La mejor manera de agregar JavaScript específico de la página en una aplicación de Rails 3?
ruby on rails caracteristicas (10)
Rails 3 tiene JavaScript discreto, lo cual es genial.
Pero me pregunto 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();
}
Entonces, ¿mi pregunta es dónde / cómo incluir ese JavaScript? No deseo llenar el archivo application.js
porque este JavaScript solo se aplica a esta vista. ¿Debo incluir un archivo JavaScript personalizado para cada página de alguna manera, o pegarlo en una variable de instancia que el encabezado busca?
¡Estas respuestas me ayudaron muchísimo! Si alguien quiere un poco más ...
- Necesita poner javascripts en manifiestos si los quiere precompilados. Sin embargo, si necesita cada archivo javascript desde
application.js.coffee
, todos los javacsripts se cargarán cada vez que navegue a una página diferente, y se eliminará el propósito de hacer javascripts específicos de la página.
Por lo tanto, debe crear su propio archivo de manifiesto (por ejemplo, speciifc.js
) que requerirá todos los archivos javascript específicos de la página. Además, modifique require_tree
desde 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 sus environments/production.rb
agregue este manifiesto a la lista precompilada con la opción de configuración,
config.assets.precompile += %w( specific.js )
¡Hecho! Todos los javascripts compartidos que siempre deben cargarse se colocarán en app/assets/javascripts/global
carpeta app/assets/javascripts/global
, y los app/assets/javascripts/specific
la página en la app/assets/javascripts/specific
. Simplemente puede llamar a los javascripts específicos de la página desde la vista, como
<%= javascript_include_tag "specific/whatever.js" %>
//.js es opcional.
Esto es suficiente, pero también quería usar javascript_include_tag params[:controller]
. Cuando crea controladores, se genera un archivo coffeescript asociado en la app/assets/javascripts
como otras personas mencionadas. Realmente hay javascripts específicos del controlador , que se cargan solo cuando el usuario llega a la vista del controlador específico.
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 )
Echa un vistazo a la gema pluggable_js . Puede encontrar que esta solución es más fácil de usar.
La forma preferida de agregar JS es en pie de página, para que pueda hacerlo de esta manera:
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 %>
Lo que me gusta hacer es incluir el Javascript por vista en un content_for :head
block y luego yield
a ese bloque en el diseño de la 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 tu archivo de diseño
<head>
...
<%= yield :head %>
</head>
No debe cargar sus archivos JS o CSS fuera de la cartera de activos porque pierde funciones importantes que hacen que Rails sea tan bueno. Y no necesitas otra joya. Creo en usar la menor cantidad posible de gemas, y no es necesario usar una gema aquí.
Lo que desea es lo que 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 CONTROLLER específico. Intentar conectar su Javascript a una Vista es algo así como ... hacia atrás y no sigue el patrón de diseño de MVC. Desea asociarlo con sus Controladores o acciones dentro de sus Controladores.
Desafortunadamente, por alguna razón, los desarrolladores de Rails decidieron que, de forma predeterminada, cada página cargará cada archivo JS ubicado en su directorio de activos. Por qué decidieron hacer esto en lugar de habilitar "JavaScript específico del controlador" de forma predeterminada, nunca lo sabré. Esto se hace a través del archivo application.js, que incluye la siguiente línea de código de manera predeterminada:
//= require_tree .
Esto se conoce como una directiva . Es lo que usan los piñones para cargar cada archivo JS en el directorio assets / javascripts. De forma predeterminada, los piñones cargan automáticamente application.js y application.css, y la directiva require_tree carga cada archivo JS y Coffee en sus respectivos directorios.
NOTA: Cuando andamios (si no es un andamio, ahora es un buen momento para comenzar), Rails genera automáticamente un archivo de café para usted, para el controlador de ese andamio. Si desea que genere un archivo JS estándar en lugar de un archivo de café , elimine la gema de café que está habilitada de manera predeterminada en su Gemfile , y su andamio creará en su lugar archivos JS.
Bien, entonces el primer paso para habilitar "JavaScript específico del controlador" es eliminar el código require_tree de su archivo application.js, O cambiarlo a una carpeta dentro de su directorio assets / javascripts si aún necesita archivos JS globales. ES DECIR:
//= require_tree ./global
Paso 2: Vaya a su archivo config / initializers / assets.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 del controlador que desee.
Paso 3: reemplace el javascript_include_tag en su archivo application.html.erb con esto (observe 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 andamio ahora solo se cargará cuando se llame a ese controlador.
¿Necesita cargar un archivo JS específico en una ACCIÓN específica en su controlador , IE / articles / new ? Haz esto en su lugar:
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(*/*)
A continuación, 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 lo cargará en esa acción específica.
Ok, tal vez este sea el peor trabajo que haya habido, pero creo un método de controlador que acaba de procesar el archivo .js
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.
Prefiero lo siguiente ...
En su archivo application_helper.rb
def include_javascript (file)
s = " <script type=/"text/javascript/">" + render(:file => file) + "</script>"
content_for(:head, raw(s))
end
y luego en su vista particular (app / views / books / index.html.erb en este ejemplo)
<% include_javascript ''books/index.js'' %>
... Parece funcionar para mi.
Según entiendo, el inventario de activos está destinado a disminuir el tiempo de carga de la página combinando todas las js en un archivo (minificado). Si bien esto puede parecer repugnante en la superficie, en realidad es una característica que ya existe en los lenguajes populares como C y Ruby. Cosas como las etiquetas "incluir" están destinadas a evitar la inclusión múltiple de un archivo y ayudar a los programadores a organizar su código. Cuando escribe y compila un programa en C, todo ese código está presente en cada parte de su programa en ejecución, pero los métodos solo se cargan en la memoria cuando se usa ese código. En cierto sentido, un programa compilado no incluye nada para garantizar que el código sea muy modular. Hacemos que el código sea modular al escribir nuestros programas de esa manera, y el sistema operativo solo carga en la memoria los objetos y métodos que necesitamos para una localidad determinada. ¿Existe incluso algo así como la "inclusión específica del método"? Si la aplicación de sus rieles es tranquila, esto es esencialmente lo que está pidiendo.
Si escribe su javascript para que aumente el comportamiento de los elementos HTML en la página, esas funciones son ''específicas para la página'' por diseño. Si hay algún código complicado que haya escrito de tal manera que se ejecutará independientemente de su contexto, tal vez considere vincular ese código a un elemento html de todas formas (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á más pequeño que todas esas etiquetas de script adicionales.
Estoy pensando en usar la gema paloma , como se describe en el railsapps.github.com/rails-javascript-include-external.html . Luego puede hacer que su página javascript sea específica al incluir funciones específicas de la página en una devolución de llamada paloma:
Paloma.callbacks[''users''][''new''] = function(params){
// This will only run after executing users/new action
alert(''Hello New Sexy User'');
};
Usas rieles, entonces sé que amas las gemas :)
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 el inventario de activos, js minimizado, es posible hacerlo y tener más js activos que se combinan y solo se cargan en páginas específicas al dividir sus js en grupos que solo se aplican en ciertos controladores / vistas / secciones del sitio.
Mueva su js en activos en carpetas, con un archivo de manifiesto por separado para cada uno, de modo que si tiene una biblioteca admin js que solo se utiliza en el back-end, puede hacer esto:
- bienes
- javascripts
- administración
- ... js
- admin.js (manifiesto para el grupo de administración)
- application.js (manifiesto para el grupo global de aplicaciones)
- global
- ... js
- administración
- javascripts
en la aplicación existente .js
//= require jquery
//= require jquery_ujs
//= require_tree ./global // requires all js files in global folder
en un nuevo archivo de manifiesto de admin.js
//= 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 )
A continuación, 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 en las que desee incluir este grupo js específico (así como también 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 manera similar para aplicar solo a ciertas áreas del sitio.
Si no desea utilizar la canalización de activos o el entorno complejo para obtener esa javascript específica de la página necesaria (simpatizo), la forma más simple y sólida, que logra lo mismo que las respuestas anteriores, pero con menos código es solo para utilizar:
<%= javascript_include_tag "my_javascipt_file" %>
Nota: esto requiere una solicitud HTTP más por etiqueta de inclusión que las respuestas que usan content_for :head