active_record_tweaks 0.2.0 → 0.2.1

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.
@@ -1,13 +1,23 @@
1
+ # Send builds to container-based infrastructure
2
+ # http://docs.travis-ci.com/user/workers/container-based-infrastructure/
3
+ sudo: false
1
4
  language: ruby
2
5
  cache:
3
6
  - bundler
4
7
  rvm:
5
- - 1.9.3
6
- - 2.0.0
7
- - 2.1.0
8
- - 2.1.1
8
+ - 2.1.10
9
+ - 2.2.5
10
+ # Since the Travis Build Env does not recognize `2.3` alias yet
11
+ # We need to specify the version precisely
12
+ - 2.3.1
13
+ - ruby-head
9
14
  gemfile:
10
- - gemfiles/rails3_2.gemfile
11
- - gemfiles/rails4_0.gemfile
12
- - gemfiles/rails4_1.gemfile
15
+ - gemfiles/rails_3_2.gemfile
16
+ - gemfiles/rails_4_0.gemfile
17
+ - gemfiles/rails_4_1.gemfile
18
+ - gemfiles/rails_4_2.gemfile
19
+ matrix:
20
+ fast_finish: true
21
+ allow_failures:
22
+ - rvm: ruby-head
13
23
 
data/Appraisals CHANGED
@@ -1,18 +1,32 @@
1
1
 
2
- appraise "rails3-2" do
3
- version = "3.2.17"
4
- gem 'activerecord', version
5
- gem 'activesupport', version
2
+ appraise "rails_3_2" do
3
+ version = "~> 3.2.20"
4
+ gem "activesupport", version
5
+ gem "actionpack", version
6
+ gem "activerecord", version
7
+ gem "railties", version
6
8
  end
7
9
 
8
- appraise "rails4-0" do
9
- version = "4.0.3"
10
- gem 'activerecord', version
11
- gem 'activesupport', version
10
+ appraise "rails_4_0" do
11
+ version = "~> 4.0.12"
12
+ gem "activesupport", version
13
+ gem "actionpack", version
14
+ gem "activerecord", version
15
+ gem "railties", version
12
16
  end
13
17
 
14
- appraise "rails4-1" do
15
- version = "4.1.0.rc1"
16
- gem 'activerecord', version
17
- gem 'activesupport', version
18
+ appraise "rails_4_1" do
19
+ version = "~> 4.1.8"
20
+ gem "activesupport", version
21
+ gem "actionpack", version
22
+ gem "activerecord", version
23
+ gem "railties", version
24
+ end
25
+
26
+ appraise "rails_4_2" do
27
+ version = "~> 4.2.0"
28
+ gem "activesupport", version
29
+ gem "actionpack", version
30
+ gem "activerecord", version
31
+ gem "railties", version
18
32
  end
data/Gemfile CHANGED
@@ -1,2 +1,2 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
  gemspec
data/README.md CHANGED
@@ -1,39 +1,42 @@
1
- Active Record Tweaks
2
- ===========
1
+ # Active Record Tweaks
3
2
 
4
3
  Active Record is great, but could be better. Here are some tweaks for it.
5
4
 
6
- ### Support
7
- ===========
8
- Tested against:
9
- - Active Record of version `3.2` and `4.0`
10
- - Ruby `1.9.3`, `2.0.0` (except Rails 4 with `1.9.2`)
11
5
 
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)
6
+ ## Status
17
7
 
18
- Install
19
- =======
8
+ [![Build Status](http://img.shields.io/travis/PikachuEXE/active_record_tweaks.svg?style=flat-square)](https://travis-ci.org/PikachuEXE/active_record_tweaks)
9
+ [![Gem Version](http://img.shields.io/gem/v/active_record_tweaks.svg?style=flat-square)](http://badge.fury.io/rb/active_record_tweaks)
10
+ [![Dependency Status](http://img.shields.io/gemnasium/PikachuEXE/active_record_tweaks.svg?style=flat-square)](https://gemnasium.com/PikachuEXE/active_record_tweaks)
11
+ [![Coverage Status](http://img.shields.io/coveralls/PikachuEXE/active_record_tweaks.svg?style=flat-square)](https://coveralls.io/r/PikachuEXE/active_record_tweaks)
12
+ [![Code Climate](http://img.shields.io/codeclimate/github/PikachuEXE/active_record_tweaks.svg?style=flat-square)](https://codeclimate.com/github/PikachuEXE/active_record_tweaks)
13
+
14
+
15
+ ## Installation
20
16
 
21
17
  ```ruby
22
18
  gem 'active_record_tweaks'
23
19
  ```
24
20
 
25
- Usage
26
- =====
21
+
22
+ ## Usage
27
23
 
28
24
  Either include it in specific record or just `ActiveRecord::Base`
29
25
  ```ruby
30
26
  class SomeRecord
27
+ include ActiveRecordTweaks::Integration::InstanceMethods
28
+ # This module is also DEPRECATED
29
+ # See below for details
30
+ extend ActiveRecordTweaks::Integration::ClassMethods
31
+
32
+ # DEPRECATED
31
33
  include ActiveRecordTweaks
32
34
  end
33
35
 
34
36
  # or
35
37
 
36
38
  # In a initialzer
39
+ # DEPRECATED
37
40
  ActiveRecord::Base.send(:include, ActiveRecordTweaks)
38
41
  ```
39
42
 
@@ -54,15 +57,23 @@ Nothing special, just like `record.cache_key` in rails 4.1
54
57
  But it does not check against columns
55
58
  e.g. When you have some virtual timestamp attribute method (cached or not)
56
59
  Just make sure you throw some name to it or it will raise error
57
- Alias: `#cache_key_from_attribute`
60
+ Alias: `#cache_key_from_attribute`
58
61
  Usage:
59
62
  ```ruby
60
63
  # Just like using #cache_key
61
- record.cache_key_from_attributes(:happy_at, :chirdren_max_updated_at)
64
+ record.cache_key_from_attributes(:happy_at, :children_max_updated_at)
62
65
  ```
63
66
 
64
67
 
65
68
  ### `.cache_key`
69
+
70
+ **DEPRECATED**
71
+ This method does NOT consider the query like filters and and sort orders.
72
+ Thus deprecated without replacement.
73
+ Rails 5 already have `#cache_key` in relation class: https://github.com/rails/rails/pull/20884
74
+ There is also a gem for older rails: https://github.com/customink/activerecord-collection_cache_key
75
+
76
+ **Usage**
66
77
  There is no class level cache key for ActiveRecord at the moment (4.0.1)
67
78
  Passing an array to `cache_digest` could lead to performance issue and the key can become too long when collection is big
68
79
  ([rails#12726](https://github.com/rails/rails/pull/12726))
@@ -98,6 +109,11 @@ RecordClass.cache_key(:updated_at, :updated_on)
98
109
 
99
110
 
100
111
  ### `.cache_key_without_timestamp`
112
+
113
+ **DEPRECATED**
114
+ Same deprecation reasons and replacement suggestion as `.cache_key` above
115
+
116
+ **Usage**
101
117
  Just like `.cache_key(nil)`
102
118
  But much clearer
103
119
  ```ruby
@@ -106,8 +122,8 @@ Person.maximum(:updated_at) # => 20131106012125528738000
106
122
  Person.cache_key_without_timestamp # => "people/all/1000"
107
123
 
108
124
  # 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)
125
+ Product.cache_key_without_timestamp # => "products/all/0" (empty, has updated timestamp columns or not)
126
+ Product.cache_key_without_timestamp # => "products/all/1" (not empty but has no updated timestamp columns)
111
127
  ```
112
128
  Usage:
113
129
  ```ruby
data/Rakefile CHANGED
@@ -1,15 +1,18 @@
1
1
  require "appraisal"
2
2
  require "bundler"
3
3
  require "rspec/core/rake_task"
4
+ require "rubocop/rake_task"
4
5
 
5
6
  Bundler::GemHelper.install_tasks
6
7
 
7
8
  RSpec::Core::RakeTask.new(:spec)
8
9
 
10
+ RuboCop::RakeTask.new(:rubocop)
11
+
9
12
  if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"]
10
13
  task :default do
11
- sh "rake appraisal:install && rake appraisal spec"
14
+ sh "appraisal install && rake appraisal spec rubocop"
12
15
  end
13
16
  else
14
- task :default => :spec
17
+ task default: [:spec, :rubocop]
15
18
  end
@@ -1,5 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
2
+ # rubocop:disable all
3
+ $LOAD_PATH.push File.expand_path("../lib", __FILE__)
3
4
 
4
5
  author_name = "PikachuEXE"
5
6
  gem_name = "active_record_tweaks"
@@ -11,7 +12,9 @@ Gem::Specification.new do |s|
11
12
  s.name = gem_name
12
13
  s.version = ActiveRecordTweaks::VERSION
13
14
  s.summary = "Some Tweaks for ActiveRecord"
14
- s.description = "ActiveRecord is great, but could be better. Here are some tweaks for it."
15
+ s.description = <<-DOC
16
+ ActiveRecord is great, but could be better. Here are some tweaks for it.
17
+ DOC
15
18
 
16
19
  s.license = "MIT"
17
20
 
@@ -21,21 +24,22 @@ Gem::Specification.new do |s|
21
24
 
22
25
  s.files = `git ls-files`.split("\n")
23
26
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
27
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
25
28
  s.require_paths = ["lib"]
26
29
 
27
30
  s.add_dependency "activerecord", ">= 3.2.0", "< 5.0.0"
28
- s.add_dependency "activesupport", ">= 3.2.0", "< 5.0.0"
29
31
 
30
32
  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"
33
+ s.add_development_dependency "rake", "~> 10.0"
34
+ s.add_development_dependency "appraisal", "~> 2.0"
35
+ s.add_development_dependency "rspec", "~> 3.0"
36
+ s.add_development_dependency "rspec-its", "~> 1.0"
34
37
  s.add_development_dependency "sqlite3", ">= 1.3"
35
38
  s.add_development_dependency "database_cleaner", ">= 1.0"
36
39
  s.add_development_dependency "coveralls", ">= 0.7"
37
40
  s.add_development_dependency "gem-release", ">= 0.7"
38
41
  s.add_development_dependency "timecop", ">= 0.7.1"
42
+ s.add_development_dependency "rubocop", "~> 0.30"
39
43
 
40
44
  s.required_rubygems_version = ">= 1.4.0"
41
45
  end
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activesupport", "~> 3.2.20"
6
+ gem "actionpack", "~> 3.2.20"
7
+ gem "activerecord", "~> 3.2.20"
8
+ gem "railties", "~> 3.2.20"
9
+
10
+ gemspec :path => "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activesupport", "~> 4.0.12"
6
+ gem "actionpack", "~> 4.0.12"
7
+ gem "activerecord", "~> 4.0.12"
8
+ gem "railties", "~> 4.0.12"
9
+
10
+ gemspec :path => "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activesupport", "~> 4.1.8"
6
+ gem "actionpack", "~> 4.1.8"
7
+ gem "activerecord", "~> 4.1.8"
8
+ gem "railties", "~> 4.1.8"
9
+
10
+ gemspec :path => "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activesupport", "~> 4.2.0"
6
+ gem "actionpack", "~> 4.2.0"
7
+ gem "activerecord", "~> 4.2.0"
8
+ gem "railties", "~> 4.2.0"
9
+
10
+ gemspec :path => "../"
@@ -1,12 +1,14 @@
1
- require 'active_support/concern'
2
-
3
- require 'active_record_tweaks/version'
4
- require 'active_record_tweaks/integration'
1
+ require "active_record_tweaks/version"
2
+ require "active_record_tweaks/integration"
5
3
 
6
4
  module ActiveRecordTweaks
7
- extend ActiveSupport::Concern
5
+ def self.included(base)
6
+ # rubocop:disable all
7
+ warn "[DEPRECATION] including `ActiveRecordTweaks` is deprecated. Please see README for recommanded usage."
8
+ # rubocop:enable all
8
9
 
9
- included do
10
- include Integration
10
+ base.class_eval do
11
+ include Integration
12
+ end
11
13
  end
12
14
  end
@@ -1,73 +1,88 @@
1
- require 'active_support/concern'
2
-
3
1
  module ActiveRecordTweaks
4
2
  module Integration
5
- extend ActiveSupport::Concern
3
+ def self.included(base)
4
+ base.class_eval do
5
+ # rubocop:disable all
6
+ warn "[DEPRECATION] including `ActiveRecordTweaks::Integration` is deprecated. Please see README for recommanded usage."
7
+ # rubocop:enable all
6
8
 
7
- # Returns a cache key that can be used to identify this record.
8
- # Timestamp is not used to allow custom caching expiration
9
- # (e.g. Cookie based caching with expiration )
10
- #
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
- def cache_key_without_timestamp
15
- case
16
- when new_record?
17
- "#{self.class.model_name.cache_key}/new"
18
- else
19
- "#{self.class.model_name.cache_key}/#{id}"
9
+ extend ClassMethods
10
+ include InstanceMethods
20
11
  end
21
12
  end
22
13
 
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
14
+ module InstanceMethods
15
+ # Returns a cache key that can be used to identify this record.
16
+ # Timestamp is not used to allow custom caching expiration
17
+ # (e.g. Cookie based caching with expiration )
18
+ #
19
+ # Product.new.cache_key_without_timestamp # => "products/new"
20
+ # Product.find(5).cache_key_without_timestamp # => "products/5" (updated_at not available)
21
+ # Person.find(5).cache_key_without_timestamp # => "people/5" (updated_at available)
22
+ def cache_key_without_timestamp
23
+ if new_record?
24
+ "#{self.class.model_name.cache_key}/new"
25
+ else
26
+ "#{self.class.model_name.cache_key}/#{id}"
27
+ end
28
+ end
29
+
30
+ # Works like #cache_key in rails 4.1, but does not check column
31
+ # Useful when you have some virtual timestamp attribute method (cached or not)
32
+ #
33
+ # @param attribute_names [Array<Symbol,String>]
34
+ # Names of attributes method(s)
35
+ # It does not have to be column(s)
36
+ #
37
+ # @raise [ArgumentError] when attribute_names is empty
38
+ def cache_key_from_attributes(*attribute_names)
39
+ attribute_names.any? || fail(ArgumentError)
33
40
 
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}"
41
+ timestamp = max_updated_attribute_timestamp_for_cache_key(attribute_names)
42
+ if timestamp
43
+ timestamp = timestamp.utc.to_s(cache_timestamp_format)
44
+ "#{self.class.model_name.cache_key}/#{id}-#{timestamp}"
45
+ else
46
+ "#{self.class.model_name.cache_key}/#{id}"
47
+ end
39
48
  end
40
- end
41
- alias_method :cache_key_from_attribute, :cache_key_from_attributes
49
+ alias cache_key_from_attribute cache_key_from_attributes
42
50
 
43
- private
51
+ private
44
52
 
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
53
+ def max_updated_attribute_timestamp_for_cache_key(timestamp_attribute_names)
54
+ timestamps = timestamp_attribute_names.map do |attribute_name|
55
+ send(attribute_name)
56
+ end.compact
49
57
 
50
- if timestamps.present?
51
- timestamps.map { |ts| ts.to_time }.max
58
+ return nil unless timestamps.present?
59
+ timestamps.map(&:to_time).max
52
60
  end
53
61
  end
54
62
 
55
63
  module ClassMethods
64
+ # rubocop:disable all
65
+ warn "[DEPRECATION] `ActiveRecordTweaks::Integration::ClassMethods` is deprecated without replacement. Please read README in project for details."
66
+ # rubocop:enable all
67
+
56
68
  # Returns a cache key for the ActiveRecord class based
57
69
  # based on count and maximum value of update timestamp columns
58
70
  # (e.g. Cookie based caching with expiration)
59
71
  #
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)
72
+ # @example when record class is empty and has updated timestamp columns or not
73
+ # Product.cache_key # => "products/all/0"
74
+ # @example when record class is not empty but has no updated timestamp columns
75
+ # Product.cache_key # => "products/all/1"
76
+ # @example when record class is not empty and has updated timestamp columns
77
+ # Person.cache_key # => "people/all/1-20071224150000"
63
78
  #
64
79
  # @param [Array<String, Symbol>] args The column name with timestamp to check
65
80
  def cache_key(*args)
66
81
  timestamp_columns = args.empty? ? [:updated_at] : args
67
82
 
68
- if timestamp = max_updated_column_timestamp_for_cache_key(timestamp_columns)
83
+ if (timestamp = max_updated_column_timestamp_for_cache_key(timestamp_columns))
69
84
  timestamp = timestamp.utc.to_s(cache_timestamp_format)
70
- "#{self.model_name.cache_key}/all/#{self.count}-#{timestamp}"
85
+ "#{model_name.cache_key}/all/#{count}-#{timestamp}"
71
86
  else
72
87
  cache_key_without_timestamp
73
88
  end
@@ -76,23 +91,23 @@ module ActiveRecordTweaks
76
91
  # Returns a cache key for the ActiveRecord class based
77
92
  # based on count only
78
93
  #
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)
94
+ # Product.cache_key # => "products/all/0" (empty, has updated timestamp columns or not)
95
+ # Product.cache_key # => "products/all/1" (not empty but has no updated timestamp columns)
96
+ # Person.cache_key # => "people/all/1" (not empty and has updated timestamp columns)
82
97
  #
83
98
  # @param [Array<String, Symbol>] args The column name with timestamp to check
84
99
  def cache_key_without_timestamp
85
- "#{self.model_name.cache_key}/all/#{self.count}"
100
+ "#{model_name.cache_key}/all/#{count}"
86
101
  end
87
102
 
88
103
  private
89
104
 
90
105
  def max_updated_column_timestamp_for_cache_key(timestamp_columns)
91
- available_timestamp_columns = timestamp_columns.select { |c| self.column_names.include?(c.to_s) }
106
+ available_timestamp_columns = timestamp_columns.select { |c| column_names.include?(c.to_s) }
107
+ timestamps = available_timestamp_columns.map { |column| maximum(column) }.compact
92
108
 
93
- if (timestamps = available_timestamp_columns.map { |column| self.maximum(column) }.compact).present?
94
- timestamps.map { |ts| ts.to_time }.max
95
- end
109
+ return nil unless timestamps.present?
110
+ timestamps.map(&:to_time).max
96
111
  end
97
112
  end
98
113
  end