aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/attributes.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/attributes.rb')
-rw-r--r--activerecord/lib/active_record/attributes.rb84
1 files changed, 27 insertions, 57 deletions
diff --git a/activerecord/lib/active_record/attributes.rb b/activerecord/lib/active_record/attributes.rb
index faf5d632ec..c1b69092bb 100644
--- a/activerecord/lib/active_record/attributes.rb
+++ b/activerecord/lib/active_record/attributes.rb
@@ -5,12 +5,8 @@ module ActiveRecord
Type = ActiveRecord::Type
included do
- class_attribute :user_provided_columns, instance_accessor: false # :internal:
- class_attribute :user_provided_defaults, instance_accessor: false # :internal:
- self.user_provided_columns = {}
- self.user_provided_defaults = {}
-
- delegate :persistable_attribute_names, to: :class
+ class_attribute :user_provided_types, instance_accessor: false # :internal:
+ self.user_provided_types = {}
end
module ClassMethods # :nodoc:
@@ -77,70 +73,44 @@ module ActiveRecord
#
# store_listing = StoreListing.new(price_in_cents: '$10.00')
# store_listing.price_in_cents # => 1000
- def attribute(name, cast_type, options = {})
+ def attribute(name, cast_type, **options)
name = name.to_s
- clear_caches_calculated_from_columns
- # Assign a new hash to ensure that subclasses do not share a hash
- self.user_provided_columns = user_provided_columns.merge(name => cast_type)
-
- if options.key?(:default)
- self.user_provided_defaults = user_provided_defaults.merge(name => options[:default])
- end
- end
+ reload_schema_from_cache
- # Returns an array of column objects for the table associated with this class.
- def columns
- @columns ||= add_user_provided_columns(connection.schema_cache.columns(table_name))
+ self.user_provided_types = user_provided_types.merge(name => [cast_type, options])
end
- # Returns a hash of column objects for the table associated with this class.
- def columns_hash
- @columns_hash ||= Hash[columns.map { |c| [c.name, c] }]
+ def define_attribute(
+ name,
+ cast_type,
+ default: NO_DEFAULT_PROVIDED,
+ user_provided_default: true
+ )
+ attribute_types[name] = cast_type
+ define_default_attribute(name, default, cast_type, from_user: user_provided_default)
end
- def persistable_attribute_names # :nodoc:
- @persistable_attribute_names ||= connection.schema_cache.columns_hash(table_name).keys
- end
-
- def reset_column_information # :nodoc:
+ def load_schema!
super
- clear_caches_calculated_from_columns
+ user_provided_types.each do |name, (type, options)|
+ define_attribute(name, type, **options)
+ end
end
private
- def add_user_provided_columns(schema_columns)
- existing_columns = schema_columns.map do |column|
- new_type = user_provided_columns[column.name]
- if new_type
- column.with_type(new_type)
- else
- column
- end
- end
+ NO_DEFAULT_PROVIDED = Object.new # :nodoc:
+ private_constant :NO_DEFAULT_PROVIDED
- existing_column_names = existing_columns.map(&:name)
- new_columns = user_provided_columns.except(*existing_column_names).map do |(name, type)|
- connection.new_column(name, nil, type)
+ def define_default_attribute(name, value, type, from_user:)
+ if value == NO_DEFAULT_PROVIDED
+ default_attribute = _default_attributes[name].with_type(type)
+ elsif from_user
+ default_attribute = Attribute.from_user(name, value, type)
+ else
+ default_attribute = Attribute.from_database(name, value, type)
end
-
- existing_columns + new_columns
- end
-
- def clear_caches_calculated_from_columns
- @arel_table = nil
- @attributes_builder = nil
- @column_names = nil
- @column_types = nil
- @columns = nil
- @columns_hash = nil
- @content_columns = nil
- @default_attributes = nil
- @persistable_attribute_names = nil
- end
-
- def raw_default_values
- super.merge(user_provided_defaults)
+ _default_attributes[name] = default_attribute
end
end
end