Clearing ActiveRecord cache
To a first approximation:
ActiveRecord::Base.connection.query_cache.clear
How can I force the rails SQL cache to clear?
All you need to do is to reestablish database connection. Try:
system("bundle exec rake db:reset")
puts User.count
User.destroy_all("username = 'user3'")
puts User.count
system("bundle exec rake db:reset")
ActiveRecord::Base.clear_all_connections!
puts User.count
User.destroy_all("username = 'user3'")
puts User.count
The main question is: why do you need to do this? I am pretty certain there is a better way to achieve what you want.
Ruby on Rails: Clear a cached page
This line in development.rb ensures that caching is not happening.
config.action_controller.perform_caching = false
You can clear the Rails cache with
Rails.cache.clear
That said - I am not convinced this is a caching issue. Are you making changes to the page and not seeing them reflected? You aren't perhaps looking at the live version of that page? I have done that once (blush).
Update:
You can call that command from in the console.
Are you sure you are running the application in development?
The only alternative is that the page that you are trying to render isn't the page that is being rendered.
If you watch the server output you should be able to see the render command when the page is rendered similar to this:
Rendered shared_partials/_latest_featured_video (31.9ms)
Rendered shared_partials/_s_invite_friends (2.9ms)
Rendered layouts/_sidebar (2002.1ms)
Rendered layouts/_footer (2.8ms)
Rendered layouts/_busy_indicator (0.6ms)
How can I tell ActiveRecord to discard an association cache AFTER a where clause
First off it's not true to say that the where
clause forces a refresh - for active record the two are just separate relations and one being loaded has no incidence on the other. If you hold onto that relation it will only be loaded once, for example
rel = m.assets.where(type: 'Source'); nil
rel.map(&:id)
rel.map(&:id)
only hits the database once.
You can clear an association cache by calling reset on it:
m.assets.reset
(however since this returns the association, in the console this will trigger a reload unless you append ;false
or similar)
What is the right way to clear cache in Rails without sweepers
Welcome to one of the two hard problems in computer science, cache invalidation :)
You would have to handle that manually since the logic for when a cached object, unlike a cached view which can be simply derived from the objects it displays, should be invalidated is application and situation dependent.
You goto method for this is the Rails.cache.fetch
method. Rails.cache.fetch
takes 3 arguments; the cache key, an options hash, and a block. It first tries to read a valid cache record based on the key; if that key exists and hasn’t expired it will return the value from the cache. If it can’t find a valid record it instead takes the return value from the block and stores it in the cache with your specified key.
For example:
@models = Rails.cache.fetch my_cache_key do
Model.where(condition: true).all
end
This will cache the block and reuse the result until something (tm) invalidates the key, forcing the block to be reevaluated. Also note the .all
at the end of the method chain. Normally Rails would return an ActiveRecord relation object that would be cached and this would then be evaluated when you tried to use @models
for the first time, neatly sidestepping the cache. The .all
call forces Rails to eager load the records and ensure that it's the result that we cache, not the question.
So now that you get all your cache on and never talk to the database again we have to make sure we cover the other end, invalidating the cache. This is done with the Rails.cache.delete
method that simply takes a cache key and removes it, causing a miss the next time you try to fetch it. You can also use the force: true
option with fetch to force a re-evaluation of the block. Whichever suits you.
The science of it all is where to call Rails.cache.delete
, in the naïve case this would be on update and delete for a single instance and update, delete, create on any member for a collection. There will always bee corner cases and they are always application specific, so I can't help you much there.
I assume in this answer that you will set up some sane cache store, like memcached or Redis.
Also remember to add this to config/environments/development.rb:
config.cache_store = :null_store
or you development environment will cache and you will end up hairless from frustration.
For further reference read: Everyone should be using low level caching in Rails and The rails API docs
It is also worth noting that functionality is not removed from Rails 4, merely extracted into a gem. If you need or would like the full features of the sweepers simply add it back to your app with a gem 'rails-observers'
line in your Gemfile. That gem contains both the sweepers and observers that where removed from Rails 4 core.
I hope that helpt you get started.
Disabling Rails SQL query caching globally
In Rails 5 we can disable active record query cache using the given function as a middleware.
In application_controller.rb add the given code.
around_action :disable_query_cache
def disable_query_cache
ActiveRecord::Base.uncached do
yield
end
end
Confusion caching Active Record queries with Rails.cache.fetch
The reason is because
User.where('status = 1').limit(1000)
returns an ActiveRecord::Relation
which is actually a scope, not a query. Rails caches the scope.
If you want to cache the query, you need to use a query method at the end, such as #all
.
Rails.cache.fetch(key) do
User.where('status = 1').limit(1000).all
end
Please note that it's never a good idea to cache ActiveRecord objects. Caching an object may result in inconsistent states and values. You should always cache primitive objects, when applicable. In this case, consider to cache the ids.
ids = Rails.cache.fetch(key) do
User.where('status = 1').limit(1000).pluck(:id)
end
User.find(ids)
You may argue that in this case a call to User.find
it's always executed. It's true, but the query using primary key is fast and you get around the problem I described before. Moreover, caching active record objects can be expensive and you might quickly end up filling all Memcached memory with just one single cache entry. Caching ids will prevent this problem as well.
Related Topics
Ruby, Tor and Net::Http::Proxy
Machinist VS Factorygirl - Pros and Cons
How to See the Ruby Code in a Proc
Accessing Nested Model Attributes Inside a Fields_For Without Using Formbuilder
How to Do Case-Insensitive Order in Rails with Postgresql
Mail Gem - How to Clean Up the Body String
Ruby Operator Overloading Question
Installing Nokogiri MAC Os X 10.8.2 Xcode Installed
Where Does Ruby Keep Track of Its Open File Descriptors
Differences Between Literals and Constructors? ([] VS Array.New and {} VS Hash.New)
How to Make the Url's in Ruby on Rails Seo Friendly Knowing a @Vendor.Name
Simple Neural Network Can't Learn Xor