izolenta 0.0.3 → 0.0.6

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
2
  SHA256:
3
- metadata.gz: '09bc2895fc70a6c50727f81242f0f06e90c4492d3c1193ba4e1a1bffb83599ec'
4
- data.tar.gz: 14d8e61fbd7bb788b05054274418d14b55e18117fc5793d5f0b4a67af1e85a41
3
+ metadata.gz: fd520ce5cefeee28f6985c56bc36b29f102dfdb5972ee736d6cabd11928139b9
4
+ data.tar.gz: 8e3e5acc0b8d853e9f78a9a8b1bc25e3e08836c506e0787fdb465420700f81fd
5
5
  SHA512:
6
- metadata.gz: 1d3fdb8446cd4698487c397bb7c8de99cdf1a44b911d84ce218c76d46f4aa98adc922813abfbbb231ad612bb0430137a538555d4620f77e813e2ac19e39c2d56
7
- data.tar.gz: c9dc6ef925404436a15358c07a1c7a640f593a02f12fae1448b8b6429063c07629768e0f8f45dc78e44367ab482ade23bd53a5e5be926cf1f23d53910f13d62d
6
+ metadata.gz: d63396b28549ecde16b8e810c3c667c2a0245ee6fdce41cc9f1239abd5ebbad50e9b22a71780bf3b73ee7911bedd865e2d4f9315af6541ca226d5891b57f5dde
7
+ data.tar.gz: 8713a4d8039f843fe4d5eb9487a1dcf54146e83bc09564383a1673407034de28b3e1d6469b349dcf44ec23ca2f9b4a77b6d5d0dff23cc3828d87bd30fe25c9c6
data/.rubocop.yml ADDED
@@ -0,0 +1,92 @@
1
+ inherit_gem:
2
+ rubocop-shopify: rubocop.yml
3
+ #
4
+ #Style/SingleLineMethods:
5
+ # Description: 'Avoid single-line methods.'
6
+ # StyleGuide: '#no-single-line-methods'
7
+ # Enabled: false
8
+ # VersionAdded: '0.9'
9
+ # VersionChanged: '1.8'
10
+ # AllowIfMethodIsEmpty: true
11
+ #
12
+ #Style/AsciiComments:
13
+ # Description: 'Use only ascii symbols in comments.'
14
+ # StyleGuide: '#english-comments'
15
+ # Enabled: false
16
+ # VersionAdded: '0.9'
17
+ # VersionChanged: '1.21'
18
+ # AllowedChars:
19
+ # - ©
20
+ #
21
+ #Layout/LineLength:
22
+ # Description: 'Checks that line length does not exceed the configured limit.'
23
+ # StyleGuide: '#max-line-length'
24
+ # Enabled: true
25
+ # VersionAdded: '0.25'
26
+ # VersionChanged: '1.4'
27
+ # Max: 120
28
+ # # To make it possible to copy or click on URIs in the code, we allow lines
29
+ # # containing a URI to be longer than Max.
30
+ # AllowHeredoc: true
31
+ # AllowURI: true
32
+ # URISchemes:
33
+ # - http
34
+ # - https
35
+ # # The IgnoreCopDirectives option causes the LineLength rule to ignore cop
36
+ # # directives like '# rubocop: enable ...' when calculating a line's length.
37
+ # IgnoreCopDirectives: true
38
+ # # The AllowedPatterns option is a list of !ruby/regexp and/or string
39
+ # # elements. Strings will be converted to Regexp objects. A line that matches
40
+ # # any regular expression listed in this option will be ignored by LineLength.
41
+ # AllowedPatterns: []
42
+ # IgnoredPatterns: [] # deprecated
43
+ # Exclude:
44
+ # - "./test/**/**/*"
45
+ #
46
+ #Metrics/ClassLength:
47
+ # Description: 'Avoid classes longer than 100 lines of code.'
48
+ # Enabled: false
49
+ # VersionAdded: '0.25'
50
+ # VersionChanged: '0.87'
51
+ # CountComments: false # count full line comments?
52
+ # Max: 100
53
+ # CountAsOne: []
54
+ #
55
+ #Lint/MissingCopEnableDirective:
56
+ # Description: 'Checks for a `# rubocop:enable` after `# rubocop:disable`.'
57
+ # Enabled: true
58
+ # VersionAdded: '0.52'
59
+ # # Maximum number of consecutive lines the cop can be disabled for.
60
+ # # 0 allows only single-line disables
61
+ # # 1 would mean the maximum allowed is the following:
62
+ # # # rubocop:disable SomeCop
63
+ # # a = 1
64
+ # # # rubocop:enable SomeCop
65
+ # # .inf for any size
66
+ # MaximumRangeSize: .inf
67
+ #
68
+ #Style/MethodCallWithArgsParentheses:
69
+ # Enabled: true
70
+ # IgnoredMethods:
71
+ # - require
72
+ # - require_relative
73
+ # - require_dependency
74
+ # - yield
75
+ # - raise
76
+ # - puts
77
+ # Exclude:
78
+ # - "/**/Gemfile"
79
+ # - "./db/**/*"
80
+ #
81
+ #Layout/EmptyLinesAroundBlockBody:
82
+ # # its more documentation than code, so it should be readable and
83
+ # # there are huge amount of multiline description, looks nasty without spaces
84
+ # Exclude:
85
+ # - "./app_doc/**/*"
86
+ #
87
+ #Style/ClassAndModuleChildren:
88
+ # Enabled: false
89
+ #
90
+ #Lint/UnderscorePrefixedVariableName:
91
+ # Exclude:
92
+ # - "./test/**/**/*"
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
+ #0.0.6
2
+ - new ruby 3 image for ruby 3 testing
3
+ - fix get_new_column_type incompatibility with ruby
4
+
5
+ #0.0.5
6
+ - rubocop-shopify added to dev dependencies
7
+ - fixed ruby 3.0 incompatibility in delegate_uniqueness, now gem could be used with ruby 3+
8
+
9
+ #0.0.4
10
+ - removed 'OR REPLACE' in trigger definition, lowering Postgres version constraint
11
+ - trigger_condition added ( could replace partial uniq index )
12
+
1
13
  #0.0.3
2
14
  - wrapper_function options added, you can define function to convert to uniquely sortable types, for instance array to string
15
+ - moved all helper functions to internal module, just to keep things clear on the migrations
3
16
 
4
17
  #0.0.2
5
18
  - delegate_uniqueness helper is available as a migration method
data/Gemfile CHANGED
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source "https://rubygems.org"
2
4
 
3
5
  # Specify your gem's dependencies in izolenta.gemspec
4
6
  gemspec
5
7
 
6
- gem "rake", "~> 12.0"
7
8
  gem "minitest", "~> 5.0"
9
+ gem "rake", "~> 12.0"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- izolenta (0.0.2)
4
+ izolenta (0.0.5)
5
5
  pg
6
6
 
7
7
  GEM
@@ -18,18 +18,41 @@ GEM
18
18
  minitest (>= 5.1)
19
19
  tzinfo (~> 2.0)
20
20
  zeitwerk (~> 2.3)
21
+ ast (2.4.2)
21
22
  byebug (11.1.3)
22
23
  coderay (1.1.3)
23
24
  concurrent-ruby (1.1.9)
24
25
  i18n (1.8.11)
25
26
  concurrent-ruby (~> 1.0)
27
+ json (2.6.2)
26
28
  method_source (1.0.0)
27
29
  minitest (5.14.4)
28
- pg (1.2.3)
30
+ parallel (1.22.1)
31
+ parser (3.1.2.0)
32
+ ast (~> 2.4.1)
33
+ pg (1.4.1)
29
34
  pry (0.13.1)
30
35
  coderay (~> 1.1)
31
36
  method_source (~> 1.0)
37
+ rainbow (3.1.1)
32
38
  rake (12.3.3)
39
+ regexp_parser (2.5.0)
40
+ rexml (3.2.5)
41
+ rubocop (1.31.2)
42
+ json (~> 2.3)
43
+ parallel (~> 1.10)
44
+ parser (>= 3.1.0.0)
45
+ rainbow (>= 2.2.2, < 4.0)
46
+ regexp_parser (>= 1.8, < 3.0)
47
+ rexml (>= 3.2.5, < 4.0)
48
+ rubocop-ast (>= 1.18.0, < 2.0)
49
+ ruby-progressbar (~> 1.7)
50
+ unicode-display_width (>= 1.4.0, < 3.0)
51
+ rubocop-ast (1.18.0)
52
+ parser (>= 3.1.1.0)
53
+ rubocop-shopify (2.8.0)
54
+ rubocop (~> 1.31)
55
+ ruby-progressbar (1.11.0)
33
56
  ruby_jard (0.3.1)
34
57
  byebug (>= 9.1, < 12.0)
35
58
  pry (~> 0.13.0)
@@ -37,6 +60,7 @@ GEM
37
60
  tty-screen (0.8.1)
38
61
  tzinfo (2.0.4)
39
62
  concurrent-ruby (~> 1.0)
63
+ unicode-display_width (2.2.0)
40
64
  zeitwerk (2.5.1)
41
65
 
42
66
  PLATFORMS
@@ -47,6 +71,8 @@ DEPENDENCIES
47
71
  izolenta!
48
72
  minitest (~> 5.0)
49
73
  rake (~> 12.0)
74
+ rubocop
75
+ rubocop-shopify
50
76
  ruby_jard
51
77
 
52
78
  BUNDLED WITH
data/README.md CHANGED
@@ -46,6 +46,15 @@ class WithWrapperFunctionMigration < ActiveRecord::Migration[5.0]
46
46
  delegate_uniqueness( :your_table_name, :column_name, wrapper_function: 'type_conversion_function' )
47
47
  end
48
48
  end
49
+
50
+
51
+ class WithWrapperFunctionMigration < ActiveRecord::Migration[5.0]
52
+ # apply trigger condition for partial uniqueness
53
+ def change
54
+ delegate_uniqueness( :your_table_name, :column_name, trigger_condition: 'NEW.type IS NOT NULL' )
55
+ end
56
+ end
57
+
49
58
  ```
50
59
 
51
60
  ## Development
@@ -55,6 +64,9 @@ docker-compose build
55
64
 
56
65
  docker-compose run test /bin/bash
57
66
  > service postgresql start && rake test
67
+
68
+ docker-compose run test3 /bin/bash
69
+ > service postgresql start && rake test
58
70
  ```
59
71
 
60
72
  ## Future Features
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rake/testtask"
3
5
 
@@ -7,4 +9,4 @@ Rake::TestTask.new(:test) do |t|
7
9
  t.test_files = FileList["test/**/*_test.rb"]
8
10
  end
9
11
 
10
- task :default => :test
12
+ task default: :test
data/docker-compose.yml CHANGED
@@ -8,3 +8,11 @@ services:
8
8
  volumes:
9
9
  - '.:/app'
10
10
 
11
+ test3:
12
+ build:
13
+ context: .
14
+ dockerfile: ruby3.Dockerfile
15
+ image: izolenta3
16
+ command: service postgresql start && rake test
17
+ volumes:
18
+ - '.:/app'
data/izolenta.gemspec CHANGED
@@ -1,4 +1,6 @@
1
- require_relative 'lib/izolenta/version'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/izolenta/version"
2
4
 
3
5
  Gem::Specification.new do |spec|
4
6
  spec.name = "izolenta"
@@ -6,8 +8,8 @@ Gem::Specification.new do |spec|
6
8
  spec.authors = ["alekseyl"]
7
9
  spec.email = ["leshchuk@gmail.com"]
8
10
 
9
- spec.summary = %q{Migration helpers for delegated uniqueness in Postgres}
10
- spec.description = %q{Migration helpers for delegated uniqueness in Postgres}
11
+ spec.summary = "Migration helpers for delegated uniqueness in Postgres"
12
+ spec.description = "Migration helpers for delegated uniqueness in Postgres"
11
13
  spec.homepage = "https://github.com/alekseyl/izolenta"
12
14
  spec.license = "MIT"
13
15
  spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
@@ -20,14 +22,15 @@ Gem::Specification.new do |spec|
20
22
 
21
23
  # Specify which files should be added to the gem when it is released.
22
24
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
24
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
26
+ %x(git ls-files -z).split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
27
  end
26
28
  spec.bindir = "exe"
27
29
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
30
  spec.require_paths = ["lib"]
29
31
 
30
- spec.add_dependency "pg"
31
- spec.add_development_dependency "activerecord", ">= 5"
32
- spec.add_development_dependency "ruby_jard"
32
+ spec.add_dependency("pg")
33
+ spec.add_development_dependency("activerecord", ">= 5")
34
+ spec.add_development_dependency("rubocop-shopify")
35
+ spec.add_development_dependency("ruby_jard")
33
36
  end
@@ -1,71 +1,86 @@
1
- module Izolenta::ActiveRecordMigration
2
- # options:
3
- # wrapper_function: 'some_func' # some_func should be defined prior
4
- def delegate_uniqueness(origin_table, column, options = {})
5
- helper_table_name = "#{column}_#{origin_table}_uniqs"
1
+ # frozen_string_literal: true
6
2
 
7
- reversible do |dir|
8
- dir.up {
9
- Helpers.create_helper_table(helper_table_name, column, Helpers.get_new_column_type(origin_table, column, options))
10
- add_index( helper_table_name, column, unique: true )
3
+ if defined? ActiveRecord
4
+ module Izolenta
5
+ module ActiveRecordMigration
6
+ # options:
7
+ # wrapper_function: 'some_func' # some_func should be defined prior
8
+ def delegate_uniqueness(origin_table, column, **options)
9
+ helper_table_name = "#{column}_#{origin_table}_uniqs"
11
10
 
12
- Helpers.create_sync_trigger( origin_table, column, helper_table_name, options )
13
- }
11
+ reversible do |dir|
12
+ dir.up do
13
+ Helpers.create_helper_table(helper_table_name, column,
14
+ Helpers.get_new_column_type(origin_table, column, **options))
15
+ add_index(helper_table_name, column, unique: true)
14
16
 
15
- dir.down {
16
- drop_table( helper_table_name )
17
- Helpers.drop_sync_trigger( origin_table, column )
18
- }
19
- end
20
- end
17
+ Helpers.create_sync_trigger(origin_table, column, helper_table_name, options)
18
+ end
21
19
 
22
- module Helpers
23
- class << self
24
- def create_helper_table(helper_table, column_name, column_type )
25
- ActiveRecord::Base.connection.execute "CREATE TABLE #{helper_table} ( #{column_name} #{column_type} );"
20
+ dir.down do
21
+ drop_table(helper_table_name)
22
+ Helpers.drop_sync_trigger(origin_table, column)
23
+ end
24
+ end
26
25
  end
27
26
 
28
- def create_sync_trigger(table, column_name, helper_table_name, options )
29
- trg_name = "#{table}_#{column_name}_trg"
30
- insert_value = options[:wrapper_function] ? "#{options[:wrapper_function]}(NEW.#{column_name})"
31
- : "NEW.#{column_name}"
32
- ActiveRecord::Base.connection.execute <<~SYNC_TRIGGER
33
- CREATE OR REPLACE FUNCTION #{trg_name}() RETURNS trigger AS $$
34
- BEGIN
35
- INSERT INTO #{helper_table_name} VALUES ( #{insert_value} );
36
- RETURN NEW;
37
- END $$ LANGUAGE plpgSQL;
38
-
39
- CREATE OR REPLACE TRIGGER #{trg_name} BEFORE INSERT ON #{table} FOR EACH ROW
40
- EXECUTE FUNCTION #{trg_name}();
41
- SYNC_TRIGGER
42
- end
27
+ # helpers na
28
+ module Helpers
29
+ class << self
30
+ def create_helper_table(helper_table, column_name, column_type)
31
+ ActiveRecord::Base.connection.execute("CREATE TABLE #{helper_table} ( #{column_name} #{column_type} );")
32
+ end
43
33
 
44
- def drop_sync_trigger(table, column_name)
45
- trg_name = "#{table}_#{column_name}_trg"
34
+ def create_sync_trigger(table, column_name, helper_table_name, options)
35
+ trg_name = "#{table}_#{column_name}_trg"
36
+ insert_value = if options[:wrapper_function]
37
+ "#{options[:wrapper_function]}(NEW.#{column_name})"
38
+ else
39
+ "NEW.#{column_name}"
40
+ end
46
41
 
47
- ActiveRecord::Base.connection.execute <<~SYNC_TRIGGER
48
- DROP TRIGGER IF EXISTS #{trg_name} ON #{table};
49
- SYNC_TRIGGER
50
- end
42
+ trigger_condition = "WHEN( #{options[:trigger_condition]} )" if options[:trigger_condition]
51
43
 
52
- def get_new_column_type(origin_table, column, wrapper_function: nil)
53
- wrapper_function ? get_function_type(wrapper_function) : get_column_type(origin_table, column)
54
- end
44
+ ActiveRecord::Base.connection.execute(<<~SYNC_TRIGGER)
45
+ CREATE OR REPLACE FUNCTION #{trg_name}() RETURNS trigger AS $$
46
+ BEGIN#{" "}
47
+ INSERT INTO #{helper_table_name} VALUES ( #{insert_value} );
48
+ RETURN NEW;
49
+ END $$ LANGUAGE plpgSQL;
55
50
 
56
- def get_column_type(origin_table, column)
57
- ActiveRecord::Base.connection.schema_cache.columns_hash(origin_table.to_s)[column.to_s]&.sql_type
58
- end
51
+ CREATE TRIGGER #{trg_name} BEFORE INSERT ON #{table}#{" "}
52
+ FOR EACH ROW
53
+ #{trigger_condition}
54
+ EXECUTE FUNCTION #{trg_name}();
55
+ SYNC_TRIGGER
56
+ end
59
57
 
60
- def get_function_type(wrapper_function)
61
- ActiveRecord::Base
62
- .connection
63
- .execute("SELECT typname FROM pg_type WHERE oid=(SELECT prorettype FROM pg_proc WHERE proname ='#{wrapper_function}')")
64
- .first['typname']
58
+ def drop_sync_trigger(table, column_name)
59
+ trg_name = "#{table}_#{column_name}_trg"
60
+
61
+ ActiveRecord::Base.connection.execute(<<~SYNC_TRIGGER)
62
+ DROP TRIGGER IF EXISTS #{trg_name} ON #{table};
63
+ SYNC_TRIGGER
64
+ end
65
+
66
+ def get_new_column_type(origin_table, column, wrapper_function: nil, **)
67
+ wrapper_function ? get_function_type(wrapper_function) : get_column_type(origin_table, column)
68
+ end
69
+
70
+ def get_column_type(origin_table, column)
71
+ ActiveRecord::Base.connection.schema_cache.columns_hash(origin_table.to_s)[column.to_s]&.sql_type
72
+ end
73
+
74
+ def get_function_type(wrapper_function)
75
+ ActiveRecord::Base
76
+ .connection
77
+ .execute("SELECT typname FROM pg_type WHERE oid=(SELECT prorettype FROM pg_proc WHERE proname ='#{wrapper_function}')") # rubocop:disable Layout/LineLength
78
+ .first["typname"]
79
+ end
80
+ end
65
81
  end
66
82
  end
67
83
  end
84
+ end
68
85
 
69
- end if defined? ActiveRecord
70
-
71
- ActiveRecord::Migration.include(Izolenta::ActiveRecordMigration) if defined? ActiveRecord
86
+ ActiveRecord::Migration.include(Izolenta::ActiveRecordMigration) if defined? ActiveRecord
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Izolenta
2
- VERSION = "0.0.3"
4
+ VERSION = "0.0.6"
3
5
  end
data/lib/izolenta.rb CHANGED
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "izolenta/version"
2
- require 'izolenta/active_record_migration'
4
+ require "izolenta/active_record_migration"
3
5
 
4
6
  module Izolenta
5
7
  class Error < StandardError; end
data/ruby3.Dockerfile ADDED
@@ -0,0 +1,20 @@
1
+ FROM ruby:3-bullseye
2
+
3
+ WORKDIR /app
4
+ RUN apt-get update && apt-get -y install lsb-release
5
+ #
6
+ RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && \
7
+ sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && \
8
+ apt-get update && apt-get -y install postgresql postgresql-client-12
9
+
10
+ RUN sh -c 'echo "local all all trust" > /etc/postgresql/14/main/pg_hba.conf' && \
11
+ service postgresql start && \
12
+ psql -U postgres -c 'CREATE DATABASE "izolenta-test"'
13
+
14
+ RUN gem install bundler
15
+
16
+ COPY lib/izolenta/version.rb /app/lib/izolenta/version.rb
17
+ COPY izolenta.gemspec /app/
18
+ COPY Gemfil* /app/
19
+ #
20
+ RUN bundle install
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: izolenta
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - alekseyl
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-12-24 00:00:00.000000000 Z
11
+ date: 2022-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop-shopify
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: ruby_jard
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -60,6 +74,7 @@ extensions: []
60
74
  extra_rdoc_files: []
61
75
  files:
62
76
  - ".gitignore"
77
+ - ".rubocop.yml"
63
78
  - ".ruby-gemset"
64
79
  - ".ruby-version"
65
80
  - ".travis.yml"
@@ -77,6 +92,7 @@ files:
77
92
  - lib/izolenta.rb
78
93
  - lib/izolenta/active_record_migration.rb
79
94
  - lib/izolenta/version.rb
95
+ - ruby3.Dockerfile
80
96
  homepage: https://github.com/alekseyl/izolenta
81
97
  licenses:
82
98
  - MIT