ben*_*ben 8 json caching ruby-on-rails
在JSON
我的Car
模型的表示中,我包括一个昂贵的方法的输出:
#car.rb
def as_json(options={})
super(options.merge(methods: [:some_expensive_method]))
end
Run Code Online (Sandbox Code Playgroud)
我有一个标准的索引操作:
#cars_controller.rb
respond_to :json
def index
respond_with(Car.all)
end
Run Code Online (Sandbox Code Playgroud)
我也在JSON
其他地方使用汽车的表示,如下所示:
#user_feed.rb
def feed_contents
Horse.all + Car.all
end
#user_feeds_controller.rb
respond_to :json
def index
respond_with(UserFeed.feed_contents)
end
Run Code Online (Sandbox Code Playgroud)
因为a的JSON
表示car
在多个地方使用,所以我希望将其car.cache_key
作为自动过期的缓存键自行缓存.
这就是我目前正在做的事情:
#car.rb
def as_json(options={})
Rails.cache.fetch("#{cache_key}/as_json") do
super(options.merge(methods: [:some_expensive_method]))
end
end
Run Code Online (Sandbox Code Playgroud)
将缓存代码放入其中as_json
是不正确的,因为缓存不是可as_json
重复性的一部分.这样做的正确方法是什么?我正在使用Rails 3.2.15.
首先我要说我对这个问题的努力表示赞赏。你会发现很难找到比我更热衷于以正确方式设计软件的人了——包括用小方法在一个抽象级别上做好一件事。
不过,我不得不说,在这一点上,我其实是反对这个问题的前提的。我认为你的as_json
样子最好。
最重要的是使客户端与实现脱钩。客户端需要知道的唯一一件事Car#as_json
是返回值是Car
. 并且as_json
做了那件事并且做得很好。缓存和/或获取是应该保留在方法内部的实现细节,并且它是该任务不可或缺的细节。
否则就好像说任何带有if
语句的方法都是“不正确的”,因为它做了两件事。当然这不是真的。在这两种情况下(usingif
和 using Rails.cache.fetch
),方法实现都是一些原子操作,其结果基于条件。
这是一件事可以以两种方式之一进行,这与两件事不同。
同时,我不得不不同意@severin 的回应。它当然可以工作,但是您现在已经将您的视图与实现细节结合起来。任何人,当然也不应该是您的观点,都不应该了解缓存的方法,甚至不应该知道涉及缓存。在我看来,你现在已经用这种方法泄露了抽象。也许这并不重要,但既然我们正在谈论做事的“正确方式”......
所以我说保持现状。但我相信这是一个很好的问题。