在Rails JSON序列化中重命名模型关联属性?

the*_*gal 10 serialization activerecord json ruby-on-rails ruby-on-rails-3

我有一个现有的Rails 3应用程序,我正在添加一个JSON API.我们有一个VendorActiveRecord模型和一个EmployeeActiveRecord模型.一个Employee属于Vendor.在API中,我们要包括EmployeeVendor在JSON序列化.例如:

# Employee as JSON, including Vendor
:employee => {
    # ... employee attributes ...
    :vendor => {
        # ... vendor attributes ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这很容易.但是,我有一个业务要求,即公共API不公开内部模型名称.也就是说,对于外部世界,它看起来好像Vendor模型实际上被称为Business:

# Employee as JSON, including Vendor as Business
:employee => {
    # ... employee attributes ...
    :business => {
        # ... vendor attributes ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这对于顶级对象来说很容易做到.也就是说,我可以打电话给@employee.as_json(:root => :dude_who_works_here)重新命名Employee,以DudeWhoWorksHere在JSON.但是包括协会呢?我尝试了一些没有成功的事情:

# :as in the association doesn't work
@employee.as_json(:include => {:vendor => {:as => :business}})

# :root in the association doesn't work
@employee.as_json(:include => {:vendor => {:root => :business}})

# Overriding Vendor's as_json doesn't work (at least, not in a association)
    # ... (in vendor.rb)
    def as_json(options)
        super(options.merge({:root => :business}))
    end
    # ... elsewhere
    @employee.as_json(:include => :vendor)
Run Code Online (Sandbox Code Playgroud)

我唯一的另一个想法是手动重命名密钥,如下所示:

# In employee.rb
def as_json(options)
    json = super(options)
    if json.key?(:vendor)
        json[:business] = json[:vendor]
        json.delete(:vendor)
    end
    return json
end
Run Code Online (Sandbox Code Playgroud)

但这似乎不够优雅.我希望有一种更干净,更Rails-y的方式来做我想要的.有任何想法吗?

ice*_*eam 11

尝试使用as_json的内置选项生成复杂的JSON是笨拙的.我会as_json在你的模型中覆盖,而不是打电话super.组成您自己的选项键,as_json以控制您想要包含在哈希中的内容.

# employee.rb
def as_json(options = {})
  json = {:name => name, ...} # whatever info you want to expose
  json[:business] = vendor.as_json(options) if options[:include_vendor]
  json
end
Run Code Online (Sandbox Code Playgroud)