@sun-asterisk/sunlint 1.3.41 → 1.3.43

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 (120) hide show
  1. package/package.json +1 -1
  2. package/rules/security/S024_xpath_xxe_protection/typescript/regex-based-analyzer.js +4 -4
  3. package/rules/security/S024_xpath_xxe_protection/typescript/symbol-based-analyzer.js +1 -1
  4. package/rules/security/S025_server_side_validation/typescript/regex-based-analyzer.js +5 -5
  5. package/rules/security/S025_server_side_validation/typescript/symbol-based-analyzer.js +6 -6
  6. package/rules/security/S032_httponly_session_cookies/typescript/regex-based-analyzer.js +8 -8
  7. package/rules/security/S033_samesite_session_cookies/typescript/regex-based-analyzer.js +12 -12
  8. package/rules/security/S033_samesite_session_cookies/typescript/symbol-based-analyzer.js +1 -1
  9. package/rules/security/S034_host_prefix_session_cookies/typescript/regex-based-analyzer.js +1 -1
  10. package/rules/security/S041_session_token_invalidation/typescript/regex-based-analyzer.js +4 -4
  11. package/rules/security/S041_session_token_invalidation/typescript/symbol-based-analyzer.js +1 -1
  12. package/rules/security/S044_re_authentication_required/typescript/regex-based-analyzer.js +1 -1
  13. package/rules/security/S044_re_authentication_required/typescript/symbol-based-analyzer.js +1 -1
  14. package/rules/security/S045_brute_force_protection/typescript/analyzer.js +1 -1
  15. package/rules/security/S045_brute_force_protection/typescript/symbol-based-analyzer.js +1 -1
  16. package/skill-assets/sunlint-code-quality/rules/dart/D001-recommended-lints.md +36 -0
  17. package/skill-assets/sunlint-code-quality/rules/dart/D002-dispose-resources.md +44 -0
  18. package/skill-assets/sunlint-code-quality/rules/dart/D003-prefer-widget-classes.md +53 -0
  19. package/skill-assets/sunlint-code-quality/rules/dart/D004-avoid-shrinkwrap.md +31 -0
  20. package/skill-assets/sunlint-code-quality/rules/dart/D005-widget-nesting.md +62 -0
  21. package/skill-assets/sunlint-code-quality/rules/dart/D006-large-callbacks.md +54 -0
  22. package/skill-assets/sunlint-code-quality/rules/dart/D007-lifecycle-order.md +44 -0
  23. package/skill-assets/sunlint-code-quality/rules/dart/D008-long-functions.md +37 -0
  24. package/skill-assets/sunlint-code-quality/rules/dart/D009-function-parameters.md +38 -0
  25. package/skill-assets/sunlint-code-quality/rules/dart/D010-cyclomatic-complexity.md +46 -0
  26. package/skill-assets/sunlint-code-quality/rules/dart/D011-named-parameters.md +31 -0
  27. package/skill-assets/sunlint-code-quality/rules/dart/D012-named-booleans.md +28 -0
  28. package/skill-assets/sunlint-code-quality/rules/dart/D013-single-public-class.md +34 -0
  29. package/skill-assets/sunlint-code-quality/rules/dart/D014-safe-collection-access.md +30 -0
  30. package/skill-assets/sunlint-code-quality/rules/dart/D015-copywith-consistency.md +52 -0
  31. package/skill-assets/sunlint-code-quality/rules/dart/D016-project-tests.md +32 -0
  32. package/skill-assets/sunlint-code-quality/rules/dart/D017-review-dependencies.md +24 -0
  33. package/skill-assets/sunlint-code-quality/rules/dart/D018-no-commented-code.md +34 -0
  34. package/skill-assets/sunlint-code-quality/rules/dart/D019-single-child-wrappers.md +31 -0
  35. package/skill-assets/sunlint-code-quality/rules/dart/D020-if-else-limit.md +41 -0
  36. package/skill-assets/sunlint-code-quality/rules/dart/D021-negated-booleans.md +26 -0
  37. package/skill-assets/sunlint-code-quality/rules/dart/D022-setstate-usage.md +35 -0
  38. package/skill-assets/sunlint-code-quality/rules/dart/D023-unnecessary-overrides.md +32 -0
  39. package/skill-assets/sunlint-code-quality/rules/dart/D024-avoid-unnecessary-statefulwidget.md +45 -0
  40. package/skill-assets/sunlint-code-quality/rules/dart/D025-nested-ternaries.md +35 -0
  41. package/skill-assets/sunlint-code-quality/rules/ruby/RB001-use-snake-case.md +30 -0
  42. package/skill-assets/sunlint-code-quality/rules/ruby/RB002-use-camel-case.md +38 -0
  43. package/skill-assets/sunlint-code-quality/rules/ruby/RB003-use-screaming-snake-case.md +26 -0
  44. package/skill-assets/sunlint-code-quality/rules/ruby/RB004-predicate-methods.md +36 -0
  45. package/skill-assets/sunlint-code-quality/rules/ruby/RB005-dangerous-methods.md +36 -0
  46. package/skill-assets/sunlint-code-quality/rules/ruby/RB006-indentation.md +32 -0
  47. package/skill-assets/sunlint-code-quality/rules/ruby/RB007-line-length.md +25 -0
  48. package/skill-assets/sunlint-code-quality/rules/ruby/RB008-rescue-exception.md +36 -0
  49. package/skill-assets/sunlint-code-quality/rules/ruby/RB009-save-bang.md +41 -0
  50. package/skill-assets/sunlint-code-quality/rules/ruby/RB010-avoid-n-plus-one.md +32 -0
  51. package/skill-assets/sunlint-code-quality/rules/ruby/RB011-use-find-each.md +30 -0
  52. package/skill-assets/sunlint-code-quality/rules/ruby/RB012-sql-injection.md +29 -0
  53. package/skill-assets/sunlint-code-quality/rules/ruby/RB013-prefer-has-many-through.md +35 -0
  54. package/skill-assets/sunlint-code-quality/rules/ruby/RB014-dependent-associations.md +28 -0
  55. package/skill-assets/sunlint-code-quality/rules/ruby/RB015-modern-validations.md +29 -0
  56. package/skill-assets/sunlint-code-quality/rules/ruby/RB016-thin-controllers.md +45 -0
  57. package/skill-assets/sunlint-code-quality/rules/ruby/RB017-avoid-fat-models.md +41 -0
  58. package/skill-assets/sunlint-code-quality/rules/ruby/RB018-service-objects.md +36 -0
  59. package/skill-assets/sunlint-code-quality/rules/ruby/RB019-avoid-metaprogramming.md +40 -0
  60. package/skill-assets/sunlint-code-quality/rules/ruby/RB020-use-pluck.md +29 -0
  61. package/skill-assets/sunlint-code-quality/rules/ruby/RB021-use-size.md +27 -0
  62. package/skill-assets/sunlint-code-quality/rules/ruby/RB022-order-by-timestamps.md +24 -0
  63. package/skill-assets/sunlint-code-quality/rules/ruby/RB023-where-missing.md +24 -0
  64. package/skill-assets/sunlint-code-quality/rules/ruby/RB024-method-length.md +41 -0
  65. package/skill-assets/sunlint-code-quality/rules/ruby/RB025-parameter-limits.md +28 -0
  66. package/skill-assets/sunlint-code-quality/rules/ruby/RB026-avoid-deep-nesting.md +38 -0
  67. package/skill-assets/sunlint-code-quality/rules/ruby/RB027-guard-clauses.md +37 -0
  68. package/skill-assets/sunlint-code-quality/rules/ruby/RB028-class-length.md +32 -0
  69. package/skill-assets/sunlint-code-quality/rules/ruby/RB029-meaningful-names.md +30 -0
  70. package/skill-assets/sunlint-code-quality/rules/ruby/RB030-dry-principle.md +37 -0
  71. package/skill-assets/sunlint-code-quality/rules/ruby/RB031-mvc-architecture.md +37 -0
  72. package/skill-assets/sunlint-code-quality/rules/ruby/RB032-use-concerns.md +31 -0
  73. package/skill-assets/sunlint-code-quality/rules/ruby/RB033-moderate-callbacks.md +31 -0
  74. package/skill-assets/sunlint-code-quality/rules/ruby/RB034-use-decorators.md +33 -0
  75. package/skill-assets/sunlint-code-quality/rules/ruby/RB035-comprehensive-tests.md +32 -0
  76. package/skill-assets/sunlint-code-quality/rules/ruby/RB036-frozen-string-literal.md +29 -0
  77. package/skill-assets/sunlint-code-quality/rules/ruby/RB037-it-parameter.md +25 -0
  78. package/skill-assets/sunlint-code-quality/rules/ruby/RB038-modern-enum-syntax.md +28 -0
  79. package/skill-assets/sunlint-code-quality/rules/ruby/RB039-solid-adapters.md +29 -0
  80. package/skill-assets/sunlint-code-quality/rules/ruby/RB040-rails-authentication.md +26 -0
  81. package/skill-assets/sunlint-code-quality/rules/ruby/RB041-async-query-loading.md +29 -0
  82. package/skill-assets/sunlint-code-quality/rules/ruby/RB042-hotwire-turbo.md +30 -0
  83. package/skill-assets/sunlint-code-quality/rules/ruby/RB043-use-propshaft.md +27 -0
  84. package/skill-assets/sunlint-code-quality/rules/ruby/RB044-structured-logging.md +35 -0
  85. package/skill-assets/sunlint-code-quality/rules/ruby/RB045-prism-parser.md +29 -0
  86. package/skill-assets/sunlint-code-quality/rules/swift/SW001-block-based-kvo.md +40 -0
  87. package/skill-assets/sunlint-code-quality/rules/swift/SW002-class-delegate-protocol.md +36 -0
  88. package/skill-assets/sunlint-code-quality/rules/swift/SW003-compiler-protocol-init.md +28 -0
  89. package/skill-assets/sunlint-code-quality/rules/swift/SW004-contains-over-filter-count.md +28 -0
  90. package/skill-assets/sunlint-code-quality/rules/swift/SW005-convenience-type.md +34 -0
  91. package/skill-assets/sunlint-code-quality/rules/swift/SW006-discarded-notification-center-observer.md +41 -0
  92. package/skill-assets/sunlint-code-quality/rules/swift/SW007-discouraged-direct-init.md +28 -0
  93. package/skill-assets/sunlint-code-quality/rules/swift/SW008-discouraged-optional-boolean.md +32 -0
  94. package/skill-assets/sunlint-code-quality/rules/swift/SW009-empty-count.md +30 -0
  95. package/skill-assets/sunlint-code-quality/rules/swift/SW010-empty-string.md +30 -0
  96. package/skill-assets/sunlint-code-quality/rules/swift/SW011-explicit-init.md +26 -0
  97. package/skill-assets/sunlint-code-quality/rules/swift/SW012-fatal-error-message.md +28 -0
  98. package/skill-assets/sunlint-code-quality/rules/swift/SW013-for-where.md +30 -0
  99. package/skill-assets/sunlint-code-quality/rules/swift/SW014-force-cast.md +26 -0
  100. package/skill-assets/sunlint-code-quality/rules/swift/SW015-force-try.md +30 -0
  101. package/skill-assets/sunlint-code-quality/rules/swift/SW016-force-unwrapping.md +32 -0
  102. package/skill-assets/sunlint-code-quality/rules/swift/SW017-function-parameter-count.md +37 -0
  103. package/skill-assets/sunlint-code-quality/rules/swift/SW018-large-tuple.md +41 -0
  104. package/skill-assets/sunlint-code-quality/rules/swift/SW019-legacy-constructor.md +28 -0
  105. package/skill-assets/sunlint-code-quality/rules/swift/SW020-nesting.md +38 -0
  106. package/skill-assets/sunlint-code-quality/rules/swift/SW021-no-extension-access-modifier.md +28 -0
  107. package/skill-assets/sunlint-code-quality/rules/swift/SW022-overridden-super-call.md +30 -0
  108. package/skill-assets/sunlint-code-quality/rules/swift/SW023-override-in-extension.md +32 -0
  109. package/skill-assets/sunlint-code-quality/rules/swift/SW024-private-over-fileprivate.md +28 -0
  110. package/skill-assets/sunlint-code-quality/rules/swift/SW025-private-unit-test.md +32 -0
  111. package/skill-assets/sunlint-code-quality/rules/swift/SW026-prohibited-super-call.md +29 -0
  112. package/skill-assets/sunlint-code-quality/rules/swift/SW027-sorted-first-last.md +28 -0
  113. package/skill-assets/sunlint-code-quality/rules/swift/SW028-syntactic-sugar.md +28 -0
  114. package/skill-assets/sunlint-code-quality/rules/swift/SW029-unused-closure-parameter.md +28 -0
  115. package/skill-assets/sunlint-code-quality/rules/swift/SW030-unused-enumerated.md +28 -0
  116. package/skill-assets/sunlint-code-quality/rules/swift/SW031-unused-optional-binding.md +26 -0
  117. package/skill-assets/sunlint-code-quality/rules/swift/SW032-valid-ibinspectable.md +26 -0
  118. package/skill-assets/sunlint-code-quality/rules/swift/SW033-vertical-parameter-alignment.md +36 -0
  119. package/skill-assets/sunlint-code-quality/rules/swift/SW034-void-return.md +28 -0
  120. package/skill-assets/sunlint-code-quality/rules/swift/SW035-weak-delegate.md +28 -0
@@ -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`)
@@ -0,0 +1,29 @@
1
+ ---
2
+ title: Avoid SQL injection with parameterized queries
3
+ impact: CRITICAL
4
+ impactDescription: Prevent SQL injection vulnerabilities.
5
+ tags: ruby, rails, security, sql-injection, active-record
6
+ ---
7
+
8
+ ## Avoid SQL injection with parameterized queries
9
+
10
+ Prevent SQL injection vulnerabilities. Never use string interpolation in SQL queries. Use parameterized queries with `?` or named placeholders (`:name`). Use hash conditions for `where` clauses instead of SQL fragments.
11
+
12
+ **Incorrect (Vulnerable):**
13
+
14
+ ```ruby
15
+ # Direct interpolation is dangerous
16
+ User.where("name = '#{params[:name]}'")
17
+ ```
18
+
19
+ **Correct (Safe):**
20
+
21
+ ```ruby
22
+ # Parameterized
23
+ User.where("name = ?", params[:name])
24
+
25
+ # Hash-based (Recommended)
26
+ User.where(name: params[:name])
27
+ ```
28
+
29
+ **Tools:** Brakeman, RuboCop (`Rails/SquishedSQLHeredocs`)
@@ -0,0 +1,35 @@
1
+ ---
2
+ title: Prefer has_many :through over HABTM
3
+ impact: MEDIUM
4
+ impactDescription: Allow for additional attributes and validations on join models.
5
+ tags: rails, database, associations, active-record
6
+ ---
7
+
8
+ ## Prefer has_many :through over HABTM
9
+
10
+ Allow for additional attributes and validations on join models. Use `has_many :through` instead of `has_and_belongs_to_many` for many-to-many relationships. This provides more flexibility for adding attributes or validations to the join table later.
11
+
12
+ **Incorrect:**
13
+
14
+ ```ruby
15
+ class User < ApplicationRecord
16
+ has_and_belongs_to_many :roles
17
+ end
18
+ ```
19
+
20
+ **Correct:**
21
+
22
+ ```ruby
23
+ class User < ApplicationRecord
24
+ has_many :assignments
25
+ has_many :roles, through: :assignments
26
+ end
27
+
28
+ class Assignment < ApplicationRecord
29
+ belongs_to :user
30
+ belongs_to :role
31
+ # Can add validations or extra fields here
32
+ end
33
+ ```
34
+
35
+ **Tools:** RuboCop (`Rails/HasAndBelongsToMany`)
@@ -0,0 +1,28 @@
1
+ ---
2
+ title: Always define dependent option for associations
3
+ impact: HIGH
4
+ impactDescription: Prevent orphaned records and ensure data integrity.
5
+ tags: rails, database, data-integrity, active-record
6
+ ---
7
+
8
+ ## Always define dependent option for associations
9
+
10
+ Prevent orphaned records and ensure data integrity. Always specify the `dependent` option for `has_many` and `has_one` associations to define what happens to associated records when the parent is deleted.
11
+
12
+ **Incorrect:**
13
+
14
+ ```ruby
15
+ class User < ApplicationRecord
16
+ has_many :posts # No dependent option
17
+ end
18
+ ```
19
+
20
+ **Correct:**
21
+
22
+ ```ruby
23
+ class User < ApplicationRecord
24
+ has_many :posts, dependent: :destroy
25
+ end
26
+ ```
27
+
28
+ **Tools:** Custom linter, Manual Review
@@ -0,0 +1,29 @@
1
+ ---
2
+ title: Use new-style validations
3
+ impact: MEDIUM
4
+ impactDescription: Follow modern Rails conventions for model validations.
5
+ tags: rails, conventions, validations, active-record
6
+ ---
7
+
8
+ ## Use new-style validations
9
+
10
+ Follow modern Rails conventions for model validations. Use the `validates` method with a hash of options. Avoid old-style validations like `validates_presence_of`.
11
+
12
+ **Incorrect:**
13
+
14
+ ```ruby
15
+ class User < ApplicationRecord
16
+ validates_presence_of :email
17
+ validates_uniqueness_of :email
18
+ end
19
+ ```
20
+
21
+ **Correct:**
22
+
23
+ ```ruby
24
+ class User < ApplicationRecord
25
+ validates :email, presence: true, uniqueness: true
26
+ end
27
+ ```
28
+
29
+ **Tools:** RuboCop (`Rails/Validation`)
@@ -0,0 +1,45 @@
1
+ ---
2
+ title: Keep controllers thin
3
+ impact: HIGH
4
+ impactDescription: Maintain single responsibility and improve testability.
5
+ tags: rails, architecture, controllers, mvc
6
+ ---
7
+
8
+ ## Keep controllers thin
9
+
10
+ Maintain single responsibility and improve testability. Controllers should only handle HTTP requests and responses (parsing params, calling logic, redirecting/rendering). Extract complex business logic into service objects, models, or concerns.
11
+
12
+ **Incorrect:**
13
+
14
+ ```ruby
15
+ class OrdersController < ApplicationController
16
+ def create
17
+ @order = Order.new(order_params)
18
+ # Complex business logic in controller
19
+ if @order.save
20
+ Inventory.decrease(@order.product_id)
21
+ EmailService.send_confirmation(@order.user)
22
+ redirect_to @order
23
+ else
24
+ render :new
25
+ end
26
+ end
27
+ end
28
+ ```
29
+
30
+ **Correct:**
31
+
32
+ ```ruby
33
+ class OrdersController < ApplicationController
34
+ def create
35
+ @order = Order.new(order_params)
36
+ if OrderCreationService.call(@order)
37
+ redirect_to @order
38
+ else
39
+ render :new
40
+ end
41
+ end
42
+ end
43
+ ```
44
+
45
+ **Tools:** RuboCop (`Metrics/MethodLength`)
@@ -0,0 +1,41 @@
1
+ ---
2
+ title: Avoid fat models
3
+ impact: HIGH
4
+ impactDescription: Prevent models from becoming monolithic and hard to maintain.
5
+ tags: rails, architecture, models, mvc
6
+ ---
7
+
8
+ ## Avoid fat models
9
+
10
+ Prevent models from becoming monolithic and hard to maintain. Keep models focused on associations, validations, and simple domain logic. Extract complex workflows or unrelated concerns into service objects or specific classes.
11
+
12
+ **Incorrect:**
13
+
14
+ ```ruby
15
+ # User model handling too many things (auth, analytics, profile, etc.)
16
+ class User < ApplicationRecord
17
+ def generate_analytics_report
18
+ # complex logic unrelated to core User state
19
+ end
20
+
21
+ def process_subscription_upgrade
22
+ # complex workflow
23
+ end
24
+ end
25
+ ```
26
+
27
+ **Correct:**
28
+
29
+ ```ruby
30
+ class User < ApplicationRecord
31
+ # core logic only
32
+ end
33
+
34
+ class AnalyticsReportGenerator
35
+ def self.call(user)
36
+ # complex logic
37
+ end
38
+ end
39
+ ```
40
+
41
+ **Tools:** RuboCop (`Metrics/ClassLength`)