Ruby on rails 使用ActiveModel::Serializer有条件地侧向加载

Ruby on rails 使用ActiveModel::Serializer有条件地侧向加载,ruby-on-rails,json,api,active-model-serializers,Ruby On Rails,Json,Api,Active Model Serializers,我正在使用ActiveModel::Serializers构建一个API。使用参数有条件地侧向加载数据的最佳方法是什么 所以我可以发出请求,比如GET/api/customers: "customers": { "first_name": "Bill", "last_name": "Gates" } 和GET/api/customers?embed=地址,注意 "customers": { "first_name": "Bill", "last_name": "Gate

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

所以我可以发出请求,比如
GET/api/customers

"customers": {
   "first_name": "Bill",
   "last_name": "Gates"
}
GET/api/customers?embed=地址,注意

"customers": {
   "first_name": "Bill",
   "last_name": "Gates"
},
"address: {
   "street": "abc"
},
"note": {
   "body": "Banned"
}
这取决于参数。我知道ActiveModel::Serializer具有
包含[ASSOCIATION]?
语法,但如何从控制器有效地使用它


这是我目前的解决方案,但并不完美:

customer\u serializer.rb:

def include_address?
  !options[:embed].nil? && options[:embed].include?(:address)
end
def embed_resources(resources = [])
  params[:embed].split(',').map { |x| resources << x.to_sym } if params[:embed]
  resources
end
def show
  respond_with @customer, embed: embed_resources
end
应用程序\u控制器.rb:

def include_address?
  !options[:embed].nil? && options[:embed].include?(:address)
end
def embed_resources(resources = [])
  params[:embed].split(',').map { |x| resources << x.to_sym } if params[:embed]
  resources
end
def show
  respond_with @customer, embed: embed_resources
end

必须是一种更简单的方法吗?

我也在寻找一种有效且干净的方法来实现这一点

我找到了一个解决方案,但并不完美

在我的BaseController/ApplicationController中,我添加了以下方法:

serialization_scope :params
因此,作用域现在是params散列,我可以在序列化程序的
include\u[ASSOCIATION]?
方法中使用它

def include_associations?
    if scope[:embed]
        embed = scope[:embed].split(',') 
        return true if embed.include?('associations')
    end
end
我不喜欢这种方法,因为如果我需要使用诸如
current\u user
之类的其他对象的作用域来有条件地返回数据(例如,如果它是管理员)

但这种解决方案在某些情况下是可行的

更新

您可以传递
查看上下文
,而不是直接传递
参数

您可以在序列化程序中委托以保留
参数
名称,而不是
范围

在应用程序控制器中:

serialization_scope :view_context
在序列化程序中:

delegate :params, to: :scope
has_many :addresses
def include_associations!
  if @options[:include_addresses]
    include! :addresses
  end
end

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

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

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

def include_associations!
    if scope[:embed]
        include! :addresses, {embed: :ids, include: true}
    else
        include! :addresses, {embed: :ids}
    end
end

了解include_协会非常有帮助!,谢谢注意,使用活动的_model _serializersgem(版本0.8.3),您可以使用
@options
在控制器中设置上下文。例如,如果在控制器中调用

render json: customer, include_addresses: true
然后在CustomerSerializer中:

delegate :params, to: :scope
has_many :addresses
def include_associations!
  if @options[:include_addresses]
    include! :addresses
  end
end
然后地址将被序列化。如果渲染时将
include_addresses
设置为
false
,则不会显示这些地址。
对于较新版本的活动\u模型\u序列化程序,请使用
serialization\u options
而不是
@options

我喜欢您使用查看\u上下文的建议。可以用rspec进行单元测试吗?我已经更新了我的问题,向您展示了我是如何做的。