Ruby on rails 使用ActiveModel::Serializer有条件地侧向加载
我正在使用ActiveModel::Serializers构建一个API。使用参数有条件地侧向加载数据的最佳方法是什么 所以我可以发出请求,比如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
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进行单元测试吗?我已经更新了我的问题,向您展示了我是如何做的。