Rails:在CoffeeScript或JavaScript资产文件中访问控制器实例变量

时间:2011-12-15 01:11:35

标签: ruby-on-rails controller coffeescript erb instance-variables

在Rails 3.1中,无法使用诸如<%= @foo%>之类的语法访问资产js.erb或coffee.erb文件中的控制器实例变量,其中@foo在控制器中设置。那么问题是将控制器变量传递给CoffeeScript或JavaScript资产的最佳方法是什么。

这个问题在论坛上有多种复杂形式的问题,但我再次提出这个问题的意思是要有一个所有建议聚集在一起的地方,并且所提供的代码简单易读。另请注意,我特指的是资产,而不是查看响应文件。

6 个答案:

答案 0 :(得分:27)

我过去做过的几种方式

将数据放入隐藏字段,访问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")

另一种选择:将数据加载到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}"

我不是像这样在erb中构建来自ruby的javascript数据的忠实粉丝,关于它的一些事情只是感觉不对 - 它可以有效但是

和另一个选项:进行ajax调用并从服务器

获取数据

我也对其他想法和方法感兴趣

答案 1 :(得分:9)

关于这个特定话题,有一个非常好的铁路演员和最近的(2012年2月): #324 Passing Data to JavaScript

它显示了3种方式:脚本标记,数据属性和Gon gem。 我认为房子涵盖了所有可用的技术。我只提到当你有大量的数据,动态数据或两者的组合时,最好使用AJAX调用。

答案 2 :(得分:5)

我选择将数据属性添加到jquery可以接收的容器div中,而不是使用隐藏字段。

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

然后jquery访问它

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

我觉得这是将数据传递给javascript的最简洁方法。在找不到将变量传递给带有来自控制器的rails资产管道的咖啡脚本文件之后。这是我现在使用的方法。不能等到有人用最好的导轨设置控制器方式。

答案 3 :(得分:3)

在控制器中:

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

在视图(HAML)中:

#foo{@foo_attr}

在CoffeeScript资产中:

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

答案 4 :(得分:1)

在您的javascript数据失控的情况下,即使在2015年,使用gon gem仍然是首选的方式。在设置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"}];

您可以阅读Gon或Ryan Bate的截屏视频中其他两个rails-javascript频道的详细实施细节。
http://railscasts.com/episodes/324-passing-data-to-javascript

答案 5 :(得分:0)

您可以编辑变量并将其添加到控制器中的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 %>