Подтвердить что ты не робот

Rails: переменная экземпляра контроллера доступа в файле ресурса CoffeeScript или JavaScript

В Rails 3.1 невозможно получить доступ к переменным экземпляра контроллера в файле js.erb или файле coffee.erb с использованием синтаксиса, такого как <% = @foo% > , где @foo установлен в контроллере. Таким образом, возникает вопрос, каковы наилучшие способы передачи переменных контроллера в ресурсы CoffeeScript или JavaScript.

Этот вопрос был задан в нескольких запутанных формах на форуме, но мой вопрос в том, чтобы снова спросить его, - это место, где все рекомендации собраны вместе, а предоставленный код прост и читабельен. Также обратите внимание, что я специально ссылаюсь на активы и не просматриваю файлы ответов.

4b9b3361

Ответ 1

несколько способов, которые я сделал в прошлом

поместите данные в скрытые поля, получите доступ к данным в js/coffee

# 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")

другая опция: загрузка данных в структуру данных js в erb, доступ к ней из js/coffee

<% 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}"

Я не большой поклонник создания javascript-данных из ruby ​​в erb, как это, что-то об этом просто кажется неправильным - оно может быть эффективным, хотя

и еще один вариант: сделать ajax-вызов и получить данные по запросу с сервера

Меня также интересуют другие идеи и подходы

Ответ 2

Есть действительно хороший рельс и довольно недавний (февраль 2012) об этой конкретной теме: # 324 Передача данных в JavaScript

Он показывает 3 способа: тег script, атрибут данных и камень Gon. Я думаю, что дом покрыл все доступные методы. Я бы сказал только, что использование вызова AJAX лучше всего использовать, когда у вас большой объем данных, динамические данные или их комбинация.

Ответ 3

Вместо того, чтобы использовать скрытое поле, я решил добавить атрибут данных в контейнер div, который может получить jquery.

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

то jquery для доступа к нему

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

Я считаю, что это самый чистый способ передачи данных на javascript. Не нашел способа передать переменную в файл кофе script с конвейером ресурсов рельсов с контроллера. Это метод, который я сейчас использую. Не могу дождаться, пока кто-то настроит путь контроллера с рельсами, которые будут лучшими.

Ответ 4

В контроллере:

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

В представлении (HAML):

#foo{@foo_attr}

В ресурсе CoffeeScript:

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

Ответ 5

В ситуациях, когда данные javascript выходят из-под контроля, использование gon gem по-прежнему является предпочтительным способом перехода на рельсы, даже в 2015 году. После настройки gon вы можете передавать данные в файлы javascript, просто присваивая данные для объекта gon в рельсах.

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

Вы можете прочитать более подробные детали реализации на Gon или два других канала rails-javascript от Ryan Bate screencast.
http://railscasts.com/episodes/324-passing-data-to-javascript

Ответ 6

Вы можете редактировать и добавлять переменные в массив params в контроллере, а затем обращаться к ним в response.js.erb. Вот пример с 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

И вот пример, сопровождающий 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 %>