如何通过 HAML 模板访问 Javascript 中的 ruby 实例变量

How to access ruby instance variable in Javascript through HAML template

我有一部分正在使用 CommentsController 呈现。让我们调用这个部分 _edit_comment.html.haml 我传入实例变量 @comment.

$("#edit-comment-#{object.id}").html('#{ escape_javascript(render :partial => 'edit_comment', locals: { story: @comment.story, comment: @comment }) }')

在我的部分,我有 JS,我想在单击按钮时调用它。

= form_with model: [story.industry, story, comment], class: "w-100" do |f|
  %fieldset.w-100                                    
    = f.text_area :content, rows: 2, hide_label: true, class: 'px-2 py-1', placeholder: "Leave a comment" 
  %fieldset  
    = f.submit "Update", class: 'btn submit text-white mt-2'   
    %span.btn.cancel.text-white.mt-2 Cancel-
:javascript
  $(document).ready( function() {
    $('.cancel').click(e => {
      console.log("#{@comment}")       
    })
  } );

我知道“#{}”适用于字符串,但我希望能够访问整个对象。目前,控制台的结果将是

#<Comment:0x000055971a9c5278>

我需要获取整个 ruby 对象,因为我想将它作为变量传递给另一个将要呈现的部分。像这样:

:javascript
  $(document).ready( function() {
    $('.cancel').click(e => {
      $("#edit-comment-#{object.id}").html('#{ escape_javascript(render :partial => 'edit_comment', locals: { story: "#{@comment}".story, comment: "#{@comment}" }) }')
    })
  } );

这可能吗?

考虑使用嵌套形式...或类似的变体

这是 rails 指南的 link:https://guides.rubyonrails.org/form_helpers.html#nested-forms

您似乎想要嵌套表单,并且想要编辑评论,使用与编辑故事 (?) 或故事行业 (?) 时所用的相同表单。如果是这种情况,那么也许可以使用嵌套表单进行调查。

其次,另一个需要注意的陷阱:您不能将一个 HTML 表格放在另一个表格中:这是不可能的。因此,您提议的 javascript 工作流程必须在上面的表单之外呈现部分编辑评论......或者您可以混合使用 javascript 并使用嵌套表单方法以上使用 jquery/javascript。瑞安·贝茨 (Ryan Bates) 为这个主题投入了两个出色的 rails 演员 - 他们是 (1) and (2):

但是要回答你的问题:

...不能那样做

我不知道你是否真的可以按照你最初尝试的方式去做 - 像那样传递复杂的 ruby 对象

...但是有解决办法:

(A) 渲染部分并根据需要隐藏

为什么不尝试不同的方法:直接在您的 html 中渲染局部(但将其隐藏起来不被用户看到)。

单击该按钮后,您可以简单地切换已存在部分的可见性。

因为您正在使用 jQuery:

(B) 不同步地获取部分

您可以在您的事件处理程序中获取带有请求的部分 - stimulus js 可以很好地完成这种类型的工作流程。您可以使用 fetch API 获取 html 部分,或者如果您想支持 Internet Explorer 等,您可以使用 AJAX

......................您必须决定是要嵌套表单,还是对完全独立的表单感到满意。

要理解为什么您不能直接做您想做的事情,考虑一下 page-rendering 过程会有所帮助。当您的 CommentsController 控制器呈现视图时,Rails 处理您的 HAML 模板,其中包括处理所有嵌入的 Ruby(如字符串插值)。不过在那之后,你的 HTML 就是 HTML 而你的 Javascript 就是 Javascript.

所以,在你的情况下,Rails 在渲染时插入 "#{@comment}",但当 Javascript 在你的浏览器中执行时它只是一个字符串,但你不能通过Ruby 对象等。同样,escape_javascriptrender 是 Rails 视图助手,因此当直接插入 Javascript 时它们将无法工作。正如@BKSpurgeon 给出的那样,一个不错的选择是在原始页面中呈现编辑部分,然后只使用一些普通的 JS 来 show/hide 它。

另一种选择是将您的按钮更改为遥控器(即 AJAX)link_to,然后将您的 Javascript 放入 JS 视图中。我并没有真正使用 HAML,但我认为 link 会是这样的:

= link_to 'Cancel', edit_comment_path(@comment), remote: true 

并且在edit_comment.js.haml中:

:plain
$("#edit-comment-#{object.id}").html('#{ escape_javascript(render :partial => 'edit_comment', locals: { story: "#{@comment}".story, comment: "#{@comment}" }) }')

(快速 google 表明 HAML 的更高版本可能不需要 :plain 包装器;如果不完全正确,也许有 HAML 经验的人可以纠正它。)