mirror of https://github.com/rails/rails
Port type_for_attribute to Active Model
This moves `type_for_attribute` from `ActiveRecord::ModelSchema::ClassMethods` to `ActiveModel::AttributeRegistration::ClassMethods`, where `attribute_types` is also defined. Co-authored-by: Petrik <petrik@deheus.net>
This commit is contained in:
parent
d0f40f71b0
commit
83f543b876
|
@ -1,2 +1,17 @@
|
|||
* Port the `type_for_attribute` method to Active Model. Classes that include
|
||||
`ActiveModel::Attributes` will now provide this method. This method behaves
|
||||
the same for Active Model as it does for Active Record.
|
||||
|
||||
```ruby
|
||||
class MyModel
|
||||
include ActiveModel::Attributes
|
||||
|
||||
attribute :my_attribute, :integer
|
||||
end
|
||||
|
||||
MyModel.type_for_attribute(:my_attribute) # => #<ActiveModel::Type::Integer ...>
|
||||
```
|
||||
|
||||
*Jonathan Hefner*
|
||||
|
||||
Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/activemodel/CHANGELOG.md) for previous changes.
|
||||
|
|
|
@ -40,6 +40,21 @@ module ActiveModel
|
|||
end
|
||||
end
|
||||
|
||||
# Returns the type of the specified attribute after applying any
|
||||
# modifiers. This method is the only valid source of information for
|
||||
# anything related to the types of a model's attributes. The return value
|
||||
# of this method will implement the interface described by
|
||||
# ActiveModel::Type::Value (though the object itself may not subclass it).
|
||||
def type_for_attribute(attribute_name, &block)
|
||||
attribute_name = resolve_attribute_name(attribute_name)
|
||||
|
||||
if block
|
||||
attribute_types.fetch(attribute_name, &block)
|
||||
else
|
||||
attribute_types[attribute_name]
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
PendingType = Struct.new(:name, :type) do # :nodoc:
|
||||
def apply_to(attribute_set)
|
||||
|
|
|
@ -73,6 +73,17 @@ module ActiveModel
|
|||
assert_equal Type::Value.new, klass.attribute_types["bar"]
|
||||
end
|
||||
|
||||
test ".type_for_attribute returns the registered attribute type" do
|
||||
klass = class_with { attribute :foo, TYPE_1 }
|
||||
assert_same TYPE_1, klass.type_for_attribute("foo")
|
||||
assert_same TYPE_1, klass.type_for_attribute(:foo)
|
||||
end
|
||||
|
||||
test ".type_for_attribute returns the default type when an unregistered attribute is specified" do
|
||||
klass = class_with { attribute :foo, TYPE_1 }
|
||||
assert_equal Type::Value.new, klass.type_for_attribute("bar")
|
||||
end
|
||||
|
||||
test "new attributes can be registered at any time" do
|
||||
klass = class_with { attribute :foo, TYPE_1 }
|
||||
assert_includes klass._default_attributes, "foo"
|
||||
|
|
|
@ -175,5 +175,13 @@ module ActiveModel
|
|||
ModelForAttributesTest.attribute :foo, :unknown
|
||||
end
|
||||
end
|
||||
|
||||
test ".type_for_attribute supports attribute aliases" do
|
||||
with_alias = Class.new(ModelForAttributesTest) do
|
||||
alias_attribute :integer_field, :x
|
||||
end
|
||||
|
||||
assert_equal with_alias.type_for_attribute(:integer_field), with_alias.type_for_attribute(:x)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -249,6 +249,15 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# :method: type_for_attribute
|
||||
# :call-seq: type_for_attribute(attribute_name, &block)
|
||||
#
|
||||
# See ActiveModel::AttributeRegistration::ClassMethods#type_for_attribute.
|
||||
#
|
||||
# This method will access the database and load the model's schema if
|
||||
# necessary.
|
||||
|
||||
protected
|
||||
def reload_schema_from_cache(*)
|
||||
reset_default_attributes!
|
||||
|
|
|
@ -439,28 +439,6 @@ module ActiveRecord
|
|||
@yaml_encoder ||= ActiveModel::AttributeSet::YAMLEncoder.new(attribute_types)
|
||||
end
|
||||
|
||||
# Returns the type of the attribute with the given name, after applying
|
||||
# all modifiers. This method is the only valid source of information for
|
||||
# anything related to the types of a model's attributes. This method will
|
||||
# access the database and load the model's schema if it is required.
|
||||
#
|
||||
# The return value of this method will implement the interface described
|
||||
# by ActiveModel::Type::Value (though the object itself may not subclass
|
||||
# it).
|
||||
#
|
||||
# +attr_name+ The name of the attribute to retrieve the type for. Must be
|
||||
# a string or a symbol.
|
||||
def type_for_attribute(attr_name, &block)
|
||||
attr_name = attr_name.to_s
|
||||
attr_name = attribute_aliases[attr_name] || attr_name
|
||||
|
||||
if block
|
||||
attribute_types.fetch(attr_name, &block)
|
||||
else
|
||||
attribute_types[attr_name]
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the column object for the named attribute.
|
||||
# Returns an +ActiveRecord::ConnectionAdapters::NullColumn+ if the
|
||||
# named attribute does not exist.
|
||||
|
|
|
@ -51,6 +51,14 @@ module ActiveRecord
|
|||
assert_equal 3, data.overloaded_float
|
||||
end
|
||||
|
||||
test ".type_for_attribute supports attribute aliases" do
|
||||
with_alias = Class.new(OverloadedType) do
|
||||
alias_attribute :overloaded_float, :x
|
||||
end
|
||||
|
||||
assert_equal with_alias.type_for_attribute(:overloaded_float), with_alias.type_for_attribute(:x)
|
||||
end
|
||||
|
||||
test "overloaded properties with limit" do
|
||||
assert_equal 50, OverloadedType.type_for_attribute("overloaded_string_with_limit").limit
|
||||
assert_equal 255, UnoverloadedType.type_for_attribute("overloaded_string_with_limit").limit
|
||||
|
|
Loading…
Reference in New Issue