如何在没有嵌套的情况下从关系中向渲染的JSON添加属性?

rad*_*und 1 ruby activerecord json ruby-on-rails

这是问题:我正在使用活动记录并返回一些照片对象.这些照片对象的最终消费者将成为一个移动应用程序.

响应需要有移动开发人员返回的缩略图版本请求JSON回来看起来像这样.

{
"root_url":'http://place.s3.amazonaws.com/folder/',
"image_300":'image_300.jpg',
"image_600":'image_600.jpg',
"image_vga":'image_VGA.jpg',
"image_full":'image.jpg'
}
Run Code Online (Sandbox Code Playgroud)

而不是这样的:

{
"root_url":'http://place.s3.amazonaws.com/folder/',
"thumbnails": {
  "image_300":'image_300.jpg',
  "image_600":'image_600.jpg',
  "image_vga":'image_VGA.jpg',
  "image_full":'image.jpg'
 }
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,简单的方法是为每个缩略图创建列并使其工作.我不喜欢被锁定,但因为如果我们想要不同的缩略图以后它会意味着向数据库添加列等.我更愿意在模型类中指定缩略图或者有一个单独的缩略图表拇指每排表.

我在一个连接中使用了GROUP_CONCAT来查看delegate,composition_of,使用:method => in to_json ..这些看起来都不像选项.是否有捷径可寻?

基本模型示例:

class Photo < ActiveRecord::Base
  has_many :thumbnails, :as => :thumbs_for #polymorphic
end

class Thumbnail < ActiveRecord::Base
  # columns = name, filename
  belongs_to :thumb_for, :polymorphic => true
end
Run Code Online (Sandbox Code Playgroud)

到目前为止,结果看起来像是基于jesse reiss的答案

def as_json(options)
  options ||= {} #even if you provide a default, it ends up as nil
  hash = super(options.merge({:include => :thumbnails}))
  if thumbs = hash.delete(:thumbnails)
    thumbs.each {|t| hash.merge!({t['name']=>t['filename']})}
  end
  hash
end
Run Code Online (Sandbox Code Playgroud)

jes*_*iss 10

您可以使用该as_json方法非常简单地自定义对象的json序列化.

为此,你可以这样做:

def as_json(*args)
  hash = super(*args)
  hash.merge!(hash.delete("thumbnails"))
end
Run Code Online (Sandbox Code Playgroud)

或者你可以超级手动完成

def as_json(*args)
  hash = super()
  thumbnails.each do |thumb|
    # build thumbnail json
  end
end
Run Code Online (Sandbox Code Playgroud)

您不必依赖ActiveRecord的超简单json序列化方法.