From 63fd88ca5c255a84b61ce81c41dfe9928ea101d9 Mon Sep 17 00:00:00 2001 From: David Verhasselt Date: Fri, 23 May 2014 13:46:03 +0300 Subject: If a counter_cache exists, use it for #empty? --- .../lib/active_record/associations/has_many_association.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb index 2727e23870..3ffc015975 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -41,6 +41,14 @@ module ActiveRecord end end + def empty? + if has_cached_counter? + size.zero? + else + super + end + end + private # Returns the number of records in this collection. -- cgit v1.2.3 From dd1ec62578db6f7a03d1c07546b00a008a0c629d Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Sat, 14 Jun 2014 02:18:36 -0700 Subject: Fixed a regression introduced in 84cf156 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 84cf156 (PR #15694) introduced a subtle regression. There are actually three distinct entry points to creating an AR object – via .new (i.e. #initialize), via #init_with (e.g. from YAML or database queries) and via .allocate. With the patch in 84cf156, attribute methods and respond_to? will not work correctly when objects are allocated directly, without going through either The reason this test case didn't catch the regression was that the `Topic` class is shared between test cases, so by the time this test case is ran the attribute methods are very likely to be defined. Switching to use a fresh anonymous class in the test to ensure we surface this problem in the future. --- activerecord/lib/active_record/core.rb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index d39e5fddfe..47183752e7 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -108,6 +108,11 @@ module ActiveRecord end module ClassMethods + def allocate + define_attribute_methods + super + end + def initialize_find_by_cache self.find_by_statement_cache = {}.extend(Mutex_m) end -- cgit v1.2.3 From c965de396f1bd7457159306f1fc10342840fdf86 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Mon, 16 Jun 2014 18:25:09 -0400 Subject: Dont swallow errors when bad alias_method --- activerecord/lib/active_record/inheritance.rb | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb index 08fc91c9df..17cec08628 100644 --- a/activerecord/lib/active_record/inheritance.rb +++ b/activerecord/lib/active_record/inheritance.rb @@ -120,14 +120,8 @@ module ActiveRecord candidates << type_name candidates.each do |candidate| - begin - constant = ActiveSupport::Dependencies.constantize(candidate) - return constant if candidate == constant.to_s - # We don't want to swallow NoMethodError < NameError errors - rescue NoMethodError - raise - rescue NameError - end + constant = ActiveSupport::Dependencies.safe_constantize(candidate) + return constant if candidate == constant.to_s end raise NameError.new("uninitialized constant #{candidates.first}", candidates.first) -- cgit v1.2.3 From f8d2899d12d59360f29c5eb6a1b1a8fe4ec82ca0 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Mon, 9 Jun 2014 18:45:29 -0400 Subject: Begin refactoring ThroughReflection This allows us to decouple AssociationReflection and ThroughReflection making ThroughReflection it's own Reflection bucket in a way. The benefit of this is to be able to remove checks against the macro's symbol for exmaple `macro == :belongs_to`. Get all tests passing again Some of the methods that used to be inherited from MacroReflection through AssociationReflection were no longer getting passed through. They needed to be duplicated into the ThroughReflection. I will extract these out into a separate class. Refactor shared methods into strategy object Now that we've separated ThroughReflection and AssociationReflection we can combine shared methods into one class to avoid duplication. Break out class for each type of reflection This creates a class for each reflection type (has_many, has_one, belongs_to and habtm). We then can remove the need to set the macro symbol in each initialization. Tests were updated to reflect these changes because creation of these reflections is now different. Remove need for @collection instance var We now define `collection?` as `false` by default and set it to `true` in `has_and_belongs_to_many` and `has_many` reflections. This removes the need for the `@collection` instance variable. Raise exception on unknown macro types We shouldn't accept just any macro when creating reflections. An unrecongnized AssociationReflection raises an error. Tests in `reflection_test` were updated to reflect these new changes. `:has_and_belongs_to_many` macro tests were removed because we no longer internally return HABTM. --- activerecord/lib/active_record/associations.rb | 2 +- activerecord/lib/active_record/reflection.rb | 193 ++++++++++++++++--------- 2 files changed, 128 insertions(+), 67 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index d9b339a1f6..7870e01dc6 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1587,7 +1587,7 @@ module ActiveRecord scope = nil end - habtm_reflection = ActiveRecord::Reflection::HasAndBelongsToManyReflection.new(:has_and_belongs_to_many, name, scope, options, self) + habtm_reflection = ActiveRecord::Reflection::HasAndBelongsToManyReflection.new(name, scope, options, self) builder = Builder::HasAndBelongsToMany.new name, self, options diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 28c39bdd5c..12208aecf7 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -13,14 +13,21 @@ module ActiveRecord end def self.create(macro, name, scope, options, ar) - case macro - when :has_many, :belongs_to, :has_one - klass = options[:through] ? ThroughReflection : AssociationReflection - when :composed_of - klass = AggregateReflection - end - - klass.new(macro, name, scope, options, ar) + klass = case macro + when :composed_of + AggregateReflection + when :has_many + HasManyReflection + when :has_one + HasOneReflection + when :belongs_to + BelongsToReflection + else + raise "Unsupported Macro: #{macro}" + end + + reflection = klass.new(name, scope, options, ar) + options[:through] ? ThroughReflection.new(reflection) : reflection end def self.add_reflection(ar, name, reflection) @@ -110,6 +117,52 @@ module ActiveRecord end end + # Holds all the methods that are shared between MacroReflection, AssociationReflection + # and ThroughReflection + class AbstractReflection # :nodoc: + def table_name + klass.table_name + end + + # Returns a new, unsaved instance of the associated class. +attributes+ will + # be passed to the class's constructor. + def build_association(attributes, &block) + klass.new(attributes, &block) + end + + def quoted_table_name + klass.quoted_table_name + end + + def primary_key_type + klass.type_for_attribute(klass.primary_key) + end + + # Returns the class name for the macro. + # + # composed_of :balance, class_name: 'Money' returns 'Money' + # has_many :clients returns 'Client' + def class_name + @class_name ||= (options[:class_name] || derive_class_name).to_s + end + + JoinKeys = Struct.new(:key, :foreign_key) # :nodoc: + + def join_keys(assoc_klass) + if source_macro == :belongs_to + if polymorphic? + reflection_key = association_primary_key(assoc_klass) + else + reflection_key = association_primary_key + end + reflection_foreign_key = foreign_key + else + reflection_foreign_key = active_record_primary_key + reflection_key = foreign_key + end + JoinKeys.new(reflection_key, reflection_foreign_key) + end + end # Base class for AggregateReflection and AssociationReflection. Objects of # AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods. # @@ -117,7 +170,7 @@ module ActiveRecord # AggregateReflection # AssociationReflection # ThroughReflection - class MacroReflection + class MacroReflection < AbstractReflection # Returns the name of the macro. # # composed_of :balance, class_name: 'Money' returns :balance @@ -142,8 +195,7 @@ module ActiveRecord attr_reader :plural_name # :nodoc: - def initialize(macro, name, scope, options, active_record) - @macro = macro + def initialize(name, scope, options, active_record) @name = name @scope = scope @options = options @@ -167,15 +219,11 @@ module ActiveRecord # composed_of :balance, class_name: 'Money' returns the Money class # has_many :clients returns the Client class def klass - @klass ||= class_name.constantize + @klass ||= compute_class(class_name) end - # Returns the class name for the macro. - # - # composed_of :balance, class_name: 'Money' returns 'Money' - # has_many :clients returns 'Client' - def class_name - @class_name ||= (options[:class_name] || derive_class_name).to_s + def compute_class(name) + name.constantize end # Returns +true+ if +self+ and +other_aggregation+ have the same +name+ attribute, +active_record+ attribute, @@ -188,23 +236,6 @@ module ActiveRecord active_record == other_aggregation.active_record end - JoinKeys = Struct.new(:key, :foreign_key) # :nodoc: - - def join_keys(assoc_klass) - if source_macro == :belongs_to - if polymorphic? - reflection_key = association_primary_key(assoc_klass) - else - reflection_key = association_primary_key - end - reflection_foreign_key = foreign_key - else - reflection_key = foreign_key - reflection_foreign_key = active_record_primary_key - end - JoinKeys.new(reflection_key, reflection_foreign_key) - end - private def derive_class_name name.to_s.camelize @@ -237,15 +268,18 @@ module ActiveRecord # a new association object. Use +build_association+ or +create_association+ # instead. This allows plugins to hook into association object creation. def klass - @klass ||= active_record.send(:compute_type, class_name) + @klass ||= compute_class(class_name) + end + + def compute_class(name) + active_record.send(:compute_type, name) end attr_reader :type, :foreign_type attr_accessor :parent_reflection # [:name, Reflection] - def initialize(macro, name, scope, options, active_record) + def initialize(name, scope, options, active_record) super - @collection = macro == :has_many @automatic_inverse_of = nil @type = options[:as] && "#{options[:as]}_type" @foreign_type = options[:foreign_type] || "#{name}_type" @@ -264,24 +298,10 @@ module ActiveRecord } end - # Returns a new, unsaved instance of the associated class. +attributes+ will - # be passed to the class's constructor. - def build_association(attributes, &block) - klass.new(attributes, &block) - end - def constructable? # :nodoc: @constructable end - def table_name - klass.table_name - end - - def quoted_table_name - klass.quoted_table_name - end - def join_table @join_table ||= options[:join_table] || derive_join_table end @@ -290,10 +310,6 @@ module ActiveRecord @foreign_key ||= options[:foreign_key] || derive_foreign_key end - def primary_key_type - klass.type_for_attribute(klass.primary_key) - end - def association_foreign_key @association_foreign_key ||= options[:association_foreign_key] || class_name.foreign_key end @@ -396,7 +412,7 @@ Joining, Preloading and eager loading of these associations is deprecated and wi # association. Returns +true+ if the +macro+ is either +has_many+ or # +has_and_belongs_to_many+, +false+ otherwise. def collection? - @collection + false end # Returns whether or not the association should be validated as part of @@ -560,22 +576,57 @@ Joining, Preloading and eager loading of these associations is deprecated and wi end end + class HasManyReflection < AssociationReflection #:nodoc: + def initialize(name, scope, options, active_record) + @macro = :has_many + super(name, scope, options, active_record) + end + + def collection? + true + end + end + + class HasOneReflection < AssociationReflection #:nodoc: + def initialize(name, scope, options, active_record) + @macro = :has_one + super(name, scope, options, active_record) + end + end + + class BelongsToReflection < AssociationReflection #:nodoc: + def initialize(name, scope, options, active_record) + @macro = :belongs_to + super(name, scope, options, active_record) + end + end + class HasAndBelongsToManyReflection < AssociationReflection #:nodoc: - def initialize(macro, name, scope, options, active_record) + def initialize(name, scope, options, active_record) + @macro = :has_and_belongs_to_many super - @collection = true + end + + def 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: + class ThroughReflection < AbstractReflection #:nodoc: + attr_reader :delegate_reflection delegate :foreign_key, :foreign_type, :association_foreign_key, :active_record_primary_key, :type, :to => :source_reflection - def initialize(macro, name, scope, options, active_record) - super - @source_reflection_name = options[:source] + def initialize(delegate_reflection) + @delegate_reflection = delegate_reflection + @klass = delegate_reflection.options[:class] + @source_reflection_name = delegate_reflection.options[:source] + end + + def klass + @klass ||= delegate_reflection.compute_class(class_name) end # Returns the source of the through reflection. It checks both a singularized @@ -777,15 +828,25 @@ directive on your declaration like: protected - def actual_source_reflection # FIXME: this is a horrible name - source_reflection.actual_source_reflection - end + def actual_source_reflection # FIXME: this is a horrible name + source_reflection.send(:actual_source_reflection) + end + + def primary_key(klass) + klass.primary_key || raise(UnknownPrimaryKey.new(klass)) + end private def derive_class_name # get the class_name of the belongs_to association of the through reflection options[:source_type] || source_reflection.class_name end + + delegate_methods = AssociationReflection.public_instance_methods - + public_instance_methods + + delegate(*delegate_methods, to: :delegate_reflection) + end end end -- cgit v1.2.3 From 584fc8b33b66aa47b2ecabedbdca7c66f16653d7 Mon Sep 17 00:00:00 2001 From: Andrey Novikov Date: Thu, 10 Jul 2014 21:00:46 +0400 Subject: Dump PostgreSQL primary key with custom function as a default. For example, if use pgcrypto extension in PostgreSQL 9.4 beta 1, where uuid-ossp extension isn't available for moment of writing, and thus to use a gen_random_uuid() method as a primary key default. In this case schema dumper wasn't able to correctly reconstruct create_table statement and lost primary key constraint on schema load. Fixes #16111. --- activerecord/lib/active_record/schema_dumper.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index 64bc68eefd..a94364bde1 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -120,7 +120,8 @@ HEADER # first dump primary key column if @connection.respond_to?(:pk_and_sequence_for) pk, _ = @connection.pk_and_sequence_for(table) - elsif @connection.respond_to?(:primary_key) + end + if !pk && @connection.respond_to?(:primary_key) pk = @connection.primary_key(table) end -- cgit v1.2.3 From d739dd1627d1b20bde417045558848fe92a82d6c Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Tue, 1 Jul 2014 08:11:59 -0600 Subject: Use a type object for type casting behavior on SQLite3 --- .../connection_adapters/sqlite3_adapter.rb | 36 +++++++++++++--------- 1 file changed, 22 insertions(+), 14 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index e6163771e8..2905cf4a01 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -50,6 +50,16 @@ module ActiveRecord end end + class SQLite3String < Type::String # :nodoc: + def type_cast_for_database(value) + if value.is_a?(::String) && value.encoding == Encoding::ASCII_8BIT + value.encode(Encoding::UTF_8) + else + super + end + end + end + # The SQLite3 adapter works SQLite 3.6.16 or newer # with the sqlite3-ruby drivers (available as gem from https://rubygems.org/gems/sqlite3). # @@ -220,13 +230,23 @@ module ActiveRecord # QUOTING ================================================== def _quote(value) # :nodoc: - if value.is_a?(Type::Binary::Data) + case value + when Type::Binary::Data "x'#{value.hex}'" else super end end + def _type_cast(value) # :nodoc: + case value + when BigDecimal + value.to_f + else + super + end + end + def quote_string(s) #:nodoc: @connection.class.quote(s) end @@ -249,19 +269,6 @@ module ActiveRecord end end - def type_cast(value, column) # :nodoc: - return value.to_f if BigDecimal === value - return super unless String === value - return super unless column && value - - value = super - if column.type == :string && value.encoding == Encoding::ASCII_8BIT - logger.error "Binary data inserted for `string` type on column `#{column.name}`" if logger - value = value.encode Encoding::UTF_8 - end - value - end - # DATABASE STATEMENTS ====================================== def explain(arel, binds = []) @@ -503,6 +510,7 @@ module ActiveRecord def initialize_type_map(m) super m.register_type(/binary/i, SQLite3Binary.new) + register_class_with_limit m, %r(char)i, SQLite3String end def select(sql, name = nil, binds = []) #:nodoc: -- cgit v1.2.3 From d5411fb37ca9a35f49a55fd52d2aefb7956b3e41 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Fri, 11 Jul 2014 07:36:03 -0600 Subject: Don't rely on the column SQL type for bit string quoting --- .../connection_adapters/postgresql/oid/bit.rb | 26 ++++++++++++++++++++++ .../connection_adapters/postgresql/quoting.rb | 20 ++++++----------- 2 files changed, 33 insertions(+), 13 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb index 243ecd13cf..1dbb40ca1d 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb @@ -19,6 +19,32 @@ module ActiveRecord value end end + + def type_cast_for_database(value) + Data.new(super) if value + end + + class Data + def initialize(value) + @value = value + end + + def to_s + value + end + + def binary? + /\A[01]*\Z/ === value + end + + def hex? + /\A[0-9A-F]*\Z/i === value + end + + protected + + attr_reader :value + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb index 5359c5b666..cf5c8d288e 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb @@ -18,8 +18,6 @@ module ActiveRecord def quote(value, column = nil) #:nodoc: return super unless column - sql_type = type_to_sql(column.type, column.limit, column.precision, column.scale) - case value when Float if value.infinite? || value.nan? @@ -27,16 +25,6 @@ module ActiveRecord else super end - when String - case sql_type - when /^bit/ - case value - when /\A[01]*\Z/ then "B'#{value}'" # Bit-string notation - when /\A[0-9A-F]*\Z/i then "X'#{value}'" # Hexadecimal notation - end - else - super - end else super end @@ -100,6 +88,12 @@ module ActiveRecord "'#{escape_bytea(value.to_s)}'" when OID::Xml::Data "xml '#{quote_string(value.to_s)}'" + when OID::Bit::Data + if value.binary? + "B'#{value}'" + elsif value.hex? + "X'#{value}'" + end else super end @@ -112,7 +106,7 @@ module ActiveRecord # See http://deveiate.org/code/pg/PGconn.html#method-i-exec_prepared-doc # for more information { value: value.to_s, format: 1 } - when OID::Xml::Data + when OID::Xml::Data, OID::Bit::Data value.to_s else super -- cgit v1.2.3 From 9c83e8401d802864dde38ddffb690a4245d01716 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Fri, 11 Jul 2014 07:50:16 -0600 Subject: AttributeSet#include? -> AttributeSet#key? https://github.com/rails/rails/pull/15868/files#r14135210 --- activerecord/lib/active_record/attribute_methods.rb | 4 ++-- activerecord/lib/active_record/attribute_set.rb | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index e3ac891520..d728fb5ddf 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -251,7 +251,7 @@ module ActiveRecord # person.has_attribute?('age') # => true # person.has_attribute?(:nothing) # => false def has_attribute?(attr_name) - @attributes.include?(attr_name.to_s) + @attributes.key?(attr_name.to_s) end # Returns an array of names for the attributes available on this object. @@ -386,7 +386,7 @@ module ActiveRecord def attribute_method?(attr_name) # :nodoc: # We check defined? because Syck calls respond_to? before actually calling initialize. - defined?(@attributes) && @attributes.include?(attr_name) + defined?(@attributes) && @attributes.key?(attr_name) end private diff --git a/activerecord/lib/active_record/attribute_set.rb b/activerecord/lib/active_record/attribute_set.rb index 64df6f6358..98ac63c7e1 100644 --- a/activerecord/lib/active_record/attribute_set.rb +++ b/activerecord/lib/active_record/attribute_set.rb @@ -21,8 +21,8 @@ module ActiveRecord end alias_method :to_h, :to_hash - def include?(name) - attributes.include?(name) && self[name].initialized? + def key?(name) + attributes.key?(name) && self[name].initialized? end def fetch_value(name, &block) @@ -53,7 +53,7 @@ module ActiveRecord end def reset(key) - if include?(key) + if key?(key) write_from_database(key, nil) end end -- cgit v1.2.3 From a37741a8f04bb90801c759935bd908e1f5848ca3 Mon Sep 17 00:00:00 2001 From: Gregory Igelmund Date: Sat, 12 Jul 2014 01:03:07 +0200 Subject: Fixing typo in comment --- activerecord/lib/active_record/attribute_methods.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index e3ac891520..cbe5cf202a 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -73,7 +73,7 @@ module ActiveRecord # accessors, mutators and query methods. def define_attribute_methods # :nodoc: return false if @attribute_methods_generated - # Use a mutex; we don't want two thread simultaneously trying to define + # Use a mutex; we don't want two threads simultaneously trying to define # attribute methods. generated_attribute_methods.synchronize do return false if @attribute_methods_generated -- cgit v1.2.3 From f378f23653259dee98061b279b628eb774e6faf1 Mon Sep 17 00:00:00 2001 From: Abdelkader Boudih Date: Thu, 29 May 2014 07:45:56 +0000 Subject: Treat invalid uuid as nil --- .../active_record/connection_adapters/postgresql/oid/uuid.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb index 89728b0fe2..dd97393eac 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb @@ -3,12 +3,21 @@ module ActiveRecord module PostgreSQL module OID # :nodoc: class Uuid < Type::Value # :nodoc: + RFC_4122 = %r{\A\{?[a-fA-F0-9]{4}-? + [a-fA-F0-9]{4}-? + [a-fA-F0-9]{4}-? + [1-5][a-fA-F0-9]{3}-? + [8-Bab][a-fA-F0-9]{3}-? + [a-fA-F0-9]{4}-? + [a-fA-F0-9]{4}-? + [a-fA-F0-9]{4}-?\}?\z}x + def type :uuid end def type_cast(value) - value.presence + value.to_s[RFC_4122, 0] end end end -- cgit v1.2.3 From 390a45e5342ea8307a87b0e57e455a0f3cb6a5e7 Mon Sep 17 00:00:00 2001 From: Guo Xiang Tan Date: Tue, 15 Jul 2014 11:44:04 +0800 Subject: [CI SKIP] Doc fix. --- activerecord/lib/active_record/associations.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 7870e01dc6..7ec7eb1b24 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -717,9 +717,9 @@ module ActiveRecord # == Eager loading of associations # # Eager loading is a way to find objects of a certain class and a number of named associations. - # This is one of the easiest ways of to prevent the dreaded 1+N problem in which fetching 100 + # This is one of the easiest ways of to prevent the dreaded N+1 problem in which fetching 100 # posts that each need to display their author triggers 101 database queries. Through the - # use of eager loading, the 101 queries can be reduced to 2. + # use of eager loading, the number of queries will be reduced from 101 to 2. # # class Post < ActiveRecord::Base # belongs_to :author -- cgit v1.2.3 From 11338183265f759b07c8dffd526b92fb550ba79d Mon Sep 17 00:00:00 2001 From: Jeff Browning Date: Fri, 27 Jun 2014 10:04:18 -0400 Subject: Fix version detection for RENAME INDEX support. Fixes #15931. --- .../connection_adapters/abstract_mysql_adapter.rb | 14 +++++++++++++- .../active_record/connection_adapters/mysql2_adapter.rb | 4 ++-- .../lib/active_record/connection_adapters/mysql_adapter.rb | 6 +++--- 3 files changed, 18 insertions(+), 6 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index ccb957d2c8..db8c16914e 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -473,7 +473,7 @@ module ActiveRecord end def rename_index(table_name, old_name, new_name) - if (version[0] == 5 && version[1] >= 7) || version[0] >= 6 + if supports_rename_index? execute "ALTER TABLE #{quote_table_name(table_name)} RENAME INDEX #{quote_table_name(old_name)} TO #{quote_table_name(new_name)}" else super @@ -774,10 +774,22 @@ module ActiveRecord private + def version + @version ||= full_version.scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i } + end + + def mariadb? + !!(full_version =~ /mariadb/i) + end + def supports_views? version[0] >= 5 end + def supports_rename_index? + mariadb? ? false : (version[0] == 5 && version[1] >= 7) || version[0] >= 6 + end + def configure_connection variables = @config.fetch(:variables, {}).stringify_keys diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb index 0a14cdfe89..39d52e6349 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb @@ -269,8 +269,8 @@ module ActiveRecord super end - def version - @version ||= @connection.info[:version].scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i } + def full_version + @full_version ||= @connection.info[:version] end def set_field_encoding field_name diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index ad07a46e51..a03bc28744 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -470,9 +470,9 @@ module ActiveRecord rows end - # Returns the version of the connected MySQL server. - def version - @version ||= @connection.server_info.scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i } + # Returns the full version of the connected MySQL server. + def full_version + @full_version ||= @connection.server_info end def set_field_encoding field_name -- cgit v1.2.3 From a66aeb84e215c8a6e365a7fd0197c5703a14f241 Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Tue, 15 Jul 2014 08:43:18 -0700 Subject: Revert "Revert "Merge pull request #16059 from jenncoop/json-serialized-attr"" This reverts commit 6f3c64eeb1dc8288dae49f114aaf619adc7dcb7f. Conflicts: activerecord/CHANGELOG.md --- .../lib/active_record/attribute_methods/serialization.rb | 7 ++++++- activerecord/lib/active_record/coders/json.rb | 13 +++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 activerecord/lib/active_record/coders/json.rb (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb index 734d94865a..264ce2bdfa 100644 --- a/activerecord/lib/active_record/attribute_methods/serialization.rb +++ b/activerecord/lib/active_record/attribute_methods/serialization.rb @@ -37,7 +37,12 @@ module ActiveRecord # serialize :preferences, Hash # end def serialize(attr_name, class_name_or_coder = Object) - coder = if [:load, :dump].all? { |x| class_name_or_coder.respond_to?(x) } + # When ::JSON is used, force it to go through the Active Support JSON encoder + # to ensure special objects (e.g. Active Record models) are dumped correctly + # using the #as_json hook. + coder = if class_name_or_coder == ::JSON + Coders::JSON + elsif [:load, :dump].all? { |x| class_name_or_coder.respond_to?(x) } class_name_or_coder else Coders::YAMLColumn.new(class_name_or_coder) diff --git a/activerecord/lib/active_record/coders/json.rb b/activerecord/lib/active_record/coders/json.rb new file mode 100644 index 0000000000..0f60b6dab2 --- /dev/null +++ b/activerecord/lib/active_record/coders/json.rb @@ -0,0 +1,13 @@ +module ActiveRecord + module Coders # :nodoc: + class JSON # :nodoc: + def self.dump(obj) + ActiveSupport::JSON.encode(obj) + end + + def self.load(json) + ActiveSupport::JSON.decode(json) + end + end + end +end -- cgit v1.2.3 From 65122025fbfe6b75efc7220c1687bf2d8a7b8879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 15 Jul 2014 12:43:19 -0300 Subject: Predicate methods don't need to return `true` / `false` --- .../lib/active_record/connection_adapters/abstract_mysql_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index db8c16914e..e5417a9556 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -779,7 +779,7 @@ module ActiveRecord end def mariadb? - !!(full_version =~ /mariadb/i) + full_version =~ /mariadb/i end def supports_views? -- cgit v1.2.3 From f4c8a4b71fcce46c3259240b50f30e134e14c4a2 Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Mon, 14 Jul 2014 10:38:14 -0700 Subject: Merge pull request #16162 from chancancode/fix_json_coder Fixed JSON coder when loading NULL from DB --- activerecord/lib/active_record/coders/json.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/coders/json.rb b/activerecord/lib/active_record/coders/json.rb index 0f60b6dab2..75d3bfe625 100644 --- a/activerecord/lib/active_record/coders/json.rb +++ b/activerecord/lib/active_record/coders/json.rb @@ -6,7 +6,7 @@ module ActiveRecord end def self.load(json) - ActiveSupport::JSON.decode(json) + ActiveSupport::JSON.decode(json) unless json.nil? end end end -- cgit v1.2.3 From 66d0a0153578ce760d822580c5b8c0b726042ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 15 Jul 2014 16:00:50 -0300 Subject: Deprecate ActiveModel::Dirty#reset_changes in favor of #clear_changes_information This method name is causing confusion with the `reset_#{attribute}` methods. While `reset_name` set the value of the name attribute for the previous value the `reset_changes` only discard the changes and previous changes. --- activerecord/lib/active_record/attribute_methods/dirty.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index e1a86fd3aa..b58295a106 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -34,7 +34,7 @@ module ActiveRecord # reload the record and clears changed attributes. def reload(*) super.tap do - reset_changes + clear_changes_information end end @@ -64,7 +64,7 @@ module ActiveRecord store_original_raw_attributes end - def reset_changes + def clear_changes_information super original_raw_attributes.clear end -- cgit v1.2.3 From b8e8096a89b0405544c8004c9c445a7894cf7ec9 Mon Sep 17 00:00:00 2001 From: Gustavo Beathyate Date: Tue, 15 Jul 2014 15:50:29 -0500 Subject: Implement required #encode_with While running the spec `ARCONN=mysql2 ruby -v -Itest test/cases/yaml_serialization_test.rb` the following warning shows up: `implementing to_yaml is deprecated, please implement "encode_with"` --- activerecord/lib/active_record/relation/delegation.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb index 50f4d5c7ab..df3ac43b0a 100644 --- a/activerecord/lib/active_record/relation/delegation.rb +++ b/activerecord/lib/active_record/relation/delegation.rb @@ -119,6 +119,10 @@ module ActiveRecord arel.respond_to?(method, include_private) end + def encode_with(coder) + coder.represent_seq(nil, to_a) + end + protected def array_delegable?(method) -- cgit v1.2.3 From 19fae86fe028162f7c487b2822e02fa96b5b861b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 15 Jul 2014 19:51:33 -0300 Subject: Move uuid_v5 and uuid_v3 to Digest::UUID These methods are not random so they should not belings to SecureRandom module. --- activerecord/lib/active_record/fixtures.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index 4cd5f92207..4306b36ae1 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -2,7 +2,7 @@ require 'erb' require 'yaml' require 'zlib' require 'active_support/dependencies' -require 'active_support/core_ext/securerandom' +require 'active_support/core_ext/digest/uuid' require 'active_record/fixture_set/file' require 'active_record/errors' @@ -551,7 +551,7 @@ module ActiveRecord # Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes. def self.identify(label, column_type = :integer) if column_type == :uuid - SecureRandom.uuid_v5(SecureRandom::UUID_OID_NAMESPACE, label.to_s) + Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, label.to_s) else Zlib.crc32(label.to_s) % MAX_ID end -- cgit v1.2.3 From ef8cae60ee330f760e35f7c2ed9497b6918587f9 Mon Sep 17 00:00:00 2001 From: Gustavo Beathyate Date: Tue, 15 Jul 2014 18:01:16 -0500 Subject: Move #encode_with to Relation --- activerecord/lib/active_record/relation.rb | 5 +++++ activerecord/lib/active_record/relation/delegation.rb | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index cef40be7ce..ad54d84665 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -242,6 +242,11 @@ module ActiveRecord @records end + # Serializes the relation objects Array. + def encode_with(coder) + coder.represent_seq(nil, to_a) + end + def as_json(options = nil) #:nodoc: to_a.as_json(options) end diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb index df3ac43b0a..50f4d5c7ab 100644 --- a/activerecord/lib/active_record/relation/delegation.rb +++ b/activerecord/lib/active_record/relation/delegation.rb @@ -119,10 +119,6 @@ module ActiveRecord arel.respond_to?(method, include_private) end - def encode_with(coder) - coder.represent_seq(nil, to_a) - end - protected def array_delegable?(method) -- cgit v1.2.3 From a4802e217e95af14ca6ae13ab72ff3b44e2b4217 Mon Sep 17 00:00:00 2001 From: Mariano Valles Date: Wed, 16 Jul 2014 13:20:53 +0200 Subject: Fix rational to decimal on type_cast_from_user --- activerecord/lib/active_record/type/decimal.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/type/decimal.rb b/activerecord/lib/active_record/type/decimal.rb index a9db51c6ba..33d4e37ea3 100644 --- a/activerecord/lib/active_record/type/decimal.rb +++ b/activerecord/lib/active_record/type/decimal.rb @@ -14,7 +14,9 @@ module ActiveRecord private def cast_value(value) - if value.respond_to?(:to_d) + if value.class == Rational + BigDecimal.new(value, precision.to_i) + elsif value.respond_to?(:to_d) value.to_d else value.to_s.to_d -- cgit v1.2.3 From 7098c9083ccd08eb36cce5abcc99ad0506945ef0 Mon Sep 17 00:00:00 2001 From: Mariano Valles Date: Wed, 16 Jul 2014 16:08:35 +0200 Subject: Change class evaluation for Rationals in cast_value --- activerecord/lib/active_record/type/decimal.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/type/decimal.rb b/activerecord/lib/active_record/type/decimal.rb index 33d4e37ea3..1c7edc12f5 100644 --- a/activerecord/lib/active_record/type/decimal.rb +++ b/activerecord/lib/active_record/type/decimal.rb @@ -14,14 +14,16 @@ module ActiveRecord private def cast_value(value) - if value.class == Rational - BigDecimal.new(value, precision.to_i) - elsif value.respond_to?(:to_d) + case value + when Numeric, String, Rational + BigDecimal(value, precision.to_i) + when proc { value.respond_to?(:to_d) } value.to_d else - value.to_s.to_d + cast_value(value.to_s) end end + end end end -- cgit v1.2.3 From 431b4b4d8881fce7bd937d7d9ff38afb1e3d8b4c Mon Sep 17 00:00:00 2001 From: Mariano Valles Date: Wed, 16 Jul 2014 16:23:54 +0200 Subject: Fix case statement to use ::Numeric and ::String --- activerecord/lib/active_record/type/decimal.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/type/decimal.rb b/activerecord/lib/active_record/type/decimal.rb index 1c7edc12f5..31c465afdc 100644 --- a/activerecord/lib/active_record/type/decimal.rb +++ b/activerecord/lib/active_record/type/decimal.rb @@ -15,7 +15,7 @@ module ActiveRecord def cast_value(value) case value - when Numeric, String, Rational + when ::Numeric, ::String BigDecimal(value, precision.to_i) when proc { value.respond_to?(:to_d) } value.to_d -- cgit v1.2.3 From dd02463a26f3d9cd20bb6fb5ef84e0df7477c75d Mon Sep 17 00:00:00 2001 From: Mariano Valles Date: Wed, 16 Jul 2014 17:17:31 +0200 Subject: Fix decimal_test module and add new test for object responding to to_d --- activerecord/lib/active_record/type/decimal.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/type/decimal.rb b/activerecord/lib/active_record/type/decimal.rb index 31c465afdc..27566cf856 100644 --- a/activerecord/lib/active_record/type/decimal.rb +++ b/activerecord/lib/active_record/type/decimal.rb @@ -23,7 +23,6 @@ module ActiveRecord cast_value(value.to_s) end end - end end end -- cgit v1.2.3 From d3ebc02aedb9b47ac76c57e7e1b64343c8fb1662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 16 Jul 2014 14:44:41 -0300 Subject: nodoc enum hooks [ci skip] --- activerecord/lib/active_record/enum.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb index 38c6dcf88d..f0ee433d0b 100644 --- a/activerecord/lib/active_record/enum.rb +++ b/activerecord/lib/active_record/enum.rb @@ -69,12 +69,12 @@ module ActiveRecord # # Where conditions on an enum attribute must use the ordinal value of an enum. module Enum - def self.extended(base) + def self.extended(base) # :nodoc: base.class_attribute(:defined_enums) base.defined_enums = {} end - def inherited(base) + def inherited(base) # :nodoc: base.defined_enums = defined_enums.deep_dup super end -- cgit v1.2.3 From bdd4d9f20c39951772f2c8a65442f3bf70217803 Mon Sep 17 00:00:00 2001 From: Chris Griego Date: Wed, 16 Jul 2014 15:46:08 -0500 Subject: Remove unused 1:1 association :remote option This option is unused, left over from pre-1.0 Rails to internally distinguish the location of the foreign key. --- .../lib/active_record/associations/builder/singular_association.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/builder/singular_association.rb b/activerecord/lib/active_record/associations/builder/singular_association.rb index 17f36acf40..6e6dd7204c 100644 --- a/activerecord/lib/active_record/associations/builder/singular_association.rb +++ b/activerecord/lib/active_record/associations/builder/singular_association.rb @@ -3,7 +3,7 @@ module ActiveRecord::Associations::Builder class SingularAssociation < Association #:nodoc: def valid_options - super + [:remote, :dependent, :primary_key, :inverse_of, :required] + super + [:dependent, :primary_key, :inverse_of, :required] end def self.define_accessors(model, reflection) -- cgit v1.2.3 From 8c263d53b3b9d190a8ae564ca043b96b76c76877 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Mon, 14 Jul 2014 18:37:59 -0400 Subject: Remove need for macro instance var Same as we did for collection, removed the `@macro` instance var and it is now set in each association. Unfortunately it can't be left undefined in AssociationReflection so it has to be set there. For now I am setting it to NotImplementedError since there is no default macro and it changes based on the reflection type. --- activerecord/lib/active_record/reflection.rb | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 12208aecf7..2eefba2dfe 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -177,12 +177,6 @@ module ActiveRecord # has_many :clients returns :clients attr_reader :name - # Returns the macro type. - # - # composed_of :balance, class_name: 'Money' returns :composed_of - # has_many :clients returns :has_many - attr_reader :macro - attr_reader :scope # Returns the hash of options used for the macro. @@ -386,7 +380,7 @@ Joining, Preloading and eager loading of these associations is deprecated and wi scope ? [[scope]] : [[]] end - alias :source_macro :macro + def source_macro; macro; end def has_inverse? inverse_name @@ -408,6 +402,11 @@ Joining, Preloading and eager loading of these associations is deprecated and wi end end + # Returns the macro type. + # + # has_many :clients returns :has_many + def macro; raise NotImplementedError; end + # Returns whether or not this association reflection is for a collection # association. Returns +true+ if the +macro+ is either +has_many+ or # +has_and_belongs_to_many+, +false+ otherwise. @@ -578,10 +577,11 @@ Joining, Preloading and eager loading of these associations is deprecated and wi class HasManyReflection < AssociationReflection #:nodoc: def initialize(name, scope, options, active_record) - @macro = :has_many super(name, scope, options, active_record) end + def macro; :has_many; end + def collection? true end @@ -589,24 +589,27 @@ Joining, Preloading and eager loading of these associations is deprecated and wi class HasOneReflection < AssociationReflection #:nodoc: def initialize(name, scope, options, active_record) - @macro = :has_one super(name, scope, options, active_record) end + + def macro; :has_one; end end class BelongsToReflection < AssociationReflection #:nodoc: def initialize(name, scope, options, active_record) - @macro = :belongs_to super(name, scope, options, active_record) end + + def macro; :belongs_to; end end class HasAndBelongsToManyReflection < AssociationReflection #:nodoc: def initialize(name, scope, options, active_record) - @macro = :has_and_belongs_to_many super end + def macro; :has_and_belongs_to_many; end + def collection? true end -- cgit v1.2.3 From f57bafe44b14f836a8c28f9a5f187d4876499621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Thu, 17 Jul 2014 17:47:03 -0300 Subject: Prefer if/else for this case One of the branches is using a proc to check if the value respond_to a method so it is better to not do case comparations --- activerecord/lib/active_record/type/decimal.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/type/decimal.rb b/activerecord/lib/active_record/type/decimal.rb index 27566cf856..ba5d244729 100644 --- a/activerecord/lib/active_record/type/decimal.rb +++ b/activerecord/lib/active_record/type/decimal.rb @@ -14,10 +14,9 @@ module ActiveRecord private def cast_value(value) - case value - when ::Numeric, ::String + if value.is_a?(::Numeric) || value.is_a?(::String) BigDecimal(value, precision.to_i) - when proc { value.respond_to?(:to_d) } + elsif value.respond_to?(:to_d) value.to_d else cast_value(value.to_s) -- cgit v1.2.3 From a013b082aa4459762b55bbc6c59a4f072eef8224 Mon Sep 17 00:00:00 2001 From: Stefan Kanev Date: Fri, 18 Jul 2014 19:46:53 +0300 Subject: create_join_table uses same logic as HABTM reflections Before this change, create_join_table would not remove the common prefix in the join table name, unlike ActiveRecord::Reflections. A HABTM between Music::Artist and Music::Record would use a table music_artists_records, while create_join table would create music_artists_music_records. --- activerecord/lib/active_record/migration/join_table.rb | 2 +- activerecord/lib/active_record/model_schema.rb | 11 +++++++++++ activerecord/lib/active_record/reflection.rb | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/migration/join_table.rb b/activerecord/lib/active_record/migration/join_table.rb index ebf64cbcdc..05569fadbd 100644 --- a/activerecord/lib/active_record/migration/join_table.rb +++ b/activerecord/lib/active_record/migration/join_table.rb @@ -8,7 +8,7 @@ module ActiveRecord end def join_table_name(table_1, table_2) - [table_1.to_s, table_2.to_s].sort.join("_").to_sym + ModelSchema.derive_join_table_name(table_1, table_2).to_sym end end end diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb index 092c3b4fb7..850220babd 100644 --- a/activerecord/lib/active_record/model_schema.rb +++ b/activerecord/lib/active_record/model_schema.rb @@ -55,6 +55,17 @@ module ActiveRecord delegate :type_for_attribute, to: :class end + # Derives the join table name for +first_table+ and +second_table+. The + # table names appear in alphabetical order. A common prefix is removed + # (useful for namespaced models like Music::Artist and Music::Record): + # + # artists, records => artists_records + # records, artists => artists_records + # music_artists, music_records => music_artists_records + def self.derive_join_table_name(first_table, second_table) # :nodoc: + [first_table.to_s, second_table.to_s].sort.join("\0").gsub(/^(.*_)(.+)\0\1(.+)/, '\1\2_\3').gsub("\0", "_") + end + module ClassMethods # Guesses the table name (in forced lower-case) based on the name of the class in the # inheritance hierarchy descending directly from ActiveRecord::Base. So if the hierarchy diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 2eefba2dfe..86eef9ca36 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -567,7 +567,7 @@ Joining, Preloading and eager loading of these associations is deprecated and wi end def derive_join_table - [active_record.table_name, klass.table_name].sort.join("\0").gsub(/^(.*_)(.+)\0\1(.+)/, '\1\2_\3').gsub("\0", "_") + ModelSchema.derive_join_table_name active_record.table_name, klass.table_name end def primary_key(klass) -- cgit v1.2.3 From 44bf33c9594f98a1d279af451850c69462c24101 Mon Sep 17 00:00:00 2001 From: Steve Date: Sat, 19 Jul 2014 00:20:41 -0700 Subject: Fixed typo in comment --- activerecord/lib/active_record/explain.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/explain.rb b/activerecord/lib/active_record/explain.rb index e65dab07ba..727a9befc1 100644 --- a/activerecord/lib/active_record/explain.rb +++ b/activerecord/lib/active_record/explain.rb @@ -27,7 +27,7 @@ module ActiveRecord end.join("\n") end.join("\n") - # Overriding inspect to be more human readable, specially in the console. + # Overriding inspect to be more human readable, especially in the console. def str.inspect self end -- cgit v1.2.3 From 3b0430f3daccb6cfdf96a554d6555798fabd71ba Mon Sep 17 00:00:00 2001 From: vadivelan Date: Mon, 21 Jul 2014 20:55:53 +0530 Subject: Touch option description grammatical error fixed [ci skip] --- activerecord/lib/active_record/associations.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 7ec7eb1b24..ec78d10124 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1418,7 +1418,7 @@ module ActiveRecord # # Note that accepts_nested_attributes_for sets :autosave to true. # [:touch] - # If true, the associated object will be touched (the updated_at/on attributes set to now) + # If true, the associated object will be touched (the updated_at/on attributes set to current time) # when this record is either saved or destroyed. If you specify a symbol, that attribute # will be updated with the current time in addition to the updated_at/on attribute. # [:inverse_of] -- cgit v1.2.3 From 6d327dbc0cd7969375e14a56c0a9bc6a7c847056 Mon Sep 17 00:00:00 2001 From: Andrey Novikov Date: Sat, 19 Jul 2014 23:38:38 +0400 Subject: Allow to specify a type for foreign key column in migrations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Andrey Novikov & Łukasz Sarnacki] --- .../connection_adapters/abstract/schema_definitions.rb | 9 ++++++++- .../connection_adapters/abstract/schema_statements.rb | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index 98e6795f10..d51bf022a4 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -280,12 +280,19 @@ module ActiveRecord column(:updated_at, :datetime, options) end + # Adds an appropriately-named _id column as :integer (or whatever :type option specifies), + # plus a corresponding _type column if the :polymorphic option is supplied. If :polymorphic + # is a hash of options, these will be used when creating the _type column. The :index option + # will also create an index, similar to calling add_index. + # + # references :tagger, polymorphic: true, index: true, type: :uuid def references(*args) options = args.extract_options! polymorphic = options.delete(:polymorphic) index_options = options.delete(:index) + type = options.delete(:type) || :integer args.each do |col| - column("#{col}_id", :integer, options) + column("#{col}_id", type, options) column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic index(polymorphic ? %w(id type).map { |t| "#{col}_#{t}" } : "#{col}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index 5814c2b711..8ecb7c0506 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -619,7 +619,8 @@ module ActiveRecord def add_reference(table_name, ref_name, options = {}) polymorphic = options.delete(:polymorphic) index_options = options.delete(:index) - add_column(table_name, "#{ref_name}_id", :integer, options) + type = options.delete(:type) || :integer + add_column(table_name, "#{ref_name}_id", type, options) add_column(table_name, "#{ref_name}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic add_index(table_name, polymorphic ? %w[id type].map{ |t| "#{ref_name}_#{t}" } : "#{ref_name}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options end -- cgit v1.2.3 From 2a67e12fdb832a6b6e94bed1a0b05290019f5514 Mon Sep 17 00:00:00 2001 From: Yves Senn Date: Thu, 24 Jul 2014 14:27:41 +0200 Subject: pg, `change_column_default, :table, :column, nil` issues `DROP DEFAULT`. Closes #16261. [Matthew Draper, Yves Senn] Using `DEFAULT NULL` results in the same behavior as `DROP DEFAULT`. However, PostgreSQL will cast the default to the columns type, which leaves us with a default like "default NULL::character varying". /cc @matthewd --- .../connection_adapters/postgresql/schema_statements.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb index e09672d239..7042817672 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb @@ -423,8 +423,16 @@ module ActiveRecord def change_column_default(table_name, column_name, default) clear_cache! column = column_for(table_name, column_name) + return unless column - execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} SET DEFAULT #{quote_default_value(default, column)}" if column + alter_column_query = "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} %s" + if default.nil? + # DEFAULT NULL results in the same behavior as DROP DEFAULT. However, PostgreSQL will + # cast the default to the columns type, which leaves us with a default like "default NULL::character varying". + execute alter_column_query % "DROP DEFAULT" + else + execute alter_column_query % "SET DEFAULT #{quote_default_value(default, column)}" + end end def change_column_null(table_name, column_name, null, default = nil) -- cgit v1.2.3 From 98d2421ef937a819ef8dadc94ba519842e33e7b6 Mon Sep 17 00:00:00 2001 From: a3gis Date: Thu, 24 Jul 2014 14:21:55 +0100 Subject: Fixes #16265 --- .../lib/active_record/connection_adapters/connection_specification.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb index 2fcb085ab2..7082989f68 100644 --- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb +++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb @@ -250,7 +250,7 @@ module ActiveRecord # Connection details inside of the "url" key win any merge conflicts def resolve_hash_connection(spec) if spec["url"] && spec["url"] !~ /^jdbc:/ - connection_hash = resolve_string_connection(spec.delete("url")) + connection_hash = resolve_url_connection(spec.delete("url")) spec.merge!(connection_hash) end spec -- cgit v1.2.3 From c0932162d27f4a41455893d38ef55cb1cc606575 Mon Sep 17 00:00:00 2001 From: a3gis Date: Thu, 24 Jul 2014 14:23:36 +0100 Subject: Fix documentation typo in ConnectionSpecification::Resolve.spec --- .../lib/active_record/connection_adapters/connection_specification.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb index 7082989f68..5693031053 100644 --- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb +++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb @@ -160,7 +160,7 @@ module ActiveRecord # config = { "production" => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" } } # spec = Resolver.new(config).spec(:production) # spec.adapter_method - # # => "sqlite3" + # # => "sqlite3_connection" # spec.config # # => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" } # -- cgit v1.2.3 From 091b246bb0111357edbb9703ea342a944b04deb6 Mon Sep 17 00:00:00 2001 From: Yves Senn Date: Thu, 24 Jul 2014 16:38:41 +0200 Subject: fix, mysql `db:purge` respects `Rails.env`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously this method always established a connection to the test database. This resulted in buggy behavior when combined with other tasks like `bin/rake db:schema:load`. This was one of the reasons why #15394 (22e9a91189af2c4e6217a888e77f22a23d3247d1) was reverted: > I’ve replicated it on a new app by the following commands: 1) rails generate model post:title, 2) rake db:migrate, 3) rake db:schema:load, 4) rails runner ‘puts Post.first’. The last command goes boom. Problem is that rake db:schema:load wipes the database, and then doesn’t actually restore it. This is all on MySQL. There’s no problem with SQLite. -- DHH https://github.com/rails/rails/commit/22e9a91189af2c4e6217a888e77f22a23d3247d1#commitcomment-6834245 --- activerecord/lib/active_record/tasks/mysql_database_tasks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb index 644c4852b9..d890196f47 100644 --- a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb @@ -42,7 +42,7 @@ module ActiveRecord end def purge - establish_connection :test + establish_connection configuration connection.recreate_database configuration['database'], creation_options end -- cgit v1.2.3 From 99b82fdf03fcf6d6ca8e2d810ba35011723a5267 Mon Sep 17 00:00:00 2001 From: Philippe Creux Date: Thu, 24 Jul 2014 10:39:39 -0700 Subject: Add support for Postgresql JSONB [Philippe Creux, Chris Teague] --- .../connection_adapters/postgresql/oid.rb | 1 + .../connection_adapters/postgresql/oid/jsonb.rb | 23 ++++++++++++++++++++++ .../postgresql/schema_definitions.rb | 4 ++++ .../connection_adapters/postgresql_adapter.rb | 1 + 4 files changed, 29 insertions(+) create mode 100644 activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb index d05ce61330..d28a2b4fa0 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb @@ -14,6 +14,7 @@ require 'active_record/connection_adapters/postgresql/oid/hstore' require 'active_record/connection_adapters/postgresql/oid/inet' require 'active_record/connection_adapters/postgresql/oid/integer' require 'active_record/connection_adapters/postgresql/oid/json' +require 'active_record/connection_adapters/postgresql/oid/jsonb' require 'active_record/connection_adapters/postgresql/oid/money' require 'active_record/connection_adapters/postgresql/oid/point' require 'active_record/connection_adapters/postgresql/oid/range' diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb new file mode 100644 index 0000000000..34ed32ad35 --- /dev/null +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb @@ -0,0 +1,23 @@ +module ActiveRecord + module ConnectionAdapters + module PostgreSQL + module OID # :nodoc: + class Jsonb < Json # :nodoc: + def type + :jsonb + end + + def changed_in_place?(raw_old_value, new_value) + # Postgres does not preserve insignificant whitespaces when + # roundtripping jsonb columns. This causes some false positives for + # the comparison here. Therefore, we need to parse and re-dump the + # raw value here to ensure the insignificant whitespaces are + # consitent with our encoder's output. + raw_old_value = type_cast_for_database(type_cast_from_database(raw_old_value)) + super(raw_old_value, new_value) + end + end + end + end + end +end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb index 0867e5ef54..83554bbf74 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb @@ -64,6 +64,10 @@ module ActiveRecord column(name, :json, options) end + def jsonb(name, options = {}) + column(name, :jsonb, options) + end + def citext(name, options = {}) column(name, :citext, options) end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index f660fc41cf..eede374678 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -451,6 +451,7 @@ module ActiveRecord m.register_type 'point', OID::Point.new m.register_type 'hstore', OID::Hstore.new m.register_type 'json', OID::Json.new + m.register_type 'jsonb', OID::Jsonb.new m.register_type 'cidr', OID::Cidr.new m.register_type 'inet', OID::Inet.new m.register_type 'uuid', OID::Uuid.new -- cgit v1.2.3 From 368525a5a5b43a2955d063c2f81af5d6ed1c2188 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Thu, 24 Jul 2014 16:25:34 -0400 Subject: Remove finishing? method from transaction. The finishing variable on the transaction object was a work-around for the savepoint name, so after a rollback/commit the savepoint could be released with the previous name. related: 9296e6939bcc786149a07dac334267c4035b623a 60c88e64e26682a954f7c8cd6669d409ffffcc8b --- .../connection_adapters/abstract/transaction.rb | 33 +++++++--------------- .../connection_adapters/abstract_adapter.rb | 4 ++- 2 files changed, 13 insertions(+), 24 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index bc4884b538..1721437615 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -78,45 +78,28 @@ module ActiveRecord @parent = parent @records = [] - @finishing = false @joinable = options.fetch(:joinable, true) end - # This state is necessary so that we correctly handle stuff that might - # happen in a commit/rollback. But it's kinda distasteful. Maybe we can - # find a better way to structure it in the future. - def finishing? - @finishing - end def joinable? - @joinable && !finishing? + @joinable end def number - if finishing? - parent.number - else - parent.number + 1 - end + parent.number + 1 end def begin(options = {}) - if finishing? - parent.begin - else - SavepointTransaction.new(connection, self, options) - end + SavepointTransaction.new(connection, self, options) end def rollback - @finishing = true perform_rollback parent end def commit - @finishing = true perform_commit parent end @@ -183,24 +166,28 @@ module ActiveRecord end class SavepointTransaction < OpenTransaction #:nodoc: + attr_reader :savepoint_name + def initialize(connection, parent, options = {}) if options[:isolation] raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction" end super - connection.create_savepoint + + @savepoint_name = "active_record_#{number}" + connection.create_savepoint(@savepoint_name) end def perform_rollback - connection.rollback_to_savepoint + connection.rollback_to_savepoint(@savepoint_name) rollback_records end def perform_commit @state.set_state(:committed) @state.parent = parent.state - connection.release_savepoint + connection.release_savepoint(@savepoint_name) end end end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index f8c054eb69..1397358f79 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -357,7 +357,9 @@ module ActiveRecord end def current_savepoint_name - "active_record_#{open_transactions}" + if current_transaction.is_a? SavepointTransaction + current_transaction.savepoint_name + end end # Check the connection back in to the connection pool -- cgit v1.2.3 From 8f32ddba776426384b46feaededaf57bb01f5aef Mon Sep 17 00:00:00 2001 From: a3gis Date: Fri, 25 Jul 2014 18:03:17 +0200 Subject: Fix documentation of SQlite3Adapter.columns As of https://github.com/rails/rails/commit/e781aa31fc52a7c696115302ef4d4e02bfd1533b SQLite3Column has been dropped. --- activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index bf96acad4a..faf1cdc686 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -385,7 +385,7 @@ module ActiveRecord table_name && tables(nil, table_name).any? end - # Returns an array of +SQLite3Column+ objects for the table specified by +table_name+. + # Returns an array of +Column+ objects for the table specified by +table_name+. def columns(table_name) #:nodoc: table_structure(table_name).map do |field| case field["dflt_value"] -- cgit v1.2.3 From 775cc7de6081f823a97a7803a6eb4d373b5c82dd Mon Sep 17 00:00:00 2001 From: a3gis Date: Fri, 25 Jul 2014 18:32:04 +0200 Subject: Remove references to SQLite3Column from documentation --- activerecord/lib/active_record/attribute_methods.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index 1cdb530815..a2bb78dfcc 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -193,7 +193,7 @@ module ActiveRecord # # person = Person.new # person.column_for_attribute(:name) # the result depends on the ConnectionAdapter - # # => # + # # => # # # person.column_for_attribute(:nothing) # # => nil -- cgit v1.2.3 From 75f3584d9b87097377b312d35bd124686723ce4a Mon Sep 17 00:00:00 2001 From: Caleb Thompson Date: Fri, 25 Jul 2014 13:30:23 -0500 Subject: Extract iterator method in AR::SchemaDumper Gems which wish to tie into ActiveRecord::SchemaDumper need to duplicate this logic currently. [Foreigner] is one such example, as is a library I'm currently working on but which hasn't been released yet: def tables_with_foreign_keys(stream) tables_without_foreign_keys(stream) @connection.tables.sort.each do |table| next if ['schema_migrations', ignore_tables].flatten.any? do |ignored| case ignored when String; table == ignored when Regexp; table =~ ignored else raise StandardError, 'ActiveRecord::SchemaDumper.ignore_tables accepts an array of String and / or Regexp values.' end end foreign_keys(table, stream) end end [Foreigner]: https://github.com/matthuhiggins/foreigner/blob/master/lib/foreigner/schema_dumper.rb#L36-L43 Extract the skip logic to a method, making it much simpler to follow this same behavior in gems that are tying into the migration flow and let them dump only tables that aren't skipped without copying this block of code. The above code could then be simplified to: def tables_with_foreign_keys(stream) tables_without_foreign_keys(stream) @connection.tables.sort.each do |table| foreign_keys(table, stream) unless ignored?(table) end end It also, in my opinion, simplifies the logic on ActiveRecord's side, and clarifies the intent of the skip logic. --- activerecord/lib/active_record/schema_dumper.rb | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index a94364bde1..fae6427ea1 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -92,16 +92,9 @@ HEADER def tables(stream) sorted_tables = @connection.tables.sort - sorted_tables.each do |tbl| - next if ['schema_migrations', ignore_tables].flatten.any? do |ignored| - case ignored - when String; remove_prefix_and_suffix(tbl) == ignored - when Regexp; remove_prefix_and_suffix(tbl) =~ ignored - else - raise StandardError, 'ActiveRecord::SchemaDumper.ignore_tables accepts an array of String and / or Regexp values.' - end - end - table(tbl, stream) + + sorted_tables.each do |table_name| + table(table_name, stream) unless ignored?(table_name) end # dump foreign keys at the end to make sure all dependent tables exist. @@ -254,5 +247,16 @@ HEADER def remove_prefix_and_suffix(table) table.gsub(/^(#{@options[:table_name_prefix]})(.+)(#{@options[:table_name_suffix]})$/, "\\2") end + + def ignored?(table_name) + ['schema_migrations', ignore_tables].flatten.any? do |ignored| + case ignored + when String; remove_prefix_and_suffix(table_name) == ignored + when Regexp; remove_prefix_and_suffix(table_name) =~ ignored + else + raise StandardError, 'ActiveRecord::SchemaDumper.ignore_tables accepts an array of String and / or Regexp values.' + end + end + end end end -- cgit v1.2.3 From 2ee8419813b643f92344097d1c8460f045967480 Mon Sep 17 00:00:00 2001 From: Kenn Ejima Date: Fri, 25 Jul 2014 11:40:28 -0700 Subject: No verbose backtrace by db:drop when database does not exist. --- activerecord/lib/active_record/tasks/database_tasks.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index 9bc23b5ec7..80186a88e3 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -110,6 +110,8 @@ module ActiveRecord def drop(*arguments) configuration = arguments.first class_for_adapter(configuration['adapter']).new(*arguments).drop + rescue ActiveRecord::NoDatabaseError + $stderr.puts "#{configuration['database']} does not exist" rescue Exception => error $stderr.puts error, *(error.backtrace) $stderr.puts "Couldn't drop #{configuration['database']}" -- cgit v1.2.3 From bd54e1956b939feb605d1f6c05d3e01943933c08 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Sun, 27 Jul 2014 19:35:00 -0400 Subject: [ci skip] Fix documentation for @macro and reflection types Since `@macro` doesn't exist anymore and these reflections are no longer AssociationReflections but their own types of reflections based on macro I updated the documentation to match the changes I made in #16089 and #16198. An `AssociationReflection` that had a `@macro` of `:has_many` now is a `HasManyReflection` --- .../associations/join_dependency/join_association.rb | 2 +- activerecord/lib/active_record/reflection.rb | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/join_dependency/join_association.rb index a0e83c0a02..719eff9acc 100644 --- a/activerecord/lib/active_record/associations/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/join_dependency/join_association.rb @@ -95,7 +95,7 @@ module ActiveRecord # end # # If I execute `Physician.joins(:appointments).to_a` then - # reflection # => # + # reflection # => # # table # => # # key # => physician_id # foreign_table # => # diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 86eef9ca36..1672128aa3 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -167,9 +167,12 @@ module ActiveRecord # AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods. # # MacroReflection - # AggregateReflection # AssociationReflection - # ThroughReflection + # AggregateReflection + # HasManyReflection + # HasOneReflection + # BelongsToReflection + # ThroughReflection class MacroReflection < AbstractReflection # Returns the name of the macro. # @@ -647,7 +650,7 @@ Joining, Preloading and eager loading of these associations is deprecated and wi # # tags_reflection = Post.reflect_on_association(:tags) # tags_reflection.source_reflection - # # => + # # => # def source_reflection through_reflection.klass._reflect_on_association(source_reflection_name) @@ -663,7 +666,7 @@ Joining, Preloading and eager loading of these associations is deprecated and wi # # tags_reflection = Post.reflect_on_association(:tags) # tags_reflection.through_reflection - # # => + # # => # def through_reflection active_record._reflect_on_association(options[:through]) @@ -683,8 +686,8 @@ Joining, Preloading and eager loading of these associations is deprecated and wi # # tags_reflection = Post.reflect_on_association(:tags) # tags_reflection.chain - # # => [:taggings}, @active_record=Post>, - # ] + # # => [, + # ] # def chain @chain ||= begin -- cgit v1.2.3 From 9fb2fdc91370c3b5d3be93feef9fc5598a770028 Mon Sep 17 00:00:00 2001 From: Tom Kadwill Date: Mon, 28 Jul 2014 15:46:57 +0100 Subject: Added nodoc to change_table --- activerecord/lib/active_record/migration/command_recorder.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/migration/command_recorder.rb b/activerecord/lib/active_record/migration/command_recorder.rb index c44d8c1665..5337106001 100644 --- a/activerecord/lib/active_record/migration/command_recorder.rb +++ b/activerecord/lib/active_record/migration/command_recorder.rb @@ -85,7 +85,7 @@ module ActiveRecord alias :add_belongs_to :add_reference alias :remove_belongs_to :remove_reference - def change_table(table_name, options = {}) + def change_table(table_name, options = {}) # :nodoc: yield delegate.update_table_definition(table_name, self) end -- cgit v1.2.3 From a09f0257580c240fc91347d60725cc5ac0d908c7 Mon Sep 17 00:00:00 2001 From: Yves Senn Date: Mon, 28 Jul 2014 17:30:43 +0200 Subject: docs, clarify attribute query methods on numeric columns. Closes #16246. [ci skip] --- activerecord/lib/active_record/base.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 64cc5b68cc..906f590c99 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -141,6 +141,7 @@ module ActiveRecord #:nodoc: # # In addition to the basic accessors, query methods are also automatically available on the Active Record object. # Query methods allow you to test whether an attribute value is present. + # For numeric values, +persent+ is defined as non-zero. # # For example, an Active Record User with the name attribute has a name? method that you can call # to determine whether the user has a name: -- cgit v1.2.3 From 4e116c56a84bd995c6f9524a84b9227b5d32a09a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 28 Jul 2014 13:44:37 -0300 Subject: Fix typo and remove code block since present is not a method. --- activerecord/lib/active_record/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 906f590c99..f978fbd0a4 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -141,7 +141,7 @@ module ActiveRecord #:nodoc: # # In addition to the basic accessors, query methods are also automatically available on the Active Record object. # Query methods allow you to test whether an attribute value is present. - # For numeric values, +persent+ is defined as non-zero. + # For numeric values, present is defined as non-zero. # # For example, an Active Record User with the name attribute has a name? method that you can call # to determine whether the user has a name: -- cgit v1.2.3 From 97bb76dc288d998a684b17a09d79708e2e4b584a Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Thu, 24 Jul 2014 13:37:49 -0400 Subject: Transactions refactoring Add a transaction manager per connection, so it can controls the connection responsibilities. Delegate transaction methods to transaction_manager --- .../abstract/database_statements.rb | 44 +++------------- .../connection_adapters/abstract/transaction.rb | 58 ++++++++++++++++++++++ .../connection_adapters/abstract_adapter.rb | 1 + 3 files changed, 65 insertions(+), 38 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb index e8ce00d92b..98e96099cb 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -203,62 +203,30 @@ module ActiveRecord if options[:isolation] raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction" end - yield else - within_new_transaction(options) { yield } + transaction_manager.within_new_transaction(options) { yield } end rescue ActiveRecord::Rollback # rollbacks are silently swallowed end - def within_new_transaction(options = {}) #:nodoc: - transaction = begin_transaction(options) - yield - rescue Exception => error - rollback_transaction if transaction - raise - ensure - begin - commit_transaction unless error - rescue Exception - rollback_transaction - raise - end - end - - def open_transactions - @transaction.number - end + attr_reader :transaction_manager #:nodoc: - def current_transaction #:nodoc: - @transaction - end + delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction, :commit_transaction, :rollback_transaction, to: :transaction_manager def transaction_open? - @transaction.open? - end - - def begin_transaction(options = {}) #:nodoc: - @transaction = @transaction.begin(options) - end - - def commit_transaction #:nodoc: - @transaction = @transaction.commit - end - - def rollback_transaction #:nodoc: - @transaction = @transaction.rollback + current_transaction.open? end def reset_transaction #:nodoc: - @transaction = ClosedTransaction.new(self) + @transaction_manager = TransactionManager.new(self) end # Register a record with the current transaction so that its after_commit and after_rollback callbacks # can be called. def add_transaction_record(record) - @transaction.add_record(record) + current_transaction.add_record(record) end # Begins the transaction (and turns off auto-committing). diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 1721437615..7618d6902d 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -1,5 +1,63 @@ module ActiveRecord module ConnectionAdapters + class TransactionManager #:nodoc: + def initialize(connection) + @stack = [] + @connection = connection + end + + def begin_transaction(options = {}) + transaction = + if @stack.empty? + RealTransaction.new(@connection, current_transaction, options) + else + SavepointTransaction.new(@connection, current_transaction, options) + end + + @stack.push(transaction) + transaction + end + + def commit_transaction + @stack.pop.commit + end + + def rollback_transaction + @stack.pop.rollback + end + + def within_new_transaction(options = {}) + transaction = begin_transaction options + yield + rescue Exception => error + transaction.rollback if transaction + raise + ensure + begin + transaction.commit unless error + rescue Exception + transaction.rollback + raise + ensure + @stack.pop if transaction + end + end + + def open_transactions + @stack.size + end + + def current_transaction + @stack.last || closed_transaction + end + + private + + def closed_transaction + @closed_transaction ||= ClosedTransaction.new(@connection) + end + end + class Transaction #:nodoc: attr_reader :connection diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 1397358f79..c31726437f 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -45,6 +45,7 @@ module ActiveRecord end autoload_at 'active_record/connection_adapters/abstract/transaction' do + autoload :TransactionManager autoload :ClosedTransaction autoload :RealTransaction autoload :SavepointTransaction -- cgit v1.2.3 From d37bcc1d5a781687384fbe632a1850ab218ccbfd Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Mon, 28 Jul 2014 13:25:19 -0400 Subject: savepoint_name should return nil for non-savepoint transactions Also add test to assets the savepoint name --- .../lib/active_record/connection_adapters/abstract/transaction.rb | 7 ++++++- .../lib/active_record/connection_adapters/abstract_adapter.rb | 4 +--- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 7618d6902d..54f873a2a2 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -69,6 +69,10 @@ module ActiveRecord def state @state end + + def savepoint_name + nil + end end class TransactionState @@ -233,7 +237,8 @@ module ActiveRecord super - @savepoint_name = "active_record_#{number}" + # Savepoint name only counts the Savepoint transactions, so we need to subtract 1 + @savepoint_name = "active_record_#{number - 1}" connection.create_savepoint(@savepoint_name) end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index c31726437f..99c728814a 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -358,9 +358,7 @@ module ActiveRecord end def current_savepoint_name - if current_transaction.is_a? SavepointTransaction - current_transaction.savepoint_name - end + current_transaction.savepoint_name end # Check the connection back in to the connection pool -- cgit v1.2.3 From f5cec76ea8de1b9d076d0b1138ab8c2cabc0390d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 28 Jul 2014 15:04:31 -0300 Subject: Extract the transaction class to a local variable --- .../lib/active_record/connection_adapters/abstract/transaction.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 54f873a2a2..3a266512a9 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -7,12 +7,8 @@ module ActiveRecord end def begin_transaction(options = {}) - transaction = - if @stack.empty? - RealTransaction.new(@connection, current_transaction, options) - else - SavepointTransaction.new(@connection, current_transaction, options) - end + transaction_class = @stack.empty? ? RealTransaction : SavepointTransaction + transaction = transaction_class.new(@connection, current_transaction, options) @stack.push(transaction) transaction -- cgit v1.2.3 From 2a7cf24cb7aab28f483a6772b608e2868a9030ba Mon Sep 17 00:00:00 2001 From: Ponomarev Nikolay Date: Tue, 29 Jul 2014 02:51:08 +0400 Subject: remove blank lines in the start of the ActiveRecord files --- .../lib/active_record/associations/has_many_through_association.rb | 1 - activerecord/lib/active_record/associations/has_one_association.rb | 1 - activerecord/lib/active_record/connection_adapters/schema_cache.rb | 1 - activerecord/lib/active_record/query_cache.rb | 1 - activerecord/lib/active_record/readonly_attributes.rb | 1 - activerecord/lib/active_record/relation/batches.rb | 1 - activerecord/lib/active_record/schema.rb | 1 - activerecord/lib/active_record/timestamp.rb | 1 - 8 files changed, 8 deletions(-) (limited to 'activerecord/lib/active_record') 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 007e3bc555..44c4436e95 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -1,4 +1,3 @@ - module ActiveRecord # = Active Record Has Many Through Association module Associations diff --git a/activerecord/lib/active_record/associations/has_one_association.rb b/activerecord/lib/active_record/associations/has_one_association.rb index 944caacab6..e6095d84dc 100644 --- a/activerecord/lib/active_record/associations/has_one_association.rb +++ b/activerecord/lib/active_record/associations/has_one_association.rb @@ -1,4 +1,3 @@ - module ActiveRecord # = Active Record Belongs To Has One Association module Associations diff --git a/activerecord/lib/active_record/connection_adapters/schema_cache.rb b/activerecord/lib/active_record/connection_adapters/schema_cache.rb index 4d8afcf16a..3116bed596 100644 --- a/activerecord/lib/active_record/connection_adapters/schema_cache.rb +++ b/activerecord/lib/active_record/connection_adapters/schema_cache.rb @@ -1,4 +1,3 @@ - module ActiveRecord module ConnectionAdapters class SchemaCache diff --git a/activerecord/lib/active_record/query_cache.rb b/activerecord/lib/active_record/query_cache.rb index 16ad942912..dcb2bd3d84 100644 --- a/activerecord/lib/active_record/query_cache.rb +++ b/activerecord/lib/active_record/query_cache.rb @@ -1,4 +1,3 @@ - module ActiveRecord # = Active Record Query Cache class QueryCache diff --git a/activerecord/lib/active_record/readonly_attributes.rb b/activerecord/lib/active_record/readonly_attributes.rb index b3ddfd63d4..85bbac43e4 100644 --- a/activerecord/lib/active_record/readonly_attributes.rb +++ b/activerecord/lib/active_record/readonly_attributes.rb @@ -1,4 +1,3 @@ - module ActiveRecord module ReadonlyAttributes extend ActiveSupport::Concern diff --git a/activerecord/lib/active_record/relation/batches.rb b/activerecord/lib/active_record/relation/batches.rb index 29fc150b3d..b069cdce7c 100644 --- a/activerecord/lib/active_record/relation/batches.rb +++ b/activerecord/lib/active_record/relation/batches.rb @@ -1,4 +1,3 @@ - module ActiveRecord module Batches # Looping through a collection of records from the database diff --git a/activerecord/lib/active_record/schema.rb b/activerecord/lib/active_record/schema.rb index 4bfd0167a4..0a5546a760 100644 --- a/activerecord/lib/active_record/schema.rb +++ b/activerecord/lib/active_record/schema.rb @@ -1,4 +1,3 @@ - module ActiveRecord # = Active Record Schema # diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index e2e37e7c00..ddf3e1804c 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -1,4 +1,3 @@ - module ActiveRecord # = Active Record Timestamp # -- cgit v1.2.3 From 7413eeee36e6f3be9ab8c1a08477314be671df84 Mon Sep 17 00:00:00 2001 From: Satoru Yamasaki Date: Tue, 29 Jul 2014 20:07:17 +0900 Subject: [ci skip] fix doc typo for validates_uniqueness_of --- activerecord/lib/active_record/validations/uniqueness.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index 2a34969a8c..2dba4c7b94 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -152,7 +152,7 @@ module ActiveRecord # or if: Proc.new { |user| user.signup_step > 2 }). The method, # proc or string should return or evaluate to a +true+ or +false+ value. # * :unless - Specifies a method, proc or string to call to - # determine if the validation should ot occur (e.g. unless: :skip_validation, + # determine if the validation should not occur (e.g. unless: :skip_validation, # or unless: Proc.new { |user| user.signup_step <= 2 }). The # method, proc or string should return or evaluate to a +true+ or +false+ # value. -- cgit v1.2.3 From dd9829a9ea460ddcfc8d954f2b95161b52fff6e7 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Tue, 29 Jul 2014 10:09:06 -0400 Subject: Remove @state.parent assignment on commit This piece of code was introduced on 67d8bb963d5d51fc644d6b1ca20164efb4cee6d7 , which was calling `committed?` in the `transaction_state` before calling the `committed!` method. However on 7386ffc781fca07a0c656db49fdb54678caef809, the `committed?` check was removed and replaced by a `finalized?`, which only checks if the state is not nil. Thus we can remove that line. --- .../lib/active_record/connection_adapters/abstract/transaction.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 3a266512a9..33cc22425d 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -72,7 +72,7 @@ module ActiveRecord end class TransactionState - attr_accessor :parent + attr_reader :parent VALID_STATES = Set.new([:committed, :rolledback, nil]) @@ -245,7 +245,6 @@ module ActiveRecord def perform_commit @state.set_state(:committed) - @state.parent = parent.state connection.release_savepoint(@savepoint_name) end end -- cgit v1.2.3 From cf629889bdc4b87e2829291a0c999289b073e0ed Mon Sep 17 00:00:00 2001 From: Jack Danger Canty Date: Wed, 30 Jul 2014 11:29:12 -0700 Subject: Remove redundant `self.` in class method calls These are the only instances of this in the whole code base. --- activerecord/lib/active_record/migration.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index e94b6ae9eb..7c4dad21a0 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -814,22 +814,22 @@ module ActiveRecord migrations = migrations(migrations_paths) migrations.select! { |m| yield m } if block_given? - self.new(:up, migrations, target_version).migrate + new(:up, migrations, target_version).migrate end def down(migrations_paths, target_version = nil, &block) migrations = migrations(migrations_paths) migrations.select! { |m| yield m } if block_given? - self.new(:down, migrations, target_version).migrate + new(:down, migrations, target_version).migrate end def run(direction, migrations_paths, target_version) - self.new(direction, migrations(migrations_paths), target_version).run + new(direction, migrations(migrations_paths), target_version).run end def open(migrations_paths) - self.new(:up, migrations(migrations_paths), nil) + new(:up, migrations(migrations_paths), nil) end def schema_migrations_table_name @@ -892,7 +892,7 @@ module ActiveRecord private def move(direction, migrations_paths, steps) - migrator = self.new(direction, migrations(migrations_paths)) + migrator = new(direction, migrations(migrations_paths)) start_index = migrator.migrations.index(migrator.current_migration) if start_index -- cgit v1.2.3 From 8d7dea766e7a5371dab09bf4c819ff1fc28ffa31 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Mon, 21 Jul 2014 17:50:31 -0400 Subject: Redefine macro checks for reflections Now that we define the macro on the reflection type we no longer need to check `macro == :what` on each type for `belongs_to?` or `has_one?` etc. These now default to false unless it's defined in the reflection class. Reuse existing belongs_to? method to check macros We don't need to do `:belongs_to == macro` anymore becasue we have a `belongs_to?` method. I didn't find this being used anywhere for `has_one?` or `collection?` since they were already fixed. --- .../active_record/associations/has_many_association.rb | 2 +- activerecord/lib/active_record/counter_cache.rb | 2 +- activerecord/lib/active_record/reflection.rb | 16 +++++++--------- 3 files changed, 9 insertions(+), 11 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb index 2a97d0ed31..79c3d2b0f5 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -124,7 +124,7 @@ module ActiveRecord def inverse_updates_counter_named?(counter_name, reflection = reflection()) reflection.klass._reflections.values.any? { |inverse_reflection| - :belongs_to == inverse_reflection.macro && + inverse_reflection.belongs_to? && inverse_reflection.counter_cache_column == counter_name } end diff --git a/activerecord/lib/active_record/counter_cache.rb b/activerecord/lib/active_record/counter_cache.rb index a33c7c64a7..f0b6afc4b4 100644 --- a/activerecord/lib/active_record/counter_cache.rb +++ b/activerecord/lib/active_record/counter_cache.rb @@ -34,7 +34,7 @@ module ActiveRecord foreign_key = has_many_association.foreign_key.to_s child_class = has_many_association.klass - reflection = child_class._reflections.values.find { |e| :belongs_to == e.macro && e.foreign_key.to_s == foreign_key && e.options[:counter_cache].present? } + reflection = child_class._reflections.values.find { |e| e.belongs_to? && e.foreign_key.to_s == foreign_key && e.options[:counter_cache].present? } counter_name = reflection.counter_cache_column stmt = unscoped.where(arel_table[primary_key].eq(object.id)).arel.compile_update({ diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 1672128aa3..21da011e8a 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -431,14 +431,10 @@ Joining, Preloading and eager loading of these associations is deprecated and wi end # Returns +true+ if +self+ is a +belongs_to+ reflection. - def belongs_to? - macro == :belongs_to - end + def belongs_to?; false; end # Returns +true+ if +self+ is a +has_one+ reflection. - def has_one? - macro == :has_one - end + def has_one?; false; end def association_class case macro @@ -585,9 +581,7 @@ Joining, Preloading and eager loading of these associations is deprecated and wi def macro; :has_many; end - def collection? - true - end + def collection?; true; end end class HasOneReflection < AssociationReflection #:nodoc: @@ -596,6 +590,8 @@ Joining, Preloading and eager loading of these associations is deprecated and wi end def macro; :has_one; end + + def has_one?; true; end end class BelongsToReflection < AssociationReflection #:nodoc: @@ -604,6 +600,8 @@ Joining, Preloading and eager loading of these associations is deprecated and wi end def macro; :belongs_to; end + + def belongs_to?; true; end end class HasAndBelongsToManyReflection < AssociationReflection #:nodoc: -- cgit v1.2.3 From 377bece684715edd802ad73fee739669d15eafa6 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Tue, 29 Jul 2014 13:56:39 -0400 Subject: Refactor join_keys to remove complex conditionals Pushing conditionals down to through reflection Only the through association needs the part of this conditional that deals with belongs to and polymorphic? so that can be pushed down into the ThroughReflection reducing the conditionals. Remove conditional because we can delegate join keys to source reflection Remove need for source_macro checking By adding join_id_for to the other reflections we remove the need to cehck against the source_macro and can reduce the conditioanl from the original join_id_for(owner) Using polymorphism instead of testing the source_macro This case statement in join_association is almost exactly the same as the original join_keys code. Testing taht theory by creating a new join_dependency_keys(assoc_klass) method. Refactor join_keys further to be more concise Fixed format of "#:nodoc:" to "# :nodoc:" where I added them to this file. --- .../join_dependency/join_association.rb | 11 ++--- activerecord/lib/active_record/reflection.rb | 47 ++++++++++++---------- 2 files changed, 29 insertions(+), 29 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/join_dependency/join_association.rb index 719eff9acc..a9d1099871 100644 --- a/activerecord/lib/active_record/associations/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/join_dependency/join_association.rb @@ -37,14 +37,9 @@ module ActiveRecord table = tables.shift klass = reflection.klass - case reflection.source_macro - when :belongs_to - key = reflection.association_primary_key - foreign_key = reflection.foreign_key - else - key = reflection.foreign_key - foreign_key = reflection.active_record_primary_key - end + join_keys = reflection.join_keys(klass) + key = join_keys.key + foreign_key = join_keys.foreign_key constraint = build_constraint(klass, table, key, foreign_table, foreign_key) diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 21da011e8a..575e588f35 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -149,19 +149,10 @@ module ActiveRecord JoinKeys = Struct.new(:key, :foreign_key) # :nodoc: def join_keys(assoc_klass) - if source_macro == :belongs_to - if polymorphic? - reflection_key = association_primary_key(assoc_klass) - else - reflection_key = association_primary_key - end - reflection_foreign_key = foreign_key - else - reflection_foreign_key = active_record_primary_key - reflection_key = foreign_key - end - JoinKeys.new(reflection_key, reflection_foreign_key) + JoinKeys.new(foreign_key, active_record_primary_key) end + + def source_macro; macro; end end # Base class for AggregateReflection and AssociationReflection. Objects of # AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods. @@ -354,9 +345,8 @@ Joining, Preloading and eager loading of these associations is deprecated and wi end alias :check_eager_loadable! :check_preloadable! - def join_id_for(owner) #:nodoc: - key = (source_macro == :belongs_to) ? foreign_key : active_record_primary_key - owner[key] + def join_id_for(owner) # :nodoc: + owner[active_record_primary_key] end def through_reflection @@ -383,8 +373,6 @@ Joining, Preloading and eager loading of these associations is deprecated and wi scope ? [[scope]] : [[]] end - def source_macro; macro; end - def has_inverse? inverse_name end @@ -574,7 +562,7 @@ Joining, Preloading and eager loading of these associations is deprecated and wi end end - class HasManyReflection < AssociationReflection #:nodoc: + class HasManyReflection < AssociationReflection # :nodoc: def initialize(name, scope, options, active_record) super(name, scope, options, active_record) end @@ -584,7 +572,7 @@ Joining, Preloading and eager loading of these associations is deprecated and wi def collection?; true; end end - class HasOneReflection < AssociationReflection #:nodoc: + class HasOneReflection < AssociationReflection # :nodoc: def initialize(name, scope, options, active_record) super(name, scope, options, active_record) end @@ -594,7 +582,7 @@ Joining, Preloading and eager loading of these associations is deprecated and wi def has_one?; true; end end - class BelongsToReflection < AssociationReflection #:nodoc: + class BelongsToReflection < AssociationReflection # :nodoc: def initialize(name, scope, options, active_record) super(name, scope, options, active_record) end @@ -602,9 +590,18 @@ Joining, Preloading and eager loading of these associations is deprecated and wi def macro; :belongs_to; end def belongs_to?; true; end + + def join_keys(assoc_klass) + key = polymorphic? ? association_primary_key(assoc_klass) : association_primary_key + JoinKeys.new(key, foreign_key) + end + + def join_id_for(owner) # :nodoc: + owner[foreign_key] + end end - class HasAndBelongsToManyReflection < AssociationReflection #:nodoc: + class HasAndBelongsToManyReflection < AssociationReflection # :nodoc: def initialize(name, scope, options, active_record) super end @@ -735,6 +732,10 @@ Joining, Preloading and eager loading of these associations is deprecated and wi end end + def join_keys(assoc_klass) + source_reflection.join_keys(assoc_klass) + end + # The macro used by the source association def source_macro source_reflection.source_macro @@ -802,6 +803,10 @@ directive on your declaration like: through_reflection.options end + def join_id_for(owner) # :nodoc: + source_reflection.join_id_for(owner) + end + def check_validity! if through_reflection.nil? raise HasManyThroughAssociationNotFoundError.new(active_record.name, self) -- cgit v1.2.3 From 1d6a87779c73bc7d9d5f235afadc0df4a36f534f Mon Sep 17 00:00:00 2001 From: joker1007 Date: Tue, 29 Jul 2014 20:16:10 +0900 Subject: Fix type casting to Decimal from Float with ... When I defines large precision column at RDBMS, I assigns float value, raise ArgumentError (precision too large). --- activerecord/lib/active_record/type/decimal.rb | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/type/decimal.rb b/activerecord/lib/active_record/type/decimal.rb index ba5d244729..d10778eeb6 100644 --- a/activerecord/lib/active_record/type/decimal.rb +++ b/activerecord/lib/active_record/type/decimal.rb @@ -14,12 +14,25 @@ module ActiveRecord private def cast_value(value) - if value.is_a?(::Numeric) || value.is_a?(::String) + case value + when ::Float + BigDecimal(value, float_precision) + when ::Numeric, ::String BigDecimal(value, precision.to_i) - elsif value.respond_to?(:to_d) - value.to_d else - cast_value(value.to_s) + if value.respond_to?(:to_d) + value.to_d + else + cast_value(value.to_s) + end + end + end + + def float_precision + if precision.to_i > ::Float::DIG + 1 + ::Float::DIG + 1 + else + precision.to_i end end end -- cgit v1.2.3 From d66ed3b08d8035d4bcb20a26a5739415c0b92428 Mon Sep 17 00:00:00 2001 From: Jack Danger Canty Date: Wed, 30 Jul 2014 14:51:17 -0700 Subject: Add ActiveRecord::Tasks::DatabaseTasks.migrate This extracts the logic that was embedded in a Rake task into a static method. Bonus: the first test for `rake db:migrate` --- activerecord/lib/active_record/railties/databases.rake | 5 +---- activerecord/lib/active_record/tasks/database_tasks.rb | 10 ++++++++++ 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index fa94df7a52..ac385817e4 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -41,10 +41,7 @@ db_namespace = namespace :db do desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)." task :migrate => [:environment, :load_config] do - ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true - ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, ENV["VERSION"] ? ENV["VERSION"].to_i : nil) do |migration| - ENV["SCOPE"].blank? || (ENV["SCOPE"] == migration.scope) - end + ActiveRecord::Tasks::DatabaseTasks.migrate db_namespace['_dump'].invoke if ActiveRecord::Base.dump_schema_after_migration end diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index b7315ed4b3..72e0cf3723 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -127,6 +127,16 @@ module ActiveRecord } end + def migrate + verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true + version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil + scope = ENV['SCOPE'] + Migration.verbose = verbose + Migrator.migrate(Migrator.migrations_paths, version) do |migration| + scope.blank? || scope == migration.scope + end + end + def charset_current(environment = env) charset ActiveRecord::Base.configurations[environment] end -- cgit v1.2.3 From 38be6335fe69966a65158639d2e00ac41618a67f Mon Sep 17 00:00:00 2001 From: Jack Danger Canty Date: Wed, 30 Jul 2014 21:57:30 -0700 Subject: Clarify how the ConnectionHandler works This makes the implicit description of how connection pooling works a little more explicit. It converts the examples of a model hierarchy into actual Ruby code and demonstrates how the key structure of the database.yml relates to the `establish_connection` method. --- .../abstract/connection_pool.rb | 51 +++++++++++++++------- 1 file changed, 36 insertions(+), 15 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb index cb75070e3a..a5fa9d6adc 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -462,23 +462,44 @@ module ActiveRecord # # For example, suppose that you have 5 models, with the following hierarchy: # - # | - # +-- Book - # | | - # | +-- ScaryBook - # | +-- GoodBook - # +-- Author - # +-- BankAccount + # class Author < ActiveRecord::Base + # end # - # Suppose that Book is to connect to a separate database (i.e. one other - # than the default database). Then Book, ScaryBook and GoodBook will all use - # the same connection pool. Likewise, Author and BankAccount will use the - # same connection pool. However, the connection pool used by Author/BankAccount - # is not the same as the one used by Book/ScaryBook/GoodBook. + # class BankAccount < ActiveRecord::Base + # end # - # Normally there is only a single ConnectionHandler instance, accessible via - # ActiveRecord::Base.connection_handler. Active Record models use this to - # determine the connection pool that they should use. + # class Book < ActiveRecord::Base + # establish_connection "library_db" + # end + # + # class ScaryBook < Book + # end + # + # class GoodBook < Book + # end + # + # And a database.yml that looked like this: + # + # development: + # database: my_application + # host: localhost + # + # library_db: + # database: library + # host: some.library.org + # + # Your primary database in the development environment is "my_application" + # but the Book model connects to a separate database called "library_db" + # (this can even be a database on a different machine). + # + # Book, ScaryBook and GoodBook will all use the same connection pool to + # "library_db" while Author, BankAccount, and any other models you create + # will use the default connection pool to "my_application". + # + # The various connection pools are managed by a single instance of + # ConnectionHandler accessible via ActiveRecord::Base.connection_handler. + # All Active Record models use this handler to determine the connection pool that they + # should use. class ConnectionHandler def initialize # These caches are keyed by klass.name, NOT klass. Keying them by klass -- cgit v1.2.3 From 91e4b65093f0c485507dadcb018c1f0d2661ba89 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Mon, 28 Jul 2014 14:26:27 -0400 Subject: Remove being/number methods from transaction class --- .../connection_adapters/abstract/transaction.rb | 35 +++++----------------- 1 file changed, 8 insertions(+), 27 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 33cc22425d..1691daf861 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -8,7 +8,7 @@ module ActiveRecord def begin_transaction(options = {}) transaction_class = @stack.empty? ? RealTransaction : SavepointTransaction - transaction = transaction_class.new(@connection, current_transaction, options) + transaction = transaction_class.new(@connection, current_transaction, "active_record_#{@stack.size}", options) @stack.push(transaction) transaction @@ -102,14 +102,6 @@ module ActiveRecord end class ClosedTransaction < Transaction #:nodoc: - def number - 0 - end - - def begin(options = {}) - RealTransaction.new(connection, self, options) - end - def closed? true end @@ -144,14 +136,6 @@ module ActiveRecord @joinable end - def number - parent.number + 1 - end - - def begin(options = {}) - SavepointTransaction.new(connection, self, options) - end - def rollback perform_rollback parent @@ -202,8 +186,8 @@ module ActiveRecord end class RealTransaction < OpenTransaction #:nodoc: - def initialize(connection, parent, options = {}) - super + def initialize(connection, parent, _, options = {}) + super(connection, parent, options) if options[:isolation] connection.begin_isolated_db_transaction(options[:isolation]) @@ -226,26 +210,23 @@ module ActiveRecord class SavepointTransaction < OpenTransaction #:nodoc: attr_reader :savepoint_name - def initialize(connection, parent, options = {}) + def initialize(connection, parent, savepoint_name, options = {}) if options[:isolation] raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction" end - super - - # Savepoint name only counts the Savepoint transactions, so we need to subtract 1 - @savepoint_name = "active_record_#{number - 1}" - connection.create_savepoint(@savepoint_name) + super(connection, parent, options) + connection.create_savepoint(@savepoint_name = savepoint_name) end def perform_rollback - connection.rollback_to_savepoint(@savepoint_name) + connection.rollback_to_savepoint(savepoint_name) rollback_records end def perform_commit @state.set_state(:committed) - connection.release_savepoint(@savepoint_name) + connection.release_savepoint(savepoint_name) end end end -- cgit v1.2.3 From dac9c92e3096ae196d7ea4b58e7141f4a36007ea Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Mon, 28 Jul 2014 13:07:47 -0400 Subject: Remove parent on Transaction object --- .../connection_adapters/abstract/transaction.rb | 25 ++++++++-------------- 1 file changed, 9 insertions(+), 16 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 1691daf861..17d57a7519 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -8,7 +8,7 @@ module ActiveRecord def begin_transaction(options = {}) transaction_class = @stack.empty? ? RealTransaction : SavepointTransaction - transaction = transaction_class.new(@connection, current_transaction, "active_record_#{@stack.size}", options) + transaction = transaction_class.new(@connection, "active_record_#{@stack.size}", options) @stack.push(transaction) transaction @@ -55,17 +55,13 @@ module ActiveRecord end class Transaction #:nodoc: - attr_reader :connection + attr_reader :connection, :state def initialize(connection) @connection = connection @state = TransactionState.new end - def state - @state - end - def savepoint_name nil end @@ -120,13 +116,12 @@ module ActiveRecord end class OpenTransaction < Transaction #:nodoc: - attr_reader :parent, :records + attr_reader :records attr_writer :joinable - def initialize(connection, parent, options = {}) + def initialize(connection, options = {}) super connection - @parent = parent @records = [] @joinable = options.fetch(:joinable, true) end @@ -138,12 +133,10 @@ module ActiveRecord def rollback perform_rollback - parent end def commit perform_commit - parent end def add_record(record) @@ -158,7 +151,7 @@ module ActiveRecord @state.set_state(:rolledback) records.uniq.each do |record| begin - record.rolledback!(parent.closed?) + record.rolledback!(self.is_a?(RealTransaction)) rescue => e record.logger.error(e) if record.respond_to?(:logger) && record.logger end @@ -186,8 +179,8 @@ module ActiveRecord end class RealTransaction < OpenTransaction #:nodoc: - def initialize(connection, parent, _, options = {}) - super(connection, parent, options) + def initialize(connection, _, options = {}) + super(connection, options) if options[:isolation] connection.begin_isolated_db_transaction(options[:isolation]) @@ -210,12 +203,12 @@ module ActiveRecord class SavepointTransaction < OpenTransaction #:nodoc: attr_reader :savepoint_name - def initialize(connection, parent, savepoint_name, options = {}) + def initialize(connection, savepoint_name, options = {}) if options[:isolation] raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction" end - super(connection, parent, options) + super(connection, options) connection.create_savepoint(@savepoint_name = savepoint_name) end -- cgit v1.2.3 From 4140797967a8f50eccaa70614c01531dab6a90f4 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Wed, 30 Jul 2014 14:32:56 -0400 Subject: Make ClosedTransaction a null object --- .../connection_adapters/abstract/transaction.rb | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 17d57a7519..ff7f922d7f 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -50,7 +50,7 @@ module ActiveRecord private def closed_transaction - @closed_transaction ||= ClosedTransaction.new(@connection) + @closed_transaction ||= ClosedTransaction.new end end @@ -98,21 +98,12 @@ module ActiveRecord end class ClosedTransaction < Transaction #:nodoc: - def closed? - true - end - - def open? - false - end - - def joinable? - false - end - + def initialize; super(nil); end + def closed?; true; end + def open?; false; end + def joinable?; false; end # This is a noop when there are no open transactions - def add_record(record) - end + def add_record(record); end end class OpenTransaction < Transaction #:nodoc: @@ -126,7 +117,6 @@ module ActiveRecord @joinable = options.fetch(:joinable, true) end - def joinable? @joinable end -- cgit v1.2.3 From 62c75f4eacf6466a3bd1b22f97cda7ab7b597064 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Thu, 31 Jul 2014 16:25:51 -0400 Subject: Move TransactionManager to bottom of class --- .../connection_adapters/abstract/transaction.rb | 134 ++++++++++----------- 1 file changed, 67 insertions(+), 67 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index ff7f922d7f..e6a53b2122 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -1,72 +1,5 @@ module ActiveRecord module ConnectionAdapters - class TransactionManager #:nodoc: - def initialize(connection) - @stack = [] - @connection = connection - end - - def begin_transaction(options = {}) - transaction_class = @stack.empty? ? RealTransaction : SavepointTransaction - transaction = transaction_class.new(@connection, "active_record_#{@stack.size}", options) - - @stack.push(transaction) - transaction - end - - def commit_transaction - @stack.pop.commit - end - - def rollback_transaction - @stack.pop.rollback - end - - def within_new_transaction(options = {}) - transaction = begin_transaction options - yield - rescue Exception => error - transaction.rollback if transaction - raise - ensure - begin - transaction.commit unless error - rescue Exception - transaction.rollback - raise - ensure - @stack.pop if transaction - end - end - - def open_transactions - @stack.size - end - - def current_transaction - @stack.last || closed_transaction - end - - private - - def closed_transaction - @closed_transaction ||= ClosedTransaction.new - end - end - - class Transaction #:nodoc: - attr_reader :connection, :state - - def initialize(connection) - @connection = connection - @state = TransactionState.new - end - - def savepoint_name - nil - end - end - class TransactionState attr_reader :parent @@ -97,6 +30,19 @@ module ActiveRecord end end + class Transaction #:nodoc: + attr_reader :connection, :state + + def initialize(connection) + @connection = connection + @state = TransactionState.new + end + + def savepoint_name + nil + end + end + class ClosedTransaction < Transaction #:nodoc: def initialize; super(nil); end def closed?; true; end @@ -212,5 +158,59 @@ module ActiveRecord connection.release_savepoint(savepoint_name) end end + + class TransactionManager #:nodoc: + def initialize(connection) + @stack = [] + @connection = connection + end + + def begin_transaction(options = {}) + transaction_class = @stack.empty? ? RealTransaction : SavepointTransaction + transaction = transaction_class.new(@connection, "active_record_#{@stack.size}", options) + + @stack.push(transaction) + transaction + end + + def commit_transaction + @stack.pop.commit + end + + def rollback_transaction + @stack.pop.rollback + end + + def within_new_transaction(options = {}) + transaction = begin_transaction options + yield + rescue Exception => error + transaction.rollback if transaction + raise + ensure + begin + transaction.commit unless error + rescue Exception + transaction.rollback + raise + ensure + @stack.pop if transaction + end + end + + def open_transactions + @stack.size + end + + def current_transaction + @stack.last || closed_transaction + end + + private + + def closed_transaction + @closed_transaction ||= ClosedTransaction.new + end + end end end -- cgit v1.2.3 From 057c23715434adcab9b12f987d615979d1f57549 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Thu, 31 Jul 2014 16:31:33 -0400 Subject: Replace ClosedTransaction with NullTransaction --- .../active_record/connection_adapters/abstract/transaction.rb | 11 ++++------- .../lib/active_record/connection_adapters/abstract_adapter.rb | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index e6a53b2122..46aaaae2ec 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -43,8 +43,8 @@ module ActiveRecord end end - class ClosedTransaction < Transaction #:nodoc: - def initialize; super(nil); end + class NullTransaction < Transaction #:nodoc: + def initialize; end def closed?; true; end def open?; false; end def joinable?; false; end @@ -203,14 +203,11 @@ module ActiveRecord end def current_transaction - @stack.last || closed_transaction + @stack.last || NULL_TRANSACTION end private - - def closed_transaction - @closed_transaction ||= ClosedTransaction.new - end + NULL_TRANSACTION = NullTransaction.new end end end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 99c728814a..a1b6671664 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -46,7 +46,7 @@ module ActiveRecord autoload_at 'active_record/connection_adapters/abstract/transaction' do autoload :TransactionManager - autoload :ClosedTransaction + autoload :NullTransaction autoload :RealTransaction autoload :SavepointTransaction autoload :TransactionState -- cgit v1.2.3 From fe24ba881a676c5119498c4d6362a4827bf695ba Mon Sep 17 00:00:00 2001 From: Carlos Antonio da Silva Date: Thu, 31 Jul 2014 18:31:19 -0300 Subject: Rename method for clarity Ruby generally does not use the is_* prefix on predicate methods. --- activerecord/lib/active_record/type/serialized.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/type/serialized.rb b/activerecord/lib/active_record/type/serialized.rb index 42bbed7103..abeea769c4 100644 --- a/activerecord/lib/active_record/type/serialized.rb +++ b/activerecord/lib/active_record/type/serialized.rb @@ -12,7 +12,7 @@ module ActiveRecord end def type_cast_from_database(value) - if is_default_value?(value) + if default_value?(value) value else coder.load(super) @@ -21,7 +21,7 @@ module ActiveRecord def type_cast_for_database(value) return if value.nil? - unless is_default_value?(value) + unless default_value?(value) super coder.dump(value) end end @@ -43,7 +43,7 @@ module ActiveRecord private - def is_default_value?(value) + def default_value?(value) value == coder.load(nil) end end -- cgit v1.2.3 From 20405e516b031db4d8230014d1dcf9601ed0a0f8 Mon Sep 17 00:00:00 2001 From: Carlos Antonio da Silva Date: Thu, 31 Jul 2014 23:10:47 -0300 Subject: Use available method rather than macro name checking --- activerecord/lib/active_record/associations/through_association.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/through_association.rb b/activerecord/lib/active_record/associations/through_association.rb index f00fef8b9e..24cb5ab545 100644 --- a/activerecord/lib/active_record/associations/through_association.rb +++ b/activerecord/lib/active_record/associations/through_association.rb @@ -77,7 +77,7 @@ module ActiveRecord end def ensure_mutable - if source_reflection.macro != :belongs_to + unless source_reflection.belongs_to? raise HasManyThroughCantAssociateThroughHasOneOrManyReflection.new(owner, reflection) end end -- cgit v1.2.3 From 30af85813094662a22dd39747233f75c54632aa0 Mon Sep 17 00:00:00 2001 From: Jack Danger Canty Date: Thu, 31 Jul 2014 21:01:00 -0700 Subject: Fixes small error in ActiveRecord::Reflection docs [ci skip] --- activerecord/lib/active_record/reflection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 1672128aa3..bb84f388a8 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -38,7 +38,7 @@ module ActiveRecord ar.aggregate_reflections = ar.aggregate_reflections.merge(name.to_s => reflection) end - # \Reflection enables to interrogate Active Record classes and objects + # \Reflection enables interrogating Active Record classes and objects # about their associations and aggregations. This information can, # for example, be used in a form builder that takes an Active Record object # and creates input fields for all of the attributes depending on their type -- cgit v1.2.3 From 01c80a12d49ffa4999861ed4b57f72e682d42a64 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 30 Jul 2014 21:02:57 -0400 Subject: Deprecate source_macro `source_macro` is no longer used in any ActiveRecord code. I've chosen to deprecate it because it was not marked as nodoc and may be in use outside of rails source. --- activerecord/lib/active_record/reflection.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 575e588f35..10a75530fd 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -152,7 +152,11 @@ module ActiveRecord JoinKeys.new(foreign_key, active_record_primary_key) end - def source_macro; macro; end + def source_macro + ActiveSupport::Deprecation.warn("ActiveRecord::Base.source_macro is deprecated and " \ + "will be removed without replacement.") + macro + end end # Base class for AggregateReflection and AssociationReflection. Objects of # AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods. @@ -738,6 +742,8 @@ Joining, Preloading and eager loading of these associations is deprecated and wi # The macro used by the source association def source_macro + ActiveSupport::Deprecation.warn("ActiveRecord::Base.source_macro is deprecated and " \ + "will be removed without replacement.") source_reflection.source_macro end -- cgit v1.2.3 From eb9816831367f709e190b385717814b5d985fbc9 Mon Sep 17 00:00:00 2001 From: Jack Danger Canty Date: Sat, 2 Aug 2014 16:58:05 -0700 Subject: updating documented parameter for build_constraint Updates documentation in line with changes made in 743b67508e2027e1d086142ccbec47a19fc943f6 --- .../lib/active_record/associations/join_dependency/join_association.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/join_dependency/join_association.rb index 719eff9acc..9dc447e4e4 100644 --- a/activerecord/lib/active_record/associations/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/join_dependency/join_association.rb @@ -95,7 +95,7 @@ module ActiveRecord # end # # If I execute `Physician.joins(:appointments).to_a` then - # reflection # => # + # klass # => Physician # table # => # # key # => physician_id # foreign_table # => # -- cgit v1.2.3 From 80af2a4935158b0d46a451d18c77971a7e0ca9e1 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Mon, 4 Aug 2014 19:39:07 -0400 Subject: Don't delegate Reflection#chain to ThroughAssociation We shouldn't be delegating chain to ThroughAssociation since the only place that needs to call it is `target_scope`. Instead we can call `reflecion.chain`. --- activerecord/lib/active_record/associations/through_association.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/through_association.rb b/activerecord/lib/active_record/associations/through_association.rb index 24cb5ab545..611d471e62 100644 --- a/activerecord/lib/active_record/associations/through_association.rb +++ b/activerecord/lib/active_record/associations/through_association.rb @@ -3,7 +3,7 @@ module ActiveRecord module Associations module ThroughAssociation #:nodoc: - delegate :source_reflection, :through_reflection, :chain, :to => :reflection + delegate :source_reflection, :through_reflection, :to => :reflection protected @@ -13,7 +13,7 @@ module ActiveRecord # 2. To get the type conditions for any STI models in the chain def target_scope scope = super - chain.drop(1).each do |reflection| + reflection.chain.drop(1).each do |reflection| relation = reflection.klass.all relation.merge!(reflection.scope) if reflection.scope -- cgit v1.2.3 From d44702ee45219153c5e56da0a06ffe6ab5d14518 Mon Sep 17 00:00:00 2001 From: Carlos Antonio da Silva Date: Tue, 5 Aug 2014 08:22:11 -0300 Subject: Remove unused text? predicate method and delegation The method has been removed in 09206716f8695f6b8467f15c1befa5a4c3c10978 (PR #16074), but the delegation was apparently missed, and one instance of the method was added back with the addition of OID::Xml in 336be2bdf7dfa1b31879d0ab27e5f3101b351923 (PR #16072), so we can safely rm both. --- activerecord/lib/active_record/connection_adapters/column.rb | 2 +- .../lib/active_record/connection_adapters/postgresql/oid/xml.rb | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index 1f1e2c46f4..5f9cc6edd0 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -16,7 +16,7 @@ module ActiveRecord attr_reader :name, :cast_type, :null, :sql_type, :default, :default_function delegate :type, :precision, :scale, :limit, :klass, :accessor, - :text?, :number?, :binary?, :changed?, + :number?, :binary?, :changed?, :type_cast_from_user, :type_cast_from_database, :type_cast_for_database, :type_cast_for_schema, to: :cast_type diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/xml.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/xml.rb index 7323f12763..334af7c598 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/xml.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/xml.rb @@ -7,10 +7,6 @@ module ActiveRecord :xml end - def text? - false - end - def type_cast_for_database(value) return unless value Data.new(super) -- cgit v1.2.3 From 8298d3adb72eb17186dc0b155afec308071a3900 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Thu, 31 Jul 2014 16:44:55 -0400 Subject: Cleanup Transaction inheritance. Transaction class doesnt need to encapsulate the transaction state using inheritance. This removes all Transaction subclasses, and let the Transaction object controls different actions based on its own state. Basically the only actions would behave differently are `being`,`commit`,`rollback` as they could act in a savepoint or in a real transaction. --- .../connection_adapters/abstract/transaction.rb | 124 +++++++++------------ 1 file changed, 54 insertions(+), 70 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 46aaaae2ec..4a7f2aaca8 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -30,49 +30,24 @@ module ActiveRecord end end - class Transaction #:nodoc: - attr_reader :connection, :state - - def initialize(connection) - @connection = connection - @state = TransactionState.new - end - - def savepoint_name - nil - end - end - - class NullTransaction < Transaction #:nodoc: + class NullTransaction #:nodoc: def initialize; end def closed?; true; end def open?; false; end def joinable?; false; end - # This is a noop when there are no open transactions def add_record(record); end end - class OpenTransaction < Transaction #:nodoc: - attr_reader :records - attr_writer :joinable - - def initialize(connection, options = {}) - super connection - - @records = [] - @joinable = options.fetch(:joinable, true) - end - - def joinable? - @joinable - end + class Transaction #:nodoc: - def rollback - perform_rollback - end + attr_reader :connection, :state, :records, :savepoint_name + attr_writer :joinable - def commit - perform_commit + def initialize(connection, options) + @connection = connection + @state = TransactionState.new + @records = [] + @joinable = options.fetch(:joinable, true) end def add_record(record) @@ -83,19 +58,25 @@ module ActiveRecord end end - def rollback_records + def rollback @state.set_state(:rolledback) + end + + def rollback_records records.uniq.each do |record| begin - record.rolledback!(self.is_a?(RealTransaction)) + record.rolledback! full_rollback? rescue => e record.logger.error(e) if record.respond_to?(:logger) && record.logger end end end - def commit_records + def commit @state.set_state(:committed) + end + + def commit_records records.uniq.each do |record| begin record.committed! @@ -105,57 +86,57 @@ module ActiveRecord end end - def closed? - false - end - - def open? - true - end + def full_rollback?; true; end + def joinable?; @joinable; end + def closed?; false; end + def open?; !closed?; end end - class RealTransaction < OpenTransaction #:nodoc: - def initialize(connection, _, options = {}) - super(connection, options) + class SavepointTransaction < Transaction + def initialize(connection, savepoint_name, options) + super(connection, options) if options[:isolation] - connection.begin_isolated_db_transaction(options[:isolation]) - else - connection.begin_db_transaction + raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction" end + connection.create_savepoint(@savepoint_name = savepoint_name) end - def perform_rollback - connection.rollback_db_transaction + def rollback + super + connection.rollback_to_savepoint(savepoint_name) rollback_records end - def perform_commit - connection.commit_db_transaction - commit_records + def commit + super + connection.release_savepoint(savepoint_name) end + + def full_rollback?; false; end end - class SavepointTransaction < OpenTransaction #:nodoc: - attr_reader :savepoint_name + class RealTransaction < Transaction - def initialize(connection, savepoint_name, options = {}) + def initialize(connection, options) + super if options[:isolation] - raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction" + connection.begin_isolated_db_transaction(options[:isolation]) + else + connection.begin_db_transaction end - - super(connection, options) - connection.create_savepoint(@savepoint_name = savepoint_name) end - def perform_rollback - connection.rollback_to_savepoint(savepoint_name) + def rollback + super + connection.rollback_db_transaction rollback_records end - def perform_commit - @state.set_state(:committed) - connection.release_savepoint(savepoint_name) + def commit + super + connection.commit_db_transaction + commit_records end end @@ -166,9 +147,12 @@ module ActiveRecord end def begin_transaction(options = {}) - transaction_class = @stack.empty? ? RealTransaction : SavepointTransaction - transaction = transaction_class.new(@connection, "active_record_#{@stack.size}", options) - + transaction = + if @stack.empty? + RealTransaction.new(@connection, options) + else + SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options) + end @stack.push(transaction) transaction end -- cgit v1.2.3 From 977a489cfad70dfd0a6a01c4ef792cf6ac0c9046 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev Date: Tue, 5 Aug 2014 18:36:29 +0300 Subject: Moved #create! method from Validations to Persistence module --- activerecord/lib/active_record/persistence.rb | 12 ++++++++++++ activerecord/lib/active_record/validations.rb | 15 --------------- 2 files changed, 12 insertions(+), 15 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 96e44c2f59..f35865f54c 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -36,6 +36,18 @@ module ActiveRecord end end + # Creates an object just like Base.create but calls save! instead of +save+ + # so an exception is raised if the record is invalid. + def create!(attributes = nil, &block) + if attributes.is_a?(Array) + attributes.collect { |attr| create!(attr, &block) } + else + object = new(attributes, &block) + object.save! + object + end + end + # Given an attributes hash, +instantiate+ returns a new instance of # the appropriate class. Accepts only keys as strings. # diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index b4b33804de..7f7d49cdb4 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -29,21 +29,6 @@ module ActiveRecord extend ActiveSupport::Concern include ActiveModel::Validations - module ClassMethods - # Creates an object just like Base.create but calls save! instead of +save+ - # so an exception is raised if the record is invalid. - def create!(attributes = nil, &block) - if attributes.is_a?(Array) - attributes.collect { |attr| create!(attr, &block) } - else - object = new(attributes) - yield(object) if block_given? - object.save! - object - end - end - end - # The validation process on save can be skipped by passing validate: false. # The regular Base#save method is replaced with this when the validations # module is mixed in, which it is by default. -- cgit v1.2.3 From 53dba73dc17502b3d3f71d4672e86a14b995a732 Mon Sep 17 00:00:00 2001 From: Yves Senn Date: Thu, 24 Jul 2014 14:46:25 +0200 Subject: Revert "Revert "Merge pull request #15394 from morgoth/fix-automatic-maintaining-test-schema-for-sql-format"" This reverts commit 5c87b5c5248154cf8aa76cce9a24a88769de022d. --- activerecord/lib/active_record/tasks/database_tasks.rb | 2 ++ activerecord/lib/active_record/tasks/sqlite_database_tasks.rb | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index 72e0cf3723..659110c066 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -188,10 +188,12 @@ module ActiveRecord when :ruby file ||= File.join(db_dir, "schema.rb") check_schema_file(file) + purge(current_config) load(file) when :sql file ||= File.join(db_dir, "structure.sql") check_schema_file(file) + purge(current_config) structure_load(current_config, file) else raise ArgumentError, "unknown format #{format.inspect}" diff --git a/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb index 5688931db2..9ab64d0325 100644 --- a/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb @@ -21,7 +21,11 @@ module ActiveRecord FileUtils.rm(file) if File.exist?(file) end - alias :purge :drop + + def purge + drop + create + end def charset connection.encoding -- cgit v1.2.3 From f15cef67f75e4b52fd45655d7c6ab6b35623c608 Mon Sep 17 00:00:00 2001 From: Yves Senn Date: Fri, 25 Jul 2014 17:49:27 +0200 Subject: schema rake tasks are specific about the configuration to act on. The rake tasks and the `DatabaseTakss` adapter classes used to assume a configuration at some places. This forced the rake tasks to establish a specific connection before calling into `load_schema`. After #15394 this started to cause issues because it could `purge` the wrong database before loading the schema. --- activerecord/lib/active_record/migration.rb | 2 +- .../lib/active_record/railties/databases.rake | 14 ++++--------- .../lib/active_record/tasks/database_tasks.rb | 23 +++++++++++++++++++--- 3 files changed, 25 insertions(+), 14 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 7c4dad21a0..a6847e28c2 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -399,7 +399,7 @@ module ActiveRecord def load_schema_if_pending! if ActiveRecord::Migrator.needs_migration? - ActiveRecord::Tasks::DatabaseTasks.load_schema + ActiveRecord::Tasks::DatabaseTasks.load_schema_current check_pending! end end diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index ac385817e4..458862a538 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -240,7 +240,7 @@ db_namespace = namespace :db do desc 'Load a schema.rb file into the database' task :load => [:environment, :load_config] do - ActiveRecord::Tasks::DatabaseTasks.load_schema(:ruby, ENV['SCHEMA']) + ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:ruby, ENV['SCHEMA']) end task :load_if_ruby => ['db:create', :environment] do @@ -286,7 +286,7 @@ db_namespace = namespace :db do desc "Recreate the databases from the structure.sql file" task :load => [:environment, :load_config] do - ActiveRecord::Tasks::DatabaseTasks.load_schema(:sql, ENV['DB_STRUCTURE']) + ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:sql, ENV['DB_STRUCTURE']) end task :load_if_sql => ['db:create', :environment] do @@ -317,9 +317,8 @@ db_namespace = namespace :db do task :load_schema => %w(db:test:deprecated db:test:purge) do begin should_reconnect = ActiveRecord::Base.connection_pool.active_connection? - ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test']) ActiveRecord::Schema.verbose = false - db_namespace["schema:load"].invoke + ActiveRecord::Tasks::DatabaseTasks.load_schema_for ActiveRecord::Base.configurations['test'], :ruby, ENV['SCHEMA'] ensure if should_reconnect ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[ActiveRecord::Tasks::DatabaseTasks.env]) @@ -329,12 +328,7 @@ db_namespace = namespace :db do # desc "Recreate the test database from an existent structure.sql file" task :load_structure => %w(db:test:deprecated db:test:purge) do - begin - ActiveRecord::Tasks::DatabaseTasks.current_config(:config => ActiveRecord::Base.configurations['test']) - db_namespace["structure:load"].invoke - ensure - ActiveRecord::Tasks::DatabaseTasks.current_config(:config => nil) - end + ActiveRecord::Tasks::DatabaseTasks.load_schema_for ActiveRecord::Base.configurations['test'], :sql, ENV['SCHEMA'] end # desc "Recreate the test database from a fresh schema" diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index 659110c066..892c78e479 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -184,22 +184,39 @@ module ActiveRecord end def load_schema(format = ActiveRecord::Base.schema_format, file = nil) + ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc) + This method will act on a specific connection in the future. + To act on the current connection, use `load_schema_current` instead. + MESSAGE + load_schema_current(format, file) + end + + # This method is the successor of +load_schema+. We should rename it + # after +load_schema+ went through a deprecation cycle. (Rails > 4.2) + def load_schema_for(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc: case format when :ruby file ||= File.join(db_dir, "schema.rb") check_schema_file(file) - purge(current_config) + purge(configuration) + ActiveRecord::Base.establish_connection(configuration) load(file) when :sql file ||= File.join(db_dir, "structure.sql") check_schema_file(file) - purge(current_config) - structure_load(current_config, file) + purge(configuration) + structure_load(configuration, file) else raise ArgumentError, "unknown format #{format.inspect}" end end + def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env) + each_current_configuration(environment) { |configuration| + load_schema_for configuration, format, file + } + end + def check_schema_file(filename) unless File.exist?(filename) message = %{#{filename} doesn't exist yet. Run `rake db:migrate` to create it, then try again.} -- cgit v1.2.3 From e6e81f856e969efda49166af82c27594f30ea592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 6 Aug 2014 23:44:00 -0300 Subject: Define id_was to get the previous value of the primary key Currently when we call id_was and we have a custom primary key name Active Record will return the current value of the primary key. This make impossible to correctly do an update operation if you change the id. Fixes #16413 --- activerecord/lib/active_record/attribute_methods/primary_key.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb index cadad60ddd..9bd333bbac 100644 --- a/activerecord/lib/active_record/attribute_methods/primary_key.rb +++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb @@ -39,6 +39,12 @@ module ActiveRecord read_attribute_before_type_cast(self.class.primary_key) end + # Returns the primary key previous value. + def id_was + sync_with_transaction_state + attribute_was(self.class.primary_key) + end + protected def attribute_method?(attr_name) @@ -54,7 +60,7 @@ module ActiveRecord end end - ID_ATTRIBUTE_METHODS = %w(id id= id? id_before_type_cast).to_set + ID_ATTRIBUTE_METHODS = %w(id id= id? id_before_type_cast id_was).to_set def dangerous_attribute_method?(method_name) super && !ID_ATTRIBUTE_METHODS.include?(method_name) -- cgit v1.2.3 From 38b6b5db58457b5445d2c42298facf322136c3ae Mon Sep 17 00:00:00 2001 From: Tom Kadwill Date: Wed, 6 Aug 2014 18:52:48 +0100 Subject: [ci skip] Updated create! documentation description and added +attributes+ for rdoc --- activerecord/lib/active_record/persistence.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index f35865f54c..b89e081542 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -36,8 +36,11 @@ module ActiveRecord end end - # Creates an object just like Base.create but calls save! instead of +save+ - # so an exception is raised if the record is invalid. + # Creates an object (or multiple objects) and saves it to the database, if validations pass. + # Works like Base#create except that it raises a RecordInvalid error if validations fail. + # + # The +attributes+ parameter can be either a Hash or an Array of Hashes. + # These Hashes describe the attributes on the objects that are to be created. def create!(attributes = nil, &block) if attributes.is_a?(Array) attributes.collect { |attr| create!(attr, &block) } -- cgit v1.2.3 From 8aead812baaacb962c15d0ab27bdaf4c388b7d59 Mon Sep 17 00:00:00 2001 From: tsukasaoishi Date: Thu, 7 Aug 2014 22:41:23 +0900 Subject: Tables existence check query is executed in large quantities When Rails starts, tables existence check query is executed number of models. In case of mysql, SHOW TABLES LIKE 'table1'; SHOW TABLES LIKE 'table2'; SHOW TABLES LIKE 'table3'; ... SHOW TABLES LIKE 'table999'; Add process to get the names of all tables by one query. --- activerecord/lib/active_record/connection_adapters/schema_cache.rb | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/schema_cache.rb b/activerecord/lib/active_record/connection_adapters/schema_cache.rb index 3116bed596..726810535d 100644 --- a/activerecord/lib/active_record/connection_adapters/schema_cache.rb +++ b/activerecord/lib/active_record/connection_adapters/schema_cache.rb @@ -19,6 +19,7 @@ module ActiveRecord # A cached lookup for table existence. def table_exists?(name) + prepare_tables if @tables.blank? return @tables[name] if @tables.key? name @tables[name] = connection.table_exists?(name) @@ -82,6 +83,12 @@ module ActiveRecord def marshal_load(array) @version, @columns, @columns_hash, @primary_keys, @tables = array end + + private + + def prepare_tables + connection.tables.each { |table| @tables[table] = true } + end end end end -- cgit v1.2.3 From 4e83815ce991efce2b84aa570f6673227ff0bb0d Mon Sep 17 00:00:00 2001 From: tsukasaoishi Date: Fri, 8 Aug 2014 01:03:09 +0900 Subject: change to empty? from blank? --- activerecord/lib/active_record/connection_adapters/schema_cache.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/schema_cache.rb b/activerecord/lib/active_record/connection_adapters/schema_cache.rb index 726810535d..a10ce330c7 100644 --- a/activerecord/lib/active_record/connection_adapters/schema_cache.rb +++ b/activerecord/lib/active_record/connection_adapters/schema_cache.rb @@ -19,7 +19,7 @@ module ActiveRecord # A cached lookup for table existence. def table_exists?(name) - prepare_tables if @tables.blank? + prepare_tables if @tables.empty? return @tables[name] if @tables.key? name @tables[name] = connection.table_exists?(name) -- cgit v1.2.3 From 399f5f6346829210b4d58ed5f7c6d4d73ef67737 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 7 Aug 2014 12:10:31 -0700 Subject: use the uri parser so that newer version of Ruby work --- .../lib/active_record/connection_adapters/connection_specification.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb index 5693031053..d28a54b8f9 100644 --- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb +++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb @@ -32,7 +32,7 @@ module ActiveRecord # } def initialize(url) raise "Database URL cannot be empty" if url.blank? - @uri = URI.parse(url) + @uri = uri_parser.parse(url) @adapter = @uri.scheme.gsub('-', '_') @adapter = "postgresql" if @adapter == "postgres" -- cgit v1.2.3 From 30529dc00f96777c325dff496930f560fb9d59e9 Mon Sep 17 00:00:00 2001 From: Zachary Scott Date: Thu, 7 Aug 2014 19:05:21 -0700 Subject: Rephrase how we explain RecordInvalid exception in the context of `#create!` regarding validations in contrast to the behavior of `#create`. Also describe creating multiple objects using an array of hashes as the +attributes+ parameter. [ci skip] /cc #16384 --- activerecord/lib/active_record/persistence.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index b89e081542..b5799d6bff 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -36,11 +36,13 @@ module ActiveRecord end end - # Creates an object (or multiple objects) and saves it to the database, if validations pass. - # Works like Base#create except that it raises a RecordInvalid error if validations fail. + # Creates an object (or multiple objects) and saves it to the database, + # if validations pass. Raises a RecordInvalid error if validations fail, + # unlike Base#create. # # The +attributes+ parameter can be either a Hash or an Array of Hashes. - # These Hashes describe the attributes on the objects that are to be created. + # These describe which attributes to be created on the object, or + # multiple objects when given an Array of Hashes. def create!(attributes = nil, &block) if attributes.is_a?(Array) attributes.collect { |attr| create!(attr, &block) } -- cgit v1.2.3 From 9ef0f0f69f669a0a0de1a01bfecc1d7fff3f90a6 Mon Sep 17 00:00:00 2001 From: Tom Kadwill Date: Fri, 8 Aug 2014 10:00:23 +0100 Subject: [ci skip] Changed 'first argument' to '+name+ argument' --- activerecord/lib/active_record/associations.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index ec78d10124..c39183ab31 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1052,7 +1052,7 @@ module ActiveRecord # Specifies a one-to-many association. The following methods for retrieval and query of # collections of associated objects will be added: # - # +collection+ is a placeholder for the symbol passed as the first argument, so + # +collection+ is a placeholder for the symbol passed as the +name+ argument, so # has_many :clients would add among others clients.empty?. # # [collection(force_reload = false)] @@ -1227,7 +1227,7 @@ module ActiveRecord # # The following methods for retrieval and query of a single associated object will be added: # - # +association+ is a placeholder for the symbol passed as the first argument, so + # +association+ is a placeholder for the symbol passed as the +name+ argument, so # has_one :manager would add among others manager.nil?. # # [association(force_reload = false)] @@ -1338,7 +1338,7 @@ module ActiveRecord # Methods will be added for retrieval and query for a single associated object, for which # this object holds an id: # - # +association+ is a placeholder for the symbol passed as the first argument, so + # +association+ is a placeholder for the symbol passed as the +name+ argument, so # belongs_to :author would add among others author.nil?. # # [association(force_reload = false)] @@ -1480,7 +1480,7 @@ module ActiveRecord # # Adds the following methods for retrieval and query: # - # +collection+ is a placeholder for the symbol passed as the first argument, so + # +collection+ is a placeholder for the symbol passed as the +name+ argument, so # has_and_belongs_to_many :categories would add among others categories.empty?. # # [collection(force_reload = false)] -- cgit v1.2.3 From 8e490827d884a87a7e1c8aab39684fcf25d95634 Mon Sep 17 00:00:00 2001 From: Joshua Delsman Date: Fri, 8 Aug 2014 22:16:28 -0700 Subject: Using delegated connection method --- activerecord/lib/active_record/tasks/postgresql_database_tasks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb index 3d02ee07d0..ce1de4b76e 100644 --- a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb @@ -54,7 +54,7 @@ module ActiveRecord command = "pg_dump -i -s -x -O -f #{Shellwords.escape(filename)} #{search_path} #{Shellwords.escape(configuration['database'])}" raise 'Error dumping database' unless Kernel.system(command) - File.open(filename, "a") { |f| f << "SET search_path TO #{ActiveRecord::Base.connection.schema_search_path};\n\n" } + File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" } end def structure_load(filename) -- cgit v1.2.3 From b7176ab9b5fbceaa257c1161801a28fa21e4f199 Mon Sep 17 00:00:00 2001 From: Tom Kadwill Date: Sat, 9 Aug 2014 08:52:15 +0100 Subject: [ci skip] Changed options to +options+ for rdoc --- activerecord/lib/active_record/associations.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index c39183ab31..1c5a737696 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1131,7 +1131,7 @@ module ActiveRecord # * Firm#clients.build (similar to Client.new("firm_id" => id)) # * Firm#clients.create (similar to c = Client.new("firm_id" => id); c.save; c) # * Firm#clients.create! (similar to c = Client.new("firm_id" => id); c.save!) - # The declaration can also include an options hash to specialize the behavior of the association. + # The declaration can also include an +options+ hash to specialize the behavior of the association. # # === Options # [:class_name] @@ -1259,7 +1259,7 @@ module ActiveRecord # # === Options # - # The declaration can also include an options hash to specialize the behavior of the association. + # The declaration can also include an +options+ hash to specialize the behavior of the association. # # Options are: # [:class_name] @@ -1364,7 +1364,7 @@ module ActiveRecord # * Post#build_author (similar to post.author = Author.new) # * Post#create_author (similar to post.author = Author.new; post.author.save; post.author) # * Post#create_author! (similar to post.author = Author.new; post.author.save!; post.author) - # The declaration can also include an options hash to specialize the behavior of the association. + # The declaration can also include an +options+ hash to specialize the behavior of the association. # # === Options # @@ -1541,7 +1541,7 @@ module ActiveRecord # * Developer#projects.exists?(...) # * Developer#projects.build (similar to Project.new("developer_id" => id)) # * Developer#projects.create (similar to c = Project.new("developer_id" => id); c.save; c) - # The declaration may include an options hash to specialize the behavior of the association. + # The declaration may include an +options+ hash to specialize the behavior of the association. # # === Options # -- cgit v1.2.3 From 0f99aa615e11c50cc64b567f54cf64f59108c5e5 Mon Sep 17 00:00:00 2001 From: lsylvester Date: Mon, 11 Aug 2014 13:31:31 +1000 Subject: update error message to reflect that the record could have been destroyed --- activerecord/lib/active_record/persistence.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index b5799d6bff..51b1931ed5 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -287,7 +287,8 @@ module ActiveRecord # This method raises an +ActiveRecord::ActiveRecordError+ when called on new # objects, or when at least one of the attributes is marked as readonly. def update_columns(attributes) - raise ActiveRecordError, "cannot update on a new record object" unless persisted? + raise ActiveRecordError, "cannot update a new record" if new_record? + raise ActiveRecordError, "cannot update a destroyed record" if destroyed? attributes.each_key do |key| verify_readonly_attribute(key.to_s) -- cgit v1.2.3