diff options
Diffstat (limited to 'activerecord/lib')
24 files changed, 85 insertions, 77 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 07dfc448e7..6222bfe903 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1577,7 +1577,7 @@ module ActiveRecord scope = nil end - habtm_reflection = ActiveRecord::Reflection::AssociationReflection.new(:has_and_belongs_to_many, name, scope, options, self) + habtm_reflection = ActiveRecord::Reflection::HasAndBelongsToManyReflection.new(:has_and_belongs_to_many, name, scope, options, self) builder = Builder::HasAndBelongsToMany.new name, self, options diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb index 4a04303fb8..f1c36cd047 100644 --- a/activerecord/lib/active_record/associations/association.rb +++ b/activerecord/lib/active_record/associations/association.rb @@ -179,7 +179,7 @@ module ActiveRecord def creation_attributes attributes = {} - if (reflection.macro == :has_one || reflection.macro == :has_many) && !options[:through] + if (reflection.has_one? || reflection.collection?) && !options[:through] attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key] if reflection.options[:as] diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb index 1edd4fa3aa..81fdd681de 100644 --- a/activerecord/lib/active_record/associations/belongs_to_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_association.rb @@ -92,7 +92,7 @@ module ActiveRecord # has_one associations. def invertible_for?(record) inverse = inverse_reflection_for(record) - inverse && inverse.macro == :has_one + inverse && inverse.has_one? end def target_id diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index c5f7bcae7d..306588ac66 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -57,7 +57,7 @@ module ActiveRecord def ids_writer(ids) pk_column = reflection.primary_key_column ids = Array(ids).reject { |id| id.blank? } - ids.map! { |i| pk_column.type_cast(i) } + ids.map! { |i| pk_column.type_cast_from_user(i) } replace(klass.find(ids).index_by { |r| r.id }.values_at(*ids)) end diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb index f6e08991f7..da9b125fd6 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -105,9 +105,9 @@ module ActiveRecord inverse = source_reflection.inverse_of if inverse - if inverse.macro == :has_many + if inverse.collection? record.send(inverse.name) << build_through_record(record) - elsif inverse.macro == :has_one + elsif inverse.has_one? record.send("#{inverse.name}=", build_through_record(record)) end end @@ -170,7 +170,7 @@ module ActiveRecord klass.decrement_counter counter, records.map(&:id) end - if through_reflection.macro == :has_many && update_through_counter?(method) + if through_reflection.collection? && update_through_counter?(method) update_counter(-count, through_reflection) end @@ -187,7 +187,7 @@ module ActiveRecord records.each do |record| through_records = through_records_for(record) - if through_reflection.macro == :has_many + if through_reflection.collection? through_records.each { |r| through_association.target.delete(r) } else if through_records.include?(through_association.target) diff --git a/activerecord/lib/active_record/associations/join_dependency.rb b/activerecord/lib/active_record/associations/join_dependency.rb index 35659766d3..fbb4551b22 100644 --- a/activerecord/lib/active_record/associations/join_dependency.rb +++ b/activerecord/lib/active_record/associations/join_dependency.rb @@ -144,7 +144,7 @@ module ActiveRecord column_aliases = aliases.column_aliases join_root result_set.each { |row_hash| - primary_id = type_caster.type_cast row_hash[primary_key] + primary_id = type_caster.type_cast_from_database row_hash[primary_key] parent = parents[primary_id] ||= join_root.instantiate(row_hash, column_aliases) construct(parent, join_root, row_hash, result_set, seen, model_cache, aliases) } diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index ae3785638a..a354cd7503 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -123,9 +123,9 @@ module ActiveRecord } if self.class.cache_attribute?(name) - @attributes[name] = column.type_cast(value) + @attributes[name] = column.type_cast_from_database(value) else - column.type_cast value + column.type_cast_from_database value end } end diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb index 684be2e845..abad949ef4 100644 --- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb +++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb @@ -2,7 +2,7 @@ module ActiveRecord module AttributeMethods module TimeZoneConversion class Type < SimpleDelegator # :nodoc: - def type_cast(value) + def type_cast_from_database(value) convert_time_to_time_zone(super) end diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index 74e2a8e6b9..b3c3e26c9f 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -187,7 +187,7 @@ module ActiveRecord # Doesn't use after_save as that would save associations added in after_create/after_update twice after_create save_method after_update save_method - elsif reflection.macro == :has_one + elsif reflection.has_one? define_method(save_method) { save_has_one_association(reflection) } unless method_defined?(save_method) # Configures two callbacks instead of a single after_save so that # the model may rely on their execution order relative to its diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index e8c067f758..e4d0abb8ef 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -311,8 +311,8 @@ module ActiveRecord #:nodoc: include Locking::Optimistic include Locking::Pessimistic include AttributeMethods - include Timestamp include Callbacks + include Timestamp include Associations include ActiveModel::SecurePassword include AutosaveAssociation diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index 22decbc2da..72c6990ba5 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -17,7 +17,7 @@ module ActiveRecord delegate :type, :precision, :scale, :limit, :klass, :accessor, :text?, :number?, :binary?, :serialized?, :changed?, - :type_cast, :type_cast_from_user, :type_cast_for_database, + :type_cast_from_user, :type_cast_from_database, :type_cast_for_database, :type_cast_for_schema, to: :cast_type @@ -52,7 +52,7 @@ module ActiveRecord end def default - @default ||= type_cast(@original_default) + @default ||= type_cast_from_database(@original_default) end def with_type(type) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb b/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb index 971f5eed7e..bb54de05c8 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb @@ -67,10 +67,6 @@ module ActiveRecord end end - def string_to_array(string, oid) # :nodoc: - parse_pg_array(string).map {|val| type_cast_array(oid, val)} - end - private HstorePair = begin @@ -103,14 +99,6 @@ module ActiveRecord "\"#{value}\"" end end - - def type_cast_array(oid, value) - if ::Array === value - value.map {|item| type_cast_array(oid, item)} - else - oid.type_cast value - end - end end end end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb index a579746815..847fd4dded 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb @@ -4,6 +4,8 @@ module ActiveRecord module ConnectionAdapters # PostgreSQL-specific extensions to column definitions in a table. class PostgreSQLColumn < Column #:nodoc: + extend PostgreSQL::Cast + attr_accessor :array def initialize(name, default, cast_type, sql_type = nil, null = true, default_function = nil) @@ -17,24 +19,6 @@ module ActiveRecord @default_function = default_function end - - # :stopdoc: - class << self - include PostgreSQL::Cast - - # Loads pg_array_parser if available. String parsing can be - # performed quicker by a native extension, which will not create - # a large amount of Ruby objects that will need to be garbage - # collected. pg_array_parser has a C and Java extension - begin - require 'pg_array_parser' - include PgArrayParser - rescue LoadError - require 'active_record/connection_adapters/postgresql/array_parser' - include PostgreSQL::ArrayParser - end - end - # :startdoc: end end end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb index 0e9dcd8c0c..87817fe8d1 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb @@ -10,11 +10,33 @@ module ActiveRecord @subtype = subtype end - def type_cast(value) - if ::String === value - ConnectionAdapters::PostgreSQLColumn.string_to_array value, @subtype + def type_cast_from_database(value) + if value.is_a?(::String) + type_cast_array(parse_pg_array(value)) else - value + super + end + end + + # Loads pg_array_parser if available. String parsing can be + # performed quicker by a native extension, which will not create + # a large amount of Ruby objects that will need to be garbage + # collected. pg_array_parser has a C and Java extension + begin + require 'pg_array_parser' + include PgArrayParser + rescue LoadError + require 'active_record/connection_adapters/postgresql/array_parser' + include PostgreSQL::ArrayParser + end + + private + + def type_cast_array(value) + if value.is_a?(::Array) + value.map { |item| type_cast_array(item) } + else + @subtype.type_cast_from_database(value) end end end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb index 0a48a14b06..88de816d4f 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb @@ -8,15 +8,15 @@ module ActiveRecord end def type_cast_from_user(value) - type_cast(type_cast_for_database(value)) + type_cast_from_database(type_cast_for_database(value)) end - def type_cast_for_database(value) - ConnectionAdapters::PostgreSQLColumn.hstore_to_string(value) + def type_cast_from_database(value) + ConnectionAdapters::PostgreSQLColumn.string_to_hstore(value) end - def cast_value(value) - ConnectionAdapters::PostgreSQLColumn.string_to_hstore value + def type_cast_for_database(value) + ConnectionAdapters::PostgreSQLColumn.hstore_to_string(value) end def accessor diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/json.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/json.rb index c64cf27797..b4fed1bcab 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/json.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/json.rb @@ -8,15 +8,15 @@ module ActiveRecord end def type_cast_from_user(value) - type_cast(type_cast_for_database(value)) + type_cast_from_database(type_cast_for_database(value)) end - def type_cast_for_database(value) - ConnectionAdapters::PostgreSQLColumn.json_to_string(value) + def type_cast_from_database(value) + ConnectionAdapters::PostgreSQLColumn.string_to_json(value) end - def cast_value(value) - ConnectionAdapters::PostgreSQLColumn.string_to_json value + def type_cast_for_database(value) + ConnectionAdapters::PostgreSQLColumn.json_to_string(value) end def accessor diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb index a0d8a94c74..c289ba8980 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb @@ -29,7 +29,7 @@ module ActiveRecord end def type_cast_single(value) - infinity?(value) ? value : @subtype.type_cast(value) + infinity?(value) ? value : @subtype.type_cast_from_database(value) end def cast_value(value) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 283ca81f94..71b05cdbae 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -348,14 +348,14 @@ module ActiveRecord if supports_extensions? res = exec_query "SELECT EXISTS(SELECT * FROM pg_available_extensions WHERE name = '#{name}' AND installed_version IS NOT NULL) as enabled", 'SCHEMA' - res.column_types['enabled'].type_cast res.rows.first.first + res.column_types['enabled'].type_cast_from_database res.rows.first.first end end def extensions if supports_extensions? res = exec_query "SELECT extname from pg_extension", "SCHEMA" - res.rows.map { |r| res.column_types['extname'].type_cast r.first } + res.rows.map { |r| res.column_types['extname'].type_cast_from_database r.first } else super end diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 1242f49e28..8a2a06f2ca 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -516,7 +516,7 @@ module ActiveRecord # Determines if a hash contains a truthy _destroy key. def has_destroy_flag?(hash) - Type::Boolean.new.type_cast(hash['_destroy']) + Type::Boolean.new.type_cast_from_user(hash['_destroy']) end # Determines if a new record should be rejected by checking diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 4d5203612c..24f3de019d 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -228,7 +228,7 @@ module ActiveRecord def initialize(macro, name, scope, options, active_record) super - @collection = [:has_many, :has_and_belongs_to_many].include?(macro) + @collection = macro == :has_many @automatic_inverse_of = nil @type = options[:as] && "#{options[:as]}_type" @foreign_type = options[:foreign_type] || "#{name}_type" @@ -392,7 +392,7 @@ Joining, Preloading and eager loading of these associations is deprecated and wi # * you use autosave; <tt>autosave: true</tt> # * the association is a +has_many+ association def validate? - !options[:validate].nil? ? options[:validate] : (options[:autosave] == true || macro == :has_many) + !options[:validate].nil? ? options[:validate] : (options[:autosave] == true || collection?) end # Returns +true+ if +self+ is a +belongs_to+ reflection. @@ -400,6 +400,10 @@ Joining, Preloading and eager loading of these associations is deprecated and wi macro == :belongs_to end + def has_one? + macro == :has_one + end + def association_class case macro when :belongs_to @@ -538,6 +542,13 @@ Joining, Preloading and eager loading of these associations is deprecated and wi end end + class HasAndBelongsToManyReflection < AssociationReflection #:nodoc: + def initialize(macro, name, scope, options, active_record) + super + @collection = true + end + end + # Holds all the meta-data about a :through association as it was specified # in the Active Record class. class ThroughReflection < AssociationReflection #:nodoc: @@ -739,7 +750,7 @@ directive on your declaration like: raise HasManyThroughAssociationPolymorphicSourceError.new(active_record.name, self, source_reflection) end - if macro == :has_one && through_reflection.collection? + if has_one? && through_reflection.collection? raise HasOneThroughCantAssociateThroughCollection.new(active_record.name, self, through_reflection) end diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index 11ab1b4595..38970a66ae 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -179,7 +179,7 @@ module ActiveRecord result = result.map do |attributes| values = attributes.values - columns.zip(values).map { |column, value| column.type_cast value } + columns.zip(values).map { |column, value| column.type_cast_from_database value } end columns.one? ? result.map!(&:first) : result end @@ -379,7 +379,7 @@ module ActiveRecord end def type_cast_using_column(value, column) - column ? column.type_cast(value) : value + column ? column.type_cast_from_database(value) : value end # TODO: refactor to allow non-string `select_values` (eg. Arel nodes). diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 47e90e9021..0c9c761f97 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -65,7 +65,7 @@ module ActiveRecord # # returns an Array of the required fields, available since Rails 3.1. def find(*args) if block_given? - to_a.find { |*block_args| yield(*block_args) } + to_a.find(*args) { |*block_args| yield(*block_args) } else find_with_ids(*args) end diff --git a/activerecord/lib/active_record/type/serialized.rb b/activerecord/lib/active_record/type/serialized.rb index a1205fa819..9144028576 100644 --- a/activerecord/lib/active_record/type/serialized.rb +++ b/activerecord/lib/active_record/type/serialized.rb @@ -9,7 +9,7 @@ module ActiveRecord super(subtype) end - def type_cast(value) + def type_cast_from_database(value) if is_default_value?(value) value else @@ -18,7 +18,7 @@ module ActiveRecord end def type_cast_from_user(value) - type_cast(type_cast_for_database(value)) + type_cast_from_database(type_cast_for_database(value)) end def type_cast_for_database(value) diff --git a/activerecord/lib/active_record/type/value.rb b/activerecord/lib/active_record/type/value.rb index deacc398ef..efcdab1c0e 100644 --- a/activerecord/lib/active_record/type/value.rb +++ b/activerecord/lib/active_record/type/value.rb @@ -16,11 +16,8 @@ module ActiveRecord # must override this method. def type; end - # Takes an input from the database, or from attribute setters, - # and casts it to a type appropriate for this object. This method - # should not be overriden by subclasses. Instead, override `cast_value`. - def type_cast(value) - cast_value(value) unless value.nil? + def type_cast_from_database(value) + type_cast(value) end def type_cast_from_user(value) @@ -64,6 +61,12 @@ module ActiveRecord end private + # Takes an input from the database, or from attribute setters, + # and casts it to a type appropriate for this object. This method + # should not be overriden by subclasses. Instead, override `cast_value`. + def type_cast(value) # :api: public + cast_value(value) unless value.nil? + end # Responsible for casting values from external sources to the appropriate # type. Called by `type_cast` for all values except `nil`. |