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

Merge pull request #42409 from shioyama/attributes_for_database

Add `attributes_for_database` method to return attributes as they would be in the database
This commit is contained in:
Jean Boussier 2021-06-08 18:33:33 +02:00 committed by GitHub
commit 5adb6a9a98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 55 additions and 0 deletions

View file

@ -1,3 +1,9 @@
* Add `ActiveModel::AttributeSet#values_for_database`
Returns attributes with values for assignment to the database.
*Chris Salzberg*
* Fix delegation in ActiveModel::Type::Registry#lookup and ActiveModel::Type.lookup
Passing a last positional argument `{}` would be incorrectly considered as keyword argument.

View file

@ -25,6 +25,10 @@ module ActiveModel
attributes.transform_values(&:value_before_type_cast)
end
def values_for_database
attributes.transform_values(&:value_for_database)
end
def to_hash
keys.index_with { |name| self[name].value }
end

View file

@ -209,6 +209,21 @@ module ActiveModel
assert_equal "value from user", attributes.fetch_value(:foo)
end
class MySerializedType < ::ActiveModel::Type::Value
def serialize(value)
value + " serialized"
end
end
test "values_for_database" do
builder = AttributeSet::Builder.new(foo: MySerializedType.new)
attributes = builder.build_from_database
attributes.write_from_user(:foo, "value")
assert_equal({ foo: "value serialized" }, attributes.values_for_database)
end
test "freezing doesn't prevent the set from materializing" do
builder = AttributeSet::Builder.new(foo: Type::String.new)
attributes = builder.build_from_database(foo: "1")

View file

@ -1,3 +1,9 @@
* Add `ActiveRecord::Base#attributes_for_database`
Returns attributes with values for assignment to the database.
*Chris Salzberg*
* Use an empty query to check if the PostgreSQL connection is still active
An empty query is faster than `SELECT 1`.

View file

@ -66,6 +66,11 @@ module ActiveRecord
@attributes.values_before_type_cast
end
# Returns a hash of attributes for assignment to the database.
def attributes_for_database
@attributes.values_for_database
end
private
# Dispatch target for <tt>*_before_type_cast</tt> attribute methods.
def attribute_before_type_cast(attr_name)

View file

@ -216,6 +216,17 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
test "read attributes_for_database" do
topic = Topic.new
topic.content = { one: 1, two: 2 }
db_attributes = Topic.instantiate(topic.attributes_for_database).attributes
before_type_cast_attributes = Topic.instantiate(topic.attributes_before_type_cast).attributes
assert_equal topic.attributes, db_attributes
assert_not_equal topic.attributes, before_type_cast_attributes
end
test "read attributes_after_type_cast on a date" do
tz = "Pacific Time (US & Canada)"

View file

@ -378,6 +378,14 @@ class EnumTest < ActiveRecord::TestCase
assert_equal "published", @book.status
end
test "attributes_for_database" do
assert_equal 2, @book.attributes_for_database["status"]
@book.status = "published"
assert_equal 2, @book.attributes_for_database["status"]
end
test "invalid definition values raise an ArgumentError" do
e = assert_raises(ArgumentError) do
Class.new(ActiveRecord::Base) do