我正在使用 ActiveModel :: Serializers 构建API。使用params有条件地加载数据的最佳方法是什么?
所以我可以提出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"
}
取决于params这样的东西。我知道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
customers_controller.rb:
def show
respond_with @customer, embed: embed_resources
end
必须更简单吗?
答案 0 :(得分: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]。
答案 1 :(得分:2)
我还有另一个基于你的答案的解决方案,因为我想要类似的功能。根据文档,如果想要对关联序列化进行较低级别的控制,他们可以覆盖include_associations!
。
例如:
def include_associations!
if scope[:embed]
include! :addresses, {embed: :ids, include: true}
else
include! :addresses, {embed: :ids}
end
end
答案 2 :(得分: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_addresses
设置为false
进行渲染,则不会。
对于较新版本的active_model_serializers,请使用serialization_options
而不是@options
。