code_aks
code_aks

Reputation: 2074

How to fetch redis data connected in multiple rails version application?

I am using redis cache to fetch data in my rails applications. In simple words I can say that I have two application first is based on rails 4 and second is on rails 6. I have to use cache data in both application.

In rails 4 application :- I have created cache in rails 4 application and It fetched data successfully.

Rails.cache.fetch("test_cache"){User.last}
=> #<User id: 100973, email: "xxxx.com", encrypted_password: "$2a$10$D8aOhoSWvNWeEQE2swAX2OEVIF5H0aY8sR/fGVQ3BhU...........> 

In rails 6 application :- But When I want to load same cache in my rails 6 application gives me an error.

Rails.cache.fetch("test_cache"){User.last}
Traceback (most recent call last):
        2: from (irb):18
        1: from (irb):18:in `rescue in irb_binding'
NameError (uninitialized constant ActiveRecord::AttributeSet)
Did you mean?  ActiveRecord::Attributes

Then I came to one solution, save data with as_json

Rails.cache.fetch("test_cache"){User.last.as_json}

which successfully work and fetched data on both application but then I have one more problem how can I access model methods, associations etc etc... for the same.

Any suggestion or any idea ?

Upvotes: 2

Views: 692

Answers (1)

Vasfed
Vasfed

Reputation: 18454

For non-string values in cache Rails uses Marshal.dump (and also compresses it via deflate for large ones). Marshalled data can be thought as something in between data and code, because it has references to class names and internal structure. That's why it has limitations: it can be unmarshalled only with same ruby version (see ruby docs on that) and app should have same classes.

Obviously, ActiveRecord::Base structure is different in rails 4 and rails 6 thus incompatible when marshalled.

To have compatibility your only option is to cache only basic ruby types and POROs, that do not reference any classes that are different in your apps. Your attempt with as_json does exactly that - store a Hash representation of the model.

But actually first move is to think again about what exactly and why you want to cache, there several thoughts to consider:

  1. Sure, Redis/Memcache is fast, but accessing it is still a database query with corresponding overhead. Simple reads from a SQL DB (like User.find(primary_key_value_here)) are almost as fast.
  2. AR models have caches for associations, also you may have some memoized data, you might encounter data stalling for these
  3. Accessing non-cached associations will still result in database calls
  4. Most probably you want to cache not the model itself, but a way to find it more easily (for example, if it is a result of some expensive computation) or some derived data. In the former case it's sufficient to store record id, in the latter you can store something like a hash/PORO with all the data that you need, like:
hash = Rails.cache.fetch("last_registered_user"){
  User.last.yield_self{|u|
    {
      user_id: u.id,
      name: u.name,
      registered_at: u.created_at,
      invited_by: u.invited_by.name
    }
  }
}

Upvotes: 1

Related Questions