Rails 3.1 - 在coffeescript中访问控制器变量的最佳方法是什么?

时间:2011-12-10 20:57:14

标签: ruby-on-rails-3.1 coffeescript

我正在寻找一个配方,将控制器的全局变量用于这样的coffeescript:

控制器:

respond_to :js

def create
  @commentable = commentable
  @comment = @commentable.comments.build({:comment => params[:comment], :user => current_user})
  @comment.save
  respond_with(@comment, @commentable)
end

create.js.coffee:

$("#form_#{@commentable.class}_#{@commentable.id}").hide()

这个想法是在一个页面中有几个可评论的内容,并识别当前被评论的一个,以隐藏/显示一个表单来评论它;表单的id是使用class和可注释的id构建的。此时,如果我尝试使用上面的代码访问元素,则它不起作用,因为脚本中似乎不存在@commentable。

修改

我阅读了答案here,并尝试了以下内容:

在我的帖子/ show.haml

:javascript
  var commentable_comments_id;
#post
  @post.body
= render :partial => 'comments/list', :locals => {:commentable => @post}

在我的部分_list.haml

#comments_container
  %div{:id => "comments_#{commentable.class}_#{commentable.id}"}
    - commentable.comments.reverse_each do |comment|
      = render :partial => 'comments/comment', :locals => {:comment => comment}
  - if current_user
    .add_comment_link{:id => "link_#{commentable.class}_#{commentable.id}"}
      #{link_to "Commenter"}
    .add_comment{:id => "form_#{commentable.class}_#{commentable.id}"}
      = render :partial => 'comments/comment_form', :locals => {:commentable => commentable}

在部分_comment_form.haml

.comment_form
  = form_tag polymorphic_path([commentable, Comment]) , :method => :post, :remote => true do |f|
    .comment_field
      = text_area_tag :comment, params[:comment], :id =>"comment_area", :rows => 4, :cols => 50
    .comment_field 
      = submit_tag "Commenter", :id => "submit_comment_#{commentable.class}_#{commentable.id}", :class => "submit_comment"

在posts.js.coffee中:

jQuery ->

  commentable_link_id = null
  commentable_form_id = null

  hide_element_by_id = (id_name) ->
    $("#"+id_name).hide()
  show_element_by_id = (id_name) ->
    $("#"+id_name).show()

  $('.add_comment_link').click ->
    currentId = $(this).attr('id')
    if(commentable_link_id != null && commentable_form_id != null)
      hide_element_by_id(commentable_form_id)
      show_element_by_id(commentable_link_id)

    commentable_link_id = currentId
    commentable_form_id = currentId.replace("link", "form")    
    hide_element_by_id(commentable_link_id)
    show_element_by_id(commentable_form_id)

    commentable_comments_id = currentId.replace("link", "comments")   
    false

  $('.submit_comment').click -> 
    if(commentable_link_id != null && commentable_form_id != null)
      hide_element_by_id(commentable_form_id)
      show_element_by_id(commentable_link_id)

因此,当用户点击链接添加评论时,它会隐藏上一个评论表单(如果有的话),它会显示新的正确表单,构建评论集合的id(例如comments_Post_3)并存储它在页面的全局js变量中:

commentable_comments_id = currentId.replace("link", "comments")

然后在create.js.coffee中,我尝试使用此变量在存储容器中追加新注释:

$('<%= escape_javascript(render(:partial => @comment))%>')
  .appendTo("#"+commentable_comments_id)
  .hide()
  .fadeIn()

我认为这是不正确的,因为最后一个操作(带有衰落的附加)不起作用,所以全局变量commentable_comments_id不能初始化或其他东西......

3 个答案:

答案 0 :(得分:2)

您可以使用coffeebeans

只需将其添加到您的Gemfile:

gem 'coffeebeans'

然后根据需要创建文件:

#app/views/posts/create.js.coffee
$("#form_<%= @commentable.class %>_<%= @commentable.id %>").hide()

答案 1 :(得分:0)

如果要在coffeescript文件中使用erb,则必须将erb扩展名附加到文件中。因此,您的文件应重命名为create.js.coffee.erb。然后你可以做类似的事情:

$ ->
  alert('<%= Post.first.name %>')

应该可以正常工作。有关详细信息,请参阅docs

修改

我想我错过了你的问题中的一点。如果你想访问js文件中的实例变量,遗憾的是你不能。有关详细信息,请参阅this答案。

答案 2 :(得分:0)

当你对js做出回应时,这意味着它会将create.js.coffee呈现为一个视图。您不需要.erb添加到最后以使用内部的erb代码,如下所示:

$("#form_<%=@commentable.class%>_<%=@commentable.id>").hide()

您可能对coffeescript中的@感到困惑,它只是在javascript中表示this.this。并且#{ .. }代码仅由coffeescript解释,而不是由ruby解释(正如您在HAML中习惯的那样),因此您拥有的代码将在javascript中输出:

$("#form_" + this.commentable["class"] + "_" + this.commentable.id).hide();