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

发布于 2024-09-18 22:46:08 字数 989 浏览 8 评论 0原文

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

假设我有一篇文章,其中 has_many 图像,

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

……但一切都以 DRY 的方式进行。在较旧的 Rails 项目中,我使用 XML 构建器来自定义输出,但跨 json、xml、html 复制它似乎并不正确。我不得不想象 Rails 专家在 Rails 3 中添加了一些我没有意识到的此类行为。有想法吗?

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.

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

深海少女心 2024-09-25 22:46:08

您可以在模型中覆盖 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 会处理剩下的事情。不完全确定 options 设置为什么,但可能是您为 respond_with 提供的选项(:include, :only 等等)

You can override as_json in your model.
Something like:

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)

醉生梦死 2024-09-25 22:46:08

可能为时已晚,但我在 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 等是安全的。

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:

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

空心↖ 2024-09-25 22:46:08

这不是 Rails 3 内置的方式,但我发现了一个在 Rails 3 上积极维护的很棒的 gem: acts_as_api< /a>

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文