database_cached_attribute 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.travis.yml +1 -0
- data/Gemfile +14 -0
- data/LICENSE +20 -0
- data/README.md +6 -0
- data/Rakefile +25 -0
- data/lib/database_cached_attribute.rb +81 -0
- data/lib/database_cached_attribute/version.rb +7 -0
- data/lib/tasks/database_cached_attribute_tasks.rake +4 -0
- data/spec/database_cached_attribute_spec.rb +144 -0
- metadata +154 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e3ef5688041c2ebdebee855e718969bc6cd71689
|
4
|
+
data.tar.gz: 9d6ddf4d939944de4cd165123d61d3a9c8cd0e15
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dabf006f76c29f149f7a0cf8663d5f18753270c129e075ed2ca440de752f40a10c6b3a907d4c88a6ea74879638094551b7b668e5c8bd54c3e5c7e7270ec9f1a1
|
7
|
+
data.tar.gz: 523acfca93ff269e49dc7631c89a2f480647de6ad29e4734f7dbb934a67bc31b85c70680acfee13e825e89b529d3d69391b2b81c829b364aac2803257066c0da
|
data/.travis.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
language: ruby
|
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
# Declare your gem's dependencies in database_cached_attribute.gemspec.
|
4
|
+
# Bundler will treat runtime dependencies like base dependencies, and
|
5
|
+
# development dependencies will be added by default to the :development group.
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
# Declare any dependencies that are still in development here instead of in
|
9
|
+
# your gemspec. These might include edge Rails or gems from your path or
|
10
|
+
# Git. Remember to move these dependencies to your gemspec before releasing
|
11
|
+
# your gem to rubygems.org.
|
12
|
+
|
13
|
+
# To use debugger
|
14
|
+
# gem 'debugger'
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Charles Smith (github.com/twohlix/)
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
database_cached_attribute
|
2
|
+
=========================
|
3
|
+
[](https://codeclimate.com/github/twohlix/database_cached_attribute)
|
4
|
+
[](https://travis-ci.org/twohlix/database_cached_attribute)
|
5
|
+
|
6
|
+
Ruby gem that adds simple functions to invalidate single columns as a cache on an ActiveRecord models.
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'DatabaseCachedAttribute'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
#rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
Bundler::GemHelper.install_tasks
|
18
|
+
|
19
|
+
require 'rspec/core/rake_task'
|
20
|
+
|
21
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
22
|
+
spec.rspec_opts = '--colour'
|
23
|
+
end
|
24
|
+
|
25
|
+
task default: :spec
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
# DatabaseCachedAttribute adds a method to add a set of easy to use cache invalidation
|
4
|
+
# methods/callbacks for specified attributes
|
5
|
+
#
|
6
|
+
# On the model where you possibly may want to cache things from this model that may
|
7
|
+
# be heavy to create:
|
8
|
+
# include DatabaseCachedAttribute
|
9
|
+
# database_cached_attribute :attribute_name, :another_attribute_name
|
10
|
+
# This will create the methods
|
11
|
+
# invalidate_attribute_name(optional_object)
|
12
|
+
# invalidate_another_attribute_name(optional_object)
|
13
|
+
# cache_attribute_name(optional_object)
|
14
|
+
# cache_another_attribute_name(optional_object)
|
15
|
+
# Which means invalidating that attribute is easy, say when you add an associated object
|
16
|
+
# has_many :things, before_add: :invalidate_attribute, before_remove: :invalidate_other_attribute
|
17
|
+
#
|
18
|
+
module DatabaseCachedAttribute
|
19
|
+
extend ActiveSupport::Concern
|
20
|
+
|
21
|
+
included do
|
22
|
+
# Cache invalidation by column
|
23
|
+
def invalidate_cache (column_name)
|
24
|
+
self[column_name.to_sym] = nil
|
25
|
+
update_cache column_name.to_sym
|
26
|
+
end
|
27
|
+
|
28
|
+
# Update cache by column
|
29
|
+
def update_cache (column_name)
|
30
|
+
save if only_change?(column_name) && persisted?
|
31
|
+
end
|
32
|
+
|
33
|
+
# Determines if the provided column name is the only change
|
34
|
+
def only_change? (column_name)
|
35
|
+
changes.length == 1 && changes.has_key?(column_name)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Determines if the provided column names are the only changes
|
39
|
+
def only_changes? (*column_names)
|
40
|
+
return false if changes.length != column_names.length
|
41
|
+
|
42
|
+
column_names.each do |column_name|
|
43
|
+
return false if !changes.has_key?(column_name)
|
44
|
+
end
|
45
|
+
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
# Determines if the changes, if any, are only in the list of column names provided
|
50
|
+
def only_changes_in? (*column_names)
|
51
|
+
return false if changes.length > column_names.length
|
52
|
+
|
53
|
+
our_changes = changes.slice column_names
|
54
|
+
return false if our_changes.length < changes.length
|
55
|
+
|
56
|
+
true
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
module ClassMethods
|
61
|
+
# Sets up cache invalidation callbacks for the provided attributes
|
62
|
+
def database_cached_attribute(*attrs)
|
63
|
+
attrs.each do |attr|
|
64
|
+
define_method("invalidate_#{attr}") do |arg=nil| # default arg to allow before_blah callbacks
|
65
|
+
invalidate_cache attr.to_sym
|
66
|
+
end
|
67
|
+
|
68
|
+
define_method("only_#{attr}_changed?") do
|
69
|
+
only_change? attr.to_sym
|
70
|
+
end
|
71
|
+
|
72
|
+
define_method("cache_#{attr}") do
|
73
|
+
update_cache attr.to_sym
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'temping'
|
2
|
+
require 'database_cached_attribute'
|
3
|
+
|
4
|
+
ActiveRecord::Base.establish_connection("sqlite3:///:memory:")
|
5
|
+
|
6
|
+
Temping.create :no_include_class do
|
7
|
+
with_columns do |t|
|
8
|
+
t.string :string_attribute
|
9
|
+
t.integer :integer_attribute
|
10
|
+
end
|
11
|
+
end
|
12
|
+
Temping.create :include_class do
|
13
|
+
include DatabaseCachedAttribute
|
14
|
+
database_cached_attribute :string_attribute
|
15
|
+
database_cached_attribute :integer_attribute
|
16
|
+
|
17
|
+
with_columns do |t|
|
18
|
+
t.string :string_attribute
|
19
|
+
t.integer :integer_attribute
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe DatabaseCachedAttribute do
|
24
|
+
# JUST INCLUDED TESTS
|
25
|
+
context "included" do
|
26
|
+
before do
|
27
|
+
@test_obj = IncludeClass.new
|
28
|
+
end
|
29
|
+
|
30
|
+
it "creates functions for invalidating cache" do
|
31
|
+
expect(@test_obj.respond_to? :invalidate_cache).to eq(true)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "creates functions for saving cache" do
|
35
|
+
expect(@test_obj.respond_to? :update_cache)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "using database_cached_attribute in the model adds nice functions to invalidate cache" do
|
39
|
+
expect(@test_obj.respond_to? :invalidate_string_attribute).to eq(true)
|
40
|
+
expect(@test_obj.respond_to? :invalidate_integer_attribute).to eq(true)
|
41
|
+
expect(@test_obj.respond_to? :invalidate_non_attribute).to eq(false)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "using database_cached_attribute in the model adds nice functions to save caches" do
|
45
|
+
expect(@test_obj.respond_to? :cache_string_attribute).to eq(true)
|
46
|
+
expect(@test_obj.respond_to? :cache_integer_attribute).to eq(true)
|
47
|
+
expect(@test_obj.respond_to? :cache_non_attribute).to eq(false)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# NEW OBJECT TESTS
|
52
|
+
context "new objects not yet saved" do
|
53
|
+
before(:each) do
|
54
|
+
@test_obj = IncludeClass.new
|
55
|
+
@test_obj.string_attribute = "original string"
|
56
|
+
expect(@test_obj.new_record?).to eq(true)
|
57
|
+
expect(@test_obj.persisted?).to eq(false)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "does not persist cache updates" do
|
61
|
+
@test_obj.cache_string_attribute
|
62
|
+
@test_obj.string_attribute = "new string"
|
63
|
+
@test_obj.cache_string_attribute
|
64
|
+
expect(@test_obj.new_record?).to eq(true)
|
65
|
+
expect(@test_obj.persisted?).to eq(false)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "does not persist cache invalidations" do
|
69
|
+
@test_obj.invalidate_string_attribute
|
70
|
+
@test_obj.string_attribute = "new string"
|
71
|
+
@test_obj.invalidate_string_attribute
|
72
|
+
expect(@test_obj.new_record?).to eq(true)
|
73
|
+
expect(@test_obj.persisted?).to eq(false)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "using .invalidate_attribute_name does change the data" do
|
77
|
+
expect(@test_obj.string_attribute).to eq("original string")
|
78
|
+
@test_obj.invalidate_string_attribute
|
79
|
+
expect(@test_obj.string_attribute).to eq(nil)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "using .cache_attribute_name does not change the data" do
|
83
|
+
expect(@test_obj.string_attribute).to eq("original string")
|
84
|
+
@test_obj.cache_string_attribute
|
85
|
+
expect(@test_obj.string_attribute).to eq("original string")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# SAVED OBJECT TESTS
|
90
|
+
context "objects persisted in the database" do
|
91
|
+
before(:each) do
|
92
|
+
@test_obj = IncludeClass.new
|
93
|
+
@test_obj.string_attribute = "original string"
|
94
|
+
@test_obj.save
|
95
|
+
expect(@test_obj.new_record?).to eq(false)
|
96
|
+
expect(@test_obj.persisted?).to eq(true)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "persists a cache invalidation" do
|
100
|
+
expect(@test_obj.string_attribute).to eq("original string")
|
101
|
+
@test_obj.invalidate_string_attribute
|
102
|
+
expect(@test_obj.string_attribute).to eq(nil)
|
103
|
+
@compare_obj = IncludeClass.last
|
104
|
+
expect(@compare_obj.id).to eq(@test_obj.id)
|
105
|
+
expect(@compare_obj.string_attribute).to eq(nil)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "persists a cache update" do
|
109
|
+
expect(@test_obj.string_attribute).to eq("original string")
|
110
|
+
@test_obj.string_attribute = "new string"
|
111
|
+
@test_obj.cache_string_attribute
|
112
|
+
expect(@test_obj.string_attribute).to eq("new string")
|
113
|
+
|
114
|
+
@compare_obj = IncludeClass.last
|
115
|
+
expect(@compare_obj.id).to eq(@test_obj.id)
|
116
|
+
expect(@compare_obj.string_attribute).to eq("new string")
|
117
|
+
end
|
118
|
+
|
119
|
+
it "does not persist cache invalidation with other changes" do
|
120
|
+
expect(@test_obj.string_attribute).to eq("original string")
|
121
|
+
@test_obj.integer_attribute = 1337
|
122
|
+
@test_obj.invalidate_string_attribute
|
123
|
+
expect(@test_obj.string_attribute).to eq(nil)
|
124
|
+
@compare_obj = IncludeClass.last
|
125
|
+
expect(@compare_obj.id).to eq(@test_obj.id)
|
126
|
+
expect(@compare_obj.string_attribute).to eq("original string")
|
127
|
+
expect(@compare_obj.integer_attribute).to eq(nil)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "does not persist cache updates with other changes" do
|
131
|
+
expect(@test_obj.string_attribute).to eq("original string")
|
132
|
+
@test_obj.string_attribute = "new string"
|
133
|
+
@test_obj.integer_attribute = 1337
|
134
|
+
@test_obj.cache_string_attribute
|
135
|
+
expect(@test_obj.string_attribute).to eq("new string")
|
136
|
+
|
137
|
+
@compare_obj = IncludeClass.last
|
138
|
+
expect(@compare_obj.id).to eq(@test_obj.id)
|
139
|
+
expect(@compare_obj.string_attribute).to eq("original string")
|
140
|
+
expect(@compare_obj.integer_attribute).to eq(nil)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
metadata
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: database_cached_attribute
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Charles Smith
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-12-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activerecord
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.1'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activesupport
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.1'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sqlite3
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: temping
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: Provides simple methods on an ActiveRecord model using an ActiveRecord
|
112
|
+
concern to invalidate/save single_column caches.
|
113
|
+
email:
|
114
|
+
- twohlix@gmail.com
|
115
|
+
executables: []
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- lib/database_cached_attribute.rb
|
120
|
+
- lib/tasks/database_cached_attribute_tasks.rake
|
121
|
+
- lib/database_cached_attribute/version.rb
|
122
|
+
- LICENSE
|
123
|
+
- Rakefile
|
124
|
+
- README.md
|
125
|
+
- Gemfile
|
126
|
+
- spec/database_cached_attribute_spec.rb
|
127
|
+
- .travis.yml
|
128
|
+
homepage: http://github.com/twohlix/database_cached_attribute/
|
129
|
+
licenses:
|
130
|
+
- MIT
|
131
|
+
metadata: {}
|
132
|
+
post_install_message:
|
133
|
+
rdoc_options: []
|
134
|
+
require_paths:
|
135
|
+
- lib
|
136
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - '>='
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
requirements: []
|
147
|
+
rubyforge_project:
|
148
|
+
rubygems_version: 2.0.3
|
149
|
+
signing_key:
|
150
|
+
specification_version: 4
|
151
|
+
summary: ActiveRecord Concern to make db caching on ActiveRecord Models simpler
|
152
|
+
test_files:
|
153
|
+
- spec/database_cached_attribute_spec.rb
|
154
|
+
- .travis.yml
|