active_record_tweaks 0.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -6
- data/Appraisals +10 -4
- data/CHANGELOG.md +5 -1
- data/README.md +50 -6
- data/Rakefile +12 -8
- data/active_record_tweaks.gemspec +22 -17
- data/gemfiles/rails3_2.gemfile +2 -2
- data/gemfiles/rails4_0.gemfile +2 -2
- data/gemfiles/rails4_1.gemfile +8 -0
- data/lib/active_record_tweaks/integration.rb +53 -7
- data/lib/active_record_tweaks/version.rb +1 -1
- data/spec/active_record_tweaks_spec.rb +192 -0
- data/spec/spec_helper.rb +2 -0
- metadata +61 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f5b2a9296038a6dc1f37c0d7dd5c7cf813ca8f00
|
4
|
+
data.tar.gz: 8f1a93dad09bc2c0561ac57d68e9added379fdde
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52745cf34fb2fd5b7cce8983cc6ac20e8c5c9a8e05c1234561da7598caf97eadf49f567e393c216d65546275c4c110bc708d009040c5ebccd8589bdcb90e63a3
|
7
|
+
data.tar.gz: 0ca70c7afec28a89e85892cc59696daeef0666722dd04fb2812f7077adbb4fb847f6b4b386d6823d517b3edbeb7187971cd2860c2f9ec3cfbcd9efc1c204fa1e
|
data/.travis.yml
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
|
1
|
+
language: ruby
|
2
|
+
cache:
|
3
|
+
- bundler
|
2
4
|
rvm:
|
3
|
-
- 1.9.2
|
4
5
|
- 1.9.3
|
5
6
|
- 2.0.0
|
7
|
+
- 2.1.0
|
8
|
+
- 2.1.1
|
6
9
|
gemfile:
|
7
10
|
- gemfiles/rails3_2.gemfile
|
8
11
|
- gemfiles/rails4_0.gemfile
|
9
|
-
|
10
|
-
exclude:
|
11
|
-
- rvm: 1.9.2
|
12
|
-
gemfile: gemfiles/rails4_0.gemfile
|
12
|
+
- gemfiles/rails4_1.gemfile
|
13
13
|
|
data/Appraisals
CHANGED
@@ -1,12 +1,18 @@
|
|
1
1
|
|
2
2
|
appraise "rails3-2" do
|
3
|
-
version = "3.2.
|
3
|
+
version = "3.2.17"
|
4
|
+
gem 'activerecord', version
|
4
5
|
gem 'activesupport', version
|
5
|
-
gem 'actionpack', version
|
6
6
|
end
|
7
7
|
|
8
8
|
appraise "rails4-0" do
|
9
|
-
version = "4.0.
|
9
|
+
version = "4.0.3"
|
10
|
+
gem 'activerecord', version
|
11
|
+
gem 'activesupport', version
|
12
|
+
end
|
13
|
+
|
14
|
+
appraise "rails4-1" do
|
15
|
+
version = "4.1.0.rc1"
|
16
|
+
gem 'activerecord', version
|
10
17
|
gem 'activesupport', version
|
11
|
-
gem 'actionpack', version
|
12
18
|
end
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -9,11 +9,11 @@ Tested against:
|
|
9
9
|
- Active Record of version `3.2` and `4.0`
|
10
10
|
- Ruby `1.9.3`, `2.0.0` (except Rails 4 with `1.9.2`)
|
11
11
|
|
12
|
-
[![Build Status](
|
13
|
-
[![Gem Version](
|
14
|
-
[![Dependency Status](
|
15
|
-
[![Coverage Status](
|
16
|
-
[![Code Climate](
|
12
|
+
[![Build Status](http://img.shields.io/travis/PikachuEXE/active_record_tweaks.svg)](https://travis-ci.org/PikachuEXE/active_record_tweaks)
|
13
|
+
[![Gem Version](http://img.shields.io/gem/v/active_record_tweaks.svg)](http://badge.fury.io/rb/active_record_tweaks)
|
14
|
+
[![Dependency Status](http://img.shields.io/gemnasium/PikachuEXE/active_record_tweaks.svg)](https://gemnasium.com/PikachuEXE/active_record_tweaks)
|
15
|
+
[![Coverage Status](http://img.shields.io/coveralls/PikachuEXE/active_record_tweaks.svg)](https://coveralls.io/r/PikachuEXE/active_record_tweaks)
|
16
|
+
[![Code Climate](http://img.shields.io/codeclimate/github/PikachuEXE/active_record_tweaks.svg)](https://codeclimate.com/github/PikachuEXE/active_record_tweaks)
|
17
17
|
|
18
18
|
Install
|
19
19
|
=======
|
@@ -41,7 +41,7 @@ ActiveRecord::Base.send(:include, ActiveRecordTweaks)
|
|
41
41
|
### `#cache_key_without_timestamp`
|
42
42
|
Nothing special, just like `record.cache_key`
|
43
43
|
But it has no timestamp so you can use it for scoped cache key
|
44
|
-
|
44
|
+
e.g. When caching with Cookie, which you want to control the expiry time independent of record update time
|
45
45
|
Usage:
|
46
46
|
```ruby
|
47
47
|
# Just like using #cache_key
|
@@ -49,6 +49,19 @@ Usage:
|
|
49
49
|
```
|
50
50
|
|
51
51
|
|
52
|
+
### `#cache_key_from_attributes`
|
53
|
+
Nothing special, just like `record.cache_key` in rails 4.1
|
54
|
+
But it does not check against columns
|
55
|
+
e.g. When you have some virtual timestamp attribute method (cached or not)
|
56
|
+
Just make sure you throw some name to it or it will raise error
|
57
|
+
Alias: `#cache_key_from_attribute`
|
58
|
+
Usage:
|
59
|
+
```ruby
|
60
|
+
# Just like using #cache_key
|
61
|
+
record.cache_key_from_attributes(:happy_at, :chirdren_max_updated_at)
|
62
|
+
```
|
63
|
+
|
64
|
+
|
52
65
|
### `.cache_key`
|
53
66
|
There is no class level cache key for ActiveRecord at the moment (4.0.1)
|
54
67
|
Passing an array to `cache_digest` could lead to performance issue and the key can become too long when collection is big
|
@@ -60,6 +73,19 @@ And the cache would only expire when there is any record created, updated, or de
|
|
60
73
|
Person.count # => 1000
|
61
74
|
Person.maximum(:updated_at) # => 20131106012125528738000
|
62
75
|
Person.cache_key # => "people/all/1000-20131106012125528738000"
|
76
|
+
|
77
|
+
# When record has multiple updated columns
|
78
|
+
Person.maximum(:updated_at) # => 20131106012125528738000
|
79
|
+
Person.maximum(:updated_on) # => 20141106012125528738000
|
80
|
+
Person.cache_key(:update_at, :updated_on) # => "people/all/1000-20141106012125528738000" (not empty but has mutiple updated timestamp columns)
|
81
|
+
|
82
|
+
# Just get cache key without timestamp
|
83
|
+
Person.maximum(:updated_on) # => some timestamp
|
84
|
+
Person.cache_key(nil) # => "people/all/1000"
|
85
|
+
|
86
|
+
# Other examples
|
87
|
+
Product.cache_key # => "products/all/0" (empty, has updated timestamp columns or not)
|
88
|
+
Product.cache_key # => "products/all/1" (not empty but has no updated timestamp columns)
|
63
89
|
```
|
64
90
|
Usage:
|
65
91
|
```ruby
|
@@ -69,3 +95,21 @@ You can also use it with multiple records (Rails 4 Record might have `updated_at
|
|
69
95
|
```ruby
|
70
96
|
RecordClass.cache_key(:updated_at, :updated_on)
|
71
97
|
```
|
98
|
+
|
99
|
+
|
100
|
+
### `.cache_key_without_timestamp`
|
101
|
+
Just like `.cache_key(nil)`
|
102
|
+
But much clearer
|
103
|
+
```ruby
|
104
|
+
Person.count # => 1000
|
105
|
+
Person.maximum(:updated_at) # => 20131106012125528738000
|
106
|
+
Person.cache_key_without_timestamp # => "people/all/1000"
|
107
|
+
|
108
|
+
# Other examples
|
109
|
+
Product.cache_key # => "products/all/0" (empty, has updated timestamp columns or not)
|
110
|
+
Product.cache_key # => "products/all/1" (not empty but has no updated timestamp columns)
|
111
|
+
```
|
112
|
+
Usage:
|
113
|
+
```ruby
|
114
|
+
RecordClass.cache_key_without_timestamp
|
115
|
+
```
|
data/Rakefile
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require 'bundler/gem_tasks'
|
5
|
-
require 'rspec/core/rake_task'
|
1
|
+
require "appraisal"
|
2
|
+
require "bundler"
|
3
|
+
require "rspec/core/rake_task"
|
6
4
|
|
7
|
-
|
8
|
-
sh "rake appraisal:install && rake appraisal spec"
|
9
|
-
end
|
5
|
+
Bundler::GemHelper.install_tasks
|
10
6
|
|
11
7
|
RSpec::Core::RakeTask.new(:spec)
|
8
|
+
|
9
|
+
if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"]
|
10
|
+
task :default do
|
11
|
+
sh "rake appraisal:install && rake appraisal spec"
|
12
|
+
end
|
13
|
+
else
|
14
|
+
task :default => :spec
|
15
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
$:.push File.expand_path("../lib", __FILE__)
|
3
3
|
|
4
|
-
author_name =
|
5
|
-
gem_name =
|
4
|
+
author_name = "PikachuEXE"
|
5
|
+
gem_name = "active_record_tweaks"
|
6
6
|
|
7
7
|
require "#{gem_name}/version"
|
8
8
|
|
@@ -10,27 +10,32 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.platform = Gem::Platform::RUBY
|
11
11
|
s.name = gem_name
|
12
12
|
s.version = ActiveRecordTweaks::VERSION
|
13
|
-
s.summary =
|
14
|
-
s.description =
|
13
|
+
s.summary = "Some Tweaks for ActiveRecord"
|
14
|
+
s.description = "ActiveRecord is great, but could be better. Here are some tweaks for it."
|
15
15
|
|
16
|
-
s.license =
|
16
|
+
s.license = "MIT"
|
17
17
|
|
18
18
|
s.authors = [author_name]
|
19
|
-
s.email = [
|
19
|
+
s.email = ["pikachuexe@gmail.com"]
|
20
20
|
s.homepage = "http://github.com/#{author_name}/#{gem_name}"
|
21
21
|
|
22
22
|
s.files = `git ls-files`.split("\n")
|
23
23
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
24
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
25
|
-
s.require_paths = [
|
26
|
-
|
27
|
-
s.add_dependency
|
28
|
-
s.add_dependency
|
29
|
-
|
30
|
-
s.add_development_dependency
|
31
|
-
s.add_development_dependency
|
32
|
-
s.add_development_dependency
|
33
|
-
s.add_development_dependency
|
34
|
-
s.add_development_dependency
|
35
|
-
s.add_development_dependency
|
25
|
+
s.require_paths = ["lib"]
|
26
|
+
|
27
|
+
s.add_dependency "activerecord", ">= 3.2.0", "< 5.0.0"
|
28
|
+
s.add_dependency "activesupport", ">= 3.2.0", "< 5.0.0"
|
29
|
+
|
30
|
+
s.add_development_dependency "bundler", ">= 1.0.0"
|
31
|
+
s.add_development_dependency "rake", ">= 0.9.2"
|
32
|
+
s.add_development_dependency "appraisal", ">= 0.5.2"
|
33
|
+
s.add_development_dependency "rspec", "~> 2.6"
|
34
|
+
s.add_development_dependency "sqlite3", ">= 1.3"
|
35
|
+
s.add_development_dependency "database_cleaner", ">= 1.0"
|
36
|
+
s.add_development_dependency "coveralls", ">= 0.7"
|
37
|
+
s.add_development_dependency "gem-release", ">= 0.7"
|
38
|
+
s.add_development_dependency "timecop", ">= 0.7.1"
|
39
|
+
|
40
|
+
s.required_rubygems_version = ">= 1.4.0"
|
36
41
|
end
|
data/gemfiles/rails3_2.gemfile
CHANGED
data/gemfiles/rails4_0.gemfile
CHANGED
@@ -8,9 +8,9 @@ module ActiveRecordTweaks
|
|
8
8
|
# Timestamp is not used to allow custom caching expiration
|
9
9
|
# (e.g. Cookie based caching with expiration )
|
10
10
|
#
|
11
|
-
# Product.new.
|
12
|
-
# Product.find(5).
|
13
|
-
# Person.find(5).
|
11
|
+
# Product.new.cache_key_without_timestamp # => "products/new"
|
12
|
+
# Product.find(5).cache_key_without_timestamp # => "products/5" (updated_at not available)
|
13
|
+
# Person.find(5).cache_key_without_timestamp # => "people/5" (updated_at available)
|
14
14
|
def cache_key_without_timestamp
|
15
15
|
case
|
16
16
|
when new_record?
|
@@ -20,14 +20,46 @@ module ActiveRecordTweaks
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
# Works like #cache_key in rails 4.1, but does not check column
|
24
|
+
# Useful when you have some virtual timestamp attribute method (cached or not)
|
25
|
+
#
|
26
|
+
# @param attribute_names [Array<Symbol,String>]
|
27
|
+
# Names of attributes method(s)
|
28
|
+
# It does not have to be column(s)
|
29
|
+
#
|
30
|
+
# @raise [ArgumentError] when attribute_names is empty
|
31
|
+
def cache_key_from_attributes(*attribute_names)
|
32
|
+
attribute_names.any? or raise ArgumentError
|
33
|
+
|
34
|
+
if timestamp = max_updated_attribute_timestamp_for_cache_key(attribute_names)
|
35
|
+
timestamp = timestamp.utc.to_s(cache_timestamp_format)
|
36
|
+
"#{self.class.model_name.cache_key}/#{id}-#{timestamp}"
|
37
|
+
else
|
38
|
+
"#{self.class.model_name.cache_key}/#{id}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
alias_method :cache_key_from_attribute, :cache_key_from_attributes
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def max_updated_attribute_timestamp_for_cache_key(timestamp_attribute_names)
|
46
|
+
timestamps = timestamp_attribute_names.map do |attribute_name|
|
47
|
+
self.send(attribute_name)
|
48
|
+
end.compact
|
49
|
+
|
50
|
+
if timestamps.present?
|
51
|
+
timestamps.map { |ts| ts.to_time }.max
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
23
55
|
module ClassMethods
|
24
56
|
# Returns a cache key for the ActiveRecord class based
|
25
57
|
# based on count and maximum value of update timestamp columns
|
26
58
|
# (e.g. Cookie based caching with expiration)
|
27
59
|
#
|
28
|
-
# Product.cache_key # => "products/0" (empty, has updated timestamp columns or not)
|
29
|
-
# Product.cache_key # => "products/1" (not empty but has no updated timestamp columns)
|
30
|
-
# Person.cache_key # => "people/1-20071224150000" (not empty and has updated timestamp columns)
|
60
|
+
# Product.cache_key # => "products/all/0" (empty, has updated timestamp columns or not)
|
61
|
+
# Product.cache_key # => "products/all/1" (not empty but has no updated timestamp columns)
|
62
|
+
# Person.cache_key # => "people/all/1-20071224150000" (not empty and has updated timestamp columns)
|
31
63
|
#
|
32
64
|
# @param [Array<String, Symbol>] args The column name with timestamp to check
|
33
65
|
def cache_key(*args)
|
@@ -37,10 +69,24 @@ module ActiveRecordTweaks
|
|
37
69
|
timestamp = timestamp.utc.to_s(cache_timestamp_format)
|
38
70
|
"#{self.model_name.cache_key}/all/#{self.count}-#{timestamp}"
|
39
71
|
else
|
40
|
-
|
72
|
+
cache_key_without_timestamp
|
41
73
|
end
|
42
74
|
end
|
43
75
|
|
76
|
+
# Returns a cache key for the ActiveRecord class based
|
77
|
+
# based on count only
|
78
|
+
#
|
79
|
+
# Product.cache_key # => "products/all/0" (empty, has updated timestamp columns or not)
|
80
|
+
# Product.cache_key # => "products/all/1" (not empty but has no updated timestamp columns)
|
81
|
+
# Person.cache_key # => "people/all/1" (not empty and has updated timestamp columns)
|
82
|
+
#
|
83
|
+
# @param [Array<String, Symbol>] args The column name with timestamp to check
|
84
|
+
def cache_key_without_timestamp
|
85
|
+
"#{self.model_name.cache_key}/all/#{self.count}"
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
44
90
|
def max_updated_column_timestamp_for_cache_key(timestamp_columns)
|
45
91
|
available_timestamp_columns = timestamp_columns.select { |c| self.column_names.include?(c.to_s) }
|
46
92
|
|
@@ -48,6 +48,101 @@ describe Parent do
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
describe '#cache_key_from_attribute' do
|
52
|
+
before { Timecop.freeze }
|
53
|
+
after { Timecop.return }
|
54
|
+
|
55
|
+
let!(:record) { Parent.create! }
|
56
|
+
|
57
|
+
before do
|
58
|
+
record.class.class_eval do
|
59
|
+
def virtual_update_at_1
|
60
|
+
1.day.from_now
|
61
|
+
end
|
62
|
+
|
63
|
+
def virtual_update_at_2
|
64
|
+
1.week.from_now
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
after do
|
69
|
+
record.class.class_eval do
|
70
|
+
remove_method :virtual_update_at_1
|
71
|
+
|
72
|
+
remove_method :virtual_update_at_2
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
let(:virtual_update_at_1) { record.virtual_update_at_1 }
|
77
|
+
let(:virtual_update_at_1_in_cache_key) { virtual_update_at_1.utc.to_s(:nsec) }
|
78
|
+
let(:virtual_update_at_2) { record.virtual_update_at_2 }
|
79
|
+
let(:virtual_update_at_2_in_cache_key) { virtual_update_at_2.utc.to_s(:nsec) }
|
80
|
+
|
81
|
+
subject { record.cache_key_from_attribute(*arguments) }
|
82
|
+
|
83
|
+
context 'when called with no argument' do
|
84
|
+
let(:arguments) { [] }
|
85
|
+
|
86
|
+
specify { expect{subject}.to raise_error(ArgumentError) }
|
87
|
+
end
|
88
|
+
context 'when called with 1 attribute name' do
|
89
|
+
let(:arguments) { [:virtual_update_at_1] }
|
90
|
+
|
91
|
+
it {should match /#{described_class.model_name.cache_key}\/#{record.id}\-#{virtual_update_at_1_in_cache_key}/}
|
92
|
+
end
|
93
|
+
context 'when called with 2 attribute names' do
|
94
|
+
let(:arguments) { [:virtual_update_at_1, :virtual_update_at_2] }
|
95
|
+
|
96
|
+
context 'and virtual_update_at_1 < virtual_update_at_2' do
|
97
|
+
before do
|
98
|
+
record.class.class_eval do
|
99
|
+
def virtual_update_at_2
|
100
|
+
virtual_update_at_1 + 1.day
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
it {should match /#{described_class.model_name.cache_key}\/#{record.id}\-#{virtual_update_at_2_in_cache_key}/}
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'and virtual_update_at_1 > virtual_update_at_2' do
|
109
|
+
before do
|
110
|
+
record.class.class_eval do
|
111
|
+
def virtual_update_at_2
|
112
|
+
virtual_update_at_1 - 1.day
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
it {should match /#{described_class.model_name.cache_key}\/#{record.id}\-#{virtual_update_at_1_in_cache_key}/}
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'and virtual_update_at_1 is nil' do
|
121
|
+
before do
|
122
|
+
record.class.class_eval do
|
123
|
+
def virtual_update_at_1
|
124
|
+
nil
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
it {should match /#{described_class.model_name.cache_key}\/#{record.id}\-#{virtual_update_at_2_in_cache_key}/}
|
130
|
+
end
|
131
|
+
context 'and virtual_update_at_2 is nil' do
|
132
|
+
before do
|
133
|
+
record.class.class_eval do
|
134
|
+
def virtual_update_at_2
|
135
|
+
nil
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
it {should match /#{described_class.model_name.cache_key}\/#{record.id}\-#{virtual_update_at_1_in_cache_key}/}
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
|
51
146
|
describe '.cache_key' do
|
52
147
|
subject { klass.cache_key }
|
53
148
|
|
@@ -166,6 +261,37 @@ describe Parent do
|
|
166
261
|
end
|
167
262
|
end
|
168
263
|
end
|
264
|
+
|
265
|
+
context 'when getting cache_key with nil' do
|
266
|
+
subject { klass.cache_key(nil) }
|
267
|
+
|
268
|
+
context 'and has no record' do
|
269
|
+
before { klass.count.should eq 0 }
|
270
|
+
|
271
|
+
it { should match /\/#{klass.count}$/ }
|
272
|
+
end
|
273
|
+
context 'and has a record' do
|
274
|
+
let!(:person) { klass.create! }
|
275
|
+
|
276
|
+
context 'and it has updated_on value only' do
|
277
|
+
before { person.update_attributes!(updated_at: nil, updated_on: Time.now) }
|
278
|
+
|
279
|
+
it { should eq "people/all/#{klass.count}" }
|
280
|
+
end
|
281
|
+
|
282
|
+
context 'and it has newer updated_at' do
|
283
|
+
before { person.update_attributes!(updated_at: Time.now + 3600, updated_on: Time.now) }
|
284
|
+
|
285
|
+
it { should eq "people/all/#{klass.count}" }
|
286
|
+
end
|
287
|
+
|
288
|
+
context 'and it has newer updated_on' do
|
289
|
+
before { person.update_attributes!(updated_at: Time.now , updated_on: Time.now+ 3600) }
|
290
|
+
|
291
|
+
it { should eq "people/all/#{klass.count}" }
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
169
295
|
end
|
170
296
|
|
171
297
|
context 'when a class has custom timestamp format' do
|
@@ -175,5 +301,71 @@ describe Parent do
|
|
175
301
|
it { should eq "animals/all/#{klass.count}-#{klass.maximum(:updated_at).utc.to_s(:number)}" }
|
176
302
|
end
|
177
303
|
end
|
304
|
+
|
305
|
+
describe '.cache_key_without_timestamp' do
|
306
|
+
subject { klass.cache_key_without_timestamp }
|
307
|
+
|
308
|
+
context 'when a class has no update_at column' do
|
309
|
+
let(:klass) { Stone }
|
310
|
+
|
311
|
+
context 'and has no record' do
|
312
|
+
before { klass.count.should eq 0 }
|
313
|
+
|
314
|
+
it { should match /\/#{klass.count}$/ }
|
315
|
+
end
|
316
|
+
context 'and has a record' do
|
317
|
+
before { klass.create! }
|
318
|
+
|
319
|
+
it { should match /\/#{klass.count}$/ }
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
context 'when a class has updated_at column' do
|
324
|
+
let(:klass) { Parent }
|
325
|
+
|
326
|
+
context 'and has no record' do
|
327
|
+
before { klass.count.should eq 0 }
|
328
|
+
|
329
|
+
it { should match /\/#{klass.count}$/ }
|
330
|
+
end
|
331
|
+
|
332
|
+
context 'and has a record' do
|
333
|
+
let!(:parent) { klass.create! }
|
334
|
+
|
335
|
+
it { should eq "parents/all/#{klass.count}" }
|
336
|
+
|
337
|
+
context 'when record all has nil updated timestamps' do
|
338
|
+
before { klass.update_all(updated_at: nil) }
|
339
|
+
|
340
|
+
it { should match /\/#{klass.count}$/ }
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
context 'when a class has updated_at AND updated_on column' do
|
346
|
+
let(:klass) { Person }
|
347
|
+
|
348
|
+
context 'and has no record' do
|
349
|
+
before { klass.count.should eq 0 }
|
350
|
+
|
351
|
+
it { should match /\/#{klass.count}$/ }
|
352
|
+
end
|
353
|
+
context 'and has a record' do
|
354
|
+
let!(:person) { klass.create! }
|
355
|
+
|
356
|
+
context 'and it has updated_at value only' do
|
357
|
+
before { person.update_attributes!(updated_at: Time.now, updated_on: nil) }
|
358
|
+
|
359
|
+
it { should eq "people/all/#{klass.count}" }
|
360
|
+
end
|
361
|
+
|
362
|
+
context 'and it has updated_on value only' do
|
363
|
+
before { person.update_attributes!(updated_at: nil, updated_on: Time.now) }
|
364
|
+
|
365
|
+
it { should eq "people/all/#{klass.count}" }
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
178
370
|
end
|
179
371
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record_tweaks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- PikachuEXE
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-03-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -50,90 +50,132 @@ dependencies:
|
|
50
50
|
- - <
|
51
51
|
- !ruby/object:Gem::Version
|
52
52
|
version: 5.0.0
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: bundler
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 1.0.0
|
60
|
+
type: :development
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 1.0.0
|
53
67
|
- !ruby/object:Gem::Dependency
|
54
68
|
name: rake
|
55
69
|
requirement: !ruby/object:Gem::Requirement
|
56
70
|
requirements:
|
57
71
|
- - '>='
|
58
72
|
- !ruby/object:Gem::Version
|
59
|
-
version:
|
73
|
+
version: 0.9.2
|
60
74
|
type: :development
|
61
75
|
prerelease: false
|
62
76
|
version_requirements: !ruby/object:Gem::Requirement
|
63
77
|
requirements:
|
64
78
|
- - '>='
|
65
79
|
- !ruby/object:Gem::Version
|
66
|
-
version:
|
80
|
+
version: 0.9.2
|
67
81
|
- !ruby/object:Gem::Dependency
|
68
82
|
name: appraisal
|
69
83
|
requirement: !ruby/object:Gem::Requirement
|
70
84
|
requirements:
|
71
85
|
- - '>='
|
72
86
|
- !ruby/object:Gem::Version
|
73
|
-
version:
|
87
|
+
version: 0.5.2
|
74
88
|
type: :development
|
75
89
|
prerelease: false
|
76
90
|
version_requirements: !ruby/object:Gem::Requirement
|
77
91
|
requirements:
|
78
92
|
- - '>='
|
79
93
|
- !ruby/object:Gem::Version
|
80
|
-
version:
|
94
|
+
version: 0.5.2
|
81
95
|
- !ruby/object:Gem::Dependency
|
82
96
|
name: rspec
|
83
97
|
requirement: !ruby/object:Gem::Requirement
|
84
98
|
requirements:
|
85
|
-
- -
|
99
|
+
- - ~>
|
86
100
|
- !ruby/object:Gem::Version
|
87
|
-
version: '
|
101
|
+
version: '2.6'
|
88
102
|
type: :development
|
89
103
|
prerelease: false
|
90
104
|
version_requirements: !ruby/object:Gem::Requirement
|
91
105
|
requirements:
|
92
|
-
- -
|
106
|
+
- - ~>
|
93
107
|
- !ruby/object:Gem::Version
|
94
|
-
version: '
|
108
|
+
version: '2.6'
|
95
109
|
- !ruby/object:Gem::Dependency
|
96
110
|
name: sqlite3
|
97
111
|
requirement: !ruby/object:Gem::Requirement
|
98
112
|
requirements:
|
99
113
|
- - '>='
|
100
114
|
- !ruby/object:Gem::Version
|
101
|
-
version: '
|
115
|
+
version: '1.3'
|
102
116
|
type: :development
|
103
117
|
prerelease: false
|
104
118
|
version_requirements: !ruby/object:Gem::Requirement
|
105
119
|
requirements:
|
106
120
|
- - '>='
|
107
121
|
- !ruby/object:Gem::Version
|
108
|
-
version: '
|
122
|
+
version: '1.3'
|
109
123
|
- !ruby/object:Gem::Dependency
|
110
124
|
name: database_cleaner
|
111
125
|
requirement: !ruby/object:Gem::Requirement
|
112
126
|
requirements:
|
113
127
|
- - '>='
|
114
128
|
- !ruby/object:Gem::Version
|
115
|
-
version: '0'
|
129
|
+
version: '1.0'
|
116
130
|
type: :development
|
117
131
|
prerelease: false
|
118
132
|
version_requirements: !ruby/object:Gem::Requirement
|
119
133
|
requirements:
|
120
134
|
- - '>='
|
121
135
|
- !ruby/object:Gem::Version
|
122
|
-
version: '0'
|
136
|
+
version: '1.0'
|
123
137
|
- !ruby/object:Gem::Dependency
|
124
138
|
name: coveralls
|
125
139
|
requirement: !ruby/object:Gem::Requirement
|
126
140
|
requirements:
|
127
141
|
- - '>='
|
128
142
|
- !ruby/object:Gem::Version
|
129
|
-
version: '0'
|
143
|
+
version: '0.7'
|
144
|
+
type: :development
|
145
|
+
prerelease: false
|
146
|
+
version_requirements: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - '>='
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0.7'
|
151
|
+
- !ruby/object:Gem::Dependency
|
152
|
+
name: gem-release
|
153
|
+
requirement: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0.7'
|
158
|
+
type: :development
|
159
|
+
prerelease: false
|
160
|
+
version_requirements: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - '>='
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0.7'
|
165
|
+
- !ruby/object:Gem::Dependency
|
166
|
+
name: timecop
|
167
|
+
requirement: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - '>='
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: 0.7.1
|
130
172
|
type: :development
|
131
173
|
prerelease: false
|
132
174
|
version_requirements: !ruby/object:Gem::Requirement
|
133
175
|
requirements:
|
134
176
|
- - '>='
|
135
177
|
- !ruby/object:Gem::Version
|
136
|
-
version:
|
178
|
+
version: 0.7.1
|
137
179
|
description: ActiveRecord is great, but could be better. Here are some tweaks for
|
138
180
|
it.
|
139
181
|
email:
|
@@ -154,6 +196,7 @@ files:
|
|
154
196
|
- active_record_tweaks.gemspec
|
155
197
|
- gemfiles/rails3_2.gemfile
|
156
198
|
- gemfiles/rails4_0.gemfile
|
199
|
+
- gemfiles/rails4_1.gemfile
|
157
200
|
- lib/active_record_tweaks.rb
|
158
201
|
- lib/active_record_tweaks/integration.rb
|
159
202
|
- lib/active_record_tweaks/version.rb
|
@@ -176,10 +219,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
176
219
|
requirements:
|
177
220
|
- - '>='
|
178
221
|
- !ruby/object:Gem::Version
|
179
|
-
version:
|
222
|
+
version: 1.4.0
|
180
223
|
requirements: []
|
181
224
|
rubyforge_project:
|
182
|
-
rubygems_version: 2.
|
225
|
+
rubygems_version: 2.2.2
|
183
226
|
signing_key:
|
184
227
|
specification_version: 4
|
185
228
|
summary: Some Tweaks for ActiveRecord
|