Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix enum writers when using integers #13542

Merged
merged 2 commits into from
Jan 1, 2014
Merged

Fix enum writers when using integers #13542

merged 2 commits into from
Jan 1, 2014

Conversation

robin850
Copy link
Member

Hello,

This is just a little pull request that resolves some issues mentioned in #13530. Basically, the problem is described in this gist. Previously, a call to:

Book.where(status: 0).first_or_initialize

Would fail (an ArgumentError would be raised) because only the symbol version of the enum was checked when calling its writer method. I guess that find_or_initialize is calling it through the initialize (new) method.

I also added a mention about the scopes generated dynamically based on the allowed values of the field in the documentation.

I'm not really comfortable with Active Record and its internals so I'm certainly not very clear ; therefore, sorry. Let me know if I should update anything.

By the way, the issue mentioned above is not totally resolved since the where method doesn't generate the same queries with either a symbol or a numeric value on enum fields.

Have a nice day.

@@ -62,7 +67,7 @@ def enum(definitions)
_enum_methods_module.module_eval do
# def status=(value) self[:status] = STATUS[value] end
define_method("#{name}=") { |value|
unless enum_values.has_key?(value)
if !enum_values.has_key?(value) && !enum_values.has_value?(value)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can change this to unless (enum_values.has_key?(value) && enum_values.has_value?(value))
to avoid double negation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I should revert it back, the other tests fail if we change this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

De Morgan's law is your friend :)

This would be !(enum_values.has_key?(value) || enum_values.has_value?(value)) but I actually prefer the version you have now anyway - much easy to read and hurts my brain less.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nvm! That's basically the same thing @vipulnsward said :P (Every time I read unless x && y || z ... my head still hurts a little)

@robin850
Copy link
Member Author

Thanks for your feedback @vipulnsward, updated!

Previously, the writer methods would simply check whether the passed
argument was the symbol representing the integer value of an enum field.
Therefore, it was not possible to specify the numeric value itself but
the dynamically defined scopes generate where clauses relying on this
kind of values so a chained call to a method like `find_or_initialize_by`
would trigger an `ArgumentError`.

Reference #13530
Add a mention about the automatic generation of scopes based on the
allowed values of the field on the enum documentation.
rafaelfranca added a commit that referenced this pull request Jan 1, 2014
Fix enum writers when using integers
@rafaelfranca rafaelfranca merged commit 50060e9 into rails:master Jan 1, 2014
chancancode added a commit that referenced this pull request Jan 3, 2014
Previously, this would give an `ArgumentError`:

   class Issue < ActiveRecord::Base
     enum :status, [:open, :finished]
   end

   Issue.open.build # => ArgumentError: '0' is not a valid status
   Issue.open.create # => ArgumentError: '0' is not a valid status

PR #13542 muted the error, but the issue remains. This commit fixes
the issue by allowing the enum value to be written directly via the
setter:

   Issue.new.status = 0 # This now sets status to :open

Assigning a value directly via the setter like this is not part of the
documented public API, so users should not rely on this behavior.

Closes #13530.
@robin850 robin850 deleted the issue-13530 branch January 9, 2014 18:21
@senny senny added the enum label Sep 4, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants