如何在Rails 3中定制to_json响应

时间:2022-09-11 00:13:29

I am using respond_with and everything is hooked up right to get data correctly. I want to customize the returned json, xml and foobar formats in a DRY way, but I cannot figure out how to do so using the limited :only and :include. These are great when the data is simple, but with complex finds, they fall short of what I want.

我正在使用respond_with,所有东西都被正确地连接起来以获得正确的数据。我想以一种枯燥的方式自定义返回的json、xml和foobar格式,但我无法理解如何使用limited:only和:include来实现这一点。当数据很简单时,这些都很好,但是如果有复杂的发现,它们就不能满足我的需求。

Lets say I have a post which has_many images

假设我有一个有很多图片的帖子。

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

I want to include the images with the response so I could do this:

我想把这些图片和响应一起包含进来,这样我就可以做到:

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

but I dont really want to send the entire image object along, just the url. In addition to this, I really want to be able to do something like this as well (pseudocode):

但是我并不想发送整个图像对象,只是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

… but all in a DRY way. In older rails projects, I have used XML builders to customize the output, but replicating it across json, xml, html whatever doesnt seem right. I have to imagine that the rails gurus put something in Rails 3 that I am not realizing for this type of behavior. Ideas?

但都是干的。在旧的rails项目中,我使用了XML构建器来定制输出,但是在json、XML和html之间进行复制,这似乎是不对的。我不得不想象rails大师在rails 3中加入了一些我没有意识到的行为。想法吗?

3 个解决方案

#1


21  

You can override as_json in your model. Something like:

可以在模型中覆盖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

And Rails takes care of the rest when using respond_with. not entirely sure what options gets set to, but probably the options you give to respond_with (:include, :only and so on)

在使用respond_with时,Rails会处理其余的问题。不完全确定要设置什么选项,但可能给respond_with (:include,:only等)的选项

#2


8  

Probably too late, but I found a more DRY solution digging through the rails docs. This works in my brief tests, but may need some tweaking:

可能太晚了,但是我找到了一个更干巴巴的解决方案,通过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

This basically allows you to have a list of fields that are allowed for your public API, and you cannot accidentally expose the whole object. You can still expose specific fields manually, but by default your object is secure for .to_json, .to_xml, etc.

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

#3


7  

It is not the rails 3 built-in way, but I found a great gem that is actively maintained on Rails 3: acts_as_api

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

#1


21  

You can override as_json in your model. Something like:

可以在模型中覆盖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

And Rails takes care of the rest when using respond_with. not entirely sure what options gets set to, but probably the options you give to respond_with (:include, :only and so on)

在使用respond_with时,Rails会处理其余的问题。不完全确定要设置什么选项,但可能给respond_with (:include,:only等)的选项

#2


8  

Probably too late, but I found a more DRY solution digging through the rails docs. This works in my brief tests, but may need some tweaking:

可能太晚了,但是我找到了一个更干巴巴的解决方案,通过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

This basically allows you to have a list of fields that are allowed for your public API, and you cannot accidentally expose the whole object. You can still expose specific fields manually, but by default your object is secure for .to_json, .to_xml, etc.

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

#3


7  

It is not the rails 3 built-in way, but I found a great gem that is actively maintained on Rails 3: acts_as_api

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