如何使用 Ruby/Rails 缓存方法?
我需要向另一个 Web 服务发出一个昂贵(耗时)的外部请求,并且我想缓存它。因此,我尝试使用这个 惯用法,将以下内容放入应用程序控制器中:
def get_listings
cache(:get_listings!)
end
def get_listings!
return Hpricot.XML(open(xml_feed))
end
当我调用 < code>get_listings! 在我的控制器中一切都很酷,但是当我调用 get_listings
Rails 抱怨没有给出任何块。当我查找该方法时,我发现它确实需要一个块,而且该方法看起来只适用于视图?所以我猜测虽然没有说明,但该示例只是伪代码。
所以我的问题是,如何缓存这样的东西?我尝试了各种其他方法但无法弄清楚。谢谢!
I have an expensive (time-consuming) external request to another web service I need to make, and I'd like to cache it. So I attempted to use this idiom, by putting the following in the application controller:
def get_listings
cache(:get_listings!)
end
def get_listings!
return Hpricot.XML(open(xml_feed))
end
When I call get_listings!
in my controller everything is cool, but when I call get_listings
Rails complains that no block was given. And when I look up that method I see that it does indeed expect a block, and additionally it looks like that method is only for use in views? So I'm guessing that although it wasn't stated, that the example is just pseudocode.
So my question is, how do I cache something like this? I tried various other ways but couldn't figure it out. Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
代码内方法可能看起来像这样:
它将基于每个请求缓存结果(每个请求新的控制器实例),尽管您可能希望将“memoize”帮助器视为 api 选项。
如果您想跨请求共享不要在类对象上保存数据,因为您的应用不会是线程安全的,除非您擅长并发编程和并发编程。确保线程不会干扰彼此对共享变量的数据访问。
跨请求缓存的“rails 方式”是 Rails.cache 存储 。 Memcached 被广泛使用,但您可能会发现文件或内存存储适合您的需求。这实际上取决于您的部署方式,以及您是否想要优先考虑缓存命中、响应时间、存储 (RAM),还是使用托管解决方案,例如 heroku 插件。
an in-code approach could look something like this:
which will cache the result on a per-request basis (new controller instance per request), though you may like to look at the 'memoize' helpers as an api option.
If you want to share across requests don't save data on the class objects, as your app will not be threadsafe, unless you're good at concurrent programming & make sure the threads don't interfere with each other's data access to the shared variable.
The "rails way" to cache across requests is the Rails.cache store. Memcached gets used a lot, but you might find the file or memory stores fit your needs. It really depends on how you're deploying and whether you want to prioritise cache hits, response time, storage (RAM), or use a hosted solution e.g. a heroku addon.
正如 nruth 所建议的,Rails 的内置缓存存储可能正是您想要的。
尝试:
fetch() 检索指定键的缓存值,或者如果不存在则将块的结果写入缓存。
默认情况下,Rails 缓存使用文件存储,但在生产环境中,memcached 是首选。
有关更多详细信息,请参阅 http://guides.rubyonrails.org/caching_with_rails.html 的第 2 节。
As nruth suggests, Rails' built-in cache store is probably what you want.
Try:
fetch() retrieves the cached value for the specified key, or writes the result of the block to the cache if it doesn't exist.
By default, the Rails cache uses file store, but in a production environment, memcached is the preferred option.
See section 2 of http://guides.rubyonrails.org/caching_with_rails.html for more details.
您可以使用 cache_method gem:
在您的代码中:
您可能会注意到我摆脱了
get_listings!
。如果您需要一种手动刷新数据的方法,我建议:这是另一个花絮:
You can use the cache_method gem:
In your code:
You might notice I got rid of
get_listings!
. If you need a way to refresh the data manually, I suggest:Here's another tidbit:
还可以使用cachethod gem (https://github.com/reneklacan/cachethod)
那么它是致命的易于缓存方法的结果
它还支持参数级缓存
You can also use cachethod gem (https://github.com/reneklacan/cachethod)
Then it is deadly simple to cache method's result
It also supports argument level caching
有人建议使用
cache_method
gem,尽管它相当重。如果您需要调用不带参数的方法,解决方案非常简单:然后您可以在任何类中使用它:
注意 - 这也将缓存 nil,这是使用它而不是
@cached_value ||=< 的唯一原因/代码>
There was suggested
cache_method
gem, though it's pretty heavy. If you need to call method without arguments, solution is very simple:then you can use it in any class:
Note - this will also cache nil, which is the only reason to use it instead of
@cached_value ||=
聚会迟到了,但以防万一有人来这里寻找。
我曾经在一个项目之间携带这个小模块,我发现它足够方便且可扩展,无需添加额外的 gem。它使用
Rails.cache
后端,因此请仅在您有后端时使用它。然后在初始化器中:
然后在模型中:
此时它仅适用于模型,但可以轻松泛化。
Late to the party, but in case someone arrives here searching.
I use to carry this little module around from project to project, I find it convenient and extensible enough, without adding an extra gem. It uses the
Rails.cache
backend, so please use it only if you have one.Then in an initializer:
And then in a model:
At this point it only works with models, but can be easily generalized.
其他答案都很好,但如果您想要一个简单的手动方法,您可以这样做。在您的类中定义一个如下所示的方法...
此后,对于要缓存的每个方法,您可以将方法主体包装在类似这样的内容中...
这比上面列出的最简单的方法做得更好的一件事是它会缓存一个零。它的优点是不需要创建重复的方法。不过,宝石方法可能更干净。
Other answers are excellent but if you want a simple hand-rolled approach you can do this. Define a method like the below one in your class...
Thereafter, for each method you want to cache you can put wrap the method body in something like this...
One thing that this does better than the simplest method listed above is that it will cache a nil. It has the convenience that it doesn't require creating duplicate methods. Probably the gem approach is cleaner, though.
我想建议我自己的 gem https://github.com/igorkasyanchuk/rails_cached_method
例如:
只需拨打:
I'd like to suggest my own gem https://github.com/igorkasyanchuk/rails_cached_method
For example:
Just call: