spbtv_code_style 1.5.0 → 1.6.0

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
  SHA1:
3
- metadata.gz: 57082afb7d19156a7145046e3989e8e73189751c
4
- data.tar.gz: defc7bcedc0a0d240e8cb8d700e801c167b2088f
3
+ metadata.gz: 0de24f59699801bfff09af903c583958f4b3c755
4
+ data.tar.gz: 197af631ec792872175430b8c7ccfe1dfacdb1a2
5
5
  SHA512:
6
- metadata.gz: 8156435a9f0fe302f9be4315edc4282af427b4553b78eaa5ef6cfe7cb5c9ff6b0e74477df5787f671b1b22a5f56f04d6fd5212fc250b9376f0709d8ce1e6ae74
7
- data.tar.gz: 75c97c92314ead99f81655fc8490ee4528e81714ba1660d6863412babf4ce272bfc3c441de76b2df6bb5467b3f00823b6a5f6b721d9541b050292ab71d7a6387
6
+ metadata.gz: 0abe4066eb2bb1c5ef46f06f721d97d2d0f3b771533e5feb483f6d00a9fea89c16b3dd1c28d6c2da4d6ef573df3e0f21161a72d69f4f3a566fc4b0edf765b5b7
7
+ data.tar.gz: 259dfdec5f01c3632aef02bec2f6445dbcd2120c310e2ec59177107a0d33e72b212a29bd95a7ac2eedb6c222416a0c3637ea62b5ca3222717e026a8b2394132e
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.rubocop.yml CHANGED
@@ -1,3 +1,11 @@
1
+ require:
2
+ - rubocop-rspec
3
+ - ./lib/rubocop/cop/spbtv/postgres/add_column_with_default
4
+ - ./lib/rubocop/cop/spbtv/postgres/add_column_with_not_null
5
+ - ./lib/rubocop/cop/spbtv/postgres/add_index
6
+ - ./lib/rubocop/cop/spbtv/postgres/change_column
7
+ - ./lib/rubocop/cop/spbtv/multiple_validation
8
+
1
9
  Rails:
2
10
  Enabled: true
3
11
 
@@ -29,9 +37,6 @@ Style/Next:
29
37
  Style/GuardClause:
30
38
  Enabled: false
31
39
 
32
- Metrics/LineLength:
33
- Max: 120
34
-
35
40
  Style/TrivialAccessors:
36
41
  AllowPredicates: true
37
42
 
@@ -41,6 +46,11 @@ Style/IfUnlessModifier:
41
46
  Style/EmptyCaseCondition:
42
47
  Enabled: false
43
48
 
49
+ Metrics/ClassLength:
50
+ Severity: refactor
51
+ Exclude:
52
+ - '**/db/**/*'
53
+
44
54
  Metrics/AbcSize:
45
55
  Severity: refactor
46
56
 
@@ -50,8 +60,18 @@ Metrics/PerceivedComplexity:
50
60
  Metrics/ParameterLists:
51
61
  Severity: refactor
52
62
 
63
+ Metrics/LineLength:
64
+ Max: 120
65
+
66
+ Metrics/AbcSize:
67
+ Severity: refactor
68
+ Exclude:
69
+ - '**/db/**/*'
70
+
53
71
  Metrics/MethodLength:
54
72
  Severity: refactor
73
+ Exclude:
74
+ - '**/db/**/*'
55
75
 
56
76
  Metrics/CyclomaticComplexity:
57
77
  Severity: refactor
@@ -76,3 +96,33 @@ Style/TrailingCommaInLiteral:
76
96
 
77
97
  Style/TrailingCommaInArguments:
78
98
  EnforcedStyleForMultiline: comma
99
+
100
+ Postgres/AddColumnWithDefault:
101
+ Exclude:
102
+ - '**/db/migrate/2015*'
103
+ - '**/db/migrate/20160*'
104
+ - '**/db/migrate/201610*'
105
+
106
+ Postgres/AddColumnWithNotNull:
107
+ Exclude:
108
+ - '**/db/migrate/2015*'
109
+ - '**/db/migrate/20160*'
110
+ - '**/db/migrate/201610*'
111
+
112
+ Postgres/AddIndex:
113
+ Exclude:
114
+ - '**/db/migrate/2015*'
115
+ - '**/db/migrate/20160*'
116
+ - '**/db/migrate/201610*'
117
+
118
+ Postgres/ChangeColumn:
119
+ Exclude:
120
+ - '**/db/migrate/2015*'
121
+ - '**/db/migrate/20160*'
122
+ - '**/db/migrate/201610*'
123
+
124
+ Rails/NotNullColumn:
125
+ Enabled: false
126
+
127
+ RSpec/MultipleExpectations:
128
+ Max: 3
data/.strict_rubocop.yml CHANGED
@@ -3,6 +3,8 @@ inherit_from:
3
3
 
4
4
  Metrics/AbcSize:
5
5
  Severity: warning
6
+ Exclude:
7
+ - '**/db/**/*'
6
8
 
7
9
  Metrics/PerceivedComplexity:
8
10
  Severity: warning
@@ -12,6 +14,8 @@ Metrics/ParameterLists:
12
14
 
13
15
  Metrics/MethodLength:
14
16
  Severity: warning
17
+ Exclude:
18
+ - '**/db/**/*'
15
19
 
16
20
  Metrics/CyclomaticComplexity:
17
21
  Severity: warning
data/.travis.yml CHANGED
@@ -1,7 +1,6 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.1.5
5
4
  - 2.2.2
6
5
  - 2.2.3
7
6
  - ruby-head
@@ -12,3 +11,4 @@ matrix:
12
11
  before_install: gem install bundler -v 1.10.6
13
12
  script:
14
13
  - bundle exec rubocop --fail-level C
14
+ - bundle exec rspec
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Spbtv
6
+ # Prefer validating one attribute at once.
7
+ #
8
+ # @example
9
+ # @bad
10
+ # validates :name, :age, presence: true
11
+ #
12
+ # @good
13
+ # validates :age, presence: true
14
+ # validates :name, presence: true
15
+ #
16
+ class MultipleValidation < Cop
17
+ MSG = 'Prefer validating one attribute at once.'.freeze
18
+
19
+ def on_send(node)
20
+ _, _, *args = *node
21
+ if node.command?(:validates) && args.length > 2
22
+ add_offense(node, :selector, MSG)
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def autocorrect(node)
29
+ _receiver, method_name, *args = *node
30
+ *attributes, options = args
31
+
32
+ multiline_replacement = attributes.map do |attribute|
33
+ "#{method_name} #{attribute.source}, #{options.source}"
34
+ end
35
+
36
+ lambda do |corrector|
37
+ corrector.replace(node.source_range, multiline_replacement.sort.join("\n"))
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Spbtv
6
+ module Postgres
7
+ # Do not add a column with a default value.
8
+ #
9
+ # Adding a column with a default requires updating each row of the table (to store
10
+ # the new column value). For big table this will create long running operation
11
+ # that locks it.
12
+ #
13
+ # So if you intend to fill the column with mostly non default values,
14
+ # it’s best to add the column with no default, insert the correct values
15
+ # using UPDATE (correct way is to do batched updates, for example,
16
+ # update 1000 rows at a time, because big update will create table-wide lock),
17
+ # and then add any desired default.
18
+ #
19
+ # @example
20
+ # @bad
21
+ # add_column :users, :name, :string, default: "Peter"
22
+ #
23
+ # @good
24
+ # add_column :users, :name, :string
25
+ # User.find_in_batches do |batch|
26
+ # batch.update_all(name: 'Peter')
27
+ # end
28
+ #
29
+ class AddColumnWithDefault < Cop
30
+ MSG = 'Do not add a column with a default value.'.freeze
31
+
32
+ def_node_matcher :add_column_with_default?, <<-PATTERN
33
+ (send nil :add_column _ _ _ (hash $...))
34
+ PATTERN
35
+
36
+ def_node_matcher :has_default?, <<-PATTERN
37
+ (pair (sym :default) !(:nil))
38
+ PATTERN
39
+
40
+ def on_send(node)
41
+ pairs = add_column_with_default?(node)
42
+ return unless pairs
43
+ has_default = pairs.detect { |pair| has_default?(pair) }
44
+
45
+ return unless has_default
46
+
47
+ add_offense(has_default, :expression)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Spbtv
6
+ module Postgres
7
+ # Do not add a NOT NULL column.
8
+ #
9
+ # This will have the same problem, as “Add a column with a default”.
10
+ # To make this operation without locking, you can create a new table
11
+ # with the addition of the non-nullable column, write to both tables,
12
+ # backfill, and then switch to the new table. This workaround is
13
+ # incredibly onerous and need two times more space than is a table takes.
14
+ #
15
+ # @example
16
+ # @bad
17
+ # add_column :users, :name, :string, null: false
18
+ #
19
+ # @good
20
+ # add_column :users, :name, :string
21
+ #
22
+ class AddColumnWithNotNull < Cop
23
+ MSG = 'Do not add a NOT NULL column.'.freeze
24
+
25
+ def_node_matcher :add_not_null_column?, <<-PATTERN
26
+ (send nil :add_column _ _ _ (hash $...))
27
+ PATTERN
28
+
29
+ def_node_matcher :null_false?, <<-PATTERN
30
+ (pair (sym :null) (false))
31
+ PATTERN
32
+
33
+ def on_send(node)
34
+ pairs = add_not_null_column?(node)
35
+ return unless pairs
36
+
37
+ null_false = pairs.detect { |pair| null_false?(pair) }
38
+ return unless null_false
39
+
40
+ add_offense(null_false, :expression)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Spbtv
6
+ module Postgres
7
+ # Do not add an index.
8
+ #
9
+ # Normally PostgreSQL locks the table to be indexed against writes and performs
10
+ # the entire index build with a single scan of the table. Other transactions
11
+ # can still read the table, but not to insert, update, or delete rows until
12
+ # the index build is finished.
13
+ #
14
+ # To overcome this issue you may specify the CONCURRENTLY option of CREATE INDEX.
15
+ # When this option is used, PostgreSQL must perform two scans of the table, and in
16
+ # addition it must wait for all existing transactions that could potentially
17
+ # modify or use the index to terminate.
18
+ #
19
+ # If a problem arises while scanning the table, such as a uniqueness violation
20
+ # in a unique index, the CREATE INDEX command will fail but leave behind an
21
+ # “invalid” index.
22
+ #
23
+ # The recommended recovery method in such cases is to drop the index and
24
+ # try again to perform CREATE INDEX CONCURRENTLY.
25
+ #
26
+ # Another difference is that a regular CREATE INDEX command can be performed
27
+ # within a transaction block, but CREATE INDEX CONCURRENTLY cannot.
28
+ #
29
+ # @see https://www.postgresql.org/docs/9.2/static/sql-createindex.html#SQL-CREATEINDEX-CONCURRENTLY
30
+ # @see https://robots.thoughtbot.com/how-to-create-postgres-indexes-concurrently-in
31
+ #
32
+ # @example
33
+ # @bad
34
+ # class AddIndexToAsksActive < ActiveRecord::Migration
35
+ # def change
36
+ # add_index :asks, :active
37
+ # end
38
+ # end
39
+ #
40
+ # @good
41
+ # class AddIndexToAsksActive < ActiveRecord::Migration
42
+ # disable_ddl_transaction!
43
+ # def change
44
+ # add_index :asks, :active, algorithm: :concurrently
45
+ # end
46
+ # end
47
+ #
48
+ class AddIndex < Cop
49
+ MSG = 'Do not add an index.'.freeze
50
+
51
+ def_node_search :disable_ddl_transaction?, '(send nil :disable_ddl_transaction!)'
52
+
53
+ def_node_matcher :add_index_without_options?, <<-PATTERN
54
+ (send nil :add_index _ _)
55
+ PATTERN
56
+
57
+ def_node_matcher :add_index_with_options?, <<-PATTERN
58
+ (send nil :add_index _ _ (hash $...))
59
+ PATTERN
60
+
61
+ def_node_matcher :concurrently?, <<-PATTERN
62
+ (pair (sym :algorithm) (sym :concurrently))
63
+ PATTERN
64
+
65
+ def on_class(node)
66
+ @disable_ddl_transaction = disable_ddl_transaction?(node)
67
+ end
68
+
69
+ def on_send(node)
70
+ if add_index_without_options?(node)
71
+ add_offense(node, :expression)
72
+ elsif (options = add_index_with_options?(node))
73
+ has_concurrently = options.detect { |pair| concurrently?(pair) }
74
+ unless has_concurrently && @disable_ddl_transaction
75
+ add_offense(node, :expression)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Spbtv
6
+ module Postgres
7
+ # Do not change column.
8
+ #
9
+ # It is not strictly unsafe for all changes. Changing the
10
+ # length of a varchar, for example, does not lock a table.
11
+ # But if column type change requires a rewrite or not depends
12
+ # on the datatype, in this case this operation requires updating
13
+ # each row of the table. As workaround, you can add a new column
14
+ # with needed type, change the code to write to both columns,
15
+ # and backfill the new column.
16
+ #
17
+ # @example
18
+ # @bad
19
+ # change_column :suppliers, :name, :string, limit: 80
20
+ #
21
+ class ChangeColumn < Cop
22
+ MSG = 'Do not change column.'.freeze
23
+
24
+ def on_send(node)
25
+ _, _, * = *node
26
+ if node.command?(:change_column)
27
+ add_offense(node, :selector, MSG)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,6 @@
1
+ require 'rubocop'
2
+ require_relative 'cop/spbtv/postgres/add_column_with_default'
3
+ require_relative 'cop/spbtv/postgres/add_column_with_not_null'
4
+ require_relative 'cop/spbtv/postgres/add_index'
5
+ require_relative 'cop/spbtv/postgres/change_column'
6
+ require_relative 'cop/spbtv/multiple_validation'
@@ -1,4 +1,4 @@
1
1
  # Just namespace for version number
2
2
  module SpbtvCodeStyle
3
- VERSION = '1.5.0'.freeze
3
+ VERSION = '1.6.0'.freeze
4
4
  end
@@ -18,7 +18,9 @@ Gem::Specification.new do |spec|
18
18
  spec.add_runtime_dependency 'rubocop-checkstyle_formatter'
19
19
  spec.add_runtime_dependency 'rspec_junit_formatter'
20
20
 
21
- spec.add_development_dependency 'rubocop', '~> 0.40.0'
22
21
  spec.add_development_dependency 'bundler', '~> 1.10'
23
22
  spec.add_development_dependency 'rake', '~> 10.0'
23
+ spec.add_development_dependency 'rspec', '~> 3.5'
24
+ spec.add_development_dependency 'rubocop', '~> 0.43.0'
25
+ spec.add_development_dependency 'rubocop-rspec', '1.7.0'
24
26
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spbtv_code_style
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tema Bolshakov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-27 00:00:00.000000000 Z
11
+ date: 2016-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop-checkstyle_formatter
@@ -39,47 +39,75 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rubocop
42
+ name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 0.40.0
47
+ version: '1.10'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 0.40.0
54
+ version: '1.10'
55
55
  - !ruby/object:Gem::Dependency
56
- name: bundler
56
+ name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '1.10'
61
+ version: '10.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '1.10'
68
+ version: '10.0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rake
70
+ name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '10.0'
75
+ version: '3.5'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '10.0'
82
+ version: '3.5'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.43.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.43.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 1.7.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '='
109
+ - !ruby/object:Gem::Version
110
+ version: 1.7.0
83
111
  description:
84
112
  email:
85
113
  - abolshakov@spbtv.com
@@ -88,6 +116,7 @@ extensions: []
88
116
  extra_rdoc_files: []
89
117
  files:
90
118
  - ".gitignore"
119
+ - ".rspec"
91
120
  - ".rubocop.yml"
92
121
  - ".strict_rubocop.yml"
93
122
  - ".travis.yml"
@@ -96,6 +125,12 @@ files:
96
125
  - LICENSE
97
126
  - README.md
98
127
  - Rakefile
128
+ - lib/rubocop/cop/spbtv/multiple_validation.rb
129
+ - lib/rubocop/cop/spbtv/postgres/add_column_with_default.rb
130
+ - lib/rubocop/cop/spbtv/postgres/add_column_with_not_null.rb
131
+ - lib/rubocop/cop/spbtv/postgres/add_index.rb
132
+ - lib/rubocop/cop/spbtv/postgres/change_column.rb
133
+ - lib/rubocop/spbtv.rb
99
134
  - lib/spbtv_code_style.rb
100
135
  - spbtv_code_style.gemspec
101
136
  homepage: https://github.com/spbtv/spbtv_code_style