如何在Rails中的respond_with json数据上运行方法?

时间:2015-10-12 10:26:08

标签: ruby-on-rails json

我有一个返回一些参数的模型,并包含来自其他模型的参数,如下所示:

def as_json(options = {})
  camelize_keys(super(options.merge(:only => [:id, :userId], include:{ 
    comments: { only: [:test, :id] },
    valediction: { only: [:name, :text, :hidden, :order] }
  })))
end

def camelize_keys(hash)
  values = hash.map do |key, value|
    [key.camelize(:lower), value]
  end
  Hash[values]
end

现在我已将代码移动到我的控制器,因为不同的控制器操作需要返回模型的不同部分。 (索引应该只返回告别,但show应该返回评论和告别)

新控制器:

  def index
    respond_with(displayed_user.microposts.all, include: {
      valediction: { only: [:name, :text] }
    })
  end

  def show
    respond_with(displayed_user.microposts.find(params[:id]), include: {
      comments: { only: [:test, :id] },
      valediction: { only: [:name, :text, :hidden, :order] }
    })
  end

但我对rails非常陌生,我不知道如何将camelize_keys函数放入其中以便它可以工作。

2 个答案:

答案 0 :(得分:0)

您可以将方法移动到模型中的类方法,例如

#class methods
class << self
  def camelize_keys(hash)
    values = hash.map do |key, value|
      [key.camelize(:lower), value]
    end
    Hash[values]
  end
end

现在你可以从

这样的地方调用它
MyModel.camelize_keys(some_hash)

答案 1 :(得分:0)

在控制器/和/或模型中执行复杂的JSON格式化通常会导致膨胀并且很难测试。

一个很好的解决方案是使用ActiveModel::Serializer(AMS)gem。它包含在Rails 5中,但您可以通过将其添加到gemfile中轻松地将其添加到Rails 4项目中:

# See rubygems.org for latest verstion!
gem 'active_model_serializers', '~> 0.9.3' 

然后运行bundle install并重新启动rails服务器。

使用AMS,您可以创建序列化程序类,这些类定义了如何使用JSON,XML等表示模型数据。序列化程序基本上是一个接受模型实例(或模型数组)并返回哈希(或数组)的类哈希)当你致电.serializable_hash时。

但Rails会自动为您处理该部分。

class MicropostSerializer < ActiveModel::Serializer
  attributes :id, :user_id
  has_many :comments
  has_many :valedictions
end

class CommentSerializer < ActiveModel::Serializer
  attributes :test, :id
end

class ValedictionSerializer < ActiveModel::Serializer
  attributes :name, :text, :hidden, :order
end

在您的控制器中,您只需致电:

def index
  render json: displayed_user.microposts.all
end

但等等,camelize_keys怎么办?

除非你必须支持一些需要camelized密钥的奇怪遗留客户端,否则很少有理由这样做。大多数大型API使用snakecase(Facebook,Google等),而Rails 5正朝着使用snakecase的JSONAPI规范发展。

从您的代码示例中,您的某些rails模型属性(以及支持它们的db列)似乎使用了camelcase。您应该尽快通过迁移更改DB列。

如果您必须支持旧数据库,则可以使用alias_attribute:

class Pet < ActiveRecord::Base
  alias_attribute :ownerId, :owner_id
end