我在我的jBuilder模板中使用了新的散列语法.看来这一行根本没有执行.

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

如果我将该行修改回旧语法,或者添加大括号或方括号,它就会起作用.

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

有人能解释一下这里发生了什么吗?是不是跟模板编译有关?谢谢.

推荐答案

为简单起见,测试模板:

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

我不知道如何通过其他方式访问它,但您可以在以下位置查看编译后的source: 一百零二

要查看模板呈现时实际运行的代码,请执行以下操作:

>> 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

formatted

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!.

It's also fixable if you put a semicolon at the end of this line:
https://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.                 

So method hash: is still an iffy syntax and much less obvious in a template. Just use parenthesis:
https://bugs.ruby-lang.org/issues/18396

Ruby-on-rails相关问答推荐

使用Hotwire/Turbo的Rails在链接悬停时获取请求

如何控制或定制S为模型使用的命名路由Rail()?

`heroku Open`和`heroku run rake db:Migrate`不工作(";没有这样的文件或目录";)

我使用rbenv安装Ruby,但我在使用";gem";->;错误:执行gem时遇到此错误.(Errno::EACCES)权限被拒绝

方法和括号之间没有空格时出错

带有data-turbo的rails`link_to‘未获得turbo_stream请求格式

Rails:序列化数据库中的对象?

设计 token_authenticable 已弃用,有什么替代方案?

如何使用 Rails 3 / Rack 在没有 www 的情况下重定向?

Ruby 地理定位Ruby /插件

PostgreSQL 无间隙序列

为 ActionMailer 渲染不同的视图(模板)

控制器规格与请求规格?

Ruby 元素是否存在于数组中

将 Amazon SES 与 Rails ActionMailer 结合使用

URL中的Rails点而不是斜杠

Rails 成语避免在 has_many 中重复:通过

如何解决弃用警告方法 to_hash 已弃用并将在 Rails 5.1 中删除

我可以将默认值传递给 rails 生成迁移吗?

从模型中获取验证