From ad45c401fbff7dda613c44786e490d666d560237 Mon Sep 17 00:00:00 2001 From: Tobias Kraze Date: Tue, 20 Nov 2018 17:52:50 +0100 Subject: [PATCH] fix caching on first save for a unused model --- CHANGELOG.md | 1 + lib/acts_as_taggable_on/taggable/cache.rb | 40 +++++++------------ spec/acts_as_taggable_on/caching_spec.rb | 8 ++++ .../app/models/single_use_cached_model.rb | 5 +++ 4 files changed, 28 insertions(+), 26 deletions(-) create mode 100644 spec/internal/app/models/single_use_cached_model.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index ed2c1604c..4e0d47ff0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ As such, _Breaking Changes_ are major. _Features_ would map to either major or m * [@mizukami234 @junmoka Make table names configurable](https://github.com/mbleigh/acts-as-taggable-on/pull/910) * Fixes * [@tonyta Avoid overriding user-defined columns cache methods](https://github.com/mbleigh/acts-as-taggable-on/pull/911) + * [@kratob Fix caching on first save for an unused model](https://github.com/mbleigh/acts-as-taggable-on/pull/928) * Misc * [@gssbzn Remove legacy code for an empty query and replace it with ` ActiveRecord::none`](https://github.com/mbleigh/acts-as-taggable-on/pull/906) * Documentation diff --git a/lib/acts_as_taggable_on/taggable/cache.rb b/lib/acts_as_taggable_on/taggable/cache.rb index 46df3fe25..70e1620f8 100644 --- a/lib/acts_as_taggable_on/taggable/cache.rb +++ b/lib/acts_as_taggable_on/taggable/cache.rb @@ -3,40 +3,28 @@ module Cache def self.included(base) # When included, conditionally adds tag caching methods when the model # has any "cached_#{tag_type}_list" column - base.extend Columns + base.extend LoadSchema end - module Columns - # ActiveRecord::Base.columns makes a database connection and caches the - # calculated columns hash for the record as @columns. Since we don't - # want to add caching methods until we confirm the presence of a - # caching column, and we don't want to force opening a database - # connection when the class is loaded, here we intercept and cache - # the call to :columns as @acts_as_taggable_on_cache_columns - # to mimic the underlying behavior. While processing this first - # call to columns, we do the caching column check and dynamically add - # the class and instance methods - # FIXME: this method cannot compile in rubinius - def columns - @acts_as_taggable_on_cache_columns ||= begin - db_columns = super - _add_tags_caching_methods if _has_tags_cache_columns?(db_columns) - db_columns - end - end + module LoadSchema + private - def reset_column_information + # @private + # ActiveRecord::Base.load_schema! makes a database connection and caches the + # calculated columns hash for the record as @column_hashs. Since we don't + # want to add caching methods until we confirm the presence of a + # caching column, and we don't want to force opening a database connection, + # we override load_schema!, do the caching column check and dynamically + # add the class and instance methods. + def load_schema! super - @acts_as_taggable_on_cache_columns = nil + _add_tags_caching_methods if _has_tags_cache_columns? end - private - # @private - def _has_tags_cache_columns?(db_columns) - db_column_names = db_columns.map(&:name) + def _has_tags_cache_columns? tag_types.any? do |context| - db_column_names.include?("cached_#{context.to_s.singularize}_list") + @columns_hash.has_key?("cached_#{context.to_s.singularize}_list") end end diff --git a/spec/acts_as_taggable_on/caching_spec.rb b/spec/acts_as_taggable_on/caching_spec.rb index 9391fe96b..8f462cb71 100644 --- a/spec/acts_as_taggable_on/caching_spec.rb +++ b/spec/acts_as_taggable_on/caching_spec.rb @@ -38,6 +38,14 @@ expect(@another_taggable.cached_language_list).to eq('ruby, .net') end + it 'should cache tags when the model is freshly loaded' do + taggable = SingleUseCachedModel.new + taggable.tag_list = 'awesome, epic' + taggable.save! + + expect(taggable.cached_tag_list).to eq('awesome, epic') + end + it 'should keep the cache' do @taggable.update_attributes(tag_list: 'awesome, epic') @taggable = CachedModel.find(@taggable.id) diff --git a/spec/internal/app/models/single_use_cached_model.rb b/spec/internal/app/models/single_use_cached_model.rb new file mode 100644 index 000000000..c262397be --- /dev/null +++ b/spec/internal/app/models/single_use_cached_model.rb @@ -0,0 +1,5 @@ +# This is used in a spec that expects this model not to have been used before. +class SingleUseCachedModel < ActiveRecord::Base + self.table_name = 'cached_models' + acts_as_taggable +end