Ruby-on-rails Rails:访问 CoffeeScript 或 JavaScript 资产文件中的控制器实例变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8513912/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rails: access controller instance variable in CoffeeScript or JavaScript asset file
提问by Safa Alai
In Rails 3.1 it is not possible to access controller instance variables in an asset js.erb or coffee.erb file using syntax such as <%= @foo %>, where @foo is set in the controller. So then the question is what are the best ways for passing controller variables to CoffeeScript or JavaScript assets.
在 Rails 3.1 中,无法使用诸如 <%= @foo %> 之类的语法访问资产 js.erb 或 coffee.erb 文件中的控制器实例变量,其中 @foo 在控制器中设置。那么问题是将控制器变量传递给 CoffeeScript 或 JavaScript 资产的最佳方法是什么。
This question has kind of been asked in multiple convoluted forms on the forum, but my point in asking it again is to have a place where all recommendations are gathered together, and the code supplied is simple and readable. Also note that I'm specifically referring to assets and not view response files.
这个问题在论坛上以多种复杂的形式被问过,但我再次提出这个问题的目的是有一个地方可以将所有建议聚集在一起,并且提供的代码简单易读。另请注意,我特别指的是资产而不是查看响应文件。
回答by house9
a couple of ways I have done this in the past
我过去做过的几种方法
put the data in hidden fields, access the data in js/coffee
将数据放入隐藏字段,访问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")
another option: load data into js data structure in erb, access it from js/coffee
另一种选择:将数据加载到 erb 中的 js 数据结构中,从 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}"
I am not a big fan of constructing javascript data from ruby in erb like this, something about it just feels wrong - it can be effective though
我不是像这样在 erb 中从 ruby 构建 javascript 数据的忠实粉丝,关于它的一些东西只是感觉不对 - 虽然它可以是有效的
and another option: make an ajax call and get the data on-demand from the server
另一种选择:进行ajax调用并从服务器按需获取数据
I am also interested in other ideas and approaches
我也对其他想法和方法感兴趣
回答by Max
There is a really nice rail cast and quite recent (feb. 2012) about this specific topic: #324 Passing Data to JavaScript
有一个非常好的铁路演员和最近(2012 年 2 月)关于这个特定主题: #324 Passing Data to JavaScript
It shows 3 ways: a script tag, a data attribute, and the Gon gem. I think house covered all the available techniques. I would only mention that using an AJAX call is best used when you have a large volume of data, dynamic data or combination of both.
它显示了 3 种方式:脚本标签、数据属性和 Gon gem。我认为 house 涵盖了所有可用的技术。我只想提一下,当您拥有大量数据、动态数据或两者的组合时,最好使用 AJAX 调用。
回答by Dave Robertson
Rather than use a hidden field I chose to add a data attribute to the container div which jquery can pick up.
我选择将数据属性添加到 jquery 可以选取的容器 div,而不是使用隐藏字段。
<div class="searchResults" data-query="<%= @q %>"></div>
then the jquery to access it
然后jquery访问它
url: "/search/get_results?search[q]=" + $(".searchResults").data("query") + "&page=" + p
I feel this is the cleanest way to pass data to javascript. After having found no way to pass a variable to a coffee script file with the rails asset pipeline from a controller. This is the method I now use. Can't wait till someone does set up the controller way with rails that will be the best.
我觉得这是将数据传递给 javascript 的最干净的方式。在发现无法通过控制器的 rails 资产管道将变量传递给咖啡脚本文件之后。这是我现在使用的方法。不能等到有人用最好的导轨设置控制器方式。
回答by michau
In the controller:
在控制器中:
@foo_attr = { "data-foo-1" => 1, "data-foo-2" => 2 }
In the view (HAML):
在视图 (HAML) 中:
#foo{@foo_attr}
In the CoffeeScript asset:
在 CoffeeScript 资产中:
$("#foo").data("foo-1")
$("#foo").data("foo-2")
回答by Ninjaxor
In situations where your javascript data gets out of hand, using the gon gem is still the preferred way to go in rails, even in 2015. After setting up gon, you are able to pass data to your javascript files by simply assigning the data to the gon object in rails.
在 javascript 数据失控的情况下,使用 gon gem 仍然是使用 Rails 的首选方式,即使在 2015 年也是如此。设置 gon 后,您可以通过简单地将数据分配给您的 javascript 文件rails 中的 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"}];
You can read more verbose implementation details on Gon or the two other rails-javascript channels from Ryan Bate's screencast.
http://railscasts.com/episodes/324-passing-data-to-javascript
您可以从 Ryan Bate 的截屏视频中阅读有关 Gon 或其他两个 rails-javascript 频道的详细实现细节。
http://railscasts.com/episodes/324-passing-data-to-javascript
回答by Archonic
You can edit and add variables to the params array in the controller then access them in the response.js.erb. Here's an example with params[:value]:
您可以编辑变量并将其添加到控制器中的 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
And here's an example accompanying response.js.erb
这是一个伴随 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 %>

