Ruby on Rails
Tuesday, December 3, 2019
Hello,
Lets say that I have a model class like `Car < ActiveRecord::Base` and then, I want to extend it with an abstract class in between a sort of `Car < CacheableActiveRecord::Base < ActiveRecord::Base`
In `CacheableActiveRecord::Base` I'll overwrite methods like `find_by`, `find_by!` and `find` with the intention of checking out Redis/Memcached before calling super and letting Rails resolve this to the underlying db, I'm using Rails 4.2.7.1
-- Lets say that I have a model class like `Car < ActiveRecord::Base` and then, I want to extend it with an abstract class in between a sort of `Car < CacheableActiveRecord::Base < ActiveRecord::Base`
In `CacheableActiveRecord::Base` I'll overwrite methods like `find_by`, `find_by!` and `find` with the intention of checking out Redis/Memcached before calling super and letting Rails resolve this to the underlying db, I'm using Rails 4.2.7.1
By extending `Car` an `after_commit` hook will be created for each instance of the `Car` class, that hook will clear the cached key for this model upon commit, This is to get the effect, of releasing the cache on save.
This is an implementation for my `find` method in `CacheableActiveRecord::Base`
```
This is an implementation for my `find` method in `CacheableActiveRecord::Base`
```
def self.find(*ids)
expects_array = ids.first.kind_of?(Array)
return ids.first if expects_array && ids.first.empty?
ids = ids.flatten.compact.uniq
case ids.size
when 0
super # calling supper will generate an exception at this point
when 1
id = ids.first
result = get_from_cache(id)
unless result
result = super # I expect this to get the data from db
if result
result = set_to_cache(id, result)
end
end
expects_array ? [ result ] : result
else
super # for now let's just skip on multiple ids
end
rescue RangeError
raise RecordNotFound, "Couldn't find #{@klass.name} with an out of range ID"
end
```I have tests for this, and they even seem to work. for the implementation of `set_to_cache` and `get_from_cache` I have the following code
```
def self.get_from_cache(entity_id)
return nil unless entity_id
cached = Rc.get!(get_cache_key(entity_id))
if cached
puts "cache hit"
end
return cached ? Marshal.load(cached) : nil
end
def self.set_to_cache(entity_id, entity)
return nil unless entity && entity_id
dump = Marshal.dump(entity)
Rc.set!(get_cache_key(entity_id), dump)
return Marshal.load(dump)
end
```
My doubts here are:
Thank you
Daniel
My doubts here are:
- Is `Marshal` safe? can one do this? taking into account that this cache will be shared among instances of the same rails app, running in different servers.
- Is it better to serialize to json? is it possible to serialize to json and then rebuilt an object that will work as regular active record object? I mean one on which you can call `.where` queries on related objects and so on?
I'm a newbie to Rails and Ruby, started coding with both two weeks ago, my background is mostly java xD (finding Ruby great BY THE WAY hahaha)
Thank you
Daniel
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-talk+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/ff0d04b7-0ea8-414e-99a5-3d9f73329091%40googlegroups.com.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment