最近在搭一些 api, 免不了就要 render json 了,本来一直是用的 rabl
, 因为 json 场景不多,所以也无所谓了。但现在要正经搞 api 了,所以还是要花点心思。
网上搜了一下,基本上就是三种
然后网上搜了一下又看到了一大牛的推和下面的评论:
然后我就自己简单测了一下,在我自己机器上 render 4w 多个 model 的数组,每个 object 就只 render 一个 id attribute. 每种 render 方法用 curl call 了 20 次,统计了一下 development.log 里面 view render 的时间取平均值:
jbuilder 明显胜出,求问一下,是我什么地方用的不对么?还是大牛去年 9 月份说的已经 out of date 了,现在的确是 jbuilder 最好?
环境是 Rails 3.2, rabl 0.8.4, jbuilder 1.5.0, active_model_serializers 0.8.1, ruby-1.9.3-p327-falcon, Mac OSX 10.8.4
把数据量增大测试了一次,这次 render 了 1080 个『简书』的长文的数组,每个 object 都包含了很长的全文,和数组类型。因为有全文数据大实在有点慢,只跑了 10 次取平均:
jbuilder 和 rabl 可以说基本没有差别,serializer 太慢了,不知道是不是我哪里写的不对。不过 serializer 里面不能直接用 helper method 对我现在来说很不方便。
@hooopo rabl 2319, jbuilder 1127, active_model_serializers 1362.
我最开始也是因为 star 数选rabl
的,但是简单测下来 jbuilder 最快,我正在多放点儿属性再测一下
我们的项目里用着 active_model_serializers,我正在考虑把它换掉。除了慢之外,active_model_serializers 的设计思想可能就是一个 model 对应一个 serializer,但实际应用中,同一个 model 在不同的 view 中需要的字段可能有很大差别。active_model_serializers 不容易解决这个问题。
@yanhao 可以对应不同的 serializer
render :json => @note, :serializer => Api::V1::NoteSerializer, :root => false
render :json => @notes, :each_serializer => Api::V1::NoteSerializer, :root => false
这样就好了
object false
node(:some_count) { |m| @user.posts.count }
child(@user) { attribute :name }
#13 楼 @hooopo 忘记了,快两年了... 如果要在 user root 里面插入 @user.posts.count 呢?
在 jbuilder 下面你可以在 任何节点随便插入什么属性.. 在 rabl 里面你要想一下该怎么插入。这就是他们的区别。
@kingwkb 这是另一个问题了,主要现在还很小,直接 Rails 我觉得蛮好,也没到要换个框架性能才能撑的阶段。
第二,Grape, 也要用这些办法来 render json 的吧,难道 Grape 有啥别的魔法 ?
#18 楼 @larryzhao Grape 有 Entity
再小把 api 分离出来都有有必要的,增加不了几很代码,但整个结构变的清晰不少,又不是要增加很多代码
json.array!
vs collection
json.set!
vs node
json.extract!
vs attributes
# app/views/users/show.rabl
object @user
# Declare the properties to include
attributes :first_name, :last_name
# Alias 'age' to 'years_old'
attributes :age => :years_old
# Include a custom node with full_name for user
node :full_name do |user|
[user.first_name, user.last_name].join(" ")
end
# Include a custom node related to if the user can drink
node :can_drink do |user|
user.age >= 21
end
#7 楼 @larryzhao 我的意思是,比如 index 页只需要显示很少几个属性,show 页要显示大部分属性,这时,都用同一个 serializer,对 index 页来说,多处理了很多不必要的数据。除非你的 API 总是返回全部属性,不然,如果针对请求返回不同的数据的话,就要设计很多 serializer,而这些 serializer 又都在同一个文件夹下。
喜欢 rabl 预设做出来跟 xml 一样可自我辨识 (self-describing) 的 node,这样子 api 增加东西可以与先前相容。而 rabl 的无脑暴力所有东西都给他 cache 目前用来也很爽。Rabl 的缺陷是 DSL 有点难懂,而且用了一些魔法,有时候以为能插用 plain ruby 时反而不行
object @foo
puts @foo
do_something @foo.bar
上次试,第二行第三行都会出错误。