ActiveResource + Caching

2019-08-02 04:39发布

问题:

I'm building an application that consumes models through an api with ActiveResource. I noticed that the

@resource ||= @resource.do a query 

doesn't work, i.e. If I put something like that in my controller, my application will still query the api. So there is no built in caching that I'm used to with ActiveRecord. Time to expand my knowledge and skill base, ok.

I found this: http://injectisforwizards.com/blog/read-through-caching-of-activeresource/, and while I don't understand this 100% yet, for controller based queries that do .find, this appears to work. But not for any custom queries I have e.g.:

@current_resource ||= Resource.get(:resource_all, :by_account=>@current_account.account_key)

(which hits a custom controller and runs a scope, returning a collection)

I'm working through this and I'll find out what is going, but I'm curious if someone could tell me simpler terms what is going on, what I can do to smooth over caching in ActiveResource to be more like ActiveRecord, how I can tailor this to cache all queries, etc. Anything really would be helpful.

EDIT:

I found this: https://github.com/Ahsizara/cached_resource which looks promising but it is new (and built off that link above)....notable is that it does not seem to handle any sort of collections, but for one resource finds/caches well.

回答1:

Since you receive a new instance of a controller for each request, caching like that is not going to work. I'm presuming you have something like this:

def show
  @resource ||= expensive_request
end

What are you expecting @resource to be when that method executes? The result of something from a previous call to show? Not going to happen.

What you need to do is put things into Rails.cache if you want them to persist between requests. If you use memcached as a back end, this can be very efficient. See the Caching with Rails guide for more information around section 2.5.

In general, a better approach than the ||= method of caching is to define protected methods that are wrapped with memoize to save the results. For example:

def load_resource
  expensive_request
end
memoize :load_resource

Remember that this will only apply to subsequent calls to that method within the context of the same request and is not the same as using Rails.cache.