db_memoize 0.2.3 → 0.3.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c30ad0bcaafd71d6b6e819e0d951561c0ccdee50
4
- data.tar.gz: 99803b69c67ad890ed66a2648c4cd414e3c0bc2d
2
+ SHA256:
3
+ metadata.gz: '095aec4c4352df19e1a55ee270414a18b240e6135733e5871d5f766dd6789077'
4
+ data.tar.gz: d9ee2695e76c0611f23aa3cfe7c8afa82ff09f04d5de1acf525d2570099b2428
5
5
  SHA512:
6
- metadata.gz: bde9f19880b5809dbf35daf2b1664223f9db45033d1cc297a3714c41afbbec98b0099b4e232566c0be1346e78dada3c92b27c607224f5480599efe91de7a644b
7
- data.tar.gz: 61aa061f01ba3df008f1b7be39f4e6510daf9f8e4dda38188b0c33deaace4c874cd60d426ea2cb3296ed4717f65635c5e4bdfa5ce9cb25cf47bd44042abaf020
6
+ metadata.gz: 50af7b39e3aed56fa829b940f4c0251c0d49fef89306a38f7f6aa69ab7c6dfecb677646869eb076c155f9fbc69abc9a6bba3d37ea57d4582b0a0465433d90a11
7
+ data.tar.gz: 97e18054c9914f961c97796650f47fff3aca4e74066f6dbe53b420633719bb7ec0f3f8354c7d2e19c11e93b864192894e538204b9bf57626fbeda427734af19c
data/.rubocop.yml CHANGED
@@ -3,21 +3,13 @@ AllCops:
3
3
  Include:
4
4
  - Rakefile
5
5
  - config.ru
6
+ - lib/**/*.rb
6
7
  Exclude:
7
8
  - Rakefile
8
9
  - bin/*
9
10
  - config.ru
10
11
  - config/**/*
11
- - db/**/*
12
- - doc/**/*
13
- - gems/**/*
14
- - gems/*/vendor/**/*
15
- - script/**/*
16
- - sh/**/*
17
- - spec/rails_helper.rb
18
- - spec/spec_helper.rb
19
12
  - vendor/**/*
20
- - spec/support/v20140601/requests_helper.rb
21
13
 
22
14
  Style/FrozenStringLiteralComment:
23
15
  Enabled: false
@@ -25,12 +17,6 @@ Style/FrozenStringLiteralComment:
25
17
  Metrics/LineLength:
26
18
  Max: 140
27
19
 
28
- Rails:
29
- Enabled: true
30
-
31
- Rails/HasAndBelongsToMany:
32
- Enabled: false
33
-
34
20
  Style/Documentation:
35
21
  Enabled: false
36
22
 
@@ -66,3 +52,9 @@ Metrics/MethodLength:
66
52
  # "Prefer !expression.nil? over expression != nil." no way!
67
53
  Style/NonNilCheck:
68
54
  Enabled: false
55
+
56
+ Style/SymbolArray:
57
+ Enabled: false
58
+
59
+ Lint/MissingCopEnableDirective:
60
+ Enabled: false
data/.travis.yml CHANGED
@@ -1,8 +1,10 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.3.1
5
- before_install: gem install bundler -v 1.13.6
4
+ - 2.5.1
5
+ before_install: gem install bundler -v 1.16.4
6
+ addons:
7
+ postgresql: "9.6"
6
8
  script:
7
9
  - bundle exec rake db:test:create
8
10
  - bundle exec rspec
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Build Status](https://travis-ci.com/mediapeers/db_memoize.svg?branch=master)](https://travis-ci.com/mediapeers/db_memoize)
2
+
1
3
  # db_memoize
2
4
  library to cache (memoize) method return values in database
3
5
 
data/Rakefile CHANGED
@@ -1,11 +1,20 @@
1
- require "bundler/gem_tasks"
2
1
  require "rspec/core/rake_task"
3
2
 
4
3
  RSpec::Core::RakeTask.new(:spec)
5
4
 
6
- task "db:test:create" do
7
- Rake.sh "dropdb db_memoize_test || true"
8
- Rake.sh "createdb db_memoize_test"
5
+ task 'db:test:create' do
6
+ Rake.sh 'dropdb db_memoize_test -U postgres || true'
7
+ Rake.sh 'createdb db_memoize_test -U postgres'
9
8
  end
10
9
 
11
10
  task :default => %w(db:test:create spec)
11
+
12
+ desc "release a new development gem version"
13
+ task :release do
14
+ sh "scripts/release.rb"
15
+ end
16
+
17
+ desc "release a new stable gem version"
18
+ task "release:stable" do
19
+ sh "BRANCH=stable scripts/release.rb"
20
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.2
data/bin/rake ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rake' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rake", "rake")
data/bin/rspec ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rspec' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rspec-core", "rspec")
data/bin/rubocop ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rubocop' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rubocop", "rubocop")
data/db_memoize.gemspec CHANGED
@@ -1,11 +1,10 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'db_memoize/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
6
  spec.name = "db_memoize"
8
- spec.version = DbMemoize::VERSION
7
+ spec.version = File.read("VERSION")
9
8
  spec.licenses = ['MIT']
10
9
  spec.authors = ["johannes-kostas goetzinger"]
11
10
  spec.email = ["goetzinger@mediapeers.com"]
@@ -21,20 +20,15 @@ Gem::Specification.new do |spec|
21
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
21
  spec.require_paths = ['lib']
23
22
 
23
+ spec.add_dependency 'simple-sql', '>= 0.4.20', '~> 0'
24
24
  spec.add_development_dependency 'railties', '~> 4.2'
25
- spec.add_development_dependency 'activerecord', '~> 4.2'
25
+ spec.add_development_dependency 'activerecord', '~> 4.2.10'
26
26
 
27
- spec.add_development_dependency 'rake', '~> 10.5'
28
- spec.add_development_dependency 'pg'
29
- spec.add_development_dependency 'rspec-rails', '~> 3.4'
30
- spec.add_development_dependency 'pry', '~> 0.10'
31
- spec.add_development_dependency 'pry-byebug', '~> 2.0'
32
- spec.add_development_dependency 'yard', '~> 0'
33
- spec.add_development_dependency 'simplecov', '~> 0.7.1'
34
- spec.add_development_dependency 'rubocop', '~> 0.37.2'
27
+ spec.add_development_dependency 'rake', '~> 12.0'
28
+ spec.add_development_dependency 'pg', '~> 0.20'
29
+ spec.add_development_dependency 'rspec', '~> 3.8'
30
+ spec.add_development_dependency 'simplecov', '~> 0.16'
31
+ spec.add_development_dependency 'rubocop', '~> 0.59.2'
35
32
  spec.add_development_dependency 'database_cleaner', '~> 1.5.3'
36
33
  spec.add_development_dependency 'factory_girl', '~> 4.7.0'
37
- spec.add_development_dependency 'ruby-progressbar', '~> 1.7'
38
- spec.add_development_dependency 'awesome_print'
39
- spec.add_development_dependency 'gem-release'
40
34
  end
data/lib/db_memoize.rb CHANGED
@@ -4,7 +4,6 @@ require 'digest'
4
4
  require 'benchmark'
5
5
 
6
6
  require 'db_memoize/version'
7
- require 'db_memoize/metal'
8
7
  require 'db_memoize/value'
9
8
  require 'db_memoize/helpers'
10
9
  require 'db_memoize/model'
@@ -16,17 +16,5 @@ module DbMemoize
16
16
  "DbMemoize <#{model.class.name}##{model.id}>##{method_name} - #{msg}"
17
17
  end
18
18
  end
19
-
20
- def calculate_arguments_hash(arguments)
21
- arguments.empty? ? nil : ::Digest::MD5.hexdigest(Marshal.dump(arguments))
22
- end
23
-
24
- def marshal(value)
25
- Marshal.dump(value)
26
- end
27
-
28
- def unmarshal(value)
29
- Marshal.load(value)
30
- end
31
19
  end
32
20
  end
@@ -13,6 +13,8 @@ module DbMemoize
13
13
 
14
14
  migration.add_index :memoized_values, [:entity_table_name, :entity_id]
15
15
  migrate_empty_arguments_support(migration)
16
+ drop_arguments_support(migration)
17
+ add_discrete_value_columns(migration)
16
18
  end
17
19
 
18
20
  def migrate_empty_arguments_support(migration)
@@ -23,7 +25,25 @@ module DbMemoize
23
25
 
24
26
  # add an index to be useful to look up entries where arguments_hash is NULL.
25
27
  # (which is the case for plain attributes of an object)
26
- migration.execute 'CREATE INDEX memoized_attributes_idx ON memoized_values((arguments_hash IS NULL))'
28
+ migration.execute 'CREATE INDEX IF NOT EXISTS memoized_attributes_idx ON memoized_values((arguments_hash IS NULL))'
29
+ end
30
+
31
+ def drop_arguments_support(migration)
32
+ migration.execute 'DROP INDEX IF EXISTS memoized_attributes_idx'
33
+ migration.execute 'ALTER TABLE memoized_values DROP COLUMN IF EXISTS arguments_hash'
34
+
35
+ migration.remove_index :memoized_values, [:entity_id, :entity_table_name]
36
+ migration.add_index :memoized_values, [:entity_id, :entity_table_name, :method_name], unique: true, name: 'memoized_attributes_idx2'
37
+ end
38
+
39
+ def add_discrete_value_columns(migration)
40
+ migration.execute 'ALTER TABLE memoized_values ADD COLUMN IF NOT EXISTS val_string varchar'
41
+ migration.execute 'ALTER TABLE memoized_values ADD COLUMN IF NOT EXISTS val_integer bigint'
42
+ migration.execute 'ALTER TABLE memoized_values ADD COLUMN IF NOT EXISTS val_float double precision'
43
+ migration.execute 'ALTER TABLE memoized_values ADD COLUMN IF NOT EXISTS val_time timestamp without time zone'
44
+ migration.execute 'ALTER TABLE memoized_values ADD COLUMN IF NOT EXISTS val_boolean boolean'
45
+ migration.execute 'ALTER TABLE memoized_values ADD COLUMN IF NOT EXISTS val_object jsonb'
46
+ migration.execute 'ALTER TABLE memoized_values ADD COLUMN IF NOT EXISTS val_nil boolean'
27
47
  end
28
48
  end
29
49
  end
@@ -1,23 +1,23 @@
1
+ require 'simple-sql'
2
+
1
3
  module DbMemoize
2
4
  module Model
3
5
  extend ActiveSupport::Concern
4
6
 
5
- def memoized_value(method_name, args)
6
- if changed? || !persisted?
7
- return send("#{method_name}_without_memoize", *args)
8
- end
7
+ def memoized_value(method_name)
8
+ memoizable = !changed? && persisted?
9
+ return send("#{method_name}_without_memoize") unless memoizable
9
10
 
10
11
  value = nil
11
- args_hash = Helpers.calculate_arguments_hash(args)
12
- cached_value = find_memoized_value(method_name, args_hash)
12
+ cached_value = find_memoized_value(method_name)
13
13
 
14
14
  if cached_value
15
- value = Helpers.unmarshal(cached_value.value)
15
+ value = cached_value.value
16
16
  Helpers.log(self, method_name, 'cache hit')
17
17
  else
18
18
  time = ::Benchmark.realtime do
19
- value = send("#{method_name}_without_memoize", *args)
20
- create_memoized_value(method_name, args_hash, value)
19
+ value = send("#{method_name}_without_memoize")
20
+ create_memoized_value(method_name, value)
21
21
  end
22
22
  Helpers.log(self, method_name, "cache miss. took #{Kernel.format '%.2f msecs', time * 1_000}")
23
23
  end
@@ -37,33 +37,28 @@ module DbMemoize
37
37
  # product.memoize_values full_title: "my full title",
38
38
  # autocomplete_info: "my autocomplete_info"
39
39
  #
40
- def memoize_values(values, *args)
41
- # [TODO] - when creating many memoized values: should we even support arguments here?
42
- args_hash = Helpers.calculate_arguments_hash(args)
43
-
40
+ # This sets the "full_title" and "autocomplete_info" values of the product.
41
+ #
42
+ def memoize_values(values)
44
43
  values.each do |name, value|
45
- create_memoized_value(name, args_hash, value)
44
+ create_memoized_value(name, value)
46
45
  end
47
46
  end
48
47
 
49
48
  private
50
49
 
51
- def create_memoized_value(method_name, arguments_hash, value)
52
- ::DbMemoize::Value.metal.create! entity_table_name: self.class.table_name,
53
- entity_id: id,
54
- method_name: method_name.to_s,
55
- arguments_hash: arguments_hash,
56
- value: Helpers.marshal(value)
57
-
58
- @association_cache.delete :memoized_values
50
+ def create_memoized_value(method_name, value)
51
+ self.class.transaction do
52
+ ::DbMemoize::Value.fast_create self.class.table_name, id, method_name, value
53
+ @association_cache.delete :memoized_values
54
+ end
59
55
  end
60
56
 
61
- def find_memoized_value(method_name, args_hash)
57
+ def find_memoized_value(method_name)
62
58
  method_name = method_name.to_s
63
59
 
64
60
  memoized_values.detect do |rec|
65
- rec.method_name == method_name &&
66
- rec.arguments_hash == args_hash
61
+ rec.method_name == method_name
67
62
  end
68
63
  end
69
64
 
@@ -93,19 +88,13 @@ module DbMemoize
93
88
  DbMemoize::Value.where(conditions).delete_all_ordered
94
89
  end
95
90
 
96
- def memoize_values(records_or_ids, values, *args)
97
- # [TODO] - when creating many memoized values: should we even support arguments here?
91
+ def memoize_values(records_or_ids, values)
98
92
  transaction do
99
- ids = Helpers.find_ids(records_or_ids)
100
- arguments_hash = Helpers.calculate_arguments_hash(args)
93
+ ids = Helpers.find_ids(records_or_ids)
101
94
 
102
95
  ids.each do |id|
103
96
  values.each do |method_name, value|
104
- ::DbMemoize::Value.metal.create! entity_table_name: table_name,
105
- entity_id: id,
106
- method_name: method_name.to_s,
107
- arguments_hash: arguments_hash,
108
- value: Helpers.marshal(value)
97
+ ::DbMemoize::Value.fast_create table_name, id, method_name, value
109
98
  end
110
99
  end
111
100
  end
@@ -113,14 +102,16 @@ module DbMemoize
113
102
 
114
103
  private
115
104
 
105
+ # rubocop:disable Style/EmptyBlockParameter
116
106
  def create_memoized_alias_method(method_name)
117
- define_method "#{method_name}_with_memoize" do |*args|
118
- memoized_value(method_name, args)
107
+ define_method "#{method_name}_with_memoize" do ||
108
+ memoized_value(method_name)
119
109
  end
120
110
 
121
111
  alias_method_chain method_name, :memoize
122
112
  end
123
113
 
114
+ # rubocop:disable Style/GuardClause
124
115
  def create_memoized_values_association
125
116
  unless reflect_on_association(:memoized_values)
126
117
  conditions = { entity_table_name: table_name }
@@ -1,15 +1,39 @@
1
+ # rubocop:disable Metrics/CyclomaticComplexity
2
+
3
+ require 'simple-sql'
4
+ require 'json'
5
+
1
6
  module DbMemoize
2
7
  class Value < ActiveRecord::Base
3
8
  self.table_name = 'memoized_values'
4
9
 
5
- include DbMemoize::Metal
10
+ SQL = ::Simple::SQL
11
+
12
+ def value=(value)
13
+ self.val_integer = self.val_float = self.val_string = self.val_boolean = self.val_time = nil
14
+
15
+ case value
16
+ when String then self.val_string = value
17
+ when Integer then self.val_integer = value
18
+ when Float then self.val_float = value
19
+ when Time then self.val_time = value
20
+ when false then self.val_boolean = value
21
+ when true then self.val_boolean = value
22
+ when nil then :nop
23
+ end
24
+ end
25
+
26
+ def value
27
+ # Note: val_boolean should come last.
28
+ val_string || val_integer || val_float || val_time || val_object || val_boolean
29
+ end
6
30
 
7
31
  def self.delete_all_ordered
8
32
  relation = self
9
33
  relation = all unless is_a?(ActiveRecord::Relation)
10
34
 
11
35
  sql = relation.select(:ctid).to_sql
12
- connection.execute <<-SQL
36
+ SQL.ask <<-SQL
13
37
  DO $$DECLARE c record;
14
38
  BEGIN
15
39
  FOR c IN #{sql} ORDER BY ctid LOOP
@@ -18,5 +42,36 @@ module DbMemoize
18
42
  END$$;
19
43
  SQL
20
44
  end
45
+
46
+ def self.fast_create(entity_table_name, id, method_name, value)
47
+ method_name = method_name.to_s
48
+
49
+ # clear out old entry (if any). This makes sure that any existing value
50
+ # is cleared out properly.
51
+ SQL.ask "DELETE FROM #{table_name} WHERE(entity_table_name, entity_id, method_name) = ($1, $2, $3)",
52
+ entity_table_name, id, method_name
53
+
54
+ dest_column = case value
55
+ when String then :val_string
56
+ when Integer then :val_integer
57
+ when Float then :val_float
58
+ when Time then :val_time
59
+ when false then :val_boolean
60
+ when nil then :val_nil
61
+ when Hash then :val_object
62
+ when Array then :val_object
63
+ else
64
+ raise "Unsupported value of type #{value.class.name}: #{value.inspect}"
65
+ end
66
+
67
+ value = JSON.generate(value) if dest_column == :val_object
68
+ sql = <<~SQL.freeze
69
+ INSERT INTO #{table_name}
70
+ (entity_table_name, entity_id, method_name, #{dest_column}, created_at)
71
+ VALUES($1,$2,$3,$4,NOW())
72
+ SQL
73
+
74
+ SQL.ask sql, entity_table_name, id, method_name, value
75
+ end
21
76
  end
22
77
  end
@@ -1,3 +1,24 @@
1
1
  module DbMemoize
2
- VERSION = '0.2.3'.freeze
2
+ module GemHelper
3
+ module_function
4
+
5
+ def version(name)
6
+ spec = Gem.loaded_specs[name]
7
+ version = spec.version.to_s
8
+ version += '+unreleased' if unreleased?(spec)
9
+ version
10
+ end
11
+
12
+ private
13
+
14
+ def unreleased?(spec)
15
+ return false unless defined?(Bundler::Source::Gemspec)
16
+ return true if spec.source.is_a?(::Bundler::Source::Gemspec)
17
+ return true if spec.source.is_a?(::Bundler::Source::Path)
18
+
19
+ false
20
+ end
21
+ end
22
+
23
+ VERSION = GemHelper.version 'db_memoize'
3
24
  end
data/scripts/release ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/bash
2
+ $0.rb "$@"
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # -- helpers ------------------------------------------------------------------
4
+
5
+ def sys(cmd)
6
+ STDERR.puts "> #{cmd}"
7
+ system cmd
8
+ return true if $?.success?
9
+
10
+ STDERR.puts "> #{cmd} returned with exitstatus #{$?.exitstatus}"
11
+ $?.success?
12
+ end
13
+
14
+ def sys!(cmd, error: nil)
15
+ return true if sys(cmd)
16
+ STDERR.puts error if error
17
+ exit 1
18
+ end
19
+
20
+ def die!(msg)
21
+ STDERR.puts msg
22
+ exit 1
23
+ end
24
+
25
+ ROOT = File.expand_path("#{File.dirname(__FILE__)}/..")
26
+
27
+ GEMSPEC = Dir.glob("*.gemspec").first || die!("Missing gemspec file.")
28
+
29
+ # -- Version reading and bumping ----------------------------------------------
30
+
31
+ module Version
32
+ extend self
33
+
34
+ VERSION_FILE = "#{Dir.getwd}/VERSION"
35
+
36
+ def read_version
37
+ version = File.exist?(VERSION_FILE) ? File.read(VERSION_FILE) : "0.0.1"
38
+ version.chomp!
39
+ raise "Invalid version number in #{VERSION_FILE}" unless version =~ /^\d+\.\d+\.\d+$/
40
+ version
41
+ end
42
+
43
+ def auto_version_bump
44
+ old_version_number = read_version
45
+ old = old_version_number.split('.')
46
+
47
+ current = old[0..-2] << old[-1].next
48
+ current.join('.')
49
+ end
50
+
51
+ def bump_version
52
+ next_version = ENV["VERSION"] || auto_version_bump
53
+ File.open(VERSION_FILE, "w") { |io| io.write next_version }
54
+ end
55
+ end
56
+
57
+ # -- check, bump, release a new gem version -----------------------------------
58
+
59
+ Dir.chdir ROOT
60
+ $BASE_BRANCH = ENV['BRANCH'] || 'master'
61
+
62
+ # ENV["BUNDLE_GEMFILE"] = "#{Dir.getwd}/Gemfile"
63
+ # sys! "bundle install"
64
+
65
+ sys! "git diff --exit-code > /dev/null", error: 'There are unstaged changes in your working directory'
66
+ sys! "git diff --cached --exit-code > /dev/null", error: 'There are staged but uncommitted changes'
67
+
68
+ sys! "git checkout #{$BASE_BRANCH}"
69
+ sys! "git pull"
70
+
71
+ Version.bump_version
72
+ version = Version.read_version
73
+
74
+ sys! "git add VERSION"
75
+ sys! "git commit -m \"bump gem to v#{version}\""
76
+ sys! "git tag -a v#{version} -m \"Tag #{version}\""
77
+
78
+ sys! "gem build #{GEMSPEC}"
79
+
80
+ sys! "git push origin #{$BASE_BRANCH}"
81
+ sys! 'git push --tags --force'
82
+
83
+ # sys! "bundle exec fury push #{Dir.glob('*.gem').first} --as mediapeers"
84
+ sys! "gem push #{Dir.glob('*.gem').first}"
85
+
86
+ sys! "mkdir -p pkg"
87
+ sys! "mv *.gem pkg"
88
+
89
+ STDERR.puts <<-MSG
90
+ ================================================================================
91
+ Thank you for releasing a new gem version. You made my day.
92
+ ================================================================================
93
+ MSG
metadata CHANGED
@@ -1,31 +1,37 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: db_memoize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - johannes-kostas goetzinger
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-06-30 00:00:00.000000000 Z
11
+ date: 2018-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: railties
14
+ name: simple-sql
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.4.20
17
20
  - - "~>"
18
21
  - !ruby/object:Gem::Version
19
- version: '4.2'
20
- type: :development
22
+ version: '0'
23
+ type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.4.20
24
30
  - - "~>"
25
31
  - !ruby/object:Gem::Version
26
- version: '4.2'
32
+ version: '0'
27
33
  - !ruby/object:Gem::Dependency
28
- name: activerecord
34
+ name: railties
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - "~>"
@@ -39,117 +45,89 @@ dependencies:
39
45
  - !ruby/object:Gem::Version
40
46
  version: '4.2'
41
47
  - !ruby/object:Gem::Dependency
42
- name: rake
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '10.5'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '10.5'
55
- - !ruby/object:Gem::Dependency
56
- name: pg
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: rspec-rails
48
+ name: activerecord
71
49
  requirement: !ruby/object:Gem::Requirement
72
50
  requirements:
73
51
  - - "~>"
74
52
  - !ruby/object:Gem::Version
75
- version: '3.4'
53
+ version: 4.2.10
76
54
  type: :development
77
55
  prerelease: false
78
56
  version_requirements: !ruby/object:Gem::Requirement
79
57
  requirements:
80
58
  - - "~>"
81
59
  - !ruby/object:Gem::Version
82
- version: '3.4'
60
+ version: 4.2.10
83
61
  - !ruby/object:Gem::Dependency
84
- name: pry
62
+ name: rake
85
63
  requirement: !ruby/object:Gem::Requirement
86
64
  requirements:
87
65
  - - "~>"
88
66
  - !ruby/object:Gem::Version
89
- version: '0.10'
67
+ version: '12.0'
90
68
  type: :development
91
69
  prerelease: false
92
70
  version_requirements: !ruby/object:Gem::Requirement
93
71
  requirements:
94
72
  - - "~>"
95
73
  - !ruby/object:Gem::Version
96
- version: '0.10'
74
+ version: '12.0'
97
75
  - !ruby/object:Gem::Dependency
98
- name: pry-byebug
76
+ name: pg
99
77
  requirement: !ruby/object:Gem::Requirement
100
78
  requirements:
101
79
  - - "~>"
102
80
  - !ruby/object:Gem::Version
103
- version: '2.0'
81
+ version: '0.20'
104
82
  type: :development
105
83
  prerelease: false
106
84
  version_requirements: !ruby/object:Gem::Requirement
107
85
  requirements:
108
86
  - - "~>"
109
87
  - !ruby/object:Gem::Version
110
- version: '2.0'
88
+ version: '0.20'
111
89
  - !ruby/object:Gem::Dependency
112
- name: yard
90
+ name: rspec
113
91
  requirement: !ruby/object:Gem::Requirement
114
92
  requirements:
115
93
  - - "~>"
116
94
  - !ruby/object:Gem::Version
117
- version: '0'
95
+ version: '3.8'
118
96
  type: :development
119
97
  prerelease: false
120
98
  version_requirements: !ruby/object:Gem::Requirement
121
99
  requirements:
122
100
  - - "~>"
123
101
  - !ruby/object:Gem::Version
124
- version: '0'
102
+ version: '3.8'
125
103
  - !ruby/object:Gem::Dependency
126
104
  name: simplecov
127
105
  requirement: !ruby/object:Gem::Requirement
128
106
  requirements:
129
107
  - - "~>"
130
108
  - !ruby/object:Gem::Version
131
- version: 0.7.1
109
+ version: '0.16'
132
110
  type: :development
133
111
  prerelease: false
134
112
  version_requirements: !ruby/object:Gem::Requirement
135
113
  requirements:
136
114
  - - "~>"
137
115
  - !ruby/object:Gem::Version
138
- version: 0.7.1
116
+ version: '0.16'
139
117
  - !ruby/object:Gem::Dependency
140
118
  name: rubocop
141
119
  requirement: !ruby/object:Gem::Requirement
142
120
  requirements:
143
121
  - - "~>"
144
122
  - !ruby/object:Gem::Version
145
- version: 0.37.2
123
+ version: 0.59.2
146
124
  type: :development
147
125
  prerelease: false
148
126
  version_requirements: !ruby/object:Gem::Requirement
149
127
  requirements:
150
128
  - - "~>"
151
129
  - !ruby/object:Gem::Version
152
- version: 0.37.2
130
+ version: 0.59.2
153
131
  - !ruby/object:Gem::Dependency
154
132
  name: database_cleaner
155
133
  requirement: !ruby/object:Gem::Requirement
@@ -178,48 +156,6 @@ dependencies:
178
156
  - - "~>"
179
157
  - !ruby/object:Gem::Version
180
158
  version: 4.7.0
181
- - !ruby/object:Gem::Dependency
182
- name: ruby-progressbar
183
- requirement: !ruby/object:Gem::Requirement
184
- requirements:
185
- - - "~>"
186
- - !ruby/object:Gem::Version
187
- version: '1.7'
188
- type: :development
189
- prerelease: false
190
- version_requirements: !ruby/object:Gem::Requirement
191
- requirements:
192
- - - "~>"
193
- - !ruby/object:Gem::Version
194
- version: '1.7'
195
- - !ruby/object:Gem::Dependency
196
- name: awesome_print
197
- requirement: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - ">="
200
- - !ruby/object:Gem::Version
201
- version: '0'
202
- type: :development
203
- prerelease: false
204
- version_requirements: !ruby/object:Gem::Requirement
205
- requirements:
206
- - - ">="
207
- - !ruby/object:Gem::Version
208
- version: '0'
209
- - !ruby/object:Gem::Dependency
210
- name: gem-release
211
- requirement: !ruby/object:Gem::Requirement
212
- requirements:
213
- - - ">="
214
- - !ruby/object:Gem::Version
215
- version: '0'
216
- type: :development
217
- prerelease: false
218
- version_requirements: !ruby/object:Gem::Requirement
219
- requirements:
220
- - - ">="
221
- - !ruby/object:Gem::Version
222
- version: '0'
223
159
  description: library to cache (memoize) method return values in database
224
160
  email:
225
161
  - goetzinger@mediapeers.com
@@ -235,12 +171,15 @@ files:
235
171
  - LICENSE
236
172
  - README.md
237
173
  - Rakefile
174
+ - VERSION
238
175
  - bin/console
176
+ - bin/rake
177
+ - bin/rspec
178
+ - bin/rubocop
239
179
  - bin/setup
240
180
  - db_memoize.gemspec
241
181
  - lib/db_memoize.rb
242
182
  - lib/db_memoize/helpers.rb
243
- - lib/db_memoize/metal.rb
244
183
  - lib/db_memoize/migrations.rb
245
184
  - lib/db_memoize/model.rb
246
185
  - lib/db_memoize/railtie.rb
@@ -249,6 +188,8 @@ files:
249
188
  - lib/tasks/clear.rake
250
189
  - lib/tasks/warmup.rake
251
190
  - log/.keep
191
+ - scripts/release
192
+ - scripts/release.rb
252
193
  homepage: https://github.com/mediapeers/db_memoize
253
194
  licenses:
254
195
  - MIT
@@ -269,7 +210,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
269
210
  version: '0'
270
211
  requirements: []
271
212
  rubyforge_project:
272
- rubygems_version: 2.5.1
213
+ rubygems_version: 2.7.7
273
214
  signing_key:
274
215
  specification_version: 4
275
216
  summary: library to cache (memoize) method return values in database
@@ -1,127 +0,0 @@
1
- module DbMemoize
2
- module Metal
3
- def self.included(base)
4
- base.extend ClassMethods
5
- # base.metal # initialize the metal adapter
6
- end
7
-
8
- module ClassMethods
9
- def metal
10
- @metal ||= Adapter.new(self)
11
- end
12
- end
13
-
14
- class Adapter
15
- class PkInfo
16
- attr_reader :column, :type
17
-
18
- def initialize(base_klass)
19
- @column = base_klass.primary_key
20
- @type = @column && base_klass.columns_hash.fetch(@column).type
21
- end
22
- end
23
-
24
- def initialize(base_klass)
25
- @base_klass = base_klass
26
- @query_cache = {}
27
- end
28
-
29
- private
30
-
31
- # setup primary key information. This is necessary to allow the create! method
32
- # to return the primary key of a newly created entry.
33
- def primary_key
34
- @primary_key ||= PkInfo.new(@base_klass)
35
- end
36
-
37
- def table_name
38
- @base_klass.table_name
39
- end
40
-
41
- def raw_connection
42
- @base_klass.connection.raw_connection # do not memoize me!
43
- end
44
-
45
- def column?(column_name)
46
- @base_klass.columns_hash.key?(column_name)
47
- end
48
-
49
- class Inserter
50
- def initialize(sql:, bytea_indices:)
51
- @sql = sql
52
- @bytea_indices = bytea_indices
53
- end
54
-
55
- def exec(raw_connection:, values:)
56
- @bytea_indices.each do |bytea_index|
57
- value = values[bytea_index]
58
- values[bytea_index] = PGconn.escape_bytea(value) if value
59
- end
60
-
61
- raw_connection.exec_params(@sql, values)
62
- end
63
- end
64
-
65
- # returns an Inserter
66
- def inserter(field_names)
67
- @query_cache[field_names] ||= _inserter(field_names)
68
- end
69
-
70
- DATABASE_IDENTIFIER_REGEX = /\A\w+\z/
71
-
72
- def check_database_identifiers!(*strings)
73
- strings.each do |s|
74
- next if DATABASE_IDENTIFIER_REGEX =~ s
75
- raise ArgumentError, "Invalid database identifier: #{s.inspect}"
76
- end
77
- end
78
-
79
- def _inserter(field_names)
80
- check_database_identifiers! table_name, *field_names
81
-
82
- placeholders = 0.upto(field_names.count - 1).map { |idx| "$#{idx + 1}" }
83
-
84
- if column?('created_at')
85
- field_names << 'created_at'
86
- placeholders << 'current_timestamp'
87
- end
88
-
89
- if column?('updated_at')
90
- field_names << 'updated_at'
91
- placeholders << 'current_timestamp'
92
- end
93
-
94
- sql = "INSERT INTO #{table_name} (#{field_names.join(',')}) VALUES(#{placeholders.join(',')})"
95
- sql += " RETURNING #{primary_key.column}" if primary_key.column
96
-
97
- columns_hash = @base_klass.columns_hash
98
- bytea_indices = []
99
- field_names.each_with_index { |column, idx|
100
- next unless :binary == columns_hash.fetch(column).type
101
- bytea_indices << idx
102
- }
103
-
104
- Inserter.new sql: sql, bytea_indices: bytea_indices
105
- end
106
-
107
- public
108
-
109
- def create!(record)
110
- keys, values = record.to_a.transpose
111
- keys = keys.map(&:to_s)
112
-
113
- result = inserter(keys).exec(raw_connection: raw_connection, values: values)
114
-
115
- # if we don't have an ID column then the sql does not return any value. The result
116
- # object would be this: #<PG::Result status=PGRES_COMMAND_OK ntuples=0 nfields=0 cmd_tuples=1>
117
- # we just return nil in that case; otherwise we return the first entry of the first result row
118
- # which would be the stringified id.
119
- first_row = result.each_row.first
120
- return nil unless first_row
121
-
122
- id = first_row.first
123
- primary_key.type == :integer ? Integer(id) : id
124
- end
125
- end
126
- end
127
- end