ducalis 0.5.11 → 0.5.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/DOCUMENTATION.md +69 -3
- data/Gemfile.lock +1 -1
- data/config/.ducalis.yml +3 -0
- data/lib/ducalis/cops/callbacks_activerecord.rb +3 -0
- data/lib/ducalis/cops/only_defs_cope.rb +47 -0
- data/lib/ducalis/cops/options_argument.rb +21 -5
- data/lib/ducalis/version.rb +1 -1
- data/lib/ducalis.rb +2 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc58534f3d61b3f00faf32d15c18fd4ade02b01d
|
4
|
+
data.tar.gz: e2e5523eab7bd5dfe942f0e09722e718148ff6c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d84c6cbef793f301ce284c6325f992ea20672f6f01938f9a0feeef6cc76b8b564992aa552d1433a6960e893c08d3aada0682ec6a1eb3f28a8c0d942797f4c6e5
|
7
|
+
data.tar.gz: cbf69b4a43714b164e21ea3f19b08634504c563ca7f008b030fa625bed221bea0efba9f14bb917e96af25d4c1e180c53634bd9fb0f01f0fd73c443bd26bfdffb
|
data/DOCUMENTATION.md
CHANGED
@@ -294,10 +294,60 @@ class TaskJournal
|
|
294
294
|
end
|
295
295
|
end
|
296
296
|
|
297
|
+
```
|
298
|
+
## Ducalis::OnlyDefsCope
|
299
|
+
|
300
|
+
Prefer object instances to class methods because class methods resist refactoring. Begin with an object instance, even if it doesn’t have state or multiple methods right away. If you come back to change it later, you will be more likely to refactor. If it never changes, the difference between the class method approach and the instance is negligible, and you certainly won’t be any worse off.
|
301
|
+
Related article: https://codeclimate.com/blog/why-ruby-class-methods-resist-refactoring/
|
302
|
+
|
303
|
+
![](https://placehold.it/10/2cbe4e/000000?text=+) ignores classes with one instance method
|
304
|
+
```ruby
|
305
|
+
|
306
|
+
class TaskJournal
|
307
|
+
def initialize(task)
|
308
|
+
# ...
|
309
|
+
end
|
310
|
+
|
311
|
+
def call(args)
|
312
|
+
# ...
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
```
|
317
|
+
|
318
|
+
![](https://placehold.it/10/2cbe4e/000000?text=+) ignores classes with mixed methods
|
319
|
+
```ruby
|
320
|
+
|
321
|
+
class TaskJournal
|
322
|
+
def self.find(task)
|
323
|
+
# ...
|
324
|
+
end
|
325
|
+
|
326
|
+
def call(args)
|
327
|
+
# ...
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
```
|
332
|
+
|
333
|
+
![](https://placehold.it/10/f03c15/000000?text=+) raises error for class with ONLY class methods
|
334
|
+
```ruby
|
335
|
+
|
336
|
+
class TaskJournal
|
337
|
+
|
338
|
+
def self.call(task)
|
339
|
+
# ...
|
340
|
+
end
|
341
|
+
|
342
|
+
def self.find(args)
|
343
|
+
# ...
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
297
347
|
```
|
298
348
|
## Ducalis::OptionsArgument
|
299
349
|
|
300
|
-
Default options argument isn't good idea. It's better to explicitly pass which keys are you interested in as keyword arguments. You can use split operator to support hash arguments.
|
350
|
+
Default `options` (or `args`) argument isn't good idea. It's better to explicitly pass which keys are you interested in as keyword arguments. You can use split operator to support hash arguments.
|
301
351
|
|
302
352
|
Compare:
|
303
353
|
|
@@ -308,7 +358,10 @@ def generate_1(document, options = {})
|
|
308
358
|
# ...
|
309
359
|
[format, limit, options]
|
310
360
|
end
|
311
|
-
|
361
|
+
|
362
|
+
options = { format: 'csv', limit: 5, useless_arg: :value }
|
363
|
+
generate_1(1, options) #=> ["csv", 5, {:useless_arg=>:value}]
|
364
|
+
generate_1(1, format: 'csv', limit: 5, useless_arg: :value) #=> ["csv", 5, {:useless_arg=>:value}]
|
312
365
|
|
313
366
|
# vs
|
314
367
|
|
@@ -316,7 +369,11 @@ def generate_2(document, format:, limit: 20, **options)
|
|
316
369
|
# ...
|
317
370
|
[format, limit, options]
|
318
371
|
end
|
319
|
-
|
372
|
+
|
373
|
+
options = { format: 'csv', limit: 5, useless_arg: :value }
|
374
|
+
generate_2(1, **options) #=> ["csv", 5, {:useless_arg=>:value}]
|
375
|
+
generate_2(1, format: 'csv', limit: 5, useless_arg: :value) #=> ["csv", 5, {:useless_arg=>:value}]
|
376
|
+
|
320
377
|
```
|
321
378
|
|
322
379
|
![](https://placehold.it/10/f03c15/000000?text=+) raises if method accepts default options argument
|
@@ -339,6 +396,15 @@ end
|
|
339
396
|
|
340
397
|
```
|
341
398
|
|
399
|
+
![](https://placehold.it/10/f03c15/000000?text=+) raises if method accepts args argument
|
400
|
+
```ruby
|
401
|
+
|
402
|
+
def log(record, args)
|
403
|
+
# ...
|
404
|
+
end
|
405
|
+
|
406
|
+
```
|
407
|
+
|
342
408
|
![](https://placehold.it/10/2cbe4e/000000?text=+) ignores passing options with split operator
|
343
409
|
```ruby
|
344
410
|
|
data/Gemfile.lock
CHANGED
data/config/.ducalis.yml
CHANGED
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rubocop'
|
4
|
+
|
5
|
+
module Ducalis
|
6
|
+
class OnlyDefsCope < RuboCop::Cop::Cop
|
7
|
+
include RuboCop::Cop::DefNode
|
8
|
+
|
9
|
+
OFFENSE = <<-MESSAGE.gsub(/^ +\|\s/, '').strip
|
10
|
+
| Prefer object instances to class methods because class methods resist refactoring. Begin with an object instance, even if it doesn’t have state or multiple methods right away. If you come back to change it later, you will be more likely to refactor. If it never changes, the difference between the class method approach and the instance is negligible, and you certainly won’t be any worse off.
|
11
|
+
MESSAGE
|
12
|
+
|
13
|
+
DETAILS = <<-MESSAGE.gsub(/^ +\|\s/, '').strip
|
14
|
+
| Related article: https://codeclimate.com/blog/why-ruby-class-methods-resist-refactoring/
|
15
|
+
MESSAGE
|
16
|
+
|
17
|
+
def on_class(node)
|
18
|
+
_name, inheritance, body = *node
|
19
|
+
return if !inheritance.nil? || body.nil?
|
20
|
+
instance_methods = children(body).select(&public_method_definition?)
|
21
|
+
class_methods = children(body).select(&class_method_definition?)
|
22
|
+
|
23
|
+
return unless instance_methods.empty? && class_methods.any?
|
24
|
+
add_offense(node, :expression, OFFENSE)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def public_method_definition?
|
30
|
+
lambda do |node|
|
31
|
+
node.type == :def && !non_public?(node) && !initialize?(node)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def class_method_definition?
|
36
|
+
lambda do |node|
|
37
|
+
node.type == :defs && !non_public?(node) && !initialize?(node)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def children(body)
|
42
|
+
(body.type != :begin ? s(:begin, body) : body).children
|
43
|
+
end
|
44
|
+
|
45
|
+
def_node_search :initialize?, '(def :initialize ...)'
|
46
|
+
end
|
47
|
+
end
|
@@ -5,7 +5,7 @@ require 'rubocop'
|
|
5
5
|
module Ducalis
|
6
6
|
class OptionsArgument < RuboCop::Cop::Cop
|
7
7
|
OFFENSE = <<-MESSAGE.gsub(/^ +\|\s/, '').strip
|
8
|
-
| Default options argument isn't good idea. It's better to explicitly pass which keys are you interested in as keyword arguments. You can use split operator to support hash arguments.
|
8
|
+
| Default `options` (or `args`) argument isn't good idea. It's better to explicitly pass which keys are you interested in as keyword arguments. You can use split operator to support hash arguments.
|
9
9
|
|
10
10
|
| Compare:
|
11
11
|
|
@@ -16,7 +16,10 @@ module Ducalis
|
|
16
16
|
| # ...
|
17
17
|
| [format, limit, options]
|
18
18
|
| end
|
19
|
-
|
19
|
+
|
20
|
+
| options = { format: 'csv', limit: 5, useless_arg: :value }
|
21
|
+
| generate_1(1, options) #=> ["csv", 5, {:useless_arg=>:value}]
|
22
|
+
| generate_1(1, format: 'csv', limit: 5, useless_arg: :value) #=> ["csv", 5, {:useless_arg=>:value}]
|
20
23
|
|
21
24
|
| # vs
|
22
25
|
|
@@ -24,10 +27,19 @@ module Ducalis
|
|
24
27
|
| # ...
|
25
28
|
| [format, limit, options]
|
26
29
|
| end
|
27
|
-
|
30
|
+
|
31
|
+
| options = { format: 'csv', limit: 5, useless_arg: :value }
|
32
|
+
| generate_2(1, **options) #=> ["csv", 5, {:useless_arg=>:value}]
|
33
|
+
| generate_2(1, format: 'csv', limit: 5, useless_arg: :value) #=> ["csv", 5, {:useless_arg=>:value}]
|
34
|
+
|
28
35
|
| ```
|
29
36
|
MESSAGE
|
30
37
|
|
38
|
+
BLACK_LIST = %i(
|
39
|
+
options
|
40
|
+
args
|
41
|
+
).freeze
|
42
|
+
|
31
43
|
def on_def(node)
|
32
44
|
_name, args, _body = *node
|
33
45
|
return unless default_options?(args)
|
@@ -36,13 +48,17 @@ module Ducalis
|
|
36
48
|
|
37
49
|
private
|
38
50
|
|
39
|
-
def_node_search :options_arg?, '(arg
|
40
|
-
def_node_search :options_arg_with_default?, '(optarg
|
51
|
+
def_node_search :options_arg?, '(arg #blacklisted?)'
|
52
|
+
def_node_search :options_arg_with_default?, '(optarg #blacklisted? ...)'
|
41
53
|
|
42
54
|
def default_options?(args)
|
43
55
|
args.children.any? do |node|
|
44
56
|
options_arg?(node) || options_arg_with_default?(node)
|
45
57
|
end
|
46
58
|
end
|
59
|
+
|
60
|
+
def blacklisted?(name)
|
61
|
+
BLACK_LIST.include?(name)
|
62
|
+
end
|
47
63
|
end
|
48
64
|
end
|
data/lib/ducalis/version.rb
CHANGED
data/lib/ducalis.rb
CHANGED
@@ -35,13 +35,14 @@ require 'ducalis/cops/black_list_suffix'
|
|
35
35
|
require 'ducalis/cops/callbacks_activerecord'
|
36
36
|
require 'ducalis/cops/case_mapping'
|
37
37
|
require 'ducalis/cops/controllers_except'
|
38
|
+
require 'ducalis/cops/only_defs_cope'
|
38
39
|
require 'ducalis/cops/keyword_defaults'
|
39
40
|
require 'ducalis/cops/module_like_class'
|
40
41
|
require 'ducalis/cops/options_argument'
|
41
42
|
require 'ducalis/cops/params_passing'
|
42
43
|
require 'ducalis/cops/possible_tap'
|
43
|
-
require 'ducalis/cops/private_instance_assign'
|
44
44
|
require 'ducalis/cops/preferable_methods'
|
45
|
+
require 'ducalis/cops/private_instance_assign'
|
45
46
|
require 'ducalis/cops/protected_scope_cop'
|
46
47
|
require 'ducalis/cops/raise_without_error_class'
|
47
48
|
require 'ducalis/cops/regex_cop'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ducalis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ignat Zakrevsky
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-12-
|
11
|
+
date: 2017-12-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: git
|
@@ -136,6 +136,7 @@ files:
|
|
136
136
|
- lib/ducalis/cops/controllers_except.rb
|
137
137
|
- lib/ducalis/cops/keyword_defaults.rb
|
138
138
|
- lib/ducalis/cops/module_like_class.rb
|
139
|
+
- lib/ducalis/cops/only_defs_cope.rb
|
139
140
|
- lib/ducalis/cops/options_argument.rb
|
140
141
|
- lib/ducalis/cops/params_passing.rb
|
141
142
|
- lib/ducalis/cops/possible_tap.rb
|