@sun-asterisk/sunlint 1.3.41 → 1.3.42

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 (106) hide show
  1. package/package.json +1 -1
  2. package/skill-assets/sunlint-code-quality/rules/dart/D001-recommended-lints.md +36 -0
  3. package/skill-assets/sunlint-code-quality/rules/dart/D002-dispose-resources.md +44 -0
  4. package/skill-assets/sunlint-code-quality/rules/dart/D003-prefer-widget-classes.md +53 -0
  5. package/skill-assets/sunlint-code-quality/rules/dart/D004-avoid-shrinkwrap.md +31 -0
  6. package/skill-assets/sunlint-code-quality/rules/dart/D005-widget-nesting.md +62 -0
  7. package/skill-assets/sunlint-code-quality/rules/dart/D006-large-callbacks.md +54 -0
  8. package/skill-assets/sunlint-code-quality/rules/dart/D007-lifecycle-order.md +44 -0
  9. package/skill-assets/sunlint-code-quality/rules/dart/D008-long-functions.md +37 -0
  10. package/skill-assets/sunlint-code-quality/rules/dart/D009-function-parameters.md +38 -0
  11. package/skill-assets/sunlint-code-quality/rules/dart/D010-cyclomatic-complexity.md +46 -0
  12. package/skill-assets/sunlint-code-quality/rules/dart/D011-named-parameters.md +31 -0
  13. package/skill-assets/sunlint-code-quality/rules/dart/D012-named-booleans.md +28 -0
  14. package/skill-assets/sunlint-code-quality/rules/dart/D013-single-public-class.md +34 -0
  15. package/skill-assets/sunlint-code-quality/rules/dart/D014-safe-collection-access.md +30 -0
  16. package/skill-assets/sunlint-code-quality/rules/dart/D015-copywith-consistency.md +52 -0
  17. package/skill-assets/sunlint-code-quality/rules/dart/D016-project-tests.md +32 -0
  18. package/skill-assets/sunlint-code-quality/rules/dart/D017-review-dependencies.md +24 -0
  19. package/skill-assets/sunlint-code-quality/rules/dart/D018-no-commented-code.md +34 -0
  20. package/skill-assets/sunlint-code-quality/rules/dart/D019-single-child-wrappers.md +31 -0
  21. package/skill-assets/sunlint-code-quality/rules/dart/D020-if-else-limit.md +41 -0
  22. package/skill-assets/sunlint-code-quality/rules/dart/D021-negated-booleans.md +26 -0
  23. package/skill-assets/sunlint-code-quality/rules/dart/D022-setstate-usage.md +35 -0
  24. package/skill-assets/sunlint-code-quality/rules/dart/D023-unnecessary-overrides.md +32 -0
  25. package/skill-assets/sunlint-code-quality/rules/dart/D024-avoid-unnecessary-statefulwidget.md +45 -0
  26. package/skill-assets/sunlint-code-quality/rules/dart/D025-nested-ternaries.md +35 -0
  27. package/skill-assets/sunlint-code-quality/rules/ruby/RB001-use-snake-case.md +30 -0
  28. package/skill-assets/sunlint-code-quality/rules/ruby/RB002-use-camel-case.md +38 -0
  29. package/skill-assets/sunlint-code-quality/rules/ruby/RB003-use-screaming-snake-case.md +26 -0
  30. package/skill-assets/sunlint-code-quality/rules/ruby/RB004-predicate-methods.md +36 -0
  31. package/skill-assets/sunlint-code-quality/rules/ruby/RB005-dangerous-methods.md +36 -0
  32. package/skill-assets/sunlint-code-quality/rules/ruby/RB006-indentation.md +32 -0
  33. package/skill-assets/sunlint-code-quality/rules/ruby/RB007-line-length.md +25 -0
  34. package/skill-assets/sunlint-code-quality/rules/ruby/RB008-rescue-exception.md +36 -0
  35. package/skill-assets/sunlint-code-quality/rules/ruby/RB009-save-bang.md +41 -0
  36. package/skill-assets/sunlint-code-quality/rules/ruby/RB010-avoid-n-plus-one.md +32 -0
  37. package/skill-assets/sunlint-code-quality/rules/ruby/RB011-use-find-each.md +30 -0
  38. package/skill-assets/sunlint-code-quality/rules/ruby/RB012-sql-injection.md +29 -0
  39. package/skill-assets/sunlint-code-quality/rules/ruby/RB013-prefer-has-many-through.md +35 -0
  40. package/skill-assets/sunlint-code-quality/rules/ruby/RB014-dependent-associations.md +28 -0
  41. package/skill-assets/sunlint-code-quality/rules/ruby/RB015-modern-validations.md +29 -0
  42. package/skill-assets/sunlint-code-quality/rules/ruby/RB016-thin-controllers.md +45 -0
  43. package/skill-assets/sunlint-code-quality/rules/ruby/RB017-avoid-fat-models.md +41 -0
  44. package/skill-assets/sunlint-code-quality/rules/ruby/RB018-service-objects.md +36 -0
  45. package/skill-assets/sunlint-code-quality/rules/ruby/RB019-avoid-metaprogramming.md +40 -0
  46. package/skill-assets/sunlint-code-quality/rules/ruby/RB020-use-pluck.md +29 -0
  47. package/skill-assets/sunlint-code-quality/rules/ruby/RB021-use-size.md +27 -0
  48. package/skill-assets/sunlint-code-quality/rules/ruby/RB022-order-by-timestamps.md +24 -0
  49. package/skill-assets/sunlint-code-quality/rules/ruby/RB023-where-missing.md +24 -0
  50. package/skill-assets/sunlint-code-quality/rules/ruby/RB024-method-length.md +41 -0
  51. package/skill-assets/sunlint-code-quality/rules/ruby/RB025-parameter-limits.md +28 -0
  52. package/skill-assets/sunlint-code-quality/rules/ruby/RB026-avoid-deep-nesting.md +38 -0
  53. package/skill-assets/sunlint-code-quality/rules/ruby/RB027-guard-clauses.md +37 -0
  54. package/skill-assets/sunlint-code-quality/rules/ruby/RB028-class-length.md +32 -0
  55. package/skill-assets/sunlint-code-quality/rules/ruby/RB029-meaningful-names.md +30 -0
  56. package/skill-assets/sunlint-code-quality/rules/ruby/RB030-dry-principle.md +37 -0
  57. package/skill-assets/sunlint-code-quality/rules/ruby/RB031-mvc-architecture.md +37 -0
  58. package/skill-assets/sunlint-code-quality/rules/ruby/RB032-use-concerns.md +31 -0
  59. package/skill-assets/sunlint-code-quality/rules/ruby/RB033-moderate-callbacks.md +31 -0
  60. package/skill-assets/sunlint-code-quality/rules/ruby/RB034-use-decorators.md +33 -0
  61. package/skill-assets/sunlint-code-quality/rules/ruby/RB035-comprehensive-tests.md +32 -0
  62. package/skill-assets/sunlint-code-quality/rules/ruby/RB036-frozen-string-literal.md +29 -0
  63. package/skill-assets/sunlint-code-quality/rules/ruby/RB037-it-parameter.md +25 -0
  64. package/skill-assets/sunlint-code-quality/rules/ruby/RB038-modern-enum-syntax.md +28 -0
  65. package/skill-assets/sunlint-code-quality/rules/ruby/RB039-solid-adapters.md +29 -0
  66. package/skill-assets/sunlint-code-quality/rules/ruby/RB040-rails-authentication.md +26 -0
  67. package/skill-assets/sunlint-code-quality/rules/ruby/RB041-async-query-loading.md +29 -0
  68. package/skill-assets/sunlint-code-quality/rules/ruby/RB042-hotwire-turbo.md +30 -0
  69. package/skill-assets/sunlint-code-quality/rules/ruby/RB043-use-propshaft.md +27 -0
  70. package/skill-assets/sunlint-code-quality/rules/ruby/RB044-structured-logging.md +35 -0
  71. package/skill-assets/sunlint-code-quality/rules/ruby/RB045-prism-parser.md +29 -0
  72. package/skill-assets/sunlint-code-quality/rules/swift/SW001-block-based-kvo.md +40 -0
  73. package/skill-assets/sunlint-code-quality/rules/swift/SW002-class-delegate-protocol.md +36 -0
  74. package/skill-assets/sunlint-code-quality/rules/swift/SW003-compiler-protocol-init.md +28 -0
  75. package/skill-assets/sunlint-code-quality/rules/swift/SW004-contains-over-filter-count.md +28 -0
  76. package/skill-assets/sunlint-code-quality/rules/swift/SW005-convenience-type.md +34 -0
  77. package/skill-assets/sunlint-code-quality/rules/swift/SW006-discarded-notification-center-observer.md +41 -0
  78. package/skill-assets/sunlint-code-quality/rules/swift/SW007-discouraged-direct-init.md +28 -0
  79. package/skill-assets/sunlint-code-quality/rules/swift/SW008-discouraged-optional-boolean.md +32 -0
  80. package/skill-assets/sunlint-code-quality/rules/swift/SW009-empty-count.md +30 -0
  81. package/skill-assets/sunlint-code-quality/rules/swift/SW010-empty-string.md +30 -0
  82. package/skill-assets/sunlint-code-quality/rules/swift/SW011-explicit-init.md +26 -0
  83. package/skill-assets/sunlint-code-quality/rules/swift/SW012-fatal-error-message.md +28 -0
  84. package/skill-assets/sunlint-code-quality/rules/swift/SW013-for-where.md +30 -0
  85. package/skill-assets/sunlint-code-quality/rules/swift/SW014-force-cast.md +26 -0
  86. package/skill-assets/sunlint-code-quality/rules/swift/SW015-force-try.md +30 -0
  87. package/skill-assets/sunlint-code-quality/rules/swift/SW016-force-unwrapping.md +32 -0
  88. package/skill-assets/sunlint-code-quality/rules/swift/SW017-function-parameter-count.md +37 -0
  89. package/skill-assets/sunlint-code-quality/rules/swift/SW018-large-tuple.md +41 -0
  90. package/skill-assets/sunlint-code-quality/rules/swift/SW019-legacy-constructor.md +28 -0
  91. package/skill-assets/sunlint-code-quality/rules/swift/SW020-nesting.md +38 -0
  92. package/skill-assets/sunlint-code-quality/rules/swift/SW021-no-extension-access-modifier.md +28 -0
  93. package/skill-assets/sunlint-code-quality/rules/swift/SW022-overridden-super-call.md +30 -0
  94. package/skill-assets/sunlint-code-quality/rules/swift/SW023-override-in-extension.md +32 -0
  95. package/skill-assets/sunlint-code-quality/rules/swift/SW024-private-over-fileprivate.md +28 -0
  96. package/skill-assets/sunlint-code-quality/rules/swift/SW025-private-unit-test.md +32 -0
  97. package/skill-assets/sunlint-code-quality/rules/swift/SW026-prohibited-super-call.md +29 -0
  98. package/skill-assets/sunlint-code-quality/rules/swift/SW027-sorted-first-last.md +28 -0
  99. package/skill-assets/sunlint-code-quality/rules/swift/SW028-syntactic-sugar.md +28 -0
  100. package/skill-assets/sunlint-code-quality/rules/swift/SW029-unused-closure-parameter.md +28 -0
  101. package/skill-assets/sunlint-code-quality/rules/swift/SW030-unused-enumerated.md +28 -0
  102. package/skill-assets/sunlint-code-quality/rules/swift/SW031-unused-optional-binding.md +26 -0
  103. package/skill-assets/sunlint-code-quality/rules/swift/SW032-valid-ibinspectable.md +26 -0
  104. package/skill-assets/sunlint-code-quality/rules/swift/SW033-vertical-parameter-alignment.md +36 -0
  105. package/skill-assets/sunlint-code-quality/rules/swift/SW034-void-return.md +28 -0
  106. package/skill-assets/sunlint-code-quality/rules/swift/SW035-weak-delegate.md +28 -0
@@ -0,0 +1,24 @@
1
+ ---
2
+ title: Pubspec dependencies should be reviewed regularly
3
+ impact: MEDIUM
4
+ impactDescription: Ensure dependencies are kept up-to-date for security and stability
5
+ tags: maintenance, security, dependencies
6
+ ---
7
+
8
+ ## Pubspec dependencies should be reviewed regularly
9
+
10
+ Dependencies in `pubspec.yaml` should be reviewed and updated regularly (at least every 4 months). Outdated dependencies may contain security vulnerabilities or miss critical performance improvements.
11
+
12
+ **Incorrect (old lock file):**
13
+
14
+ ```text
15
+ # pubspec.lock last modified: 6 months ago
16
+ ```
17
+
18
+ **Correct (regularly updated):**
19
+
20
+ ```text
21
+ # run 'flutter pub upgrade' and review dependencies regularly
22
+ ```
23
+
24
+ **Tools:** Custom analyzer (D017)
@@ -0,0 +1,34 @@
1
+ ---
2
+ title: Remove Commented-Out Code
3
+ impact: LOW
4
+ impactDescription: Keep codebase clean by removing commented-out code
5
+ tags: cleanliness, readability, maintenance
6
+ ---
7
+
8
+ ## Remove Commented-Out Code
9
+
10
+ Commented-out code should be removed instead of being left in the source files. Dead code comments create clutter and confusion. If you need to reference old code, rely on version control (Git).
11
+
12
+ **Incorrect (abandoned code):**
13
+
14
+ ```dart
15
+ void calculate() {
16
+ final result = 10 + 5;
17
+ // print("Debug result: $result");
18
+ // if (result > 10) {
19
+ // doSomething();
20
+ // }
21
+ return result;
22
+ }
23
+ ```
24
+
25
+ **Correct (clean file):**
26
+
27
+ ```dart
28
+ void calculate() {
29
+ final result = 10 + 5;
30
+ return result;
31
+ }
32
+ ```
33
+
34
+ **Tools:** Custom analyzer (D018)
@@ -0,0 +1,31 @@
1
+ ---
2
+ title: Avoid Single Child in Multi-Child Widget
3
+ impact: LOW
4
+ impactDescription: Use appropriate widget types for the number of children
5
+ tags: performance, efficiency, best-practices
6
+ ---
7
+
8
+ ## Avoid Single Child in Multi-Child Widget
9
+
10
+ Multi-child widgets like `Column`, `Row`, `Stack`, `ListView`, or `GridView` are inefficient when used with only a single child. Use single-child optimized widgets like `SizedBox`, `Padding`, `Center`, or `Container` instead.
11
+
12
+ **Incorrect (inefficient Column):**
13
+
14
+ ```dart
15
+ Column(
16
+ children: [
17
+ Text("Only one child here"),
18
+ ],
19
+ )
20
+ ```
21
+
22
+ **Correct (efficient wrapper):**
23
+
24
+ ```dart
25
+ Padding(
26
+ padding: const EdgeInsets.all(8.0),
27
+ child: Text("Only one child here"),
28
+ )
29
+ ```
30
+
31
+ **Tools:** Custom analyzer (D019)
@@ -0,0 +1,41 @@
1
+ ---
2
+ title: Limit If/Else Branches
3
+ impact: LOW
4
+ impactDescription: Reduce complexity by limiting the number of if/else branches
5
+ tags: readability, complexity, clean-code
6
+ ---
7
+
8
+ ## Limit If/Else Branches
9
+
10
+ Complex if/else chains with more than 3 branches reduce code readability and increase cyclomatic complexity. When facing multiple branches, consider using `switch` statements, lookup tables (Maps), or the Strategy pattern.
11
+
12
+ **Incorrect (long if/else chain):**
13
+
14
+ ```dart
15
+ if (type == 'A') {
16
+ doA();
17
+ } else if (type == 'B') {
18
+ doB();
19
+ } else if (type == 'C') {
20
+ doC();
21
+ } else if (type == 'D') {
22
+ doD();
23
+ } else {
24
+ doDefault();
25
+ }
26
+ ```
27
+
28
+ **Correct (using switch or Map):**
29
+
30
+ ```dart
31
+ // Option 1: Switch (better readability)
32
+ switch (type) {
33
+ case 'A': doA(); break;
34
+ case 'B': doB(); break;
35
+ case 'C': doC(); break;
36
+ case 'D': doD(); break;
37
+ default: doDefault();
38
+ }
39
+ ```
40
+
41
+ **Tools:** Custom analyzer (D020)
@@ -0,0 +1,26 @@
1
+ ---
2
+ title: Avoid Negated Boolean Checks
3
+ impact: LOW
4
+ impactDescription: Improve code readability by avoiding inverted or negated boolean conditions
5
+ tags: readability, logic, clean-code
6
+ ---
7
+
8
+ ## Avoid Negated Boolean Checks
9
+
10
+ Negated boolean checks (using `!`) make code harder to read and understand. Replace negative conditions with positive ones wherever possible, and avoid double negations like `!!`.
11
+
12
+ **Incorrect (fragmented logic):**
13
+
14
+ ```dart
15
+ if (!isNotAuthorized) { ... }
16
+ if (!(a == b)) { ... }
17
+ ```
18
+
19
+ **Correct (clear logic):**
20
+
21
+ ```dart
22
+ if (isAuthorized) { ... }
23
+ if (a != b) { ... }
24
+ ```
25
+
26
+ **Tools:** Custom analyzer (D021)
@@ -0,0 +1,35 @@
1
+ ---
2
+ title: Use setState Correctly
3
+ impact: HIGH
4
+ impactDescription: Ensure setState is used correctly in StatefulWidget to avoid performance issues and bugs
5
+ tags: performance, best-practices, lifecycle, state-management
6
+ ---
7
+
8
+ ## Use setState Correctly
9
+
10
+ Common `setState` anti-patterns include: calling `setState` inside `build()`, nesting `setState` calls, making multiple `setState` calls in the same method, or using async callbacks inside `setState`. These lead to performance issues, unnecessary rebuilds, or hard-to-track UI bugs.
11
+
12
+ **Incorrect (async inside setState):**
13
+
14
+ ```dart
15
+ setState(() async {
16
+ await fetchData(); // WRONG: setState should be synchronous
17
+ _data = "new data";
18
+ });
19
+ ```
20
+
21
+ **Correct (sync update after async):**
22
+
23
+ ```dart
24
+ // Fetch data first
25
+ final newData = await fetchData();
26
+
27
+ // Update state synchronously
28
+ if (mounted) {
29
+ setState(() {
30
+ _data = newData;
31
+ });
32
+ }
33
+ ```
34
+
35
+ **Tools:** Custom analyzer (D022)
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Avoid Unnecessary Method Overrides
3
+ impact: LOW
4
+ impactDescription: Remove methods that only call super with the same parameters as they add no value
5
+ tags: readability, clean-code, refactoring
6
+ ---
7
+
8
+ ## Avoid Unnecessary Method Overrides
9
+
10
+ Methods that override a parent method but only call `super.methodName()` with the same parameters are unnecessary and should be removed. These empty overrides add no functionality and create unnecessary code clutter. Common examples include lifecycle methods like `initState()`, `dispose()`, or `didUpdateWidget()` that only call their super implementation.
11
+
12
+ **Incorrect (super call only):**
13
+
14
+ ```dart
15
+ @override
16
+ void initState() {
17
+ super.initState();
18
+ }
19
+
20
+ @override
21
+ void dispose() {
22
+ super.dispose();
23
+ }
24
+ ```
25
+
26
+ **Correct (remove if no logic):**
27
+
28
+ ```dart
29
+ // Just remove the method override entirely if it only calls super
30
+ ```
31
+
32
+ **Tools:** Custom analyzer (D023)
@@ -0,0 +1,45 @@
1
+ ---
2
+ title: Avoid Unnecessary StatefulWidget
3
+ impact: LOW
4
+ impactDescription: Use StatelessWidget when no state management is needed to improve performance
5
+ tags: performance, flutter, widgets, best-practices
6
+ ---
7
+
8
+ ## Avoid Unnecessary StatefulWidget
9
+
10
+ StatefulWidget should only be used when the widget needs to maintain mutable state that changes over time. If a widget extends StatefulWidget but its State class has no mutable fields, never calls setState(), and doesn't use lifecycle methods beyond build(), it should be converted to StatelessWidget. StatelessWidget is more efficient as it doesn't maintain state and has less overhead.
11
+
12
+ **Incorrect (StatefulWidget with no state):**
13
+
14
+ ```dart
15
+ class MyTitle extends StatefulWidget {
16
+ final String text;
17
+ const MyTitle({super.key, required this.text});
18
+
19
+ @override
20
+ State<MyTitle> createState() => _MyTitleState();
21
+ }
22
+
23
+ class _MyTitleState extends State<MyTitle> {
24
+ @override
25
+ Widget build(BuildContext context) {
26
+ return Text(widget.text);
27
+ }
28
+ }
29
+ ```
30
+
31
+ **Correct (StatelessWidget):**
32
+
33
+ ```dart
34
+ class MyTitle extends StatelessWidget {
35
+ final String text;
36
+ const MyTitle({super.key, required this.text});
37
+
38
+ @override
39
+ Widget build(BuildContext context) {
40
+ return Text(text);
41
+ }
42
+ }
43
+ ```
44
+
45
+ **Tools:** Custom analyzer (D024)
@@ -0,0 +1,35 @@
1
+ ---
2
+ title: Avoid Nested Conditional Expressions
3
+ impact: LOW
4
+ impactDescription: Improve code readability by avoiding nested ternary operators
5
+ tags: readability, maintainability, clean-code
6
+ ---
7
+
8
+ ## Avoid Nested Conditional Expressions
9
+
10
+ Nested conditional expressions (ternary operators like `a ? b : c ? d : e`) reduce code readability significantly. When logic is complex, use if-else statements or extract the logic into a well-named variable or function.
11
+
12
+ **Incorrect (hard to follow):**
13
+
14
+ ```dart
15
+ final color = isAdmin ? Colors.red : isLogged ? Colors.green : Colors.grey;
16
+ ```
17
+
18
+ **Correct (descriptive logic):**
19
+
20
+ ```dart
21
+ // Option 1: if-else
22
+ Color userColor;
23
+ if (isAdmin) {
24
+ userColor = Colors.red;
25
+ } else if (isLogged) {
26
+ userColor = Colors.green;
27
+ } else {
28
+ userColor = Colors.grey;
29
+ }
30
+
31
+ // Option 2: Extracted getter
32
+ Color get userColor => _calculateUserColor();
33
+ ```
34
+
35
+ **Tools:** Custom analyzer (D025)
@@ -0,0 +1,30 @@
1
+ ---
2
+ title: Use snake_case for symbols, methods, and variables
3
+ impact: MEDIUM
4
+ impactDescription: Follow Ruby community naming conventions for consistency and readability.
5
+ tags: ruby, naming, snake_case, convention
6
+ ---
7
+
8
+ ## Use snake_case for symbols, methods, and variables
9
+
10
+ Follow Ruby community naming conventions for consistency and readability. Use `snake_case` (all lowercase with underscores) for symbols, methods, and variables. Avoid camelCase or other naming styles for these elements.
11
+
12
+ **Incorrect:**
13
+
14
+ ```ruby
15
+ def calculateTotal(price, taxRate)
16
+ totalAmount = price * taxRate
17
+ :orderStatus
18
+ end
19
+ ```
20
+
21
+ **Correct:**
22
+
23
+ ```ruby
24
+ def calculate_total(price, tax_rate)
25
+ total_amount = price * tax_rate
26
+ :order_status
27
+ end
28
+ ```
29
+
30
+ **Tools:** RuboCop (`Naming/VariableName`, `Naming/MethodName`)
@@ -0,0 +1,38 @@
1
+ ---
2
+ title: Use CamelCase for classes and modules
3
+ impact: MEDIUM
4
+ impactDescription: Follow Ruby community naming conventions for classes and modules.
5
+ tags: ruby, naming, CamelCase, architecture
6
+ ---
7
+
8
+ ## Use CamelCase for classes and modules
9
+
10
+ Use `CamelCase` (also known as PascalCase) for class and module names. Keep acronyms uppercase (e.g., `HTTPClient`, `XMLParser`).
11
+
12
+ **Incorrect:**
13
+
14
+ ```ruby
15
+ class User_profile
16
+ end
17
+
18
+ module Api_Helper
19
+ end
20
+
21
+ class HttpClient # Acronym 'HTTP' should be all caps
22
+ end
23
+ ```
24
+
25
+ **Correct:**
26
+
27
+ ```ruby
28
+ class UserProfile
29
+ end
30
+
31
+ module ApiHelper
32
+ end
33
+
34
+ class HTTPClient
35
+ end
36
+ ```
37
+
38
+ **Tools:** RuboCop (`Naming/ClassName`)
@@ -0,0 +1,26 @@
1
+ ---
2
+ title: Use SCREAMING_SNAKE_CASE for constants
3
+ impact: LOW
4
+ impactDescription: Clearly distinguish constants from other identifiers.
5
+ tags: ruby, naming, constants, readability
6
+ ---
7
+
8
+ ## Use SCREAMING_SNAKE_CASE for constants
9
+
10
+ Clearly distinguish constants from other identifiers. Use `SCREAMING_SNAKE_CASE` for constants that do not refer to classes or modules.
11
+
12
+ **Incorrect:**
13
+
14
+ ```ruby
15
+ DefaultTimeout = 30
16
+ Max_Retry_Count = 5
17
+ ```
18
+
19
+ **Correct:**
20
+
21
+ ```ruby
22
+ DEFAULT_TIMEOUT = 30
23
+ MAX_RETRY_COUNT = 5
24
+ ```
25
+
26
+ **Tools:** RuboCop (`Naming/ConstantName`)
@@ -0,0 +1,36 @@
1
+ ---
2
+ title: Predicate methods should end with ?
3
+ impact: MEDIUM
4
+ impactDescription: Make boolean-returning methods immediately recognizable.
5
+ tags: ruby, naming, predicate, boolean
6
+ ---
7
+
8
+ ## Predicate methods should end with ?
9
+
10
+ Make boolean-returning methods immediately recognizable. Methods that return boolean values should end with a question mark (`?`). Avoid prefixing with auxiliary verbs like `is_`, `does_`, or `can_`.
11
+
12
+ **Incorrect:**
13
+
14
+ ```ruby
15
+ def is_valid
16
+ # logic
17
+ end
18
+
19
+ if user.is_authenticated
20
+ # logic
21
+ end
22
+ ```
23
+
24
+ **Correct:**
25
+
26
+ ```ruby
27
+ def valid?
28
+ # logic
29
+ end
30
+
31
+ if user.authenticated?
32
+ # logic
33
+ end
34
+ ```
35
+
36
+ **Tools:** RuboCop (`Naming/PredicateName`)
@@ -0,0 +1,36 @@
1
+ ---
2
+ title: Dangerous methods should end with !
3
+ impact: MEDIUM
4
+ impactDescription: Clearly indicate methods that modify the receiver or can raise exceptions.
5
+ tags: ruby, naming, bang, side-effect
6
+ ---
7
+
8
+ ## Dangerous methods should end with !
9
+
10
+ Clearly indicate methods that modify the receiver or can raise exceptions. Methods that modify the object in place or can raise exceptions should end with a bang (`!`).
11
+
12
+ **Incorrect:**
13
+
14
+ ```ruby
15
+ # Method raises an exception if validation fails
16
+ def save
17
+ # complex logic
18
+ end
19
+
20
+ # In-place sort
21
+ values.sort
22
+ ```
23
+
24
+ **Correct:**
25
+
26
+ ```ruby
27
+ # Recommends save! for raising exceptions
28
+ def save!
29
+ # complex logic
30
+ end
31
+
32
+ # Indicates in-place sort
33
+ values.sort!
34
+ ```
35
+
36
+ **Tools:** RuboCop (`Style/BangPredicate`)
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Use 2 spaces for indentation
3
+ impact: LOW
4
+ impactDescription: Follow Ruby community standard for code formatting.
5
+ tags: ruby, formatting, indentation, style
6
+ ---
7
+
8
+ ## Use 2 spaces for indentation
9
+
10
+ Follow Ruby community standard for code formatting. Use 2 spaces for indentation, never tabs. Ensure consistent indentation throughout the codebase.
11
+
12
+ **Incorrect:**
13
+
14
+ ```ruby
15
+ def hello
16
+ puts "hello" # Tab used
17
+ end
18
+
19
+ def world
20
+ puts "world" # 4 spaces used
21
+ end
22
+ ```
23
+
24
+ **Correct:**
25
+
26
+ ```ruby
27
+ def hello
28
+ puts "hello" # 2 spaces
29
+ end
30
+ ```
31
+
32
+ **Tools:** RuboCop (`Layout/IndentationWidth`)
@@ -0,0 +1,25 @@
1
+ ---
2
+ title: Keep lines under 120 characters
3
+ impact: LOW
4
+ impactDescription: Improve code readability and prevent horizontal scrolling.
5
+ tags: ruby, formatting, readability, side-scrolling
6
+ ---
7
+
8
+ ## Keep lines under 120 characters
9
+
10
+ Improve code readability and prevent horizontal scrolling. Limit line length to 120 characters maximum. Break long lines into multiple lines when necessary.
11
+
12
+ **Incorrect:**
13
+
14
+ ```ruby
15
+ puts "This is an extremely long string that definitely exceeds the recommended limit of one hundred and twenty characters that we have set for our coding standards in this project."
16
+ ```
17
+
18
+ **Correct:**
19
+
20
+ ```ruby
21
+ puts "This is an extremely long string that definitely exceeds " \
22
+ "the recommended limit of one hundred and twenty characters..."
23
+ ```
24
+
25
+ **Tools:** RuboCop (`Layout/LineLength`)
@@ -0,0 +1,36 @@
1
+ ---
2
+ title: Avoid rescuing the Exception class
3
+ impact: HIGH
4
+ impactDescription: Prevent hiding critical system errors.
5
+ tags: ruby, errors, exception, safety
6
+ ---
7
+
8
+ ## Avoid rescuing the Exception class
9
+
10
+ Prevent hiding critical system errors. Never rescue the generic `Exception` class as it catches system-level errors (like `SignalException`, `NoMemoryError`, `SystemExit`). Rescue specific exception classes or `StandardError` instead.
11
+
12
+ **Incorrect (Dangerous):**
13
+
14
+ ```ruby
15
+ begin
16
+ do_something
17
+ rescue Exception => e
18
+ logger.error(e.message)
19
+ end
20
+ ```
21
+
22
+ **Correct (Safe):**
23
+
24
+ ```ruby
25
+ begin
26
+ do_something
27
+ rescue StandardError => e # Or just 'rescue => e' which defaults to StandardError
28
+ logger.error(e.message)
29
+ end
30
+
31
+ # Or specific
32
+ rescue ActiveRecord::RecordNotFound => e
33
+ # handle
34
+ ```
35
+
36
+ **Tools:** RuboCop (`Lint/RescueException`)
@@ -0,0 +1,41 @@
1
+ ---
2
+ title: Use save! or handle return values
3
+ impact: HIGH
4
+ impactDescription: Ensure database operations are properly validated and errors are not silently ignored.
5
+ tags: rails, database, validations, active-record
6
+ ---
7
+
8
+ ## Use save! or handle return values
9
+
10
+ Ensure database operations are properly validated and errors are not silently ignored. Use bang methods (`save!`, `create!`, `update!`, `destroy!`) to raise exceptions on failure. If using non-bang methods, always check the return value.
11
+
12
+ **Incorrect:**
13
+
14
+ ```ruby
15
+ def create
16
+ @user = User.new(user_params)
17
+ @user.save # Failure will be silent
18
+ redirect_to @user
19
+ end
20
+ ```
21
+
22
+ **Correct:**
23
+
24
+ ```ruby
25
+ def create
26
+ @user = User.new(user_params)
27
+ if @user.save
28
+ redirect_to @user
29
+ else
30
+ render :new
31
+ end
32
+ end
33
+
34
+ # Or using bang
35
+ def create
36
+ @user = User.create!(user_params)
37
+ redirect_to @user
38
+ end
39
+ ```
40
+
41
+ **Tools:** RuboCop (`Rails/SaveBang`)
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Avoid N+1 queries with eager loading
3
+ impact: HIGH
4
+ impactDescription: Prevent performance issues caused by N+1 query problems.
5
+ tags: rails, performance, database, n+1, active-record
6
+ ---
7
+
8
+ ## Avoid N+1 queries with eager loading
9
+
10
+ Prevent performance issues caused by N+1 query problems. Use `includes`, `preload`, or `eager_load` to load associations upfront. Avoid iterating over collections and accessing associations without eager loading.
11
+
12
+ **Incorrect:**
13
+
14
+ ```ruby
15
+ # Triggers N+1 queries (one query for users, and one query per user for posts)
16
+ users = User.limit(10)
17
+ users.each do |user|
18
+ puts user.posts.count
19
+ end
20
+ ```
21
+
22
+ **Correct:**
23
+
24
+ ```ruby
25
+ # Eager loads posts in 2 queries total
26
+ users = User.includes(:posts).limit(10)
27
+ users.each do |user|
28
+ puts user.posts.count
29
+ end
30
+ ```
31
+
32
+ **Tools:** Bullet gem, RuboCop Rails (`Rails/FindEach`)
@@ -0,0 +1,30 @@
1
+ ---
2
+ title: Use find_each for large collections
3
+ impact: HIGH
4
+ impactDescription: Reduce memory consumption when iterating over large datasets.
5
+ tags: rails, performance, database, memory, active-record
6
+ ---
7
+
8
+ ## Use find_each for large collections
9
+
10
+ Reduce memory consumption when iterating over large datasets. Use `find_each` or `find_in_batches` instead of `each` for large ActiveRecord collections. `find_each` loads records in batches (default 1000) to avoid loading all records into memory at once.
11
+
12
+ **Incorrect:**
13
+
14
+ ```ruby
15
+ # Loads ALL users into memory, which can crash the process for large datasets
16
+ User.all.each do |user|
17
+ user.do_something
18
+ end
19
+ ```
20
+
21
+ **Correct:**
22
+
23
+ ```ruby
24
+ # Loads users in batches of 1000
25
+ User.find_each do |user|
26
+ user.do_something
27
+ end
28
+ ```
29
+
30
+ **Tools:** RuboCop (`Rails/FindEach`)