counter_culture 2.6.1 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d5f74128800b0a21f52ee32279a4ea9eb89cfb707705101958753c065077e30
4
- data.tar.gz: 89c64173bb719cafe1594918779e3bef02b93b567bf9f098593d1b99f0888c38
3
+ metadata.gz: 99af13953d00540dac3d0b149483d190f03f4c0f77063cdd440b2b18c1ef6031
4
+ data.tar.gz: fedce32d590b66c8ff0bf291d612ef1f1fd08356afb81a56ae310caa6a9eeac9
5
5
  SHA512:
6
- metadata.gz: e2383f82c2c46bab51d9bfe7b4ada1f579768463f38d8ab93d1e0e33c0b878b6c1f38bbd0793c43ee38d3fca6c2a13a27b2453b20daeb69f96c4242a192e56e6
7
- data.tar.gz: ee3d106b3abb6b4c362d0c6b4861ef2e04ed3cfccd5dd5611b96db50435fc573d3d23a16c3558e0a5d8eafc4c48aa4650fc8edf4f2301d93d9a30fb408de69f9
6
+ metadata.gz: 510c27a1188f8cbe9073487f2f0f7579ffad46a1b140c44bdfcea07308ddb0975587140dd96a60087475d8c6ad94d1b415cb40f57a1ba59e7d19673bd426bf93
7
+ data.tar.gz: 5c2acebf87a92a8ca02e7bd38d4d683cde4fa77c46f611ae29f6007509450baeeb72a69df6107c38606b9243d1e61e5a38302ec51bbd60bdb1fbd8bd53b1289f
data/.travis.yml CHANGED
@@ -1,31 +1,45 @@
1
1
  language: ruby
2
+ cache:
3
+ directories:
4
+ - ~/.rvm/gems
2
5
  services:
3
6
  - postgresql
4
7
  - mysql
8
+ branches:
9
+ only:
10
+ - master
5
11
  addons:
6
12
  postgresql: "9.6"
7
13
  rvm:
8
- - "2.5.7"
9
- - "2.6.5"
10
- - "2.7.0"
14
+ - "2.5.9"
15
+ - "2.6.8"
16
+ - "2.7.4"
17
+ - "3.0.2"
11
18
  gemfile:
12
19
  - gemfiles/rails_4.2.gemfile
13
20
  - gemfiles/rails_5.0.gemfile
14
21
  - gemfiles/rails_5.1.gemfile
15
22
  - gemfiles/rails_5.2.gemfile
16
23
  - gemfiles/rails_6.0.gemfile
24
+ - gemfiles/rails_6.1.gemfile
17
25
  matrix:
18
26
  exclude:
19
- - rvm: "2.7.0"
27
+ - rvm: "3.0.1"
20
28
  gemfile: gemfiles/rails_4.2.gemfile
29
+ - rvm: "3.0.1"
30
+ gemfile: gemfiles/rails_5.0.gemfile
31
+ - rvm: "3.0.1"
32
+ gemfile: gemfiles/rails_5.1.gemfile
33
+ - rvm: "3.0.1"
34
+ gemfile: gemfiles/rails_5.2.gemfile
21
35
  env:
22
36
  - DB=postgresql
23
37
  - DB=sqlite3
24
38
  - DB=mysql2
25
39
  before_install:
26
- - gem install bundler -v '1.17.3'
40
+ - if [ "$BUNDLE_GEMFILE" = "$PWD/gemfiles/rails_4.2.gemfile" ]; then gem install bundler -v '1.17.3'; else gem install bundler -v '> 2'; fi
27
41
  install:
28
- - bundle _1.17.3_ update
42
+ - if [ "$BUNDLE_GEMFILE" = "$PWD/gemfiles/rails_4.2.gemfile" ]; then bundle _1.17.3_ update; else bundle update; fi
29
43
  before_script:
30
44
  - psql -c 'create database counter_culture_test;' -U postgres
31
45
  - mysql -e 'CREATE DATABASE counter_culture_test;'
data/Appraisals CHANGED
@@ -4,6 +4,7 @@
4
4
  5.1
5
5
  5.2
6
6
  6.0
7
+ 6.1
7
8
  ].each do |rails_version|
8
9
  gem_rails_version = Gem::Version.new(rails_version)
9
10
  if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5.0') &&
@@ -15,8 +16,19 @@
15
16
  appraise "rails-#{rails_version}" do
16
17
  gem 'rails', "~> #{rails_version}.0"
17
18
 
18
- gem 'pg', gem_rails_version < Gem::Version.new('5.0') ? '~> 0.15' : '~> 1.0'
19
+ if gem_rails_version < Gem::Version.new('5.0')
20
+ gem 'pg', '~> 0.15'
21
+ else
22
+ gem 'pg'
23
+ end
19
24
  gem 'mysql2'
20
- gem 'sqlite3', gem_rails_version < Gem::Version.new(5.2) ? '~> 1.3.0' : '~> 1.4'
25
+ if gem_rails_version < Gem::Version.new('5.2')
26
+ gem 'sqlite3', '~> 1.3.0'
27
+ else
28
+ gem 'sqlite3'
29
+ end
30
+ if gem_rails_version < Gem::Version.new('5.0')
31
+ gem 'bigdecimal', '~> 1.3.5'
32
+ end
21
33
  end
22
34
  end
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ## 2.9.0 (August 27, 2021)
2
+
3
+ Improvements:
4
+ - Allow `execute_after_commit` to be a `Proc` for dynamic control (#326)
5
+
6
+ ## 2.8.0 (March 16, 2021)
7
+
8
+ Improvements:
9
+ - New `execute_after_commit` option (#309)
10
+
11
+ ## 2.7.0 (November 16, 2020)
12
+
13
+ Improvements:
14
+ - New `column_name` option for `counter_culture_fix_counts` (#300)
15
+
16
+ ## 2.6.2 (October 21, 2020)
17
+
18
+ Improvements:
19
+ - Remove superfluous dependency to after_commit_action gem (#297)
20
+
1
21
  ## 2.6.1 (September 8, 2020)
2
22
 
3
23
  Bugfixes:
data/README.md CHANGED
@@ -7,7 +7,7 @@ Turbo-charged counter caches for your Rails app. Huge improvements over the Rail
7
7
  * Supports dynamic column names, making it possible to split up the counter cache for different types of objects
8
8
  * Can keep a running count, or a running total
9
9
 
10
- Tested against Ruby 2.3.8, 2.4.7, 2.5.6 and 2.6.4 and against the latest patch releases of Rails 4.2, 5.0, 5.1, 5.2 and 6.0.
10
+ Tested against Ruby 2.5.8, 2.6.6, 2.7.2 and 3.0.0, and against the latest patch releases of Rails 4.2, 5.0, 5.1, 5.2, 6.0 and 6.1.
11
11
 
12
12
  Please note that -- unlike Rails' built-in counter-caches -- counter_culture does not currently change the behavior of the `.size` method on ActiveRecord associations. If you want to avoid a database query and read the cached value, please use the attribute name containing the counter cache directly.
13
13
  ```
@@ -187,6 +187,8 @@ end
187
187
 
188
188
  Now, the ```Category``` model will keep the counter cache in ```special_count``` up-to-date. Only products where ```special?``` returns true will affect the special_count.
189
189
 
190
+ If you would like to use this with `counter_culture_fix_counts`, make sure to also provide [the `column_names` configuration](#handling-dynamic-column-names).
191
+
190
192
  ### Totaling instead of counting
191
193
 
192
194
  Instead of keeping a running count, you may want to automatically track a running total.
@@ -248,6 +250,28 @@ You may also specify a custom timestamp column that gets updated only when a par
248
250
 
249
251
  With this option, any time the `category_counter_cache` changes both the `category_count_changed` and `updated_at` columns will get updated.
250
252
 
253
+ ### Avoiding deadlocks / executing counter cache updates after commit
254
+
255
+ Some applications run into issues with deadlocks involving counter cache updates when using this gem. See [#263](https://github.com/magnusvk/counter_culture/issues/263#issuecomment-772284439) for information and helpful links on how to avoid this issue.
256
+
257
+ Another option is to simply defer the update of counter caches to outside of the transaction. This gives up transacrtional guarantees for your counter cache updates but should resolve any deadlocks you experience. This behavior is disabled by default, enable it on each affected counter cache as follows:
258
+
259
+ ```ruby
260
+ counter_culture :category, execute_after_commit: true
261
+ ```
262
+ [NOTE] You need to manually specify the `after_commit_action` as dependency in the Gemfile to use this feature
263
+ ```ruby
264
+ ...
265
+ gem "after_commit_action"
266
+ ...
267
+ ```
268
+
269
+ You can also pass a `Proc` for dynamic control. This is useful for temporarily moving the counter cache update inside of the transaction:
270
+
271
+ ```ruby
272
+ counter_culture :category, execute_after_commit: proc { !Thread.current[:update_counter_cache_in_transaction] }
273
+ ```
274
+
251
275
  ### Manually populating counter cache values
252
276
 
253
277
  You will sometimes want to populate counter-cache values from primary data. This is required when adding counter-caches to existing data. It is also recommended to run this regularly (at BestVendor, we run it once a week) to catch any incorrect values in the counter caches.
@@ -268,6 +292,10 @@ Product.counter_culture_fix_counts only: :category
268
292
  Product.counter_culture_fix_counts only: [[:subcategory, :category]]
269
293
  # will automatically fix counts only on the two-level [:subcategory, :category] relation on Product
270
294
 
295
+ Product.counter_culture_fix_counts column_name: :reviews_count
296
+ # will automatically fix counts only on the :reviews_count column on Product
297
+ # This allows us to skip the columns that have already been processed. This is useful after running big DB changes that affect only one counter cache column.
298
+
271
299
  # :except and :only also accept arrays
272
300
 
273
301
  Product.counter_culture_fix_counts verbose: true
@@ -440,4 +468,4 @@ counter_culture now supports polymorphic associations of one level only.
440
468
 
441
469
  ## Copyright
442
470
 
443
- Copyright (c) 2012-2013 BestVendor, Magnus von Koeller. See LICENSE.txt for further details.
471
+ Copyright (c) 2012-2021 BestVendor, Magnus von Koeller. See LICENSE.txt for further details.
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
 
11
11
  spec.summary = 'Turbo-charged counter caches for your Rails app.'
12
12
  spec.description = 'counter_culture provides turbo-charged counter caches that are kept up-to-date not just on create and destroy, that support multiple levels of indirection through relationships, allow dynamic column names and that avoid deadlocks by updating in the after_commit callback.'
13
- spec.homepage = 'http://github.com/magnusvk/counter_culture'
13
+ spec.homepage = 'https://github.com/magnusvk/counter_culture'
14
14
  spec.license = 'MIT'
15
15
 
16
16
  spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
@@ -25,17 +25,17 @@ Gem::Specification.new do |spec|
25
25
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
26
  spec.require_paths = ['lib']
27
27
 
28
- spec.add_dependency 'after_commit_action', '~> 1.0'
29
28
  spec.add_dependency 'activerecord', '>= 4.2'
30
29
  spec.add_dependency 'activesupport', '>= 4.2'
31
30
 
32
31
  spec.add_development_dependency 'appraisal', '> 2.0.0'
33
32
  spec.add_development_dependency 'awesome_print'
34
- spec.add_development_dependency 'bundler', '~> 1.17'
33
+ spec.add_development_dependency 'bundler'
35
34
  spec.add_development_dependency 'database_cleaner', '>= 1.1.1'
36
35
  spec.add_development_dependency 'discard'
37
36
  spec.add_development_dependency 'paper_trail'
38
37
  spec.add_development_dependency 'paranoia'
38
+ spec.add_development_dependency 'after_commit_action'
39
39
  spec.add_development_dependency 'rails', '>= 4.2'
40
40
  spec.add_development_dependency 'rake', '>= 10.0'
41
41
  spec.add_development_dependency 'rdoc', '~> 5.0.0'
@@ -6,5 +6,6 @@ gem "sqlite3", "~> 1.3.0"
6
6
  gem "rails", "~> 4.2.0"
7
7
  gem "pg", "~> 0.15"
8
8
  gem "mysql2"
9
+ gem "bigdecimal", "~> 1.3.5"
9
10
 
10
11
  gemspec path: "../"
@@ -4,7 +4,7 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "sqlite3", "~> 1.3.0"
6
6
  gem "rails", "~> 5.0.0"
7
- gem "pg", "~> 1.0"
7
+ gem "pg"
8
8
  gem "mysql2"
9
9
 
10
10
  gemspec path: "../"
@@ -4,7 +4,7 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "sqlite3", "~> 1.3.0"
6
6
  gem "rails", "~> 5.1.0"
7
- gem "pg", "~> 1.0"
7
+ gem "pg"
8
8
  gem "mysql2"
9
9
 
10
10
  gemspec path: "../"
@@ -2,9 +2,9 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "sqlite3", "~> 1.4"
5
+ gem "sqlite3"
6
6
  gem "rails", "~> 5.2.0"
7
- gem "pg", "~> 1.0"
7
+ gem "pg"
8
8
  gem "mysql2"
9
9
 
10
10
  gemspec path: "../"
@@ -2,9 +2,9 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "sqlite3", "~> 1.4"
5
+ gem "sqlite3"
6
6
  gem "rails", "~> 6.0.0"
7
- gem "pg", "~> 1.0"
7
+ gem "pg"
8
8
  gem "mysql2"
9
9
 
10
10
  gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "sqlite3"
6
+ gem "rails", "~> 6.1.0"
7
+ gem "pg"
8
+ gem "mysql2"
9
+
10
+ gemspec path: "../"
@@ -1,6 +1,6 @@
1
1
  module CounterCulture
2
2
  class Counter
3
- CONFIG_OPTIONS = [ :column_names, :counter_cache_name, :delta_column, :foreign_key_values, :touch, :delta_magnitude]
3
+ CONFIG_OPTIONS = [ :column_names, :counter_cache_name, :delta_column, :foreign_key_values, :touch, :delta_magnitude, :execute_after_commit ]
4
4
  ACTIVE_RECORD_VERSION = Gem.loaded_specs["activerecord"].version
5
5
 
6
6
  attr_reader :model, :relation, *CONFIG_OPTIONS
@@ -9,10 +9,6 @@ module CounterCulture
9
9
  @model = model
10
10
  @relation = relation.is_a?(Enumerable) ? relation : [relation]
11
11
 
12
- if options.fetch(:execute_after_commit, false)
13
- fail("execute_after_commit was removed; updates now run within the transaction")
14
- end
15
-
16
12
  @counter_cache_name = options.fetch(:column_name, "#{model.name.demodulize.tableize}_count")
17
13
  @column_names = options[:column_names]
18
14
  @delta_column = options[:delta_column]
@@ -20,6 +16,18 @@ module CounterCulture
20
16
  @touch = options.fetch(:touch, false)
21
17
  @delta_magnitude = options[:delta_magnitude] || 1
22
18
  @with_papertrail = options.fetch(:with_papertrail, false)
19
+ @execute_after_commit = options.fetch(:execute_after_commit, false)
20
+
21
+ if @execute_after_commit
22
+ begin
23
+ require 'after_commit_action'
24
+ rescue LoadError
25
+ fail(LoadError.new(
26
+ "You need to include the `after_commit_action` gem in your "\
27
+ "gem dependencies to use the execute_after_commit option"))
28
+ end
29
+ model.include(AfterCommitAction)
30
+ end
23
31
  end
24
32
 
25
33
  # increments or decrements a counter cache
@@ -93,14 +101,20 @@ module CounterCulture
93
101
  instance.send("#{timestamp_column}=", current_time)
94
102
  end
95
103
 
96
- instance.paper_trail.save_with_version(validate: false)
104
+ execute_now_or_after_commit(obj) do
105
+ instance.paper_trail.save_with_version(validate: false)
106
+ end
97
107
  else
98
- instance.paper_trail.touch_with_version
108
+ execute_now_or_after_commit(obj) do
109
+ instance.paper_trail.touch_with_version
110
+ end
99
111
  end
100
112
  end
101
113
  end
102
114
 
103
- klass.where(primary_key => id_to_change).update_all updates.join(', ')
115
+ execute_now_or_after_commit(obj) do
116
+ klass.where(primary_key => id_to_change).update_all updates.join(', ')
117
+ end
104
118
  end
105
119
  end
106
120
 
@@ -296,6 +310,16 @@ module CounterCulture
296
310
  prev
297
311
  end
298
312
 
313
+ def execute_now_or_after_commit(obj, &block)
314
+ execute_after_commit = @execute_after_commit.is_a?(Proc) ? @execute_after_commit.call : @execute_after_commit
315
+
316
+ if execute_after_commit
317
+ obj.execute_after_commit(&block)
318
+ else
319
+ block.call
320
+ end
321
+ end
322
+
299
323
  private
300
324
  def attribute_was(obj, attr)
301
325
  changes_method =
@@ -15,8 +15,6 @@ module CounterCulture
15
15
  # called to configure counter caches
16
16
  def counter_culture(relation, options = {})
17
17
  unless @after_commit_counter_cache
18
- include AfterCommitAction unless include?(AfterCommitAction)
19
-
20
18
  # initialize callbacks only once
21
19
  after_create :_update_counts_after_create
22
20
 
@@ -61,7 +59,8 @@ module CounterCulture
61
59
  #
62
60
  # options:
63
61
  # { :exclude => list of relations to skip when fixing counts,
64
- # :only => only these relations will have their counts fixed }
62
+ # :only => only these relations will have their counts fixed,
63
+ # :column_name => only this column will have its count fixed }
65
64
  # returns: a list of fixed record as an array of hashes of the form:
66
65
  # { :entity => which model the count was fixed on,
67
66
  # :id => the id of the model that had the incorrect count,
@@ -81,7 +80,7 @@ module CounterCulture
81
80
  next if options[:exclude] && options[:exclude].include?(counter.relation)
82
81
  next if options[:only] && !options[:only].include?(counter.relation)
83
82
 
84
- reconciler_options = %i(batch_size finish skip_unsupported start touch verbose where)
83
+ reconciler_options = %i(batch_size column_name finish skip_unsupported start touch verbose where)
85
84
 
86
85
  reconciler = CounterCulture::Reconciler.new(counter, options.slice(*reconciler_options))
87
86
  reconciler.reconcile!
@@ -76,6 +76,10 @@ module CounterCulture
76
76
 
77
77
  counter_column_names = column_names || {nil => counter_cache_name}
78
78
 
79
+ if options[:column_name]
80
+ counter_column_names = counter_column_names.select{ |_, v| options[:column_name].to_s == v }
81
+ end
82
+
79
83
  # iterate over all the possible counter cache column names
80
84
  counter_column_names.each do |where, column_name|
81
85
  # if the column name is nil, that means those records don't affect
@@ -1,3 +1,3 @@
1
1
  module CounterCulture
2
- VERSION = '2.6.1'.freeze
2
+ VERSION = '2.9.0'.freeze
3
3
  end
@@ -1,4 +1,3 @@
1
- require 'after_commit_action'
2
1
  require 'active_support/concern'
3
2
  require 'active_support/lazy_load_hooks'
4
3
 
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: counter_culture
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.1
4
+ version: 2.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Magnus von Koeller
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-08 00:00:00.000000000 Z
11
+ date: 2021-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: after_commit_action
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: activerecord
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -84,16 +70,16 @@ dependencies:
84
70
  name: bundler
85
71
  requirement: !ruby/object:Gem::Requirement
86
72
  requirements:
87
- - - "~>"
73
+ - - ">="
88
74
  - !ruby/object:Gem::Version
89
- version: '1.17'
75
+ version: '0'
90
76
  type: :development
91
77
  prerelease: false
92
78
  version_requirements: !ruby/object:Gem::Requirement
93
79
  requirements:
94
- - - "~>"
80
+ - - ">="
95
81
  - !ruby/object:Gem::Version
96
- version: '1.17'
82
+ version: '0'
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: database_cleaner
99
85
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +136,20 @@ dependencies:
150
136
  - - ">="
151
137
  - !ruby/object:Gem::Version
152
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: after_commit_action
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: rails
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -277,6 +277,7 @@ files:
277
277
  - gemfiles/rails_5.1.gemfile
278
278
  - gemfiles/rails_5.2.gemfile
279
279
  - gemfiles/rails_6.0.gemfile
280
+ - gemfiles/rails_6.1.gemfile
280
281
  - lib/counter_culture.rb
281
282
  - lib/counter_culture/counter.rb
282
283
  - lib/counter_culture/extensions.rb
@@ -284,12 +285,11 @@ files:
284
285
  - lib/counter_culture/version.rb
285
286
  - lib/generators/counter_culture_generator.rb
286
287
  - lib/generators/templates/counter_culture_migration.rb.erb
287
- - run_tests_locally.sh
288
- homepage: http://github.com/magnusvk/counter_culture
288
+ homepage: https://github.com/magnusvk/counter_culture
289
289
  licenses:
290
290
  - MIT
291
291
  metadata: {}
292
- post_install_message:
292
+ post_install_message:
293
293
  rdoc_options: []
294
294
  require_paths:
295
295
  - lib
@@ -304,8 +304,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
304
304
  - !ruby/object:Gem::Version
305
305
  version: '0'
306
306
  requirements: []
307
- rubygems_version: 3.1.2
308
- signing_key:
307
+ rubygems_version: 3.1.4
308
+ signing_key:
309
309
  specification_version: 4
310
310
  summary: Turbo-charged counter caches for your Rails app.
311
311
  test_files: []
data/run_tests_locally.sh DELETED
@@ -1,20 +0,0 @@
1
- #! /bin/bash
2
-
3
- set -e
4
- source /usr/local/share/chruby/chruby.sh
5
-
6
- for RUBY_VERSION in 2.5.7 2.6.5 2.7.0; do
7
- chruby $RUBY_VERSION
8
- ruby --version
9
-
10
- gem install bundler -v '1.17.3'
11
-
12
- (bundle _1.17.3_ check > /dev/null || bundle _1.17.3_ install)
13
- gem install appraisal
14
- bundle exec appraisal install
15
-
16
- for DB in mysql2 postgresql sqlite3; do
17
- echo "RUBY $RUBY_VERSION; DB $DB"
18
- DB=$DB bundle exec appraisal rspec spec/counter_culture_spec.rb
19
- done
20
- done