如何在Rails 3中自定义to_json响应

我正在使用respond_with ,所有内容都正确连接以正确获取数据。 我想以干燥的方式自定义返回的jsonxmlfoobar格式,但我无法弄清楚如何使用有限的:only:include 。 当数据很简单时,这些都很棒,但是对于复杂的发现,它们不符合我的要求。

可以说我有一个有很多图像的post

 def show @post = Post.find params[:id] respond_with(@post) end 

我想用响应包含图像,所以我可以这样做:

 def show @post = Post.find params[:id] respond_with(@post, :include => :images) end 

但我真的不想发送整个图像对象,只是url。 除此之外,我真的希望能够做到这样的事情(伪代码):

 def show @post = Post.find params[:id] respond_with(@post, :include => { :foo => @posts.each.really_cool_method } ) end def index @post = Post.find params[:id] respond_with(@post, :include => { :foo => @post.really_cool_method } ) end 

……但是一切都干了。 在旧的rails项目中,我使用XML构建器来自定义输出,但是在json,xml,html中复制它看起来不对。 我不得不想象铁路大师在Rails 3中放了一些东西,我没有意识到这种行为。 想法?

您可以在模型中覆盖as_json 。 就像是:

 class Post < ActiveRecord::Base def as_json(options = {}) { attribute: self.attribute, # and so on for all you want to include images: self.images, # then do the same `as_json` method for Image foo: self.really_cool_method } end end 

当使用respond_with时,Rails会处理其余的respond_with 。 不完全确定哪些options设置为,但可能是您为respond_with:include:only等)提供的选项

可能为时已晚,但我发现了更多DRY解决方案正在挖掘rails文档。 这适用于我的简短测试,但可能需要一些调整:

 # This method overrides the default by forcing an :only option to be limited to entries in our # PUBLIC_FIELDS list def serializable_hash(options = nil) options ||= {} options[:only] ||= [] options[:only] += PUBLIC_FIELDS options[:only].uniq! super(options) end 

这基本上允许您拥有公共API允许的字段列表,并且您不会意外地暴露整个对象。 您仍然可以手动公开特定字段,但默认情况下,您的对象对.to_json,.to_xml等是安全的。

它不是rails 3内置的方式,但我发现了一个在Rails 3上积极维护的伟大gem: acts_as_api