Class: RuboCop::Cop::DevDoc::Rails::EnumMustBeSymbolized
- Inherits:
-
Base
- Object
- Base
- RuboCop::Cop::DevDoc::Rails::EnumMustBeSymbolized
- Defined in:
- lib/rubocop/cop/dev_doc/rails/enum_must_be_symbolized.rb
Overview
Rails enum must never be declared directly — use glib-web's
enum_symbolize :name, { … } declaring form instead.
Rationale
Two problems with a bare enum:
- Type.
enumresolves its attribute type by introspecting the DB column. When the column doesn't exist yet — a not-yet-migrated column loaded on deploy, eager-loaded CI, or an un-migrated local DB — Rails raises "Undeclared attribute type for enum". Declaring the attribute up front (whichenum_symbolizedoes, from the enum's own values) removes that dependency on the column. - Reader.
enumdefines a reader that returns the string form, sorecord.status == :activesilently fails (:foo == 'foo'is false).enum_symbolizeoverrides the reader to return a symbol.
The enum_symbolize :name, { … } form does both in one call — it
declares the attribute, defines the enum, adds a presence validation,
and symbolizes the reader — so neither footgun can be reintroduced by
forgetting a pairing line.
See best_practices/backend/en/01a_defensive_programming.md item 7.
❌
class Order < ApplicationRecord
enum :payment_status, { draft: 0, pending: 1, finalized: 2 }
enum_symbolize :payment_status
end
✔
class Order < ApplicationRecord
enum_symbolize :payment_status, { draft: 0, pending: 1, finalized: 2 }
end
Enum options pass straight through:
✔
enum_symbolize :finalize_intent, { unknown: 0, charge: 1 }, prefix: true
Enums declared inside a concern's included do block are checked the
same way:
✔
included do
enum_symbolize :discount_type, DISCOUNT_TYPES
end
Constant Summary collapse
- MSG =
'Declare enums with `enum_symbolize :%<name>s, { … }` instead of `enum`, so the ' \ 'attribute type is set before the enum (surviving a not-yet-migrated column) and the ' \ 'reader returns a symbol (see backend/01a_defensive_programming.md item 7).'.freeze
Instance Method Summary collapse
-
#on_block(node) ⇒ Object
Concern-declared enums: `included do ...
- #on_class(node) ⇒ Object
Instance Method Details
#on_block(node) ⇒ Object
Concern-declared enums: included do ... end runs in the including
class's context, so its statements are checked like a class body.
77 78 79 80 81 |
# File 'lib/rubocop/cop/dev_doc/rails/enum_must_be_symbolized.rb', line 77 def on_block(node) return unless included_block?(node) check_body(node.body) end |
#on_class(node) ⇒ Object
71 72 73 |
# File 'lib/rubocop/cop/dev_doc/rails/enum_must_be_symbolized.rb', line 71 def on_class(node) check_body(node.body) end |