Allow default to be configured for Enum#39820
Conversation
kamipo
commented
Jul 10, 2020
```ruby class Book < ActiveRecord::Base enum status: [:proposed, :written, :published], _default: :published end Book.new.status # => "published" ```
Before this change using a boolean or TINYINT as a enum value would be set correctly in the database, but always return nil. This behavior changed in: rails#39820
|
Maybe a silly question, but why is default prefixed with an underscore? |
|
@dwightwatson I had similar question asked here: #39895 (comment) Thanks, @kamipo 👍 .
I am sorry but I did not clearly understand so I am putting it here again. Hope you don't mind 😊 . The enum options like |
|
If people have a |
|
@kamipo would it be possible to have a second parameter that will be hash (to differentiate between data) like: enum default: [:foo, :bar], { default: :foo }Using this approach you could:
What are your thoughts? |
|
It is impossible to omit hash braces for non-last arguments. |
Unlike other features built on Attribute API, reserved options for `enum` has leading `_`. * `_prefix`/`_suffix`: rails#19813, rails#20999 * `_scopes`: rails#34605 * `_default`: rails#39820 That is due to `enum` takes one hash argument only, which contains both enum definitions and reserved options. I propose new syntax for `enum` to avoid leading `_` from reserved options, by allowing `enum(attr_name, ..., **options)` more Attribute API like syntax. Before: ```ruby class Book < ActiveRecord::Base enum status: [ :proposed, :written ], _prefix: true, _scopes: false enum cover: [ :hard, :soft ], _suffix: true, _default: :hard end ``` After: ```ruby class Book < ActiveRecord::Base enum :status, [ :proposed, :written ], prefix: true, scopes: false enum :cover, [ :hard, :soft ], suffix: true, default: :hard end ```
|
It looks like the default value does not apply to |
|
@pomartel For what it's worth, I was feeling the same way when I discovered the same issue today, and was about to write up a test for a pull request, but as I thought about it, I'm pretty sure rails expects us to add the default value for pre-existing records through a migration. I can't say I share your opinion that it would be disruptive to add this change even with millions of rows of nulls. If you want the default to be a certain value in the code, what's stopping you from making it so in the database? Happy to hear your explanation if you'd like to elaborate. UPDATE I also had to add a migration to update existing records from null to the new default |
|
@joemsak I am not quite sure how to update millions of records in a non-blocking way but I am also no database expert. I just wish there was a way to set a default for NULL values without touching the database. I tried to override the getter but it did not play nice with the enum. |
|
@pomartel Gotcha yeah. I would have to say it would have to be done in a scheduled maintenance window while shutting down access to the database. Unless you have rolling migrations enabled but I don't know off hand how to do that. I prefer scheduling the maintenance period, alerting customers, getting a backup snapshot, and doing the migrations at the scheduled time. As for overriding, yeah, I started getting into the guts of active record enum/attributes and based on the workflow of the code it really seems like Rails would prefer we just have a default set and updated on all null rows in the database. |