rubocop-yiffspace 0.0.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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.idea/.gitignore +8 -0
  3. data/.idea/jsonSchemas.xml +25 -0
  4. data/.idea/misc.xml +4 -0
  5. data/.idea/modules.xml +8 -0
  6. data/.idea/rubocop-plugin.iml +65 -0
  7. data/.idea/vcs.xml +6 -0
  8. data/.rspec +3 -0
  9. data/.ruby-version +1 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +39 -0
  12. data/Rakefile +33 -0
  13. data/config/custom.yml +17 -0
  14. data/config/default.yml +54 -0
  15. data/config/rails.yml +8 -0
  16. data/config/shared/bundler.yml +1 -0
  17. data/config/shared/gemspec.yml +1 -0
  18. data/config/shared/layout.yml +18 -0
  19. data/config/shared/lint.yml +4 -0
  20. data/config/shared/metrics.yml +35 -0
  21. data/config/shared/migration.yml +1 -0
  22. data/config/shared/naming.yml +7 -0
  23. data/config/shared/rails.yml +14 -0
  24. data/config/shared/security.yml +1 -0
  25. data/config/shared/style.yml +45 -0
  26. data/config/shared.yml +12 -0
  27. data/lib/rubocop/cop/mixin/active_record_helper.rb +18 -0
  28. data/lib/rubocop/cop/mixin/node_formatting_helper.rb +59 -0
  29. data/lib/rubocop/cop/yiff_space/belongs_to_user.rb +121 -0
  30. data/lib/rubocop/cop/yiff_space/belongs_to_user_invalid_ip.rb +107 -0
  31. data/lib/rubocop/cop/yiff_space/belongs_to_user_missing_ip.rb +105 -0
  32. data/lib/rubocop/cop/yiff_space/current_user_outside_of_requests.rb +194 -0
  33. data/lib/rubocop/cop/yiff_space/resolvable_user.rb +113 -0
  34. data/lib/rubocop/cop/yiff_space/user_to_id.rb +64 -0
  35. data/lib/rubocop/cop/yiffspace_cops.rb +10 -0
  36. data/lib/rubocop/yiff_space/plugin.rb +31 -0
  37. data/lib/rubocop/yiff_space/version.rb +7 -0
  38. data/lib/rubocop/yiff_space.rb +8 -0
  39. data/lib/rubocop-yiffspace.rb +9 -0
  40. data/spec/rubocop/cop/yiff_space/belongs_to_user_invalid_ip_spec.rb +109 -0
  41. data/spec/rubocop/cop/yiff_space/belongs_to_user_missing_ip_spec.rb +91 -0
  42. data/spec/rubocop/cop/yiff_space/belongs_to_user_spec.rb +158 -0
  43. data/spec/rubocop/cop/yiff_space/current_user_outside_of_requests_spec.rb +398 -0
  44. data/spec/rubocop/cop/yiff_space/resolvable_user_spec.rb +99 -0
  45. data/spec/rubocop/cop/yiff_space/user_to_id_spec.rb +67 -0
  46. data/spec/spec_helper.rb +20 -0
  47. metadata +118 -0
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative("mixin/node_formatting_helper")
4
+ require_relative("mixin/active_record_helper")
5
+ require_relative("yiff_space/belongs_to_user")
6
+ require_relative("yiff_space/belongs_to_user_invalid_ip")
7
+ require_relative("yiff_space/belongs_to_user_missing_ip")
8
+ require_relative("yiff_space/current_user_outside_of_requests")
9
+ require_relative("yiff_space/resolvable_user")
10
+ require_relative("yiff_space/user_to_id")
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require("lint_roller")
4
+
5
+ module RuboCop
6
+ module YiffSpace
7
+ # A plugin that integrates rubocop-yiffspace with RuboCop's plugin system.
8
+ class Plugin < LintRoller::Plugin
9
+ def about
10
+ LintRoller::About.new(
11
+ name: "rubocop-yiffspace",
12
+ version: VERSION,
13
+ homepage: "https://github.com/YiffSpace/rubocop-plugin",
14
+ description: "Shared rubocop rules for YiffSpace",
15
+ )
16
+ end
17
+
18
+ def supported?(context)
19
+ context.engine == :rubocop
20
+ end
21
+
22
+ def rules(_context)
23
+ LintRoller::Rules.new(
24
+ type: :path,
25
+ config_format: :rubocop,
26
+ value: Pathname.new(__dir__).join("../../../config/default.yml"),
27
+ )
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module YiffSpace
5
+ VERSION = "0.0.1"
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative("yiff_space/version")
4
+
5
+ module RuboCop
6
+ module YiffSpace
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require("rubocop")
4
+
5
+ require_relative("rubocop/yiff_space")
6
+ require_relative("rubocop/yiff_space/version")
7
+ require_relative("rubocop/yiff_space/plugin")
8
+
9
+ require_relative("rubocop/cop/yiffspace_cops")
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe(RuboCop::Cop::YiffSpace::BelongsToUserInvalidIp, :config) do
4
+ let(:schema) { double("schema") }
5
+ let(:posts_table) { double("posts_table", name: "posts") }
6
+
7
+ before do
8
+ allow(cop).to(receive(:schema).and_return(schema))
9
+ allow(schema).to(receive(:table_by).and_return(posts_table))
10
+ end
11
+
12
+ context("when ip: true is set but the column does not exist") do
13
+ before { allow(posts_table).to(receive(:with_column?).and_return(false)) }
14
+
15
+ it("registers an offense and removes the ip: option") do
16
+ expect_offense(<<~RUBY)
17
+ class Post < ApplicationRecord
18
+ belongs_to_user(:creator, ip: true)
19
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ip: true` set for `belongs_to_user(:creator)` when `"posts.creator_ip_addr"` column does not exist
20
+ end
21
+ RUBY
22
+
23
+ expect_correction(<<~RUBY)
24
+ class Post < ApplicationRecord
25
+ belongs_to_user(:creator)
26
+ end
27
+ RUBY
28
+ end
29
+ end
30
+
31
+ context("when a custom ip column string is set but does not exist") do
32
+ before { allow(posts_table).to(receive(:with_column?).and_return(false)) }
33
+
34
+ it("registers an offense using the custom column name") do
35
+ expect_offense(<<~RUBY)
36
+ class Post < ApplicationRecord
37
+ belongs_to_user(:creator, ip: "custom_col")
38
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ip: "custom_col"` set for `belongs_to_user(:creator)` when `"posts.custom_col"` column does not exist
39
+ end
40
+ RUBY
41
+
42
+ expect_correction(<<~RUBY)
43
+ class Post < ApplicationRecord
44
+ belongs_to_user(:creator)
45
+ end
46
+ RUBY
47
+ end
48
+ end
49
+
50
+ context("when ip: true is set and the column exists") do
51
+ before { allow(posts_table).to(receive(:with_column?).with(name: "creator_ip_addr").and_return(true)) }
52
+
53
+ it("does not register an offense") do
54
+ expect_no_offenses(<<~RUBY)
55
+ class Post < ApplicationRecord
56
+ belongs_to_user(:creator, ip: true)
57
+ end
58
+ RUBY
59
+ end
60
+ end
61
+
62
+ it("does not register an offense when ip: is not specified") do
63
+ allow(posts_table).to(receive(:with_column?).and_return(false))
64
+
65
+ expect_no_offenses(<<~RUBY)
66
+ class Post < ApplicationRecord
67
+ belongs_to_user(:creator)
68
+ end
69
+ RUBY
70
+ end
71
+
72
+ it("does not register an offense when ip: false") do
73
+ allow(posts_table).to(receive(:with_column?).and_return(false))
74
+
75
+ expect_no_offenses(<<~RUBY)
76
+ class Post < ApplicationRecord
77
+ belongs_to_user(:creator, ip: false)
78
+ end
79
+ RUBY
80
+ end
81
+
82
+ it("does not register an offense when the schema is unavailable") do
83
+ allow(cop).to(receive(:schema).and_return(nil))
84
+
85
+ expect_no_offenses(<<~RUBY)
86
+ class Post < ApplicationRecord
87
+ belongs_to_user(:creator, ip: true)
88
+ end
89
+ RUBY
90
+ end
91
+
92
+ it("does not register an offense when the table is not found in the schema") do
93
+ allow(schema).to(receive(:table_by).and_return(nil))
94
+
95
+ expect_no_offenses(<<~RUBY)
96
+ class Post < ApplicationRecord
97
+ belongs_to_user(:creator, ip: true)
98
+ end
99
+ RUBY
100
+ end
101
+
102
+ it("does not register an offense when the call is outside a class") do
103
+ allow(posts_table).to(receive(:with_column?).and_return(false))
104
+
105
+ expect_no_offenses(<<~RUBY)
106
+ belongs_to_user(:creator, ip: true)
107
+ RUBY
108
+ end
109
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe(RuboCop::Cop::YiffSpace::BelongsToUserMissingIp, :config) do
4
+ let(:schema) { double("schema") }
5
+ let(:posts_table) { double("posts_table", name: "posts") }
6
+
7
+ before do
8
+ allow(cop).to(receive(:schema).and_return(schema))
9
+ allow(schema).to(receive(:table_by).and_return(posts_table))
10
+ end
11
+
12
+ context("when the ip column exists but ip: is not specified") do
13
+ before { allow(posts_table).to(receive(:with_column?).with(name: "creator_ip_addr").and_return(true)) }
14
+
15
+ it("registers an offense and adds ip: true") do
16
+ expect_offense(<<~RUBY)
17
+ class Post < ApplicationRecord
18
+ belongs_to_user(:creator)
19
+ ^^^^^^^^^^^^^^^^^^^^^^^^^ Specify `ip: true` when a `belongs_to_user(:creator)` relation has a corresponding `"creator_ip_addr"` column
20
+ end
21
+ RUBY
22
+
23
+ expect_correction(<<~RUBY)
24
+ class Post < ApplicationRecord
25
+ belongs_to_user(:creator, ip: true)
26
+ end
27
+ RUBY
28
+ end
29
+
30
+ it("registers an offense when ip: false is explicitly set") do
31
+ expect_offense(<<~RUBY)
32
+ class Post < ApplicationRecord
33
+ belongs_to_user(:creator, ip: false)
34
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Specify `ip: true` when a `belongs_to_user(:creator)` relation has a corresponding `"creator_ip_addr"` column
35
+ end
36
+ RUBY
37
+ end
38
+ end
39
+
40
+ context("when ip: true is already set") do
41
+ before { allow(posts_table).to(receive(:with_column?).with(name: "creator_ip_addr").and_return(true)) }
42
+
43
+ it("does not register an offense") do
44
+ expect_no_offenses(<<~RUBY)
45
+ class Post < ApplicationRecord
46
+ belongs_to_user(:creator, ip: true)
47
+ end
48
+ RUBY
49
+ end
50
+ end
51
+
52
+ context("when the ip column does not exist") do
53
+ before { allow(posts_table).to(receive(:with_column?).with(name: "creator_ip_addr").and_return(false)) }
54
+
55
+ it("does not register an offense") do
56
+ expect_no_offenses(<<~RUBY)
57
+ class Post < ApplicationRecord
58
+ belongs_to_user(:creator)
59
+ end
60
+ RUBY
61
+ end
62
+ end
63
+
64
+ it("does not register an offense when the schema is unavailable") do
65
+ allow(cop).to(receive(:schema).and_return(nil))
66
+
67
+ expect_no_offenses(<<~RUBY)
68
+ class Post < ApplicationRecord
69
+ belongs_to_user(:creator)
70
+ end
71
+ RUBY
72
+ end
73
+
74
+ it("does not register an offense when the table is not found in the schema") do
75
+ allow(schema).to(receive(:table_by).and_return(nil))
76
+
77
+ expect_no_offenses(<<~RUBY)
78
+ class Post < ApplicationRecord
79
+ belongs_to_user(:creator)
80
+ end
81
+ RUBY
82
+ end
83
+
84
+ it("does not register an offense when the call is outside a class") do
85
+ allow(posts_table).to(receive(:with_column?).with(name: "creator_ip_addr").and_return(true))
86
+
87
+ expect_no_offenses(<<~RUBY)
88
+ belongs_to_user(:creator)
89
+ RUBY
90
+ end
91
+ end
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe(RuboCop::Cop::YiffSpace::BelongsToUser, :config) do
4
+ it("registers an offense for belongs_to(:user) when options are present") do
5
+ expect_offense(<<~RUBY)
6
+ belongs_to(:user, optional: false)
7
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `belongs_to_user(:user)` instead of `belongs_to(:user)`
8
+ RUBY
9
+
10
+ expect_correction(<<~RUBY)
11
+ belongs_to_user(:user, optional: false)
12
+ RUBY
13
+ end
14
+
15
+ it('registers an offense for belongs_to with class_name: "User"') do
16
+ expect_offense(<<~RUBY)
17
+ belongs_to(:creator, class_name: "User")
18
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `belongs_to_user(:creator)` instead of `belongs_to(:creator)`
19
+ RUBY
20
+
21
+ expect_correction(<<~RUBY)
22
+ belongs_to_user(:creator)
23
+ RUBY
24
+ end
25
+
26
+ it("removes class_name while preserving other options") do
27
+ expect_offense(<<~RUBY)
28
+ belongs_to(:creator, class_name: "User", optional: true)
29
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `belongs_to_user(:creator)` instead of `belongs_to(:creator)`
30
+ RUBY
31
+
32
+ expect_correction(<<~RUBY)
33
+ belongs_to_user(:creator, optional: true)
34
+ RUBY
35
+ end
36
+
37
+ it('registers an offense for belongs_to with a string attribute and class_name: "User"') do
38
+ expect_offense(<<~RUBY)
39
+ belongs_to("creator", class_name: "User")
40
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `belongs_to_user("creator")` instead of `belongs_to("creator")`
41
+ RUBY
42
+
43
+ expect_correction(<<~RUBY)
44
+ belongs_to_user("creator")
45
+ RUBY
46
+ end
47
+
48
+ it("does not register an offense for belongs_to(:user) with no options hash") do
49
+ # The cop requires at least one option present to trigger
50
+ expect_no_offenses(<<~RUBY)
51
+ belongs_to(:user)
52
+ RUBY
53
+ end
54
+
55
+ it("does not register an offense for belongs_to(:creator) without class_name") do
56
+ expect_no_offenses(<<~RUBY)
57
+ belongs_to(:creator, optional: true)
58
+ RUBY
59
+ end
60
+
61
+ it("does not register an offense for belongs_to with a non-User class_name") do
62
+ expect_no_offenses(<<~RUBY)
63
+ belongs_to(:creator, class_name: "Admin")
64
+ RUBY
65
+ end
66
+
67
+ it("does not register an offense when already using belongs_to_user") do
68
+ expect_no_offenses(<<~RUBY)
69
+ belongs_to_user(:creator)
70
+ RUBY
71
+ end
72
+
73
+ context("with a custom ClassName") do
74
+ let(:config) do
75
+ RuboCop::Config.new("YiffSpace/BelongsToUser" => { "ClassName" => "CurrentUser" })
76
+ end
77
+
78
+ it("registers an offense for belongs_to with the inferred attribute name") do
79
+ expect_offense(<<~RUBY)
80
+ belongs_to(:current_user, optional: false)
81
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `belongs_to_user(:current_user)` instead of `belongs_to(:current_user)`
82
+ RUBY
83
+
84
+ expect_correction(<<~RUBY)
85
+ belongs_to_user(:current_user, optional: false)
86
+ RUBY
87
+ end
88
+
89
+ it("registers an offense for belongs_to with the configured class_name") do
90
+ expect_offense(<<~RUBY)
91
+ belongs_to(:creator, class_name: "CurrentUser")
92
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `belongs_to_user(:creator)` instead of `belongs_to(:creator)`
93
+ RUBY
94
+
95
+ expect_correction(<<~RUBY)
96
+ belongs_to_user(:creator)
97
+ RUBY
98
+ end
99
+
100
+ it("does not register an offense for the default :user attribute") do
101
+ expect_no_offenses(<<~RUBY)
102
+ belongs_to(:user, optional: false)
103
+ RUBY
104
+ end
105
+
106
+ it('does not register an offense for class_name: "User" when ClassName is CurrentUser') do
107
+ expect_no_offenses(<<~RUBY)
108
+ belongs_to(:creator, class_name: "User")
109
+ RUBY
110
+ end
111
+ end
112
+
113
+ context("with a namespaced ClassName") do
114
+ let(:config) do
115
+ RuboCop::Config.new("YiffSpace/BelongsToUser" => { "ClassName" => "Logical::CurrentUser" })
116
+ end
117
+
118
+ it("infers the attribute name from the last segment") do
119
+ expect_offense(<<~RUBY)
120
+ belongs_to(:current_user, optional: false)
121
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `belongs_to_user(:current_user)` instead of `belongs_to(:current_user)`
122
+ RUBY
123
+
124
+ expect_correction(<<~RUBY)
125
+ belongs_to_user(:current_user, optional: false)
126
+ RUBY
127
+ end
128
+
129
+ it("matches the full namespaced class_name") do
130
+ expect_offense(<<~RUBY)
131
+ belongs_to(:creator, class_name: "Logical::CurrentUser")
132
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `belongs_to_user(:creator)` instead of `belongs_to(:creator)`
133
+ RUBY
134
+
135
+ expect_correction(<<~RUBY)
136
+ belongs_to_user(:creator)
137
+ RUBY
138
+ end
139
+
140
+ it("does not register an offense for a non-matching class_name") do
141
+ expect_no_offenses(<<~RUBY)
142
+ belongs_to(:creator, class_name: "CurrentUser")
143
+ RUBY
144
+ end
145
+ end
146
+
147
+ it('registers an offense for belongs_to with class_name: "User" on the :user attribute') do
148
+ # :user + class_name: "User" triggers the class_name path, not the :user shorthand
149
+ expect_offense(<<~RUBY)
150
+ belongs_to(:user, class_name: "User")
151
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `belongs_to_user(:user)` instead of `belongs_to(:user)`
152
+ RUBY
153
+
154
+ expect_correction(<<~RUBY)
155
+ belongs_to_user(:user)
156
+ RUBY
157
+ end
158
+ end