如何向API json响应添加虚拟属性

时间:2014-03-05 16:46:29

标签: ruby-on-rails ruby json api

上下文:ruby“2.0.0”和rails“4.0.0”

我想知道如何返回比模型的简单JSON表示更多的数据。我的API控制器中有这个方法:

def show
  @entry = params[:id].to_i != 0 ? Entry.find(params[:id]) : Entry.where(slug: params[:id]).first
  respond_with @entry
end

通过http://pow.url.dev/en/tenant/api/v1/entries/23调用时返回格式正确的JSON文章。

我还有另外两种方法来获取下一篇和上一篇文章,例如,next看起来像这样:

def next
  @current_entry = params[:entry_id].to_i != 0 ? Entry.find(params[:entry_id]) : Entry.where(slug: params[:entry_id]).first
  @entry = Entry.where( status_id: 0 ).where( "published_at > ?", @current_entry.published_at ).first
  respond_with @entry
end

问题是客户端应用程序需要对 1进行3次API调用才能获取文章,2)获取下一篇文章,3)获取上一篇文章。

如果客户只需要一次拨打电话即可获得所有信息,那就好多了。

我想在show方法中添加下一篇和上一篇文章的标题和ID 以及JSON结果,最好的方法是什么?< / p>

3 个答案:

答案 0 :(得分:3)

又快又脏:

def show
  @entry = ...
  render :json => @entry.attributes.merge({
    :next_id => id_of_next_article, 
    :next_title => title_of_next_article...
  })
end

更灵活的解决方案:使用某种JSON序列化定制器(或自己动手),我之前使用的是ActiveModel Serializers(https://github.com/rails-api/active_model_serializers)。我确定还有其他人。

答案 1 :(得分:1)

用户是否会始终使用Next和Prev文章?如果是这样,将它们放在JSON上,否则,在返回的JSON上使用REL为prevnext的链接位置标记,然后clint将能够知道从哪里获取{{1 }和next文章。您可以获得更多信息:RESTful Web Service usage of custom link relations - 'rel'

答案 2 :(得分:1)

以下是我提出的解决方案:

nextprevious的Entry模型对象中实现两个方法,如下所示:

def next
  Entry.where( status_id: 0 ).where( "published_at > ?", self.published_at ).select('id, title, slug').first
end

def previous
  Entry.where( status_id: 0 ).where( "published_at < ?", self.published_at ).select('id, title, slug').last
end

并在我的控制器的respond_with操作中将render :json替换为show

def show
  @entry = params[:id].to_i != 0 ? Entry.find(params[:id]) : Entry.where(slug: params[:id]).first
  render :json => @entry.to_json(:include => :entry_fields, 
                                 :methods => [:next, :previous])
end

输出:

{
    "id": 20,
    "title": "Video Test",
    "slug": "video-test",
    "status_id": 0,
    "promoted": true,
    "published_at": "2014-01-20T11:51:00.000Z",
    "created_at": "2014-01-20T11:51:37.406Z",
    "updated_at": "2014-03-05T13:42:49.981Z",
    "excerpt": "Video",
    "user_id": "933dc175-0d73-45fb-9437-61ecc4f55705",
    "next": {
        "id": 21,
        "title": "Test Multiple",
        "slug": "test-multiple"
    },
    "previous": {
        "id": 18,
        "title": "Example Entry",
        "slug": "example-entry"
    },
    ...
    ... (associations)
    ...
}