web-dev-qa-db-fra.com

Rails: accéder à la variable d'instance du contrôleur dans un fichier d'actif CoffeeScript ou JavaScript

Dans Rails 3.1, il n'est pas possible d'accéder aux variables d'instance de contrôleur dans un fichier d'actif js.erb ou coffee.erb en utilisant une syntaxe telle que <% = @foo%>, où @foo est défini dans Alors, la question est de savoir quelles sont les meilleures façons de passer des variables de contrôleur aux ressources CoffeeScript ou JavaScript.

Cette question a en quelque sorte été posée sous de multiples formes compliquées sur le forum, mais mon point en la posant à nouveau est d'avoir un endroit où toutes les recommandations sont rassemblées, et le code fourni est simple et lisible. Notez également que je fais spécifiquement référence aux actifs et non aux fichiers de réponses.

40
Safa Alai

un couple de façons que je l'ai fait dans le passé

mettre les données dans des champs cachés, accéder aux données 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")

une autre option: charger les données dans la structure de données js dans erb, y accéder depuis 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}"

Je ne suis pas un grand fan de la construction de données javascript à partir de Ruby en erb comme celui-ci, quelque chose à ce sujet ne semble pas correct - il peut être efficace cependant

et une autre option: passer un appel ajax et obtenir les données à la demande du serveur

Je suis également intéressé par d'autres idées et approches

27
house9

Il y a une distribution ferroviaire vraiment sympa et assez récente (février 2012) sur ce sujet spécifique: # 324 Passing Data to JavaScript

Il montre 3 façons: une balise de script, un attribut de données et la gemme Gon. Je pense que la maison couvrait toutes les techniques disponibles. Je voudrais seulement mentionner que l'utilisation d'un appel AJAX est mieux utilisée lorsque vous avez un grand volume de données, des données dynamiques ou une combinaison des deux.

9
Max

Plutôt que d'utiliser un champ caché, j'ai choisi d'ajouter un attribut de données à la div de conteneur que jquery peut récupérer.

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

puis le jquery pour y accéder

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

Je pense que c'est le moyen le plus propre de transmettre des données à javascript. Après avoir trouvé aucun moyen de passer une variable à un fichier de script café avec le pipeline d'actifs Rails à partir d'un contrôleur. C'est la méthode que j'utilise maintenant. Je ne peux pas attendre que quelqu'un configure le façon contrôleur avec Rails ce sera le meilleur.

5
Dave Robertson

Dans le contrôleur:

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

Dans la vue (HAML):

#foo{@foo_attr}

Dans l'actif CoffeeScript:

$("#foo").data("foo-1")
$("#foo").data("foo-2")
3
michau

Dans les situations où vos données javascript deviennent incontrôlables, l'utilisation de la gemme gon est toujours la manière préférée d'aller dans Rails, même en 2015. Après avoir configuré gon, vous pouvez transmettre des données à vos fichiers javascript en affectant simplement les données à l'objet gon dans Rails.

(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"}];

Vous pouvez lire des détails d'implémentation plus détaillés sur Gon ou les deux autres canaux Rails-javascript du screencast de Ryan Bate.
http://railscasts.com/episodes/324-passing-data-to-javascript

1
Ninjaxor

Vous pouvez modifier et ajouter des variables au tableau de paramètres dans le contrôleur, puis y accéder dans le fichier response.js.erb. Voici un exemple avec 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

Et voici un exemple accompagnant 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 %>
0
Archonic