35

En Rails 3.1 no es posible acceder a las variables de instancia del controlador en un archivo js.erb o coffee.erb de activos usando sintaxis como <% = @foo%>, donde @foo está configurado en el controlador. Entonces, la pregunta es cuáles son las mejores formas de pasar variables de controlador a CoffeeScript o activos de JavaScript.Rieles: variable de instancia del controlador de acceso en CoffeeScript o el archivo de activos de JavaScript

Esta pregunta ha sido formulada en múltiples formas intrincadas en el foro, pero lo que quiero decir es que todas las recomendaciones se recopilan juntas y el código proporcionado es simple y legible. También tenga en cuenta que me refiero específicamente a los activos y no a los archivos de respuestas.

+0

Es este un duplicado de http://stackoverflow.com/questions/8108511/how-to-access-instance-variables-in-coffeescript-engine-inside-a-slim-template? Parece que la respuesta aceptada allí ayudaría. – Thilo

+0

@Thilo Según tengo entendido, esa pregunta se refiere a una plantilla .slim en la carpeta de vistas, por lo que, en efecto, CoffeeScript se está procesando como parte de la vista y no como un archivo de activos por adelantado. Por favor corrígeme si estoy equivocado. –

+0

Sí, no estoy lo suficientemente familiarizado con Rails para estar seguro de si se aplica esa respuesta. Pero lo esencial parece ser convertir todas las variables de instancia que vas a necesitar en un fragmento de Javascript, a lo que los otros activos pueden referirse. – Thilo

Respuesta

26

un par de maneras que he hecho esto en el pasado

poner los datos en los campos ocultos, acceder a los datos en js/café

# single value 
<%= hidden_field_tag "foo_name", @foo.name, { :id => "foo-name" } %> 
$('#foo-name').val(); 

# when the 'value' has multiple attributes 
<%= hidden_field_tag "foo", @foo.id, { :id => "foo", "data-first-name" => @foo.first_name, "data-last-name" => @foo.last_name } %> 
$foo = $('#foo') 
console.log $foo.val() 
console.log $foo.data("firstName") 
console.log $foo.data("lastName") 

otra opción: Cargar datos en la estructura de datos js en erb, acceder a ella desde js/café

<% content_for(:head) do %> 
    <script> 
    window.App = window.App || {}; 
    window.App.Data = window.App.Data || {}; 
    window.App.Data.fooList = [ 
     <% @list.each do |foo| %> 
      <%= foo.to_json %>, 
     <% end %> 
    ]; 
    </script> 
<% end %> 


# coffee 
for foo in window.App.Data.fooList 
    console.log "#{foo.id}, #{foo.first_name} #{foo.last_name}" 

no soy un gran fan de la construcción de los datos de Javascript de rubí en erb como este, algo acerca de que sólo se siente mal - que puede ser eficaz a pesar de

y otra opción: realizar una llamada de Ajax y obtener los datos bajo demanda desde el servidor

También estoy interesado en otras ideas y enfoques

+0

Si necesita ejecutar bucles y construir json, podría usar un before_filter que ejecuta un método para construir un solo objeto JSON y asignarlo a una variable de instancia. Luego simplemente emite la variable de una instancia en la asignación Javascript de su vista. Encuentro esto mejor que ajax porque es una solicitud HTTP menos. – BradGreens

+0

La segunda opción se ve muy bien. Tengo que recordar eso. – Donato

8

hay un muy buen elenco de carril y bastante reciente (feb. 2012) sobre este tema específico: #324 Passing Data to JavaScript

Muestra 3 formas: una etiqueta de script, un atributo de datos y la gema Gon. Creo que House cubrió todas las técnicas disponibles. Solo mencionaría que usar una llamada AJAX se usa mejor cuando tiene un gran volumen de datos, datos dinámicos o una combinación de ambos.

+2

¿Podría agregar algún código de ejemplo a su respuesta? – rudolph9

+1

Rudolph, abre RailsCast y también muestra ejemplos de código. Mejores ejemplos de los que podría dar :) – Max

+1

Abrí, vi, pero se supone que las respuestas son independientes con todos los códigos de ejemplo pertinentes (es decir, _no_ requieren que accedas a otra página para obtener información pertinente) ... – rudolph9

5

En lugar de usar un campo oculto, elegí agregar un atributo de datos al contenedor div que jquery puede recoger.

<div class="searchResults" data-query="<%= @q %>"></div> 

entonces el jQuery para acceder a ella

url: "/search/get_results?search[q]=" + $(".searchResults").data("query") + "&page=" + p 

Siento que esto es la manera más limpia para pasar datos a javascript. Después de haber encontrado ninguna forma de pasar una variable a un archivo de script de café con la canalización de activos de los raíles desde un controlador. Este es el método que ahora uso. No puedo esperar hasta que alguien configure el controlador con rieles que serán los mejores.

3

En el controlador:

@foo_attr = { "data-foo-1" => 1, "data-foo-2" => 2 } 

En la vista (HAML):

#foo{@foo_attr} 

En el activo CoffeeScript:

$("#foo").data("foo-1") 
$("#foo").data("foo-2") 
0

Puede editar y añadir variables a los parametros array en el controlador y luego acceder a ellos en response.js.erb.He aquí un ejemplo con params[:value]:

def vote 
    value = params[:type] == "up" ? 1 : -1 
    params[:value] = value 
    @public_comment = PublicComment.find(params[:id]) 

    have_voted = @public_comment.evaluators_for(:pub_votes_up) << @public_comment.evaluators_for(:pub_votes_down) 

    unless have_voted.include?(@current_user) # vote 
    @public_comment.add_or_update_evaluation(:"pub_votes_#{params[:type]}", value, @current_user) 
    else          # unvote 
    @public_comment.delete_evaluation(:"pub_votes_#{params[:type]}", @current_user) 
    params[:value] = 0 
    end 

    respond_to do |format| 
    format.js # vote.js.erb 
    end 
end 

Y he aquí un ejemplo que acompaña response.js.erb

button = $('<%= ".pub#{params[:type]}_#{params[:id]}" %>') 
label = button.find('strong') 
<% comment = PublicComment.find(params[:id]) %> 
label.html('<%= comment.reputation_for(:"pub_votes_#{params[:type]}").to_i %>') 

<% if params[:value] == 1 %> 
    button.addClass('btn-success') 
<% elsif params[:value] == -1 %> 
    button.addClass('btn-danger') 
<% else %> 
    if button.hasClass('btn-success') { button.removeClass('btn-success') } 
    if button.hasClass('btn-danger') { button.removeClass('btn-danger') } 
<% end %> 
1

En situaciones en las que sus datos javascript va de las manos, utilizando la gema gon sigue siendo la forma preferida ir en rieles, incluso en 2015. Después de configurar gon, puede pasar datos a sus archivos javascript simplemente asignando los datos al objeto gon en rieles.

(Gemfile) 
gem 'gon' 

(controller) 
def index 
    gon.products = Product.all 

(layouts) 
<%= include_gon %> 

(public/javascripts/your_js_can_be_here.js) 
alert(gon.products[0]['id'); 

(html source automatically produced) 
<script> 
    window.gon = {}; 
    gon.products = [{"created_at":"2015", "updated_at":"2015, "id":1, "etc":"etc"}]; 

Puede leer los detalles de implementación más detallado en Gon o los canales de otros dos carriles en JavaScript de screencast de Ryan Bate.
http://railscasts.com/episodes/324-passing-data-to-javascript

Cuestiones relacionadas