ruby 为什么jbuiler模板中的json.partial!行在使用新的哈希语法传递局部变量时不执行?

cnh2zyt3  于 2023-04-20  发布在  Ruby
关注(0)|答案(1)|浏览(95)

我在我的jbuilder模板中使用了新的哈希语法,这一行似乎根本没有被执行。

json.partial! 'comments', post:, comments:

如果我将该行修改回旧语法或添加大括号或中括号,它就可以工作。

json.partial!('comments', post:, comments:)
json.partial! 'comments', { post:, comments: }
json.partial! 'comments', post: post, comments: comments

有谁能解释一下这里发生了什么吗?是不是和模板编译有关?谢谢。

ca1c2owp

ca1c2owp1#

简单测试模板:

# app/views/test.json.jbuilder
json.attr name:

我不知道如何以其他方式访问它,但您可以在以下位置检查已编译的source:* 网址:http:github.com/rails/rails/blob/v7.0.4.3/actionview/lib/action_view/template.rb#L282*
查看模板呈现时实际运行的代码:

>> ApplicationController.renderer.render(template: "test", locals: {name: "first"})
  Rendering test.json.jbuilder
"          def _app_views_test_json_jbuilder__1585277848127427767_29960(local_assigns, output_buffer)\n            @virtual_path = \"test\";name = local_assigns[:name]; name = name;;__already_defined = defined?(json); json||=JbuilderTemplate.new(self); json.attr name:\n\n      json.target! unless (__already_defined && __already_defined != \"method\")\n          end\n"
=> TypeError # doesn't actually render
  • 格式化 *
def _app_views_test_json_jbuilder__1161877154070863274_90100(local_assigns, output_buffer)
  @virtual_path = "test";               # ActionView
  name = local_assigns[:name];          # ActionView
  name = name;;                         # ActionView
  __already_defined = defined?(json);   # Jbuilder
  json||=JbuilderTemplate.new(self);    # Jbuilder
  json.attr name:                       # Your template
  json.target! unless (__already_defined && __already_defined != "method")
  #    ^ Jbuilder json output
end

如果没有方括号,json.target!将成为name的值,模板将返回json.attr返回的值或json.partial!返回的值。
如果你在这一行的末尾放一个分号,它也是可以修复的:

  • 网址:http:github.com/rails/jbuilder/blob/v2.11.5/lib/jbuilder/jbuilder_template.rb#L277*
#                                                                            here v
%{__already_defined = defined?(json); json||=JbuilderTemplate.new(self); #{source};
>> ApplicationController.renderer.render(template: "test", locals: {name: "first"})
=> "{\"attr\":{\"name\":\"first\"}}"

简化版

def json *args
  @buffer = [*@buffer, *args]
end

def target 
  @buffer&.join
ensure
  @buffer = nil
end

# ^ this is action view/jbuilder
# v this is jbuilder templates

def good_template name = "first"
  json(name:)
  target
end

# same as doing:
# `json name: target`
def bad_template name = "first"
  json name:
  target
end
>> good_template
=> "{:name=>\"first\"}"
>> bad_template
=> [{:name=>nil}]       # Array instead of a String, if we had a controller
                        # there would be a TypeError somewhere.

所以method hash:仍然是一个不确定的语法,在模板中不太明显。只需使用括号:
https://bugs.ruby-lang.org/issues/18396

相关问题