我想我可以在Rails控制器之外使用Jbuilder。文件是这样说的。
我编写了这个模块,以包含在服务对象中。它集成在Rails 6 api应用程序中,但不是从ActiveRecord继承的。
module JsonGenerator
def to_json
template = File.read("#{::Rails.root}/path/to/template.json.jbuilder")
Jbuilder.new { |json| eval template }.target!
end
end
class Converter::Album
include JsonGenerator
end
如果我不使用任何部分,这是有效的。但是当我这样做时,使用这样的语法:
json.artists artists do |artist|
json.partial! 'artist', artist: artist
end
我收到此错误:
Failure/Error: eval template
TypeError:
{:artist=>#<Converter::Artist:0x00007fd0d1a99dc8 @name="Bob">} is not a symbol nor a string
问题似乎是 Jbuilder 部分不能接受 PORO 作为论据?
无论如何我都不想使用eval
,但这是我找到的加载不在views
文件夹中的模板的唯一方法。
如果我将所有模板直接复制粘贴为Jbuilder.new
方法的参数,则会出现相同的错误。
更新 04/12/2019
我试过这条线
json.partial! partial: 'artist', locals: { artist: artist }
即使它加载了部分,它生成的数据也是错误的。
我明白这个
"artists" => [{"partial!"=>{"locals"=>{"name"=>"Bob", "instrument"=>"piano"}, "partial"=>"artist"}}]
而不是
"artists" => [{"name"=>"Bob", "instrument"=>"piano"}]
无论出于何种原因,当外部轨道魔法时,您似乎必须明确命名参数:
json.partial! partial: 'artist', locals: { artist: artist }
为了避免 eval,我会尝试一些渲染的东西(未经测试(:
def to_json
ApplicationController.render(template: 'albums/show.json.jbuilder', assigns: { album: self }, formats: [:json], handlers: [:builder])
end
或者使用新的渲染器:
def to_json
renderer = ApplicationController.new
renderer.render('albums/show.json.jbuilder', locals: { album: self }, formats: [:json], handlers: [:builder])
end
我想我可以在Rails控制器之外使用Jbuilder。这 文件是这样说的。
可以,但并非所有可以在视图上下文中使用的方法都可用。 这是因为它们实际上是两个不同的对象,Jbuilder 和 JbuilderTemplate,后者接受context
参数,它是ActionView::Base
(或其子类(的实例。
您在视图上下文之外使用的对象是Jbuilder
的实例,并且没有#partial!
方法,这就是为什么您在返回的 JSON 中有"partial!"
键的原因——它的处理方式与任何其他键没有任何不同。
据我所知,完成你想做的事情的唯一(简单(方法是使用ActionController::Renderer(正如@Mene所说(。
ApplicationController.render 'path/to/template.jbuilder', locals: {...}, assigns: {...}