1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Add attribute_for_database attribute method

I've been reported an issue on enum from friends, they want a way to get
mapped value, but currently there is no reliable way to get that value.

If a record is loaded from database, `attribute_before_type_cast` works
for that. but the attribute is changed by user, the attribute method
won't work for that.

```ruby
book = Book.new(status: "published")

# returns "published", but what we really want is 2.
book.status_before_type_cast
```

So I propose to add `attribute_for_database` attribute method, it
consistently returns mapped value for enum.
This commit is contained in:
Ryuta Kamizono 2020-10-26 18:11:18 +09:00
parent 1f5a4d1d5e
commit 1429893b24
3 changed files with 17 additions and 3 deletions

View file

@ -29,7 +29,7 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
attribute_method_suffix "_before_type_cast"
attribute_method_suffix "_before_type_cast", "_for_database"
attribute_method_suffix "_came_from_user?"
end
@ -72,6 +72,10 @@ module ActiveRecord
@attributes[attr_name].value_before_type_cast
end
def attribute_for_database(attr_name)
@attributes[attr_name].value_for_database
end
def attribute_came_from_user?(attr_name)
@attributes[attr_name].came_from_user?
end

View file

@ -54,7 +54,7 @@ module ActiveRecord
end
module ClassMethods
ID_ATTRIBUTE_METHODS = %w(id id= id? id_before_type_cast id_was id_in_database).to_set
ID_ATTRIBUTE_METHODS = %w(id id= id? id_before_type_cast id_was id_in_database id_for_database).to_set
def instance_method_already_implemented?(method_name)
super || primary_key && ID_ATTRIBUTE_METHODS.include?(method_name)

View file

@ -290,7 +290,7 @@ class EnumTest < ActiveRecord::TestCase
assert_predicate Book.illustrator_visibility_invisible.create, :illustrator_visibility_invisible?
end
test "_before_type_cast" do
test "attribute_before_type_cast" do
assert_equal 2, @book.status_before_type_cast
assert_equal "published", @book.status
@ -300,6 +300,16 @@ class EnumTest < ActiveRecord::TestCase
assert_equal "published", @book.status
end
test "attribute_for_database" do
assert_equal 2, @book.status_for_database
assert_equal "published", @book.status
@book.status = "published"
assert_equal 2, @book.status_for_database
assert_equal "published", @book.status
end
test "invalid definition values raise an ArgumentError" do
e = assert_raises(ArgumentError) do
Class.new(ActiveRecord::Base) do