17

我正在使用ActiveModel::Serializers构建 API 。使用参数有条件地侧载数据的最佳方法是什么?

所以我可以提出如下要求GET /api/customers

"customers": {
   "first_name": "Bill",
   "last_name": "Gates"
}

GET /api/customers?embed=address,note

"customers": {
   "first_name": "Bill",
   "last_name": "Gates"
},
"address: {
   "street": "abc"
},
"note": {
   "body": "Banned"
}

类似的东西取决于参数。我知道 ActiveModel::Serializers 有include_[ASSOCIATION]?语法,但我怎样才能从我的控制器有效地使用它?


这是我目前的解决方案,但它并不整洁:

customer_serializer.rb:

def include_address?
  !options[:embed].nil? && options[:embed].include?(:address)
end

application_controller.rb:

def embed_resources(resources = [])
  params[:embed].split(',').map { |x| resources << x.to_sym } if params[:embed]
  resources
end

客户控制器.rb:

def show
  respond_with @customer, embed: embed_resources
end

必须是更简单的方法吗?

4

3 回答 3

8

我也在寻找一种有效且干净的方法来做到这一点。

我找到了一个解决方案,但它并不漂亮。

在我的 BaseController/ApplicationController 我添加了这个方法:

serialization_scope :params

所以范围现在是 params Hash,我可以在include_[ASSOCIATION]?我的序列化程序的方法中使用它。

def include_associations?
    if scope[:embed]
        embed = scope[:embed].split(',') 
        return true if embed.include?('associations')
    end
end

我不喜欢这种方法,因为如果我需要将范围用于其他东西,例如current_user如果它是管理员,则有条件地返回数据。

但是这个解决方案在某些情况下可以工作。

更新

您可以通过view_context而不是直接通过params.

您可以委托您的序列化程序保留params名称而不是scope.

在您的应用程序控制器中:

serialization_scope :view_context

在您的序列化程序中:

delegate :params, to: :scope

瞧,您可以在include_[ASSOCIATION]?序列化程序的方法中使用 params[:embed] 。

于 2013-07-23T16:53:02.260 回答
2

根据您的答案,我还有另一个解决方案,因为我想要类似的功能。根据文档,如果想要对关联序列化进行较低级别的控制,他们可以覆盖include_associations!.

例如:

def include_associations!
    if scope[:embed]
        include! :addresses, {embed: :ids, include: true}
    else
        include! :addresses, {embed: :ids}
    end
end
于 2013-11-14T01:19:38.717 回答
1

了解 include_associations 非常有帮助!谢谢!请注意,您可以使用 active_model_serializers gem(版本 0.8.3)@options在控制器中设置上下文。例如,如果在您调用的控制器中

render json: customer, include_addresses: true

然后在 CustomerSerializer 中:

has_many :addresses
def include_associations!
  if @options[:include_addresses]
    include! :addresses
  end
end

然后地址将被序列化。如果您使用include_addressesset to 进行渲染false,则不会。对于较新版本的 active_model_serializers,使用serialization_options而不是@options.

于 2015-03-01T18:04:11.970 回答