From 126fbd7ed8a310bf940414c1b7ddab06b03d400e Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Wed, 17 Nov 2010 21:46:55 -0500 Subject: unscoped takes care of named_scopes too --- activerecord/lib/active_record/base.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index f588475bbf..d7a7101404 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -856,8 +856,7 @@ module ActiveRecord #:nodoc: # limit(10) # Fires "SELECT * FROM posts LIMIT 10" # } # - # It is recommended to use block form of unscoped because chaining unscoped with named_scope - # does not work. Assuming that published is a named_scope following two statements are same. + # Assuming that published is a named_scope following two statements are same. # # Post.unscoped.published # Post.published -- cgit v1.2.3 From d9ac62c91466e40b557d27c4d712f86759d63a4b Mon Sep 17 00:00:00 2001 From: Matthew Rudy Jacobs Date: Sun, 21 Nov 2010 00:18:33 +0800 Subject: Fix Bug: disable_referential_integrity doesn't work for postgres 9.0.1 --- .../lib/active_record/connection_adapters/postgresql_adapter.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index ccc5085b84..7dd81abc7e 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -404,10 +404,7 @@ module ActiveRecord # REFERENTIAL INTEGRITY ==================================== def supports_disable_referential_integrity?() #:nodoc: - version = query("SHOW server_version")[0][0].split('.') - version[0].to_i >= 8 && version[1].to_i >= 1 - rescue - return false + postgresql_version >= 80100 end def disable_referential_integrity #:nodoc: -- cgit v1.2.3 From d7db6a88734c3b666f4b85f266d223eff408b294 Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Fri, 19 Nov 2010 18:29:33 +0100 Subject: class inheritable attributes is used no more! all internal use of class inheritable has been changed to class_attribute. class inheritable attributes has been deprecated. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activerecord/lib/active_record/associations.rb | 13 +++++++------ .../associations/association_collection.rb | 2 +- .../lib/active_record/attribute_methods/dirty.rb | 3 ++- .../attribute_methods/time_zone_conversion.rb | 6 ++++-- activerecord/lib/active_record/base.rb | 20 ++++++++++++-------- activerecord/lib/active_record/named_scope.rb | 10 ++++++---- activerecord/lib/active_record/nested_attributes.rb | 13 +++++++++---- activerecord/lib/active_record/reflection.rb | 20 +++++++++----------- activerecord/lib/active_record/timestamp.rb | 8 +++++--- 9 files changed, 55 insertions(+), 40 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 08a4ebfd7e..7da38cd03f 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -4,6 +4,7 @@ require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/string/conversions' require 'active_support/core_ext/module/remove_method' +require 'active_support/core_ext/class/attribute' module ActiveRecord class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc: @@ -1810,12 +1811,12 @@ module ActiveRecord callbacks.each do |callback_name| full_callback_name = "#{callback_name}_for_#{association_name}" defined_callbacks = options[callback_name.to_sym] - if options.has_key?(callback_name.to_sym) - class_inheritable_reader full_callback_name.to_sym - write_inheritable_attribute(full_callback_name.to_sym, [defined_callbacks].flatten) - else - write_inheritable_attribute(full_callback_name.to_sym, []) - end + + full_callback_value = options.has_key?(callback_name.to_sym) ? [defined_callbacks].flatten : [] + + # TODO : why do i need method_defined? I think its because of the inheritance chain + class_attribute full_callback_name.to_sym unless method_defined?(full_callback_name) + self.send("#{full_callback_name}=", full_callback_value) end end diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index 6090376bb8..774103342a 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -530,7 +530,7 @@ module ActiveRecord def callbacks_for(callback_name) full_callback_name = "#{callback_name}_for_#{@reflection.name}" - @owner.class.read_inheritable_attribute(full_callback_name.to_sym) || [] + @owner.class.send(full_callback_name.to_sym) || [] end def ensure_owner_is_not_new diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index 439880c1fa..c19a33faa8 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -1,3 +1,4 @@ +require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/object/blank' module ActiveRecord @@ -88,7 +89,7 @@ module ActiveRecord end def clone_with_time_zone_conversion_attribute?(attr, old) - old.class.name == "Time" && time_zone_aware_attributes && !skip_time_zone_conversion_for_attributes.include?(attr.to_sym) + old.class.name == "Time" && time_zone_aware_attributes && !self.skip_time_zone_conversion_for_attributes.include?(attr.to_sym) end end end diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb index d640b26b74..dc2785b6bf 100644 --- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb +++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/class/attribute' + module ActiveRecord module AttributeMethods module TimeZoneConversion @@ -7,7 +9,7 @@ module ActiveRecord cattr_accessor :time_zone_aware_attributes, :instance_writer => false self.time_zone_aware_attributes = false - class_inheritable_accessor :skip_time_zone_conversion_for_attributes, :instance_writer => false + class_attribute :skip_time_zone_conversion_for_attributes, :instance_writer => false self.skip_time_zone_conversion_for_attributes = [] end @@ -54,7 +56,7 @@ module ActiveRecord private def create_time_zone_conversion_attribute?(name, column) - time_zone_aware_attributes && !skip_time_zone_conversion_for_attributes.include?(name.to_sym) && [:datetime, :timestamp].include?(column.type) + time_zone_aware_attributes && !self.skip_time_zone_conversion_for_attributes.include?(name.to_sym) && [:datetime, :timestamp].include?(column.type) end end end diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 314f676711..8bde1869c7 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -7,7 +7,7 @@ require 'active_support/time' require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/class/attribute_accessors' require 'active_support/core_ext/class/delegating_attributes' -require 'active_support/core_ext/class/inheritable_attributes' +require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/array/extract_options' require 'active_support/core_ext/hash/deep_merge' require 'active_support/core_ext/hash/indifferent_access' @@ -412,7 +412,7 @@ module ActiveRecord #:nodoc: self.store_full_sti_class = true # Stores the default scope for the class - class_inheritable_accessor :default_scoping, :instance_writer => false + class_attribute :default_scoping, :instance_writer => false self.default_scoping = [] # Returns a hash of all the attributes that have been specified for serialization as @@ -420,6 +420,9 @@ module ActiveRecord #:nodoc: class_attribute :serialized_attributes self.serialized_attributes = {} + class_attribute :_attr_readonly, :instance_writer => false + self._attr_readonly = [] + class << self # Class methods delegate :find, :first, :last, :all, :destroy, :destroy_all, :exists?, :delete, :delete_all, :update, :update_all, :to => :scoped delegate :find_each, :find_in_batches, :to => :scoped @@ -504,12 +507,12 @@ module ActiveRecord #:nodoc: # Attributes listed as readonly will be used to create a new record but update operations will # ignore these fields. def attr_readonly(*attributes) - write_inheritable_attribute(:attr_readonly, Set.new(attributes.map { |a| a.to_s }) + (readonly_attributes || [])) + self._attr_readonly = Set.new(attributes.map { |a| a.to_s }) + (self._attr_readonly || []) end # Returns an array of all the attributes that have been specified as readonly. def readonly_attributes - read_inheritable_attribute(:attr_readonly) || [] + self._attr_readonly end # If you have an attribute that needs to be saved to the database as an object, and retrieved as the same object, @@ -724,8 +727,8 @@ module ActiveRecord #:nodoc: @arel_engine = @relation = @arel_table = nil end - def reset_column_information_and_inheritable_attributes_for_all_subclasses#:nodoc: - descendants.each { |klass| klass.reset_inheritable_attributes; klass.reset_column_information } + def reset_column_information_for_all_subclasses#:nodoc: + descendants.each { |klass| klass.reset_column_information } end def attribute_method?(attribute) @@ -1126,7 +1129,8 @@ MSG # Article.create.published # => true def default_scope(options = {}) reset_scoped_methods - self.default_scoping << construct_finder_arel(options, default_scoping.pop) + default_scoping = self.default_scoping.dup + self.default_scoping = default_scoping << construct_finder_arel(options, default_scoping.pop) end def current_scoped_methods #:nodoc: @@ -1579,7 +1583,7 @@ MSG self.class.columns_hash[name.to_s] end - # Returns true if +comparison_object+ is the same exact object, or +comparison_object+ + # Returns true if +comparison_object+ is the same exact object, or +comparison_object+ # is of the same type and +self+ has an ID and it is equal to +comparison_object.id+. # # Note that new records are different from any other record by definition, unless the diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb index 0b92ba5caa..0f421560f0 100644 --- a/activerecord/lib/active_record/named_scope.rb +++ b/activerecord/lib/active_record/named_scope.rb @@ -2,12 +2,18 @@ require 'active_support/core_ext/array' require 'active_support/core_ext/hash/except' require 'active_support/core_ext/kernel/singleton_class' require 'active_support/core_ext/object/blank' +require 'active_support/core_ext/class/attribute' module ActiveRecord # = Active Record Named \Scopes module NamedScope extend ActiveSupport::Concern + included do + class_attribute :scopes + self.scopes = {} + end + module ClassMethods # Returns an anonymous \scope. # @@ -33,10 +39,6 @@ module ActiveRecord end end - def scopes - read_inheritable_attribute(:scopes) || write_inheritable_attribute(:scopes, {}) - end - # Adds a class method for retrieving and querying objects. A \scope represents a narrowing of a database query, # such as where(:color => :red).select('shirts.*').includes(:washing_instructions). # diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 0c3392263a..f1d3eaed38 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -2,6 +2,7 @@ require 'active_support/core_ext/hash/except' require 'active_support/core_ext/object/try' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/hash/indifferent_access' +require 'active_support/core_ext/class/attribute' module ActiveRecord module NestedAttributes #:nodoc: @@ -11,7 +12,7 @@ module ActiveRecord extend ActiveSupport::Concern included do - class_inheritable_accessor :nested_attributes_options, :instance_writer => false + class_attribute :nested_attributes_options, :instance_writer => false self.nested_attributes_options = {} end @@ -268,7 +269,11 @@ module ActiveRecord if reflection = reflect_on_association(association_name) reflection.options[:autosave] = true add_autosave_association_callbacks(reflection) + + nested_attributes_options = self.nested_attributes_options.dup nested_attributes_options[association_name.to_sym] = options + self.nested_attributes_options = nested_attributes_options + type = (reflection.collection? ? :collection : :one_to_one) # def pirate_attributes=(attributes) @@ -315,7 +320,7 @@ module ActiveRecord # update_only is true, and a :_destroy key set to a truthy value, # then the existing record will be marked for destruction. def assign_nested_attributes_for_one_to_one_association(association_name, attributes) - options = nested_attributes_options[association_name] + options = self.nested_attributes_options[association_name] attributes = attributes.with_indifferent_access check_existing_record = (options[:update_only] || !attributes['id'].blank?) @@ -364,7 +369,7 @@ module ActiveRecord # { :id => '2', :_destroy => true } # ]) def assign_nested_attributes_for_collection_association(association_name, attributes_collection) - options = nested_attributes_options[association_name] + options = self.nested_attributes_options[association_name] unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array) raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})" @@ -433,7 +438,7 @@ module ActiveRecord end def call_reject_if(association_name, attributes) - case callback = nested_attributes_options[association_name][:reject_if] + case callback = self.nested_attributes_options[association_name][:reject_if] when Symbol method(callback).arity == 0 ? send(callback) : send(callback, attributes) when Proc diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index a2260e9a19..a07c321960 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -1,8 +1,15 @@ +require 'active_support/core_ext/class/attribute' + module ActiveRecord # = Active Record Reflection module Reflection # :nodoc: extend ActiveSupport::Concern + included do + class_attribute :reflections + self.reflections = {} + end + # Reflection enables to interrogate 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 @@ -20,18 +27,9 @@ module ActiveRecord when :composed_of reflection = AggregateReflection.new(macro, name, options, active_record) end - write_inheritable_hash :reflections, name => reflection - reflection - end - # Returns a hash containing all AssociationReflection objects for the current class. - # Example: - # - # Invoice.reflections - # Account.reflections - # - def reflections - read_inheritable_attribute(:reflections) || write_inheritable_attribute(:reflections, {}) + self.reflections = self.reflections.merge(name => reflection) + reflection end # Returns an array of AggregateReflection objects for all the aggregations in the class. diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index 230adf6b2b..2ecbd906bd 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/class/attribute' + module ActiveRecord # = Active Record Timestamp # @@ -29,14 +31,14 @@ module ActiveRecord extend ActiveSupport::Concern included do - class_inheritable_accessor :record_timestamps, :instance_writer => false + class_attribute :record_timestamps, :instance_writer => false self.record_timestamps = true end private def create #:nodoc: - if record_timestamps + if self.record_timestamps current_time = current_time_from_proper_timezone all_timestamp_attributes.each do |column| @@ -61,7 +63,7 @@ module ActiveRecord end def should_record_timestamps? - record_timestamps && (!partial_updates? || changed? || (attributes.keys & self.class.serialized_attributes.keys).present?) + self.record_timestamps && (!partial_updates? || changed? || (attributes.keys & self.class.serialized_attributes.keys).present?) end def timestamp_attributes_for_update_in_model -- cgit v1.2.3 From 8796f9a31a77bb2ab97ea6c2cf2036fb6e38497e Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Fri, 19 Nov 2010 18:30:48 +0100 Subject: removed an AR method which wasn't used internally, had no tests, and had no docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activerecord/lib/active_record/base.rb | 4 ---- 1 file changed, 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 8bde1869c7..aee6f3a7eb 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -727,10 +727,6 @@ module ActiveRecord #:nodoc: @arel_engine = @relation = @arel_table = nil end - def reset_column_information_for_all_subclasses#:nodoc: - descendants.each { |klass| klass.reset_column_information } - end - def attribute_method?(attribute) super || (table_exists? && column_names.include?(attribute.to_s.sub(/=$/, ''))) end -- cgit v1.2.3 From c8ab3992f85569e43055b9e57c67324f5d5088cd Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Wed, 17 Nov 2010 21:46:55 -0500 Subject: unscoped takes care of named_scopes too --- activerecord/lib/active_record/base.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index aee6f3a7eb..aa028c6f36 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -852,8 +852,7 @@ module ActiveRecord #:nodoc: # limit(10) # Fires "SELECT * FROM posts LIMIT 10" # } # - # It is recommended to use block form of unscoped because chaining unscoped with named_scope - # does not work. Assuming that published is a named_scope following two statements are same. + # Assuming that published is a named_scope following two statements are same. # # Post.unscoped.published # Post.published -- cgit v1.2.3 From 16d7ba0698ef28efab31940ba4d3aed237814c7e Mon Sep 17 00:00:00 2001 From: Matthew Rudy Jacobs Date: Sun, 21 Nov 2010 20:45:01 +0800 Subject: Cleaner way to extract the Postgres version --- .../lib/active_record/connection_adapters/postgresql_adapter.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 7dd81abc7e..a4b1aa7154 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -953,8 +953,12 @@ module ActiveRecord else # Mimic PGconn.server_version behavior begin - query('SELECT version()')[0][0] =~ /PostgreSQL (\d+)\.(\d+)\.(\d+)/ - ($1.to_i * 10000) + ($2.to_i * 100) + $3.to_i + if query('SELECT version()')[0][0] =~ /PostgreSQL ([0-9.]+)/ + major, minor, tiny = $1.split(".") + (major.to_i * 10000) + (minor.to_i * 100) + tiny.to_i + else + 0 + end rescue 0 end -- cgit v1.2.3 From 1c68e55ae5e90b7c072a1f6030ea3dd4becd8a07 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 22 Nov 2010 17:32:15 -0500 Subject: Revert "unscoped takes care of named_scopes too" This reverts commit 126fbd7ed8a310bf940414c1b7ddab06b03d400e. --- activerecord/lib/active_record/base.rb | 3 ++- 1 file changed, 2 insertions(+), 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 d7a7101404..f588475bbf 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -856,7 +856,8 @@ module ActiveRecord #:nodoc: # limit(10) # Fires "SELECT * FROM posts LIMIT 10" # } # - # Assuming that published is a named_scope following two statements are same. + # It is recommended to use block form of unscoped because chaining unscoped with named_scope + # does not work. Assuming that published is a named_scope following two statements are same. # # Post.unscoped.published # Post.published -- cgit v1.2.3 From 66c09372f3ef3d4ca2b99d44cf1859d585b9dcb3 Mon Sep 17 00:00:00 2001 From: Alex Rothenberg Date: Tue, 23 Nov 2010 06:10:19 +0800 Subject: Removed ids_in_list_limit in favor of in_clause_length defined in database_limits.rb --- activerecord/lib/active_record/association_preload.rb | 4 ++-- .../lib/active_record/connection_adapters/abstract_adapter.rb | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb index 9743b1b4a7..5eb1071ba2 100644 --- a/activerecord/lib/active_record/association_preload.rb +++ b/activerecord/lib/active_record/association_preload.rb @@ -391,9 +391,9 @@ module ActiveRecord # Some databases impose a limit on the number of ids in a list (in Oracle its 1000) # Make several smaller queries if necessary or make one query if the adapter supports it def associated_records(ids) - max_ids_in_a_list = connection.ids_in_list_limit || ids.size + in_clause_length = connection.in_clause_length || ids.size records = [] - ids.each_slice(max_ids_in_a_list) do |some_ids| + ids.each_slice(in_clause_length) do |some_ids| records += yield(some_ids) end records diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index ada1560ce2..f3fba9a3a9 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -91,11 +91,6 @@ module ActiveRecord false end - # Does this adapter restrict the number of ids you can use in a list. Oracle has a limit of 1000. - def ids_in_list_limit - nil - end - # QUOTING ================================================== # Override to return the quoted table name. Defaults to column quoting. -- cgit v1.2.3 From 4d31ee1e0e2eccae0c9964214455ff75c647bd7f Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 22 Nov 2010 16:14:37 -0800 Subject: removing unused variables --- .../lib/active_record/associations/through_association_scope.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_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index bd8e304e99..acddfda924 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -16,7 +16,7 @@ module ActiveRecord :readonly => @reflection.options[:readonly] } end - + def construct_create_scope construct_owner_attributes(@reflection) end @@ -51,7 +51,7 @@ module ActiveRecord def construct_select(custom_select = nil) distinct = "DISTINCT " if @reflection.options[:uniq] - selected = custom_select || @reflection.options[:select] || "#{distinct}#{@reflection.quoted_table_name}.*" + custom_select || @reflection.options[:select] || "#{distinct}#{@reflection.quoted_table_name}.*" end def construct_joins(custom_joins = nil) -- cgit v1.2.3 From 4ece7e06fd0009f024fd167107324122c564d551 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 22 Nov 2010 17:06:55 -0800 Subject: removing space error --- activerecord/lib/active_record/associations/belongs_to_association.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb index b624951cd9..b438620c8f 100644 --- a/activerecord/lib/active_record/associations/belongs_to_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_association.rb @@ -61,7 +61,7 @@ module ActiveRecord set_inverse_instance(the_target, @owner) the_target end - + def construct_find_scope { :conditions => conditions } end -- cgit v1.2.3 From dc320d5873e54338a917ced26d849a64001edf28 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 22 Nov 2010 17:23:37 -0800 Subject: skip cloning if arguments are blank --- .../lib/active_record/relation/query_methods.rb | 30 ++++++++++++++++------ 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 9e7503a60d..0a4c119849 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -13,7 +13,7 @@ module ActiveRecord def includes(*args) args.reject! {|a| a.blank? } - return clone if args.empty? + return self if args.empty? relation = clone relation.includes_values = (relation.includes_values + args).flatten.uniq @@ -21,14 +21,18 @@ module ActiveRecord end def eager_load(*args) + return self if args.blank? + relation = clone - relation.eager_load_values += args unless args.blank? + relation.eager_load_values += args relation end def preload(*args) + return self if args.blank? + relation = clone - relation.preload_values += args unless args.blank? + relation.preload_values += args relation end @@ -43,22 +47,28 @@ module ActiveRecord end def group(*args) + return self if args.blank? + relation = clone - relation.group_values += args.flatten unless args.blank? + relation.group_values += args.flatten relation end def order(*args) + return self if args.blank? + relation = clone - relation.order_values += args.flatten unless args.blank? + relation.order_values += args.flatten relation end def joins(*args) + return self if args.blank? + relation = clone args.flatten! - relation.joins_values += args unless args.blank? + relation.joins_values += args relation end @@ -70,14 +80,18 @@ module ActiveRecord end def where(opts, *rest) + return self if opts.blank? + relation = clone - relation.where_values += build_where(opts, rest) unless opts.blank? + relation.where_values += build_where(opts, rest) relation end def having(*args) + return self if args.blank? + relation = clone - relation.having_values += build_where(*args) unless args.blank? + relation.having_values += build_where(*args) relation end -- cgit v1.2.3 From de829f871becc87424d75a5050883a02435c01e4 Mon Sep 17 00:00:00 2001 From: Ray Baxter Date: Mon, 22 Nov 2010 22:11:56 -0800 Subject: fix typo --- activerecord/lib/active_record/autosave_association.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index cb5bc06580..73ac8e82c6 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -89,7 +89,7 @@ module ActiveRecord # post = Post.create(:title => 'ruby rocks') # post.comments.create(:body => 'hello world') # post.comments[0].body = 'hi everyone' - # post.save # => saves both post and comment, with 'hi everyone' as title + # post.save # => saves both post and comment, with 'hi everyone' as body # # Destroying one of the associated models as part of the parent's save action # is as simple as marking it for destruction: -- cgit v1.2.3 From 14055ea28285107af04ed0ce4ef0ec542a9a9530 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Sat, 20 Nov 2010 07:38:08 +0800 Subject: No need to define a local var here. --- activerecord/lib/active_record/base.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index aa028c6f36..f9743b4fea 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1569,8 +1569,7 @@ MSG # Returns true if the specified +attribute+ has been set by the user or by a database load and is neither # nil nor empty? (the latter only applies to objects that respond to empty?, most notably Strings). def attribute_present?(attribute) - value = read_attribute(attribute) - !value.blank? + !read_attribute(attribute).blank? end # Returns the column object for the named attribute. -- cgit v1.2.3 From a9e963d51d262a0693f0b83508c40a250421f826 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Sat, 20 Nov 2010 07:38:58 +0800 Subject: Remove confusing parenthesis. --- 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 f9743b4fea..18d30d2540 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1595,7 +1595,7 @@ MSG # Delegates to == def eql?(comparison_object) - self == (comparison_object) + self == comparison_object end # Delegates to id in order to allow two records of the same type and id to work with something like: -- cgit v1.2.3 From 9c161599ac1e37eedd56bece4d975dde8cdaa151 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Sat, 20 Nov 2010 07:46:56 +0800 Subject: Remove uneeded local var definition. --- activerecord/lib/active_record/nested_attributes.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index f1d3eaed38..a2101a02eb 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -322,9 +322,8 @@ module ActiveRecord def assign_nested_attributes_for_one_to_one_association(association_name, attributes) options = self.nested_attributes_options[association_name] attributes = attributes.with_indifferent_access - check_existing_record = (options[:update_only] || !attributes['id'].blank?) - if check_existing_record && (record = send(association_name)) && + if (options[:update_only] || !attributes['id'].blank?) && (record = send(association_name)) && (options[:update_only] || record.id.to_s == attributes['id'].to_s) assign_to_or_mark_for_destruction(record, attributes, options[:allow_destroy]) unless call_reject_if(association_name, attributes) -- cgit v1.2.3 From 861cdc4c59dabdc8cca42a9f29b7cccb3cd23505 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Sat, 20 Nov 2010 07:48:49 +0800 Subject: Remove unneeded local var. --- activerecord/lib/active_record/nested_attributes.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index a2101a02eb..15f83a8579 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -446,8 +446,7 @@ module ActiveRecord end def raise_nested_attributes_record_not_found(association_name, record_id) - reflection = self.class.reflect_on_association(association_name) - raise RecordNotFound, "Couldn't find #{reflection.klass.name} with ID=#{record_id} for #{self.class.name} with ID=#{id}" + raise RecordNotFound, "Couldn't find #{self.class.reflect_on_association(association_name).klass.name} with ID=#{record_id} for #{self.class.name} with ID=#{id}" end end end -- cgit v1.2.3 From b8df3a9197252ec62f390ef1f8cd0e0e827c6252 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Sun, 21 Nov 2010 00:41:39 +0800 Subject: Use params default. --- activerecord/lib/active_record/connection_adapters/abstract_adapter.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_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index f3fba9a3a9..0282493219 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -204,8 +204,7 @@ module ActiveRecord protected - def log(sql, name) - name ||= "SQL" + def log(sql, name = "SQL") @instrumenter.instrument("sql.active_record", :sql => sql, :name => name, :connection_id => object_id) do yield -- cgit v1.2.3 From 1b531b7ee2054beadb23853d79b15d588b9ffd88 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Sun, 21 Nov 2010 00:35:11 +0800 Subject: Remove explicit return. --- activerecord/lib/active_record/associations/has_many_association.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 830a82980d..a682ec52d8 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -46,7 +46,7 @@ module ActiveRecord count = [ @reflection.options[:limit], count ].min end - return count + count end def has_cached_counter? -- cgit v1.2.3 From 63c9185b62076f416c63b472a356bf9faac143db Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Sun, 21 Nov 2010 00:38:35 +0800 Subject: Remove explicit return and avoid creating local var. --- activerecord/lib/active_record/associations/has_many_association.rb | 3 +-- 1 file changed, 1 insertion(+), 2 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 a682ec52d8..6423536fb9 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -112,8 +112,7 @@ module ActiveRecord end def we_can_set_the_inverse_on_this?(record) - inverse = @reflection.inverse_of - return !inverse.nil? + !@reflection.inverse_of.nil? end end end -- cgit v1.2.3 From 6ffe0ef55bbabf59a533402a6420942c7397e441 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Sun, 21 Nov 2010 00:43:28 +0800 Subject: Avoid creating local var. --- activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb | 3 +-- 1 file changed, 1 insertion(+), 2 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 5ca1923d89..c2cd9e8d5e 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -40,8 +40,7 @@ module ActiveRecord if @connection.respond_to?(:encoding) @connection.encoding.to_s else - encoding = @connection.execute('PRAGMA encoding') - encoding[0]['encoding'] + @connection.execute('PRAGMA encoding')[0]['encoding'] end end -- cgit v1.2.3 From d29d793c9096a732274298cdba07c654e9128484 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Sun, 21 Nov 2010 00:51:01 +0800 Subject: Don't create local vars. --- activerecord/lib/active_record/locking/optimistic.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb index bf626301f1..9e1a33a6bf 100644 --- a/activerecord/lib/active_record/locking/optimistic.rb +++ b/activerecord/lib/active_record/locking/optimistic.rb @@ -110,12 +110,9 @@ module ActiveRecord return super unless locking_enabled? if persisted? - lock_col = self.class.locking_column - previous_value = send(lock_col).to_i - table = self.class.arel_table predicate = table[self.class.primary_key].eq(id) - predicate = predicate.and(table[self.class.locking_column].eq(previous_value)) + predicate = predicate.and(table[self.class.locking_column].eq(send(self.class.locking_column).to_i)) affected_rows = self.class.unscoped.where(predicate).delete_all -- cgit v1.2.3 From e2bad8a2e7e020901ddb74c3404a1c339b5a99f9 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Sun, 21 Nov 2010 00:46:28 +0800 Subject: No need to create a variables to use them once. --- activerecord/lib/active_record/validations/uniqueness.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (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 3eba7510ac..853808eebf 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -14,17 +14,14 @@ module ActiveRecord def validate_each(record, attribute, value) finder_class = find_finder_class_for(record) - table = finder_class.unscoped - - table_name = record.class.quoted_table_name if value && record.class.serialized_attributes.key?(attribute.to_s) value = YAML.dump value end - sql, params = mount_sql_and_params(finder_class, table_name, attribute, value) + sql, params = mount_sql_and_params(finder_class, record.class.quoted_table_name, attribute, value) - relation = table.where(sql, *params) + relation = finder_class.unscoped.where(sql, *params) Array.wrap(options[:scope]).each do |scope_item| scope_value = record.send(scope_item) -- cgit v1.2.3 From 9f35799221c8a3c06b3f34a38525654b59598cfd Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Sat, 20 Nov 2010 13:37:54 -0300 Subject: Refactor && simplify count_records. --- activerecord/lib/active_record/associations/has_many_association.rb | 6 +----- 1 file changed, 1 insertion(+), 5 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 6423536fb9..23831e0b08 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -42,11 +42,7 @@ module ActiveRecord # documented side-effect of the method that may avoid an extra SELECT. @target ||= [] and loaded if count == 0 - if @reflection.options[:limit] - count = [ @reflection.options[:limit], count ].min - end - - count + @reflection.options[:limit] ? [@reflection.options[:limit], count].min : count end def has_cached_counter? -- cgit v1.2.3 From ca7b0a0d1a424aec0973fe22c299b8f04e309784 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Nov 2010 10:13:43 -0800 Subject: dup is working better --- activerecord/lib/active_record/base.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 9e15784f61..0d3df938e6 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1420,7 +1420,7 @@ MSG @attributes = coder['attributes'] @attributes_cache, @previously_changed, @changed_attributes = {}, {}, {} @readonly = @destroyed = @marked_for_destruction = false - @persisted = true + @persisted = false _run_find_callbacks _run_initialize_callbacks end @@ -1615,11 +1615,15 @@ MSG @attributes.frozen? end + def initialize_dup(other) + super + init_with 'attributes' => other.attributes + self + end + # Returns duplicated record with unfreezed attributes. def dup - obj = super - obj.instance_variable_set('@attributes', @attributes.dup) - obj + super end # Returns +true+ if the record is read only. Records loaded through joins with piggy-back -- cgit v1.2.3 From 5badf60d128cb958fa7a0e3f140517b71b88c7ac Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Nov 2010 10:58:19 -0800 Subject: dup keeps changes --- activerecord/lib/active_record/base.rb | 49 +++++++++++++++------------------- 1 file changed, 21 insertions(+), 28 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 0d3df938e6..be8ebd4d59 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1382,30 +1382,6 @@ MSG result end - # Cloned objects have no id assigned and are treated as new records. Note that this is a "shallow" clone - # as it copies the object's attributes only, not its associations. The extent of a "deep" clone is - # application specific and is therefore left to the application to implement according to its need. - def initialize_copy(other) - _run_after_initialize_callbacks if respond_to?(:_run_after_initialize_callbacks) - cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast) - cloned_attributes.delete(self.class.primary_key) - - @attributes = cloned_attributes - - @changed_attributes = {} - attributes_from_column_definition.each do |attr, orig_value| - @changed_attributes[attr] = orig_value if field_changed?(attr, orig_value, @attributes[attr]) - end - - clear_aggregation_cache - clear_association_cache - @attributes_cache = {} - @persisted = false - ensure_proper_type - - populate_with_current_scope_attributes - end - # Initialize an empty model object from +coder+. +coder+ must contain # the attributes necessary for initializing an empty model object. For # example: @@ -1420,7 +1396,7 @@ MSG @attributes = coder['attributes'] @attributes_cache, @previously_changed, @changed_attributes = {}, {}, {} @readonly = @destroyed = @marked_for_destruction = false - @persisted = false + @persisted = true _run_find_callbacks _run_initialize_callbacks end @@ -1615,15 +1591,32 @@ MSG @attributes.frozen? end + # Duped objects have no id assigned and are treated as new records. Note + # that this is a "shallow" clone as it copies the object's attributes + # only, not its associations. The extent of a "deep" dup is application + # specific and is therefore left to the application to implement according + # to its need. def initialize_dup(other) super - init_with 'attributes' => other.attributes + cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast) + cloned_attributes.delete(self.class.primary_key) + + @attributes = cloned_attributes + @changed_attributes = other.changed_attributes.dup + @attributes_cache = {} + @persisted = false + + _run_after_initialize_callbacks if respond_to?(:_run_after_initialize_callbacks) + clear_aggregation_cache + clear_association_cache + ensure_proper_type + populate_with_current_scope_attributes self end - # Returns duplicated record with unfreezed attributes. - def dup + def initialize_clone(other) super + @persisted = other.persisted? end # Returns +true+ if the record is read only. Records loaded through joins with piggy-back -- cgit v1.2.3 From 4c1f76eaab670ffa95d185374ea91f0d2e2818c7 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Nov 2010 10:59:58 -0800 Subject: initialize_clone can go away --- activerecord/lib/active_record/base.rb | 5 ----- 1 file changed, 5 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index be8ebd4d59..6f0e71cc7b 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1614,11 +1614,6 @@ MSG self end - def initialize_clone(other) - super - @persisted = other.persisted? - end - # Returns +true+ if the record is read only. Records loaded through joins with piggy-back # attributes will be marked as read only since they cannot be saved. def readonly? -- cgit v1.2.3 From 93d78b831831a1c8e324d4c5404b99e81fe77725 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Nov 2010 11:30:14 -0800 Subject: fixing more dup tests --- activerecord/lib/active_record/base.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 6f0e71cc7b..f9de4b7918 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1598,20 +1598,20 @@ MSG # to its need. def initialize_dup(other) super + _run_after_initialize_callbacks if respond_to?(:_run_after_initialize_callbacks) cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast) cloned_attributes.delete(self.class.primary_key) @attributes = cloned_attributes @changed_attributes = other.changed_attributes.dup - @attributes_cache = {} - @persisted = false - _run_after_initialize_callbacks if respond_to?(:_run_after_initialize_callbacks) clear_aggregation_cache clear_association_cache + @attributes_cache = {} + @persisted = false + ensure_proper_type populate_with_current_scope_attributes - self end # Returns +true+ if the record is read only. Records loaded through joins with piggy-back -- cgit v1.2.3 From 064c28d6c290cb9b6222b2348e38e713b82a89d6 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Nov 2010 11:57:33 -0800 Subject: fixing dup regressions --- activerecord/lib/active_record/base.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index f9de4b7918..7cc4f957fe 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1592,8 +1592,8 @@ MSG end # Duped objects have no id assigned and are treated as new records. Note - # that this is a "shallow" clone as it copies the object's attributes - # only, not its associations. The extent of a "deep" dup is application + # that this is a "shallow" copy as it copies the object's attributes + # only, not its associations. The extent of a "deep" copy is application # specific and is therefore left to the application to implement according # to its need. def initialize_dup(other) @@ -1602,8 +1602,12 @@ MSG cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast) cloned_attributes.delete(self.class.primary_key) - @attributes = cloned_attributes - @changed_attributes = other.changed_attributes.dup + @attributes = cloned_attributes + + @changed_attributes = {} + attributes_from_column_definition.each do |attr, orig_value| + @changed_attributes[attr] = orig_value if field_changed?(attr, orig_value, @attributes[attr]) + end clear_aggregation_cache clear_association_cache -- cgit v1.2.3 From d717cb29136b8e4f557e6f6ddf076ae3de8476fc Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Nov 2010 13:38:20 -0800 Subject: clone and dup are working on 1.8 --- activerecord/lib/active_record/base.rb | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 7cc4f957fe..d2fa3bed35 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1591,19 +1591,28 @@ MSG @attributes.frozen? end + # Backport dup from 1.9 so that initialize_dup() gets called + unless Object.respond_to?(:initialize_dup) + def dup # :nodoc: + copy = super + copy.initialize_dup(self) + copy + end + end + # Duped objects have no id assigned and are treated as new records. Note # that this is a "shallow" copy as it copies the object's attributes # only, not its associations. The extent of a "deep" copy is application # specific and is therefore left to the application to implement according # to its need. def initialize_dup(other) - super - _run_after_initialize_callbacks if respond_to?(:_run_after_initialize_callbacks) cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast) cloned_attributes.delete(self.class.primary_key) @attributes = cloned_attributes + _run_after_initialize_callbacks if respond_to?(:_run_after_initialize_callbacks) + @changed_attributes = {} attributes_from_column_definition.each do |attr, orig_value| @changed_attributes[attr] = orig_value if field_changed?(attr, orig_value, @attributes[attr]) @@ -1612,7 +1621,7 @@ MSG clear_aggregation_cache clear_association_cache @attributes_cache = {} - @persisted = false + @persisted = false ensure_proper_type populate_with_current_scope_attributes -- cgit v1.2.3 From d33dcba72d19beffc4a359f2fb89659f24122e9a Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Tue, 23 Nov 2010 14:58:10 -0500 Subject: Do not send id for quoting twice if the primary key is string. [#6022 state:resolved] --- activerecord/lib/active_record/relation/predicate_builder.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb index 32c7d08daa..7e2ce06dae 100644 --- a/activerecord/lib/active_record/relation/predicate_builder.rb +++ b/activerecord/lib/active_record/relation/predicate_builder.rb @@ -26,7 +26,8 @@ module ActiveRecord when Range, Arel::Relation attribute.in(value) when ActiveRecord::Base - attribute.eq(value.quoted_id) + sanitized_id = attribute.class == Arel::Attributes::String ? value.id : value.quoted_id + attribute.eq(sanitized_id) when Class # FIXME: I think we need to deprecate this behavior attribute.eq(value.name) -- cgit v1.2.3 From 8e8fb8a4291cc288b1189338f0de643c409eb028 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Nov 2010 14:42:55 -0800 Subject: just wrap as a sql literal --- activerecord/lib/active_record/relation/predicate_builder.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb index 7e2ce06dae..70d84619a1 100644 --- a/activerecord/lib/active_record/relation/predicate_builder.rb +++ b/activerecord/lib/active_record/relation/predicate_builder.rb @@ -26,8 +26,7 @@ module ActiveRecord when Range, Arel::Relation attribute.in(value) when ActiveRecord::Base - sanitized_id = attribute.class == Arel::Attributes::String ? value.id : value.quoted_id - attribute.eq(sanitized_id) + attribute.eq(Arel.sql(value.quoted_id)) when Class # FIXME: I think we need to deprecate this behavior attribute.eq(value.name) -- cgit v1.2.3 From 1aaa8edeb958a263c7a256344f442867c4b90c5f Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Nov 2010 17:34:18 -0800 Subject: breaking classes up in to respective files --- activerecord/lib/active_record/associations.rb | 575 +-------------------- .../associations/class_methods/join_dependency.rb | 216 ++++++++ .../join_dependency/join_association.rb | 278 ++++++++++ .../class_methods/join_dependency/join_base.rb | 34 ++ .../class_methods/join_dependency/join_part.rb | 76 +++ 5 files changed, 605 insertions(+), 574 deletions(-) create mode 100644 activerecord/lib/active_record/associations/class_methods/join_dependency.rb create mode 100644 activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb create mode 100644 activerecord/lib/active_record/associations/class_methods/join_dependency/join_base.rb create mode 100644 activerecord/lib/active_record/associations/class_methods/join_dependency/join_part.rb (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 7da38cd03f..0d9171d876 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -5,6 +5,7 @@ require 'active_support/core_ext/object/blank' require 'active_support/core_ext/string/conversions' require 'active_support/core_ext/module/remove_method' require 'active_support/core_ext/class/attribute' +require 'active_record/associations/class_methods/join_dependency' module ActiveRecord class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc: @@ -1832,580 +1833,6 @@ module ActiveRecord Array.wrap(extensions) end end - - class JoinDependency # :nodoc: - attr_reader :join_parts, :reflections, :table_aliases - - def initialize(base, associations, joins) - @join_parts = [JoinBase.new(base, joins)] - @associations = {} - @reflections = [] - @table_aliases = Hash.new(0) - @table_aliases[base.table_name] = 1 - build(associations) - end - - def graft(*associations) - associations.each do |association| - join_associations.detect {|a| association == a} || - build(association.reflection.name, association.find_parent_in(self) || join_base, association.join_type) - end - self - end - - def join_associations - join_parts.last(join_parts.length - 1) - end - - def join_base - join_parts.first - end - - def count_aliases_from_table_joins(name) - # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase - quoted_name = join_base.active_record.connection.quote_table_name(name.downcase).downcase - join_sql = join_base.table_joins.to_s.downcase - join_sql.blank? ? 0 : - # Table names - join_sql.scan(/join(?:\s+\w+)?\s+#{quoted_name}\son/).size + - # Table aliases - join_sql.scan(/join(?:\s+\w+)?\s+\S+\s+#{quoted_name}\son/).size - end - - def instantiate(rows) - primary_key = join_base.aliased_primary_key - parents = {} - - records = rows.map { |model| - primary_id = model[primary_key] - parent = parents[primary_id] ||= join_base.instantiate(model) - construct(parent, @associations, join_associations.dup, model) - parent - }.uniq - - remove_duplicate_results!(join_base.active_record, records, @associations) - records - end - - def remove_duplicate_results!(base, records, associations) - case associations - when Symbol, String - reflection = base.reflections[associations] - remove_uniq_by_reflection(reflection, records) - when Array - associations.each do |association| - remove_duplicate_results!(base, records, association) - end - when Hash - associations.keys.each do |name| - reflection = base.reflections[name] - remove_uniq_by_reflection(reflection, records) - - parent_records = [] - records.each do |record| - if descendant = record.send(reflection.name) - if reflection.collection? - parent_records.concat descendant.target.uniq - else - parent_records << descendant - end - end - end - - remove_duplicate_results!(reflection.klass, parent_records, associations[name]) unless parent_records.empty? - end - end - end - - protected - - def cache_joined_association(association) - associations = [] - parent = association.parent - while parent != join_base - associations.unshift(parent.reflection.name) - parent = parent.parent - end - ref = @associations - associations.each do |key| - ref = ref[key] - end - ref[association.reflection.name] ||= {} - end - - def build(associations, parent = nil, join_type = Arel::InnerJoin) - parent ||= join_parts.last - case associations - when Symbol, String - reflection = parent.reflections[associations.to_s.intern] or - raise ConfigurationError, "Association named '#{ associations }' was not found; perhaps you misspelled it?" - unless join_association = find_join_association(reflection, parent) - @reflections << reflection - join_association = build_join_association(reflection, parent) - join_association.join_type = join_type - @join_parts << join_association - cache_joined_association(join_association) - end - join_association - when Array - associations.each do |association| - build(association, parent, join_type) - end - when Hash - associations.keys.sort{|a,b|a.to_s<=>b.to_s}.each do |name| - join_association = build(name, parent, join_type) - build(associations[name], join_association, join_type) - end - else - raise ConfigurationError, associations.inspect - end - end - - def find_join_association(name_or_reflection, parent) - if String === name_or_reflection - name_or_reflection = name_or_reflection.to_sym - end - - join_associations.detect { |j| - j.reflection == name_or_reflection && j.parent == parent - } - end - - def remove_uniq_by_reflection(reflection, records) - if reflection && reflection.collection? - records.each { |record| record.send(reflection.name).target.uniq! } - end - end - - def build_join_association(reflection, parent) - JoinAssociation.new(reflection, self, parent) - end - - def construct(parent, associations, join_parts, row) - case associations - when Symbol, String - name = associations.to_s - - join_part = join_parts.detect { |j| - j.reflection.name.to_s == name && - j.parent_table_name == parent.class.table_name } - - raise(ConfigurationError, "No such association") unless join_part - - join_parts.delete(join_part) - construct_association(parent, join_part, row) - when Array - associations.each do |association| - construct(parent, association, join_parts, row) - end - when Hash - associations.sort_by { |k,_| k.to_s }.each do |name, assoc| - association = construct(parent, name, join_parts, row) - construct(association, assoc, join_parts, row) if association - end - else - raise ConfigurationError, associations.inspect - end - end - - def construct_association(record, join_part, row) - return if record.id.to_s != join_part.parent.record_id(row).to_s - - macro = join_part.reflection.macro - if macro == :has_one - return if record.instance_variable_defined?("@#{join_part.reflection.name}") - association = join_part.instantiate(row) unless row[join_part.aliased_primary_key].nil? - set_target_and_inverse(join_part, association, record) - else - return if row[join_part.aliased_primary_key].nil? - association = join_part.instantiate(row) - case macro - when :has_many, :has_and_belongs_to_many - collection = record.send(join_part.reflection.name) - collection.loaded - collection.target.push(association) - collection.__send__(:set_inverse_instance, association, record) - when :belongs_to - set_target_and_inverse(join_part, association, record) - else - raise ConfigurationError, "unknown macro: #{join_part.reflection.macro}" - end - end - association - end - - def set_target_and_inverse(join_part, association, record) - association_proxy = record.send("set_#{join_part.reflection.name}_target", association) - association_proxy.__send__(:set_inverse_instance, association, record) - end - - # A JoinPart represents a part of a JoinDependency. It is an abstract class, inherited - # by JoinBase and JoinAssociation. A JoinBase represents the Active Record which - # everything else is being joined onto. A JoinAssociation represents an association which - # is joining to the base. A JoinAssociation may result in more than one actual join - # operations (for example a has_and_belongs_to_many JoinAssociation would result in - # two; one for the join table and one for the target table). - class JoinPart # :nodoc: - # The Active Record class which this join part is associated 'about'; for a JoinBase - # this is the actual base model, for a JoinAssociation this is the target model of the - # association. - attr_reader :active_record - - delegate :table_name, :column_names, :primary_key, :reflections, :sanitize_sql, :arel_engine, :to => :active_record - - def initialize(active_record) - @active_record = active_record - @cached_record = {} - end - - def ==(other) - raise NotImplementedError - end - - # An Arel::Table for the active_record - def table - raise NotImplementedError - end - - # The prefix to be used when aliasing columns in the active_record's table - def aliased_prefix - raise NotImplementedError - end - - # The alias for the active_record's table - def aliased_table_name - raise NotImplementedError - end - - # The alias for the primary key of the active_record's table - def aliased_primary_key - "#{aliased_prefix}_r0" - end - - # An array of [column_name, alias] pairs for the table - def column_names_with_alias - unless defined?(@column_names_with_alias) - @column_names_with_alias = [] - - ([primary_key] + (column_names - [primary_key])).each_with_index do |column_name, i| - @column_names_with_alias << [column_name, "#{aliased_prefix}_r#{i}"] - end - end - - @column_names_with_alias - end - - def extract_record(row) - Hash[column_names_with_alias.map{|cn, an| [cn, row[an]]}] - end - - def record_id(row) - row[aliased_primary_key] - end - - def instantiate(row) - @cached_record[record_id(row)] ||= active_record.send(:instantiate, extract_record(row)) - end - end - - class JoinBase < JoinPart # :nodoc: - # Extra joins provided when the JoinDependency was created - attr_reader :table_joins - - def initialize(active_record, joins = nil) - super(active_record) - @table_joins = joins - end - - def ==(other) - other.class == self.class && - other.active_record == active_record - end - - def aliased_prefix - "t0" - end - - def table - Arel::Table.new(table_name, :engine => arel_engine, :columns => active_record.columns) - end - - def aliased_table_name - active_record.table_name - end - end - - class JoinAssociation < JoinPart # :nodoc: - # The reflection of the association represented - attr_reader :reflection - - # The JoinDependency object which this JoinAssociation exists within. This is mainly - # relevant for generating aliases which do not conflict with other joins which are - # part of the query. - attr_reader :join_dependency - - # A JoinBase instance representing the active record we are joining onto. - # (So in Author.has_many :posts, the Author would be that base record.) - attr_reader :parent - - # What type of join will be generated, either Arel::InnerJoin (default) or Arel::OuterJoin - attr_accessor :join_type - - # These implement abstract methods from the superclass - attr_reader :aliased_prefix, :aliased_table_name - - delegate :options, :through_reflection, :source_reflection, :to => :reflection - delegate :table, :table_name, :to => :parent, :prefix => true - - def initialize(reflection, join_dependency, parent = nil) - reflection.check_validity! - - if reflection.options[:polymorphic] - raise EagerLoadPolymorphicError.new(reflection) - end - - super(reflection.klass) - - @reflection = reflection - @join_dependency = join_dependency - @parent = parent - @join_type = Arel::InnerJoin - - # This must be done eagerly upon initialisation because the alias which is produced - # depends on the state of the join dependency, but we want it to work the same way - # every time. - allocate_aliases - end - - def ==(other) - other.class == self.class && - other.reflection == reflection && - other.parent == parent - end - - def find_parent_in(other_join_dependency) - other_join_dependency.join_parts.detect do |join_part| - self.parent == join_part - end - end - - def join_to(relation) - send("join_#{reflection.macro}_to", relation) - end - - def join_relation(joining_relation) - self.join_type = Arel::OuterJoin - joining_relation.joins(self) - end - - def table - @table ||= Arel::Table.new( - table_name, :as => aliased_table_name, - :engine => arel_engine, :columns => active_record.columns - ) - end - - # More semantic name given we are talking about associations - alias_method :target_table, :table - - protected - - def aliased_table_name_for(name, suffix = nil) - if @join_dependency.table_aliases[name].zero? - @join_dependency.table_aliases[name] = @join_dependency.count_aliases_from_table_joins(name) - end - - if !@join_dependency.table_aliases[name].zero? # We need an alias - name = active_record.connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}#{suffix}" - @join_dependency.table_aliases[name] += 1 - if @join_dependency.table_aliases[name] == 1 # First time we've seen this name - # Also need to count the aliases from the table_aliases to avoid incorrect count - @join_dependency.table_aliases[name] += @join_dependency.count_aliases_from_table_joins(name) - end - table_index = @join_dependency.table_aliases[name] - name = name[0..active_record.connection.table_alias_length-3] + "_#{table_index}" if table_index > 1 - else - @join_dependency.table_aliases[name] += 1 - end - - name - end - - def pluralize(table_name) - ActiveRecord::Base.pluralize_table_names ? table_name.to_s.pluralize : table_name - end - - def interpolate_sql(sql) - instance_eval("%@#{sql.gsub('@', '\@')}@", __FILE__, __LINE__) - end - - private - - def allocate_aliases - @aliased_prefix = "t#{ join_dependency.join_parts.size }" - @aliased_table_name = aliased_table_name_for(table_name) - - if reflection.macro == :has_and_belongs_to_many - @aliased_join_table_name = aliased_table_name_for(reflection.options[:join_table], "_join") - elsif [:has_many, :has_one].include?(reflection.macro) && reflection.options[:through] - @aliased_join_table_name = aliased_table_name_for(reflection.through_reflection.klass.table_name, "_join") - end - end - - def process_conditions(conditions, table_name) - Arel.sql(interpolate_sql(sanitize_sql(conditions, table_name))) - end - - def join_target_table(relation, *conditions) - relation = relation.join(target_table, join_type) - - # If the target table is an STI model then we must be sure to only include records of - # its type and its sub-types. - unless active_record.descends_from_active_record? - sti_column = target_table[active_record.inheritance_column] - - sti_condition = sti_column.eq(active_record.sti_name) - active_record.descendants.each do |subclass| - sti_condition = sti_condition.or(sti_column.eq(subclass.sti_name)) - end - - conditions << sti_condition - end - - # If the reflection has conditions, add them - if options[:conditions] - conditions << process_conditions(options[:conditions], aliased_table_name) - end - - relation = relation.on(*conditions) - end - - def join_has_and_belongs_to_many_to(relation) - join_table = Arel::Table.new( - options[:join_table], :engine => arel_engine, - :as => @aliased_join_table_name - ) - - fk = options[:foreign_key] || reflection.active_record.to_s.foreign_key - klass_fk = options[:association_foreign_key] || reflection.klass.to_s.foreign_key - - relation = relation.join(join_table, join_type) - relation = relation.on( - join_table[fk]. - eq(parent_table[reflection.active_record.primary_key]) - ) - - join_target_table( - relation, - target_table[reflection.klass.primary_key]. - eq(join_table[klass_fk]) - ) - end - - def join_has_many_to(relation) - if reflection.options[:through] - join_has_many_through_to(relation) - elsif reflection.options[:as] - join_has_many_polymorphic_to(relation) - else - foreign_key = options[:foreign_key] || reflection.active_record.name.foreign_key - primary_key = options[:primary_key] || parent.primary_key - - join_target_table( - relation, - target_table[foreign_key]. - eq(parent_table[primary_key]) - ) - end - end - alias :join_has_one_to :join_has_many_to - - def join_has_many_through_to(relation) - join_table = Arel::Table.new( - through_reflection.klass.table_name, :engine => arel_engine, - :as => @aliased_join_table_name - ) - - jt_conditions = [] - jt_foreign_key = first_key = second_key = nil - - if through_reflection.options[:as] # has_many :through against a polymorphic join - as_key = through_reflection.options[:as].to_s - jt_foreign_key = as_key + '_id' - - jt_conditions << - join_table[as_key + '_type']. - eq(parent.active_record.base_class.name) - else - jt_foreign_key = through_reflection.primary_key_name - end - - case source_reflection.macro - when :has_many - second_key = options[:foreign_key] || primary_key - - if source_reflection.options[:as] - first_key = "#{source_reflection.options[:as]}_id" - else - first_key = through_reflection.klass.base_class.to_s.foreign_key - end - - unless through_reflection.klass.descends_from_active_record? - jt_conditions << - join_table[through_reflection.active_record.inheritance_column]. - eq(through_reflection.klass.sti_name) - end - when :belongs_to - first_key = primary_key - - if reflection.options[:source_type] - second_key = source_reflection.association_foreign_key - - jt_conditions << - join_table[reflection.source_reflection.options[:foreign_type]]. - eq(reflection.options[:source_type]) - else - second_key = source_reflection.primary_key_name - end - end - - jt_conditions << - parent_table[parent.primary_key]. - eq(join_table[jt_foreign_key]) - - if through_reflection.options[:conditions] - jt_conditions << process_conditions(through_reflection.options[:conditions], aliased_table_name) - end - - relation = relation.join(join_table, join_type).on(*jt_conditions) - - join_target_table( - relation, - target_table[first_key].eq(join_table[second_key]) - ) - end - - def join_has_many_polymorphic_to(relation) - join_target_table( - relation, - target_table["#{reflection.options[:as]}_id"]. - eq(parent_table[parent.primary_key]), - target_table["#{reflection.options[:as]}_type"]. - eq(parent.active_record.base_class.name) - ) - end - - def join_belongs_to_to(relation) - foreign_key = options[:foreign_key] || reflection.primary_key_name - primary_key = options[:primary_key] || reflection.klass.primary_key - - join_target_table( - relation, - target_table[primary_key].eq(parent_table[foreign_key]) - ) - end - end - end end end end diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb new file mode 100644 index 0000000000..79fdb2d4cb --- /dev/null +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -0,0 +1,216 @@ +require 'active_record/associations/class_methods/join_dependency/join_part' +require 'active_record/associations/class_methods/join_dependency/join_base' +require 'active_record/associations/class_methods/join_dependency/join_association' + +module ActiveRecord + module Associations + module ClassMethods + class JoinDependency # :nodoc: + attr_reader :join_parts, :reflections, :table_aliases + + def initialize(base, associations, joins) + @join_parts = [JoinBase.new(base, joins)] + @associations = {} + @reflections = [] + @table_aliases = Hash.new(0) + @table_aliases[base.table_name] = 1 + build(associations) + end + + def graft(*associations) + associations.each do |association| + join_associations.detect {|a| association == a} || + build(association.reflection.name, association.find_parent_in(self) || join_base, association.join_type) + end + self + end + + def join_associations + join_parts.last(join_parts.length - 1) + end + + def join_base + join_parts.first + end + + def count_aliases_from_table_joins(name) + # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase + quoted_name = join_base.active_record.connection.quote_table_name(name.downcase).downcase + join_sql = join_base.table_joins.to_s.downcase + join_sql.blank? ? 0 : + # Table names + join_sql.scan(/join(?:\s+\w+)?\s+#{quoted_name}\son/).size + + # Table aliases + join_sql.scan(/join(?:\s+\w+)?\s+\S+\s+#{quoted_name}\son/).size + end + + def instantiate(rows) + primary_key = join_base.aliased_primary_key + parents = {} + + records = rows.map { |model| + primary_id = model[primary_key] + parent = parents[primary_id] ||= join_base.instantiate(model) + construct(parent, @associations, join_associations.dup, model) + parent + }.uniq + + remove_duplicate_results!(join_base.active_record, records, @associations) + records + end + + def remove_duplicate_results!(base, records, associations) + case associations + when Symbol, String + reflection = base.reflections[associations] + remove_uniq_by_reflection(reflection, records) + when Array + associations.each do |association| + remove_duplicate_results!(base, records, association) + end + when Hash + associations.keys.each do |name| + reflection = base.reflections[name] + remove_uniq_by_reflection(reflection, records) + + parent_records = [] + records.each do |record| + if descendant = record.send(reflection.name) + if reflection.collection? + parent_records.concat descendant.target.uniq + else + parent_records << descendant + end + end + end + + remove_duplicate_results!(reflection.klass, parent_records, associations[name]) unless parent_records.empty? + end + end + end + + protected + + def cache_joined_association(association) + associations = [] + parent = association.parent + while parent != join_base + associations.unshift(parent.reflection.name) + parent = parent.parent + end + ref = @associations + associations.each do |key| + ref = ref[key] + end + ref[association.reflection.name] ||= {} + end + + def build(associations, parent = nil, join_type = Arel::InnerJoin) + parent ||= join_parts.last + case associations + when Symbol, String + reflection = parent.reflections[associations.to_s.intern] or + raise ConfigurationError, "Association named '#{ associations }' was not found; perhaps you misspelled it?" + unless join_association = find_join_association(reflection, parent) + @reflections << reflection + join_association = build_join_association(reflection, parent) + join_association.join_type = join_type + @join_parts << join_association + cache_joined_association(join_association) + end + join_association + when Array + associations.each do |association| + build(association, parent, join_type) + end + when Hash + associations.keys.sort{|a,b|a.to_s<=>b.to_s}.each do |name| + join_association = build(name, parent, join_type) + build(associations[name], join_association, join_type) + end + else + raise ConfigurationError, associations.inspect + end + end + + def find_join_association(name_or_reflection, parent) + if String === name_or_reflection + name_or_reflection = name_or_reflection.to_sym + end + + join_associations.detect { |j| + j.reflection == name_or_reflection && j.parent == parent + } + end + + def remove_uniq_by_reflection(reflection, records) + if reflection && reflection.collection? + records.each { |record| record.send(reflection.name).target.uniq! } + end + end + + def build_join_association(reflection, parent) + JoinAssociation.new(reflection, self, parent) + end + + def construct(parent, associations, join_parts, row) + case associations + when Symbol, String + name = associations.to_s + + join_part = join_parts.detect { |j| + j.reflection.name.to_s == name && + j.parent_table_name == parent.class.table_name } + + raise(ConfigurationError, "No such association") unless join_part + + join_parts.delete(join_part) + construct_association(parent, join_part, row) + when Array + associations.each do |association| + construct(parent, association, join_parts, row) + end + when Hash + associations.sort_by { |k,_| k.to_s }.each do |name, assoc| + association = construct(parent, name, join_parts, row) + construct(association, assoc, join_parts, row) if association + end + else + raise ConfigurationError, associations.inspect + end + end + + def construct_association(record, join_part, row) + return if record.id.to_s != join_part.parent.record_id(row).to_s + + macro = join_part.reflection.macro + if macro == :has_one + return if record.instance_variable_defined?("@#{join_part.reflection.name}") + association = join_part.instantiate(row) unless row[join_part.aliased_primary_key].nil? + set_target_and_inverse(join_part, association, record) + else + return if row[join_part.aliased_primary_key].nil? + association = join_part.instantiate(row) + case macro + when :has_many, :has_and_belongs_to_many + collection = record.send(join_part.reflection.name) + collection.loaded + collection.target.push(association) + collection.__send__(:set_inverse_instance, association, record) + when :belongs_to + set_target_and_inverse(join_part, association, record) + else + raise ConfigurationError, "unknown macro: #{join_part.reflection.macro}" + end + end + association + end + + def set_target_and_inverse(join_part, association, record) + association_proxy = record.send("set_#{join_part.reflection.name}_target", association) + association_proxy.__send__(:set_inverse_instance, association, record) + end + end + end + end +end diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb new file mode 100644 index 0000000000..5e5c01c77a --- /dev/null +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -0,0 +1,278 @@ +module ActiveRecord + module Associations + module ClassMethods + class JoinDependency # :nodoc: + class JoinAssociation < JoinPart # :nodoc: + # The reflection of the association represented + attr_reader :reflection + + # The JoinDependency object which this JoinAssociation exists within. This is mainly + # relevant for generating aliases which do not conflict with other joins which are + # part of the query. + attr_reader :join_dependency + + # A JoinBase instance representing the active record we are joining onto. + # (So in Author.has_many :posts, the Author would be that base record.) + attr_reader :parent + + # What type of join will be generated, either Arel::InnerJoin (default) or Arel::OuterJoin + attr_accessor :join_type + + # These implement abstract methods from the superclass + attr_reader :aliased_prefix, :aliased_table_name + + delegate :options, :through_reflection, :source_reflection, :to => :reflection + delegate :table, :table_name, :to => :parent, :prefix => true + + def initialize(reflection, join_dependency, parent = nil) + reflection.check_validity! + + if reflection.options[:polymorphic] + raise EagerLoadPolymorphicError.new(reflection) + end + + super(reflection.klass) + + @reflection = reflection + @join_dependency = join_dependency + @parent = parent + @join_type = Arel::InnerJoin + + # This must be done eagerly upon initialisation because the alias which is produced + # depends on the state of the join dependency, but we want it to work the same way + # every time. + allocate_aliases + end + + def ==(other) + other.class == self.class && + other.reflection == reflection && + other.parent == parent + end + + def find_parent_in(other_join_dependency) + other_join_dependency.join_parts.detect do |join_part| + self.parent == join_part + end + end + + def join_to(relation) + send("join_#{reflection.macro}_to", relation) + end + + def join_relation(joining_relation) + self.join_type = Arel::OuterJoin + joining_relation.joins(self) + end + + def table + @table ||= Arel::Table.new( + table_name, :as => aliased_table_name, + :engine => arel_engine, :columns => active_record.columns + ) + end + + # More semantic name given we are talking about associations + alias_method :target_table, :table + + protected + + def aliased_table_name_for(name, suffix = nil) + if @join_dependency.table_aliases[name].zero? + @join_dependency.table_aliases[name] = @join_dependency.count_aliases_from_table_joins(name) + end + + if !@join_dependency.table_aliases[name].zero? # We need an alias + name = active_record.connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}#{suffix}" + @join_dependency.table_aliases[name] += 1 + if @join_dependency.table_aliases[name] == 1 # First time we've seen this name + # Also need to count the aliases from the table_aliases to avoid incorrect count + @join_dependency.table_aliases[name] += @join_dependency.count_aliases_from_table_joins(name) + end + table_index = @join_dependency.table_aliases[name] + name = name[0..active_record.connection.table_alias_length-3] + "_#{table_index}" if table_index > 1 + else + @join_dependency.table_aliases[name] += 1 + end + + name + end + + def pluralize(table_name) + ActiveRecord::Base.pluralize_table_names ? table_name.to_s.pluralize : table_name + end + + def interpolate_sql(sql) + instance_eval("%@#{sql.gsub('@', '\@')}@", __FILE__, __LINE__) + end + + private + + def allocate_aliases + @aliased_prefix = "t#{ join_dependency.join_parts.size }" + @aliased_table_name = aliased_table_name_for(table_name) + + if reflection.macro == :has_and_belongs_to_many + @aliased_join_table_name = aliased_table_name_for(reflection.options[:join_table], "_join") + elsif [:has_many, :has_one].include?(reflection.macro) && reflection.options[:through] + @aliased_join_table_name = aliased_table_name_for(reflection.through_reflection.klass.table_name, "_join") + end + end + + def process_conditions(conditions, table_name) + Arel.sql(interpolate_sql(sanitize_sql(conditions, table_name))) + end + + def join_target_table(relation, *conditions) + relation = relation.join(target_table, join_type) + + # If the target table is an STI model then we must be sure to only include records of + # its type and its sub-types. + unless active_record.descends_from_active_record? + sti_column = target_table[active_record.inheritance_column] + + sti_condition = sti_column.eq(active_record.sti_name) + active_record.descendants.each do |subclass| + sti_condition = sti_condition.or(sti_column.eq(subclass.sti_name)) + end + + conditions << sti_condition + end + + # If the reflection has conditions, add them + if options[:conditions] + conditions << process_conditions(options[:conditions], aliased_table_name) + end + + relation = relation.on(*conditions) + end + + def join_has_and_belongs_to_many_to(relation) + join_table = Arel::Table.new( + options[:join_table], :engine => arel_engine, + :as => @aliased_join_table_name + ) + + fk = options[:foreign_key] || reflection.active_record.to_s.foreign_key + klass_fk = options[:association_foreign_key] || reflection.klass.to_s.foreign_key + + relation = relation.join(join_table, join_type) + relation = relation.on( + join_table[fk]. + eq(parent_table[reflection.active_record.primary_key]) + ) + + join_target_table( + relation, + target_table[reflection.klass.primary_key]. + eq(join_table[klass_fk]) + ) + end + + def join_has_many_to(relation) + if reflection.options[:through] + join_has_many_through_to(relation) + elsif reflection.options[:as] + join_has_many_polymorphic_to(relation) + else + foreign_key = options[:foreign_key] || reflection.active_record.name.foreign_key + primary_key = options[:primary_key] || parent.primary_key + + join_target_table( + relation, + target_table[foreign_key]. + eq(parent_table[primary_key]) + ) + end + end + alias :join_has_one_to :join_has_many_to + + def join_has_many_through_to(relation) + join_table = Arel::Table.new( + through_reflection.klass.table_name, :engine => arel_engine, + :as => @aliased_join_table_name + ) + + jt_conditions = [] + jt_foreign_key = first_key = second_key = nil + + if through_reflection.options[:as] # has_many :through against a polymorphic join + as_key = through_reflection.options[:as].to_s + jt_foreign_key = as_key + '_id' + + jt_conditions << + join_table[as_key + '_type']. + eq(parent.active_record.base_class.name) + else + jt_foreign_key = through_reflection.primary_key_name + end + + case source_reflection.macro + when :has_many + second_key = options[:foreign_key] || primary_key + + if source_reflection.options[:as] + first_key = "#{source_reflection.options[:as]}_id" + else + first_key = through_reflection.klass.base_class.to_s.foreign_key + end + + unless through_reflection.klass.descends_from_active_record? + jt_conditions << + join_table[through_reflection.active_record.inheritance_column]. + eq(through_reflection.klass.sti_name) + end + when :belongs_to + first_key = primary_key + + if reflection.options[:source_type] + second_key = source_reflection.association_foreign_key + + jt_conditions << + join_table[reflection.source_reflection.options[:foreign_type]]. + eq(reflection.options[:source_type]) + else + second_key = source_reflection.primary_key_name + end + end + + jt_conditions << + parent_table[parent.primary_key]. + eq(join_table[jt_foreign_key]) + + if through_reflection.options[:conditions] + jt_conditions << process_conditions(through_reflection.options[:conditions], aliased_table_name) + end + + relation = relation.join(join_table, join_type).on(*jt_conditions) + + join_target_table( + relation, + target_table[first_key].eq(join_table[second_key]) + ) + end + + def join_has_many_polymorphic_to(relation) + join_target_table( + relation, + target_table["#{reflection.options[:as]}_id"]. + eq(parent_table[parent.primary_key]), + target_table["#{reflection.options[:as]}_type"]. + eq(parent.active_record.base_class.name) + ) + end + + def join_belongs_to_to(relation) + foreign_key = options[:foreign_key] || reflection.primary_key_name + primary_key = options[:primary_key] || reflection.klass.primary_key + + join_target_table( + relation, + target_table[primary_key].eq(parent_table[foreign_key]) + ) + end + end + end + end + end +end diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_base.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_base.rb new file mode 100644 index 0000000000..ed05003f66 --- /dev/null +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_base.rb @@ -0,0 +1,34 @@ +module ActiveRecord + module Associations + module ClassMethods + class JoinDependency # :nodoc: + class JoinBase < JoinPart # :nodoc: + # Extra joins provided when the JoinDependency was created + attr_reader :table_joins + + def initialize(active_record, joins = nil) + super(active_record) + @table_joins = joins + end + + def ==(other) + other.class == self.class && + other.active_record == active_record + end + + def aliased_prefix + "t0" + end + + def table + Arel::Table.new(table_name, :engine => arel_engine, :columns => active_record.columns) + end + + def aliased_table_name + active_record.table_name + end + end + end + end + end +end diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_part.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_part.rb new file mode 100644 index 0000000000..64d751344d --- /dev/null +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_part.rb @@ -0,0 +1,76 @@ +module ActiveRecord + module Associations + module ClassMethods + class JoinDependency # :nodoc: + # A JoinPart represents a part of a JoinDependency. It is an abstract class, inherited + # by JoinBase and JoinAssociation. A JoinBase represents the Active Record which + # everything else is being joined onto. A JoinAssociation represents an association which + # is joining to the base. A JoinAssociation may result in more than one actual join + # operations (for example a has_and_belongs_to_many JoinAssociation would result in + # two; one for the join table and one for the target table). + class JoinPart # :nodoc: + # The Active Record class which this join part is associated 'about'; for a JoinBase + # this is the actual base model, for a JoinAssociation this is the target model of the + # association. + attr_reader :active_record + + delegate :table_name, :column_names, :primary_key, :reflections, :sanitize_sql, :arel_engine, :to => :active_record + + def initialize(active_record) + @active_record = active_record + @cached_record = {} + end + + def ==(other) + raise NotImplementedError + end + + # An Arel::Table for the active_record + def table + raise NotImplementedError + end + + # The prefix to be used when aliasing columns in the active_record's table + def aliased_prefix + raise NotImplementedError + end + + # The alias for the active_record's table + def aliased_table_name + raise NotImplementedError + end + + # The alias for the primary key of the active_record's table + def aliased_primary_key + "#{aliased_prefix}_r0" + end + + # An array of [column_name, alias] pairs for the table + def column_names_with_alias + unless defined?(@column_names_with_alias) + @column_names_with_alias = [] + + ([primary_key] + (column_names - [primary_key])).each_with_index do |column_name, i| + @column_names_with_alias << [column_name, "#{aliased_prefix}_r#{i}"] + end + end + + @column_names_with_alias + end + + def extract_record(row) + Hash[column_names_with_alias.map{|cn, an| [cn, row[an]]}] + end + + def record_id(row) + row[aliased_primary_key] + end + + def instantiate(row) + @cached_record[record_id(row)] ||= active_record.send(:instantiate, extract_record(row)) + end + end + end + end + end +end -- cgit v1.2.3 From 0687b21de879d53157e52a2b688e34a1bd1e31f0 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Nov 2010 17:52:51 -0800 Subject: removing ternary --- activerecord/lib/active_record/associations/has_many_association.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 23831e0b08..156279a67a 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -42,7 +42,7 @@ module ActiveRecord # documented side-effect of the method that may avoid an extra SELECT. @target ||= [] and loaded if count == 0 - @reflection.options[:limit] ? [@reflection.options[:limit], count].min : count + [@reflection.options[:limit], count].compact.min end def has_cached_counter? -- cgit v1.2.3 From c17cb7326d6af7c4226e955abd3f89db95fabb33 Mon Sep 17 00:00:00 2001 From: Franck Verrot Date: Wed, 24 Nov 2010 16:32:41 +0800 Subject: Dup should reset the timestamps as it is considered a new record --- activerecord/lib/active_record/base.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index d2fa3bed35..49b30f4779 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1625,6 +1625,7 @@ MSG ensure_proper_type populate_with_current_scope_attributes + clear_timestamp_attributes end # Returns +true+ if the record is read only. Records loaded through joins with piggy-back @@ -1831,6 +1832,16 @@ MSG create_with.each { |att,value| self.respond_to?(:"#{att}=") && self.send("#{att}=", value) } if create_with end end + + # Clear attributes and changged_attributes + def clear_timestamp_attributes + %w(created_at created_on updated_at updated_on).each do |attribute_name| + if self.has_attribute?(attribute_name) + self[attribute_name] = nil + self.changed_attributes.delete(attribute_name) + end + end + end end Base.class_eval do -- cgit v1.2.3 From 7b77a1fc71e54f6e42e97b426380303d696051c0 Mon Sep 17 00:00:00 2001 From: Franck Verrot Date: Thu, 25 Nov 2010 02:53:28 +0800 Subject: Typo in the comments of the clear_timestamp_attributes 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 49b30f4779..1e0fd7c6fd 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1833,7 +1833,7 @@ MSG end end - # Clear attributes and changged_attributes + # Clear attributes and changed_attributes def clear_timestamp_attributes %w(created_at created_on updated_at updated_on).each do |attribute_name| if self.has_attribute?(attribute_name) -- cgit v1.2.3 From 7f8ce38b0d294b5c5d38116f8de63f175f446bd4 Mon Sep 17 00:00:00 2001 From: Franck Verrot Date: Thu, 25 Nov 2010 02:54:59 +0800 Subject: Document the behavior of the dup method: does not preserve timestamps --- 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 1e0fd7c6fd..b7aac7a7c9 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1605,6 +1605,7 @@ MSG # only, not its associations. The extent of a "deep" copy is application # specific and is therefore left to the application to implement according # to its need. + # The dup method does not preserve the timestamps (created|updated)_(at|on). def initialize_dup(other) cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast) cloned_attributes.delete(self.class.primary_key) -- cgit v1.2.3 From 66212f69acc3d51af10ff76a18ff4c0bfa305ea5 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Thu, 11 Nov 2010 11:41:15 -0500 Subject: If a nested_attribute is being marked for destruction and at the same time an attr_accessor value is being assigned then the value being assigned is being ignored. This patch is a fix for that issue. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [#5939 state:resolved] Signed-off-by: José Valim --- activerecord/lib/active_record/nested_attributes.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 15f83a8579..050b521b6a 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -417,11 +417,8 @@ module ActiveRecord # Updates a record with the +attributes+ or marks it for destruction if # +allow_destroy+ is +true+ and has_destroy_flag? returns +true+. def assign_to_or_mark_for_destruction(record, attributes, allow_destroy) - if has_destroy_flag?(attributes) && allow_destroy - record.mark_for_destruction - else - record.attributes = attributes.except(*UNASSIGNABLE_KEYS) - end + record.attributes = attributes.except(*UNASSIGNABLE_KEYS) + record.mark_for_destruction if has_destroy_flag?(attributes) && allow_destroy end # Determines if a hash contains a truthy _destroy key. -- cgit v1.2.3 From a3ba60fd814a980cc929fcbe0f9d48fa4d0292e5 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Nov 2010 18:08:23 -0800 Subject: reduce method calls --- activerecord/lib/active_record/associations/has_many_association.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 156279a67a..685d818ab3 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -108,7 +108,7 @@ module ActiveRecord end def we_can_set_the_inverse_on_this?(record) - !@reflection.inverse_of.nil? + @reflection.inverse_of end end end -- cgit v1.2.3 From d4b8d3bafa54e233d3f1ef43c43bfb460d9f2435 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 24 Nov 2010 13:29:18 -0800 Subject: moving column_aliases to JoinDependency --- .../associations/class_methods/join_dependency.rb | 8 ++++++++ activerecord/lib/active_record/relation/finder_methods.rb | 11 +---------- 2 files changed, 9 insertions(+), 10 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index 79fdb2d4cb..87541e0529 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -33,6 +33,14 @@ module ActiveRecord join_parts.first end + def columns(connection) + join_parts.collect { |join_part| + join_part.column_names_with_alias.collect{ |column_name, aliased_name| + "#{connection.quote_table_name join_part.aliased_table_name}.#{connection.quote_column_name column_name} AS #{aliased_name}" + } + }.flatten.join(", ") + end + def count_aliases_from_table_joins(name) # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase quoted_name = join_base.active_record.connection.quote_table_name(name.downcase).downcase diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 4192456447..74ec83091c 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -202,7 +202,7 @@ module ActiveRecord end def construct_relation_for_association_find(join_dependency) - relation = except(:includes, :eager_load, :preload, :select).select(column_aliases(join_dependency)) + relation = except(:includes, :eager_load, :preload, :select).select(join_dependency.columns(connection)) apply_join_dependency(relation, join_dependency) end @@ -349,17 +349,8 @@ module ActiveRecord end end - def column_aliases(join_dependency) - join_dependency.join_parts.collect { |join_part| - join_part.column_names_with_alias.collect{ |column_name, aliased_name| - "#{connection.quote_table_name join_part.aliased_table_name}.#{connection.quote_column_name column_name} AS #{aliased_name}" - } - }.flatten.join(", ") - end - def using_limitable_reflections?(reflections) reflections.none? { |r| r.collection? } end - end end -- cgit v1.2.3 From afe51afcc6b7c0245fddbd879d369818b54e460a Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 24 Nov 2010 13:32:01 -0800 Subject: remove useless join --- .../lib/active_record/associations/class_methods/join_dependency.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index 87541e0529..7c7fa964f8 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -38,7 +38,7 @@ module ActiveRecord join_part.column_names_with_alias.collect{ |column_name, aliased_name| "#{connection.quote_table_name join_part.aliased_table_name}.#{connection.quote_column_name column_name} AS #{aliased_name}" } - }.flatten.join(", ") + }.flatten end def count_aliases_from_table_joins(name) -- cgit v1.2.3 From cdf6cf01cb47bdcbc1e011c8f5f72b161f12bf9c Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 24 Nov 2010 13:40:23 -0800 Subject: use ARel rather than generate SQL strings --- .../lib/active_record/associations/class_methods/join_dependency.rb | 5 +++-- activerecord/lib/active_record/relation/finder_methods.rb | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index 7c7fa964f8..b1521b3706 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -33,10 +33,11 @@ module ActiveRecord join_parts.first end - def columns(connection) + def columns join_parts.collect { |join_part| + table = Arel::Nodes::TableAlias.new join_part.aliased_table_name, nil join_part.column_names_with_alias.collect{ |column_name, aliased_name| - "#{connection.quote_table_name join_part.aliased_table_name}.#{connection.quote_column_name column_name} AS #{aliased_name}" + table[column_name].as aliased_name } }.flatten end diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 74ec83091c..23ae0b4325 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -202,7 +202,7 @@ module ActiveRecord end def construct_relation_for_association_find(join_dependency) - relation = except(:includes, :eager_load, :preload, :select).select(join_dependency.columns(connection)) + relation = except(:includes, :eager_load, :preload, :select).select(join_dependency.columns) apply_join_dependency(relation, join_dependency) end -- cgit v1.2.3 From 34d21b87bb237bf55214bd476be71116a2a5258f Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 24 Nov 2010 13:53:55 -0800 Subject: adding a factory method to the join part for generating a table alias --- .../lib/active_record/associations/class_methods/join_dependency.rb | 2 +- .../associations/class_methods/join_dependency/join_part.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index b1521b3706..19d2d55ca0 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -35,7 +35,7 @@ module ActiveRecord def columns join_parts.collect { |join_part| - table = Arel::Nodes::TableAlias.new join_part.aliased_table_name, nil + table = join_part.aliased_table join_part.column_names_with_alias.collect{ |column_name, aliased_name| table[column_name].as aliased_name } diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_part.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_part.rb index 64d751344d..5d55ca202e 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_part.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_part.rb @@ -21,6 +21,10 @@ module ActiveRecord @cached_record = {} end + def aliased_table + Arel::Nodes::TableAlias.new aliased_table_name, table + end + def ==(other) raise NotImplementedError end -- cgit v1.2.3 From 38eb01863c9281d142c6494bae485b9c215ec9b7 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 24 Nov 2010 14:11:12 -0800 Subject: initialize instance variables in initialize... o_O --- .../associations/class_methods/join_dependency/join_part.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_part.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_part.rb index 5d55ca202e..0b093b65e9 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_part.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_part.rb @@ -19,6 +19,7 @@ module ActiveRecord def initialize(active_record) @active_record = active_record @cached_record = {} + @column_names_with_alias = nil end def aliased_table @@ -51,14 +52,13 @@ module ActiveRecord # An array of [column_name, alias] pairs for the table def column_names_with_alias - unless defined?(@column_names_with_alias) + unless @column_names_with_alias @column_names_with_alias = [] ([primary_key] + (column_names - [primary_key])).each_with_index do |column_name, i| @column_names_with_alias << [column_name, "#{aliased_prefix}_r#{i}"] end end - @column_names_with_alias end -- cgit v1.2.3 From ee74f2c6238dbaca00e9b667c3c239f3cae8aca5 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 24 Nov 2010 14:16:38 -0800 Subject: alias should be a SQL literal --- .../lib/active_record/associations/class_methods/join_dependency.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index 19d2d55ca0..6ab7bd0b06 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -37,7 +37,7 @@ module ActiveRecord join_parts.collect { |join_part| table = join_part.aliased_table join_part.column_names_with_alias.collect{ |column_name, aliased_name| - table[column_name].as aliased_name + table[column_name].as Arel.sql(aliased_name) } }.flatten end -- cgit v1.2.3 From d8692985feb4db9fe8d113549535b658fe6058e5 Mon Sep 17 00:00:00 2001 From: raggi Date: Thu, 25 Nov 2010 06:21:55 +0800 Subject: Don't depend on rubygems loading thread (for Mutex) --- .../lib/active_record/connection_adapters/abstract/connection_pool.rb | 1 + 1 file changed, 1 insertion(+) (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 ca9314ec99..cffa2387de 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -1,3 +1,4 @@ +require 'thread' require 'monitor' require 'set' require 'active_support/core_ext/module/synchronization' -- cgit v1.2.3 From c4d31d0f13783f3cfadbde666fd2a06996b456a2 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Thu, 25 Nov 2010 15:36:08 -0300 Subject: Reuse lock_col variable instead calling locking_column class method. Signed-off-by: Santiago Pastorino --- activerecord/lib/active_record/locking/optimistic.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb index 9e1a33a6bf..6503004e38 100644 --- a/activerecord/lib/active_record/locking/optimistic.rb +++ b/activerecord/lib/active_record/locking/optimistic.rb @@ -89,7 +89,7 @@ module ActiveRecord affected_rows = relation.where( relation.table[self.class.primary_key].eq(quoted_id).and( - relation.table[self.class.locking_column].eq(quote_value(previous_value)) + relation.table[lock_col].eq(quote_value(previous_value)) ) ).arel.update(arel_attributes_values(false, false, attribute_names)) @@ -111,8 +111,9 @@ module ActiveRecord if persisted? table = self.class.arel_table - predicate = table[self.class.primary_key].eq(id) - predicate = predicate.and(table[self.class.locking_column].eq(send(self.class.locking_column).to_i)) + lock_col = self.class.locking_column + predicate = table[self.class.primary_key].eq(id). + and(table[lock_col].eq(send(lock_col).to_i)) affected_rows = self.class.unscoped.where(predicate).delete_all -- cgit v1.2.3 From 1b6b80355c52cc97d96f6d747271ff43efebab0a Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Thu, 25 Nov 2010 16:01:41 -0300 Subject: Remove explicit return. Signed-off-by: Santiago Pastorino --- activerecord/lib/active_record/locking/optimistic.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb index 6503004e38..c0e1dda2bd 100644 --- a/activerecord/lib/active_record/locking/optimistic.rb +++ b/activerecord/lib/active_record/locking/optimistic.rb @@ -70,7 +70,7 @@ module ActiveRecord result[self.class.locking_column] ||= 0 end - return result + result end def update(attribute_names = @attributes.keys) #:nodoc: -- cgit v1.2.3 From ac6e9447e521a6ab2e3b60acd00a1ae2b863329e Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Thu, 25 Nov 2010 16:11:53 -0300 Subject: Remove return, we are already returning self. Signed-off-by: Santiago Pastorino --- .../lib/active_record/associations/association_collection.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index 774103342a..8a98c0fcbe 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -235,12 +235,12 @@ module ActiveRecord # Removes all records from this association. Returns +self+ so method calls may be chained. def clear - return self if length.zero? # forces load_target if it hasn't happened already - - if @reflection.options[:dependent] && @reflection.options[:dependent] == :destroy - destroy_all - else - delete_all + unless length.zero? # forces load_target if it hasn't happened already + if @reflection.options[:dependent] && @reflection.options[:dependent] == :destroy + destroy_all + else + delete_all + end end self -- cgit v1.2.3 From c91a13f8f557cc1d21fccb5f964d50438cd60a52 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Thu, 25 Nov 2010 16:12:30 -0300 Subject: Use ternary instead explicit return. Signed-off-by: Santiago Pastorino --- activerecord/lib/active_record/associations/association_collection.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index 8a98c0fcbe..e4e5ffd2b3 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -357,8 +357,7 @@ module ActiveRecord return false unless record.is_a?(@reflection.klass) return include_in_memory?(record) unless record.persisted? load_target if @reflection.options[:finder_sql] && !loaded? - return @target.include?(record) if loaded? - exists?(record) + loaded? ? @target.include?(record) : exists?(record) end def proxy_respond_to?(method, include_private = false) -- cgit v1.2.3 From a3bd62e1bae64569d0c2d45f8068f291e3e0e776 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Thu, 25 Nov 2010 16:12:57 -0300 Subject: Remove explicit return. Signed-off-by: Santiago Pastorino --- .../active_record/associations/has_and_belongs_to_many_association.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb index da742fa668..2c72fd0004 100644 --- a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb +++ b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb @@ -67,7 +67,7 @@ module ActiveRecord relation.insert(attributes) end - return true + true end def delete_records(records) @@ -80,7 +80,7 @@ module ActiveRecord ).delete end end - + def construct_joins "INNER JOIN #{@owner.connection.quote_table_name @reflection.options[:join_table]} ON #{@reflection.quoted_table_name}.#{@reflection.klass.primary_key} = #{@owner.connection.quote_table_name @reflection.options[:join_table]}.#{@reflection.association_foreign_key}" end -- cgit v1.2.3 From 438c0188f8aa07d0e9895a2c13886901ca40ed5e Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 25 Nov 2010 20:00:40 -0200 Subject: nil check unneeded ht. exviva --- activerecord/lib/active_record/associations/association_collection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index e4e5ffd2b3..ba9373ba6a 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -236,7 +236,7 @@ module ActiveRecord # Removes all records from this association. Returns +self+ so method calls may be chained. def clear unless length.zero? # forces load_target if it hasn't happened already - if @reflection.options[:dependent] && @reflection.options[:dependent] == :destroy + if @reflection.options[:dependent] == :destroy destroy_all else delete_all -- cgit v1.2.3 From 9332cc582ebaa9b6755fa7bdfe0bc04dd51c098d Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Fri, 26 Nov 2010 00:35:23 +0100 Subject: removes a couple of redundant selfs --- activerecord/lib/active_record/base.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index b7aac7a7c9..9b09b14c87 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1837,9 +1837,9 @@ MSG # Clear attributes and changed_attributes def clear_timestamp_attributes %w(created_at created_on updated_at updated_on).each do |attribute_name| - if self.has_attribute?(attribute_name) + if has_attribute?(attribute_name) self[attribute_name] = nil - self.changed_attributes.delete(attribute_name) + changed_attributes.delete(attribute_name) end end end -- cgit v1.2.3 From e444439fe28f873c783a4b99b1c9f29a7405dd0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 28 Nov 2010 16:55:48 +0100 Subject: Partialy revert f1c13b0dd7b22b5f6289ca1a09f1d7a8c7c8584b --- .../associations/association_collection.rb | 22 +++++++++++----------- .../associations/association_proxy.rb | 2 +- .../has_and_belongs_to_many_association.rb | 4 ++-- .../associations/has_many_through_association.rb | 4 ++-- .../associations/has_one_association.rb | 2 +- .../associations/has_one_through_association.rb | 2 +- .../lib/active_record/autosave_association.rb | 14 +++++++------- activerecord/lib/active_record/base.rb | 10 +++++----- activerecord/lib/active_record/persistence.rb | 10 +++++----- activerecord/lib/active_record/session_store.rb | 8 ++++---- activerecord/lib/active_record/transactions.rb | 15 ++++++++------- activerecord/lib/active_record/validations.rb | 2 +- 12 files changed, 48 insertions(+), 47 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index ba9373ba6a..abb17a11c6 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -121,13 +121,13 @@ module ActiveRecord # Since << flattens its argument list and inserts each record, +push+ and +concat+ behave identically. def <<(*records) result = true - load_target unless @owner.persisted? + load_target if @owner.new_record? transaction do flatten_deeper(records).each do |record| raise_on_type_mismatch(record) add_record_to_target_with_callbacks(record) do |r| - result &&= insert_record(record) if @owner.persisted? + result &&= insert_record(record) unless @owner.new_record? end end end @@ -286,12 +286,12 @@ module ActiveRecord # This method is abstract in the sense that it relies on # +count_records+, which is a method descendants have to provide. def size - if !@owner.persisted? || (loaded? && !@reflection.options[:uniq]) + if @owner.new_record? || (loaded? && !@reflection.options[:uniq]) @target.size elsif !loaded? && @reflection.options[:group] load_target.size elsif !loaded? && !@reflection.options[:uniq] && @target.is_a?(Array) - unsaved_records = @target.reject { |r| r.persisted? } + unsaved_records = @target.select { |r| r.new_record? } unsaved_records.size + count_records else count_records @@ -355,7 +355,7 @@ module ActiveRecord def include?(record) return false unless record.is_a?(@reflection.klass) - return include_in_memory?(record) unless record.persisted? + return include_in_memory?(record) if record.new_record? load_target if @reflection.options[:finder_sql] && !loaded? loaded? ? @target.include?(record) : exists?(record) end @@ -369,7 +369,7 @@ module ActiveRecord end def load_target - if @owner.persisted? || foreign_key_present + if !@owner.new_record? || foreign_key_present begin unless loaded? if @target.is_a?(Array) && @target.any? @@ -478,7 +478,7 @@ module ActiveRecord private def create_record(attrs) attrs.update(@reflection.options[:conditions]) if @reflection.options[:conditions].is_a?(Hash) - ensure_owner_is_not_new + ensure_owner_is_persisted! scoped_where = scoped.where_values_hash create_scope = scoped_where ? @scope[:create].merge(scoped_where) : @scope[:create] @@ -508,7 +508,7 @@ module ActiveRecord transaction do records.each { |record| callback(:before_remove, record) } - old_records = records.select { |r| r.persisted? } + old_records = records.reject { |r| r.new_record? } yield(records, old_records) records.each { |record| callback(:after_remove, record) } end @@ -532,15 +532,15 @@ module ActiveRecord @owner.class.send(full_callback_name.to_sym) || [] end - def ensure_owner_is_not_new + def ensure_owner_is_persisted! unless @owner.persisted? raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved" end end def fetch_first_or_last_using_find?(args) - (args.first.kind_of?(Hash) && !args.first.empty?) || !(loaded? || !@owner.persisted? || @reflection.options[:finder_sql] || - !@target.all? { |record| record.persisted? } || args.first.kind_of?(Integer)) + (args.first.kind_of?(Hash) && !args.first.empty?) || !(loaded? || @owner.new_record? || @reflection.options[:finder_sql] || + @target.any? { |record| record.new_record? } || args.first.kind_of?(Integer)) end def include_in_memory?(record) diff --git a/activerecord/lib/active_record/associations/association_proxy.rb b/activerecord/lib/active_record/associations/association_proxy.rb index 7cd04a1ad5..252ff7e7ea 100644 --- a/activerecord/lib/active_record/associations/association_proxy.rb +++ b/activerecord/lib/active_record/associations/association_proxy.rb @@ -252,7 +252,7 @@ module ActiveRecord def load_target return nil unless defined?(@loaded) - if !loaded? and (@owner.persisted? || foreign_key_present) + if !loaded? && (!@owner.new_record? || foreign_key_present) @target = find_target end diff --git a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb index 2c72fd0004..f6f291a039 100644 --- a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb +++ b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb @@ -34,7 +34,7 @@ module ActiveRecord end def insert_record(record, force = true, validate = true) - unless record.persisted? + if record.new_record? if force record.save! else @@ -113,7 +113,7 @@ module ActiveRecord private def create_record(attributes, &block) # Can't use Base.create because the foreign key may be a protected attribute. - ensure_owner_is_not_new + ensure_owner_is_persisted! if attributes.is_a?(Array) attributes.collect { |attr| create(attr) } else 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 79c229d9c4..d0c8af1801 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -36,7 +36,7 @@ module ActiveRecord protected def create_record(attrs, force = true) - ensure_owner_is_not_new + ensure_owner_is_persisted! transaction do object = @reflection.klass.new(attrs) @@ -59,7 +59,7 @@ module ActiveRecord end def insert_record(record, force = true, validate = true) - unless record.persisted? + if record.new_record? if force record.save! else diff --git a/activerecord/lib/active_record/associations/has_one_association.rb b/activerecord/lib/active_record/associations/has_one_association.rb index e6e037441f..c49fd6e66a 100644 --- a/activerecord/lib/active_record/associations/has_one_association.rb +++ b/activerecord/lib/active_record/associations/has_one_association.rb @@ -56,7 +56,7 @@ module ActiveRecord set_inverse_instance(obj, @owner) @loaded = true - unless !@owner.persisted? or obj.nil? or dont_save + unless !@owner.persisted? || obj.nil? || dont_save return (obj.save ? self : false) else return (obj.nil? ? nil : self) diff --git a/activerecord/lib/active_record/associations/has_one_through_association.rb b/activerecord/lib/active_record/associations/has_one_through_association.rb index 6e98f7dffb..7f28abf464 100644 --- a/activerecord/lib/active_record/associations/has_one_through_association.rb +++ b/activerecord/lib/active_record/associations/has_one_through_association.rb @@ -21,7 +21,7 @@ module ActiveRecord if current_object new_value ? current_object.update_attributes(construct_join_attributes(new_value)) : current_object.destroy elsif new_value - unless @owner.persisted? + if @owner.new_record? self.target = new_value through_association = @owner.send(:association_instance_get, @reflection.through_reflection.name) through_association.build(construct_join_attributes(new_value)) diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index 73ac8e82c6..c3dda29d03 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -217,7 +217,7 @@ module ActiveRecord # Returns whether or not this record has been changed in any way (including whether # any of its nested autosave associations are likewise changed) def changed_for_autosave? - !persisted? || changed? || marked_for_destruction? || nested_records_changed_for_autosave? + new_record? || changed? || marked_for_destruction? || nested_records_changed_for_autosave? end private @@ -231,7 +231,7 @@ module ActiveRecord elsif autosave association.target.find_all { |record| record.changed_for_autosave? } else - association.target.find_all { |record| !record.persisted? } + association.target.find_all { |record| record.new_record? } end end @@ -257,7 +257,7 @@ module ActiveRecord # +reflection+. def validate_collection_association(reflection) if association = association_instance_get(reflection.name) - if records = associated_records_to_validate_or_save(association, !persisted?, reflection.options[:autosave]) + if records = associated_records_to_validate_or_save(association, new_record?, reflection.options[:autosave]) records.each { |record| association_valid?(reflection, record) } end end @@ -286,7 +286,7 @@ module ActiveRecord # Is used as a before_save callback to check while saving a collection # association whether or not the parent was a new record before saving. def before_save_collection_association - @new_record_before_save = !persisted? + @new_record_before_save = new_record? true end @@ -308,7 +308,7 @@ module ActiveRecord if autosave && record.marked_for_destruction? association.destroy(record) - elsif autosave != false && (@new_record_before_save || !record.persisted?) + elsif autosave != false && (@new_record_before_save || record.new_record?) if autosave saved = association.send(:insert_record, record, false, false) else @@ -343,7 +343,7 @@ module ActiveRecord association.destroy else key = reflection.options[:primary_key] ? send(reflection.options[:primary_key]) : id - if autosave != false && (!persisted? || !association.persisted? || association[reflection.primary_key_name] != key || autosave) + if autosave != false && (new_record? || association.new_record? || association[reflection.primary_key_name] != key || autosave) association[reflection.primary_key_name] = key saved = association.save(:validate => !autosave) raise ActiveRecord::Rollback if !saved && autosave @@ -363,7 +363,7 @@ module ActiveRecord if autosave && association.marked_for_destruction? association.destroy elsif autosave != false - saved = association.save(:validate => !autosave) if !association.persisted? || autosave + saved = association.save(:validate => !autosave) if association.new_record? || autosave if association.updated? association_id = association.send(reflection.options[:primary_key] || :id) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 9b09b14c87..6076aaf4c3 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1365,7 +1365,7 @@ MSG def initialize(attributes = nil) @attributes = attributes_from_column_definition @attributes_cache = {} - @persisted = false + @new_record = true @readonly = false @destroyed = false @marked_for_destruction = false @@ -1396,7 +1396,7 @@ MSG @attributes = coder['attributes'] @attributes_cache, @previously_changed, @changed_attributes = {}, {}, {} @readonly = @destroyed = @marked_for_destruction = false - @persisted = true + @new_record = false _run_find_callbacks _run_initialize_callbacks end @@ -1437,7 +1437,7 @@ MSG # Person.find(5).cache_key # => "people/5-20071224150000" (updated_at available) def cache_key case - when !persisted? + when new_record? "#{self.class.model_name.cache_key}/new" when timestamp = self[:updated_at] "#{self.class.model_name.cache_key}/#{id}-#{timestamp.to_s(:number)}" @@ -1622,7 +1622,7 @@ MSG clear_aggregation_cache clear_association_cache @attributes_cache = {} - @persisted = false + @new_record = true ensure_proper_type populate_with_current_scope_attributes @@ -1643,7 +1643,7 @@ MSG # Returns the contents of the record as a nicely formatted string. def inspect attributes_as_nice_string = self.class.column_names.collect { |name| - if has_attribute?(name) || !persisted? + if has_attribute?(name) || new_record? "#{name}: #{attribute_for_inspect(name)}" end }.compact.join(", ") diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 594a2214bb..75dba0206d 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -4,7 +4,7 @@ module ActiveRecord # Returns true if this object hasn't been saved yet -- that is, a record # for the object doesn't exist in the data store yet; otherwise, returns false. def new_record? - !@persisted + @new_record end # Returns true if this object has been destroyed, otherwise returns false. @@ -15,7 +15,7 @@ module ActiveRecord # Returns if the record is persisted, i.e. it's not a new record and it was # not destroyed. def persisted? - @persisted && !destroyed? + !(new_record? || destroyed?) end # Saves the model. @@ -94,7 +94,7 @@ module ActiveRecord became = klass.new became.instance_variable_set("@attributes", @attributes) became.instance_variable_set("@attributes_cache", @attributes_cache) - became.instance_variable_set("@persisted", persisted?) + became.instance_variable_set("@new_record", new_record?) became.instance_variable_set("@destroyed", destroyed?) became.type = klass.name unless self.class.descends_from_active_record? became @@ -241,7 +241,7 @@ module ActiveRecord private def create_or_update raise ReadOnlyRecord if readonly? - result = persisted? ? update : create + result = new_record? ? create : update result != false end @@ -270,7 +270,7 @@ module ActiveRecord self.id ||= new_id - @persisted = true + @new_record = false id end diff --git a/activerecord/lib/active_record/session_store.rb b/activerecord/lib/active_record/session_store.rb index ba99800fb2..3400fd6ade 100644 --- a/activerecord/lib/active_record/session_store.rb +++ b/activerecord/lib/active_record/session_store.rb @@ -228,7 +228,7 @@ module ActiveRecord @session_id = attributes[:session_id] @data = attributes[:data] @marshaled_data = attributes[:marshaled_data] - @persisted = !@marshaled_data.nil? + @new_record = @marshaled_data.nil? end # Lazy-unmarshal session state. @@ -252,8 +252,8 @@ module ActiveRecord marshaled_data = self.class.marshal(data) connect = connection - unless @persisted - @persisted = true + if @new_record + @new_record = false connect.update <<-end_sql, 'Create session' INSERT INTO #{table_name} ( #{connect.quote_column_name(session_id_column)}, @@ -272,7 +272,7 @@ module ActiveRecord end def destroy - return unless @persisted + return if @new_record connect = connection connect.delete <<-end_sql, 'Destroy session' diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index 8c94d1a2bc..654c475aed 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -11,6 +11,7 @@ module ActiveRecord included do define_callbacks :commit, :rollback, :terminator => "result == false", :scope => [:kind, :name] end + # = Active Record Transactions # # Transactions are protective blocks where SQL statements are only permanent @@ -242,7 +243,7 @@ module ActiveRecord with_transaction_returning_status { super } end - # Reset id and @persisted if the transaction rolls back. + # Reset id and @new_record if the transaction rolls back. def rollback_active_record_state! remember_transaction_record_state yield @@ -297,9 +298,9 @@ module ActiveRecord # Save the new record state and id of a record so it can be restored later if a transaction fails. def remember_transaction_record_state #:nodoc @_start_transaction_state ||= {} - unless @_start_transaction_state.include?(:persisted) + unless @_start_transaction_state.include?(:new_record) @_start_transaction_state[:id] = id if has_attribute?(self.class.primary_key) - @_start_transaction_state[:persisted] = @persisted + @_start_transaction_state[:new_record] = @new_record end unless @_start_transaction_state.include?(:destroyed) @_start_transaction_state[:destroyed] = @destroyed @@ -323,8 +324,8 @@ module ActiveRecord restore_state = remove_instance_variable(:@_start_transaction_state) if restore_state @attributes = @attributes.dup if @attributes.frozen? - @persisted = restore_state[:persisted] - @destroyed = restore_state[:destroyed] + @new_record = restore_state[:new_record] + @destroyed = restore_state[:destroyed] if restore_state[:id] self.id = restore_state[:id] else @@ -345,11 +346,11 @@ module ActiveRecord def transaction_include_action?(action) #:nodoc case action when :create - transaction_record_state(:new_record) || !transaction_record_state(:persisted) + transaction_record_state(:new_record) when :destroy destroyed? when :update - !(transaction_record_state(:new_record) || !transaction_record_state(:persisted) || destroyed?) + !(transaction_record_state(:new_record) || destroyed?) end end end diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index ee45fcdf35..f367315b22 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -51,7 +51,7 @@ module ActiveRecord # Runs all the specified validations and returns true if no errors were added otherwise false. def valid?(context = nil) - context ||= (persisted? ? :update : :create) + context ||= (new_record? ? :create : :update) output = super(context) errors.empty? && output end -- cgit v1.2.3 From 439a7dc0e62858a5ed1fc397e36626f9be1d7c87 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 29 Nov 2010 10:39:33 -0800 Subject: moving method to subclass that actually uses the method --- .../associations/class_methods/join_dependency/join_association.rb | 4 ++++ .../associations/class_methods/join_dependency/join_part.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index 5e5c01c77a..e7d1ffa9f2 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -123,6 +123,10 @@ module ActiveRecord Arel.sql(interpolate_sql(sanitize_sql(conditions, table_name))) end + def sanitize_sql(condition, table_name) + active_record.send(:sanitize_sql, condition, table_name) + end + def join_target_table(relation, *conditions) relation = relation.join(target_table, join_type) diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_part.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_part.rb index 0b093b65e9..cd16ae5a8b 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_part.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_part.rb @@ -14,7 +14,7 @@ module ActiveRecord # association. attr_reader :active_record - delegate :table_name, :column_names, :primary_key, :reflections, :sanitize_sql, :arel_engine, :to => :active_record + delegate :table_name, :column_names, :primary_key, :reflections, :arel_engine, :to => :active_record def initialize(active_record) @active_record = active_record -- cgit v1.2.3 From aae3c3538492f19f1c4e1fcfe6c942ff72a30ce1 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 29 Nov 2010 10:58:21 -0800 Subject: removing interpolate_sql from join associations --- .../associations/class_methods/join_dependency/join_association.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index e7d1ffa9f2..3db80d341f 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -102,10 +102,6 @@ module ActiveRecord ActiveRecord::Base.pluralize_table_names ? table_name.to_s.pluralize : table_name end - def interpolate_sql(sql) - instance_eval("%@#{sql.gsub('@', '\@')}@", __FILE__, __LINE__) - end - private def allocate_aliases @@ -120,7 +116,7 @@ module ActiveRecord end def process_conditions(conditions, table_name) - Arel.sql(interpolate_sql(sanitize_sql(conditions, table_name))) + Arel.sql(sanitize_sql(conditions, table_name)) end def sanitize_sql(condition, table_name) -- cgit v1.2.3 From b6848b6491b75d69c0e1ceaa6a66d86305124d24 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 30 Nov 2010 12:05:02 -0800 Subject: cleaning up where_values_hash --- activerecord/lib/active_record/relation.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 3b22be78cb..1ed42ffb95 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -319,13 +319,13 @@ module ActiveRecord end def where_values_hash - Hash[@where_values.find_all { |w| - w.respond_to?(:operator) && w.operator == :== && w.left.relation.name == table_name - }.map { |where| - [ - where.left.name, - where.right.respond_to?(:value) ? where.right.value : where.right - ] + equalities = @where_values.grep(Arel::Nodes::Equality).find_all { |node| + node.left.relation.name == table_name + } + + Hash[equalities.map { |where| + left, right = where.left, where.right + [ left.name, right.respond_to?(:value) ? right.value : right ] }] end -- cgit v1.2.3 From 8998aea4b751ba8d9a6362f8cc11db5cf46a71ee Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 30 Nov 2010 13:31:00 -0800 Subject: making relationship merge cheaper --- activerecord/lib/active_record/relation/spawn_methods.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index a61a3bd41c..5acf3ec83a 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -3,10 +3,11 @@ require 'active_support/core_ext/object/blank' module ActiveRecord module SpawnMethods def merge(r) - merged_relation = clone - return merged_relation unless r + return self unless r return to_a & r if r.is_a?(Array) + merged_relation = clone + Relation::ASSOCIATION_METHODS.each do |method| value = r.send(:"#{method}_values") @@ -24,7 +25,7 @@ module ActiveRecord merged_relation.send(:"#{method}_values=", merged_relation.send(:"#{method}_values") + value) if value.present? end - merged_relation = merged_relation.joins(r.joins_values) + merged_relation.joins_values += r.joins_values merged_wheres = @where_values + r.where_values -- cgit v1.2.3 From 6c32290bac460ce53ea2d29b50047248f9f0de92 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 30 Nov 2010 14:29:35 -0800 Subject: testing Relation#table_name --- activerecord/lib/active_record/relation.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 1ed42ffb95..098a03b39b 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -356,6 +356,10 @@ module ActiveRecord to_a.inspect end + def table_name + @klass.table_name + end + protected def method_missing(method, *args, &block) -- cgit v1.2.3 From c856e25b32f3c2ea198d6f4ac46276a15fd20d80 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 30 Nov 2010 14:56:53 -0800 Subject: removing arel 1.0 compatibility --- activerecord/lib/active_record/relation.rb | 5 +---- 1 file changed, 1 insertion(+), 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 098a03b39b..c31a6e8feb 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -323,10 +323,7 @@ module ActiveRecord node.left.relation.name == table_name } - Hash[equalities.map { |where| - left, right = where.left, where.right - [ left.name, right.respond_to?(:value) ? right.value : right ] - }] + Hash[equalities.map { |where| [where.left.name, where.right] }] end def scope_for_create -- cgit v1.2.3 From dccf624b643398afdf1b0e048e57f04cb182c55e Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 30 Nov 2010 15:20:27 -0800 Subject: Ruby 1.8, how does it work? --- activerecord/lib/active_record/relation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index c31a6e8feb..4bc7f73013 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -329,7 +329,7 @@ module ActiveRecord def scope_for_create @scope_for_create ||= begin if @create_with_value - @create_with_value.reverse_merge(where_values_hash) + where_values_hash.merge @create_with_value else where_values_hash end -- cgit v1.2.3 From 7ff980031bc49fe332d3b9ea8fbc6c2aae935db5 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 30 Nov 2010 15:39:49 -0800 Subject: scope_for_create always returns something --- activerecord/lib/active_record/base.rb | 4 +++- 1 file changed, 3 insertions(+), 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 6076aaf4c3..b972b193e4 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1830,7 +1830,9 @@ MSG def populate_with_current_scope_attributes if scope = self.class.send(:current_scoped_methods) create_with = scope.scope_for_create - create_with.each { |att,value| self.respond_to?(:"#{att}=") && self.send("#{att}=", value) } if create_with + create_with.each { |att,value| + respond_to?(:"#{att}=") && send("#{att}=", value) + } end end -- cgit v1.2.3 From ae6033331fe78cf5b3af04e1f6f930b98ddab66f Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 30 Nov 2010 15:48:15 -0800 Subject: shorten up scope_for_create --- activerecord/lib/active_record/relation.rb | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 4bc7f73013..8d0d99a125 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -327,13 +327,7 @@ module ActiveRecord end def scope_for_create - @scope_for_create ||= begin - if @create_with_value - where_values_hash.merge @create_with_value - else - where_values_hash - end - end + @scope_for_create ||= where_values_hash.merge(@create_with_value || {}) end def eager_loading? -- cgit v1.2.3 From fe522f79c772c915efc88a8476fa69a503955967 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 30 Nov 2010 15:53:04 -0800 Subject: we already know it is already an array, so we do not need to make really really sure it is an array --- activerecord/lib/active_record/relation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 8d0d99a125..45fc3c20c2 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -339,7 +339,7 @@ module ActiveRecord when Relation other.to_sql == to_sql when Array - to_a == other.to_a + to_a == other end end -- cgit v1.2.3 From 39f5fc06cb5661b93275e3f7bf98e63b98b57550 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 30 Nov 2010 16:42:21 -0800 Subject: just call join_sql against the manager object --- activerecord/lib/active_record/relation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 45fc3c20c2..bebdd1292c 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -371,7 +371,7 @@ module ActiveRecord def references_eager_loaded_tables? # always convert table names to downcase as in Oracle quoted table names are in uppercase - joined_tables = (tables_in_string(arel.joins(arel)) + [table.name, table.table_alias]).compact.map{ |t| t.downcase }.uniq + joined_tables = (tables_in_string(arel.join_sql) + [table.name, table.table_alias]).compact.map{ |t| t.downcase }.uniq (tables_in_string(to_sql) - joined_tables).any? end -- cgit v1.2.3 From f1758525f940eb6c4dd4178784db2ba66316083d Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 30 Nov 2010 16:51:03 -0800 Subject: reduce method calls on arel --- activerecord/lib/active_record/relation/calculations.rb | 2 +- activerecord/lib/active_record/relation/finder_methods.rb | 2 +- activerecord/lib/active_record/relation/query_methods.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index c8adaddfca..013b878293 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -166,7 +166,7 @@ module ActiveRecord if operation == "count" column_name ||= (select_for_count || :all) - if arel.joins(arel) =~ /LEFT OUTER/i + if arel.join_sql =~ /LEFT OUTER/i distinct = true column_name = @klass.primary_key if column_name == :all end diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 23ae0b4325..1da7411589 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -196,7 +196,7 @@ module ActiveRecord def construct_relation_for_association_calculations including = (@eager_load_values + @includes_values).uniq - join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, including, arel.joins(arel)) + join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, including, arel.join_sql) relation = except(:includes, :eager_load, :preload) apply_join_dependency(relation, join_dependency) end diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 0a4c119849..1eb7f04bdf 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -180,7 +180,7 @@ module ActiveRecord arel.join(join) end - arel.joins(arel) + arel.join_sql end def build_arel -- cgit v1.2.3 From 7408b6ec842c87644460430827b8ce27e43ccfc7 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 30 Nov 2010 17:29:19 -0800 Subject: just grep the AST for OuterJoin nodes rather than converting the tree to SQL --- activerecord/lib/active_record/relation/calculations.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index 013b878293..fd45bb24dd 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -166,7 +166,7 @@ module ActiveRecord if operation == "count" column_name ||= (select_for_count || :all) - if arel.join_sql =~ /LEFT OUTER/i + unless arel.ast.grep(Arel::Nodes::OuterJoin).empty? distinct = true column_name = @klass.primary_key if column_name == :all end -- cgit v1.2.3 From d51854a6be66ea39973e8880726be3a17dfbd7b8 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 30 Nov 2010 17:42:17 -0800 Subject: stop using splat args when we do not need them --- activerecord/lib/active_record/relation/query_methods.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 1eb7f04bdf..30cd4f4477 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -162,7 +162,7 @@ module ActiveRecord @arel ||= build_arel end - def custom_join_sql(*joins) + def custom_join_sql(joins) arel = table.select_manager joins.each do |join| @@ -254,7 +254,7 @@ module ActiveRecord stashed_association_joins = joins.grep(ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation) non_association_joins = (joins - association_joins - stashed_association_joins) - custom_joins = custom_join_sql(*non_association_joins) + custom_joins = custom_join_sql(non_association_joins) join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, custom_joins) -- cgit v1.2.3 From 10b1887a719588c1252906169f9d3d12ee1387c6 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 30 Nov 2010 17:48:10 -0800 Subject: JoinBase initialize can be deleted --- .../active_record/associations/class_methods/join_dependency.rb | 5 +++-- .../associations/class_methods/join_dependency/join_base.rb | 8 -------- 2 files changed, 3 insertions(+), 10 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index 6ab7bd0b06..c578845878 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -9,7 +9,8 @@ module ActiveRecord attr_reader :join_parts, :reflections, :table_aliases def initialize(base, associations, joins) - @join_parts = [JoinBase.new(base, joins)] + @table_joins = joins || '' + @join_parts = [JoinBase.new(base)] @associations = {} @reflections = [] @table_aliases = Hash.new(0) @@ -45,7 +46,7 @@ module ActiveRecord def count_aliases_from_table_joins(name) # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase quoted_name = join_base.active_record.connection.quote_table_name(name.downcase).downcase - join_sql = join_base.table_joins.to_s.downcase + join_sql = @table_joins.downcase join_sql.blank? ? 0 : # Table names join_sql.scan(/join(?:\s+\w+)?\s+#{quoted_name}\son/).size + diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_base.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_base.rb index ed05003f66..97003c1457 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_base.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_base.rb @@ -3,14 +3,6 @@ module ActiveRecord module ClassMethods class JoinDependency # :nodoc: class JoinBase < JoinPart # :nodoc: - # Extra joins provided when the JoinDependency was created - attr_reader :table_joins - - def initialize(active_record, joins = nil) - super(active_record) - @table_joins = joins - end - def ==(other) other.class == self.class && other.active_record == active_record -- cgit v1.2.3 From 542cb5c327f92d3f6ae6159a54e86949441f095e Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 30 Nov 2010 18:46:56 -0800 Subject: fix warnings, stop using global variables --- activerecord/lib/active_record/relation/query_methods.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 30cd4f4477..0483950db7 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -243,12 +243,10 @@ module ActiveRecord end def build_joins(relation, joins) - association_joins = [] - joins = joins.map {|j| j.respond_to?(:strip) ? j.strip : j}.uniq - joins.each do |join| - association_joins << join if [Hash, Array, Symbol].include?(join.class) && !array_of_strings?(join) + association_joins = joins.find_all do |join| + [Hash, Array, Symbol].include?(join.class) && !array_of_strings?(join) end stashed_association_joins = joins.grep(ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation) -- cgit v1.2.3 From c283cdd63cafdb04784cfcc5094da41c9268c20c Mon Sep 17 00:00:00 2001 From: Josh Susser Date: Mon, 15 Mar 2010 00:53:57 -0700 Subject: Add migrated_at column to schema_migrations table. --- .../connection_adapters/abstract/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/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index 4e770c37da..730b1c7425 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -422,9 +422,17 @@ module ActiveRecord def initialize_schema_migrations_table sm_table = ActiveRecord::Migrator.schema_migrations_table_name - unless table_exists?(sm_table) + if table_exists?(sm_table) + cols = columns(sm_table).collect { |col| col.name } + unless cols.include?("migrated_at") + add_column sm_table, :migrated_at, :datetime + update "UPDATE #{quote_table_name(sm_table)} SET migrated_at = '#{quoted_date(Time.now)}' WHERE migrated_at IS NULL" + change_column sm_table, :migrated_at, :datetime, :null => false + end + else create_table(sm_table, :id => false) do |schema_migrations_table| schema_migrations_table.column :version, :string, :null => false + schema_migrations_table.column :migrated_at, :datetime, :null => false end add_index sm_table, :version, :unique => true, :name => "#{Base.table_name_prefix}unique_schema_migrations#{Base.table_name_suffix}" -- cgit v1.2.3 From 4e4e9ad48a222ac94a904c62ae684c609bd8e177 Mon Sep 17 00:00:00 2001 From: Josh Susser Date: Tue, 16 Mar 2010 23:02:03 -0700 Subject: record migration timestamp when migrations run --- activerecord/lib/active_record/migration.rb | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index f6321f1499..2cf2f4acd0 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -628,7 +628,7 @@ module ActiveRecord raise UnknownMigrationVersionError.new(@target_version) if target.nil? unless (up? && migrated.include?(target.version.to_i)) || (down? && !migrated.include?(target.version.to_i)) target.migrate(@direction) - record_version_state_after_migrating(target.version) + record_version_state_after_migrating(target) end end @@ -664,7 +664,7 @@ module ActiveRecord begin ddl_transaction do migration.migrate(@direction) - record_version_state_after_migrating(migration.version) + record_version_state_after_migrating(migration) end rescue => e canceled_msg = Base.connection.supports_ddl_transactions? ? "this and " : "" @@ -690,16 +690,19 @@ module ActiveRecord end private - def record_version_state_after_migrating(version) + def record_version_state_after_migrating(target) table = Arel::Table.new(self.class.schema_migrations_table_name) @migrated_versions ||= [] if down? - @migrated_versions.delete(version) - table.where(table["version"].eq(version.to_s)).delete + @migrated_versions.delete(target.version) + table.where(table["version"].eq(target.version.to_s)).delete else - @migrated_versions.push(version).sort! - table.insert table["version"] => version.to_s + @migrated_versions.push(target.version).sort! + table.insert( + table["version"] => target.version.to_s, + table["migrated_at"] => Time.now + ) end end -- cgit v1.2.3 From 7139aa878ceea8dd17a60955cd4d07f5f68980d9 Mon Sep 17 00:00:00 2001 From: Josh Susser Date: Sat, 20 Mar 2010 18:26:12 -0700 Subject: name in schema_migrations, migrations in schema dump --- .../connection_adapters/abstract/schema_statements.rb | 4 ++++ activerecord/lib/active_record/migration.rb | 1 + activerecord/lib/active_record/schema.rb | 17 +++++++++++++---- activerecord/lib/active_record/schema_dumper.rb | 10 ++++++++++ 4 files changed, 28 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') 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 730b1c7425..ccb6fe3be2 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -429,9 +429,13 @@ module ActiveRecord update "UPDATE #{quote_table_name(sm_table)} SET migrated_at = '#{quoted_date(Time.now)}' WHERE migrated_at IS NULL" change_column sm_table, :migrated_at, :datetime, :null => false end + unless cols.include?("name") + add_column sm_table, :name, :string, :null => false, :default => "" + end else create_table(sm_table, :id => false) do |schema_migrations_table| schema_migrations_table.column :version, :string, :null => false + schema_migrations_table.column :name, :string, :null => false, :default => "" schema_migrations_table.column :migrated_at, :datetime, :null => false end add_index sm_table, :version, :unique => true, diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 2cf2f4acd0..d2ebf656cb 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -701,6 +701,7 @@ module ActiveRecord @migrated_versions.push(target.version).sort! table.insert( table["version"] => target.version.to_s, + table["name"] => File.basename(target.filename,'.rb').gsub(/^\d+_/,''), table["migrated_at"] => Time.now ) end diff --git a/activerecord/lib/active_record/schema.rb b/activerecord/lib/active_record/schema.rb index c6bb5c1961..c9b5539e4f 100644 --- a/activerecord/lib/active_record/schema.rb +++ b/activerecord/lib/active_record/schema.rb @@ -49,10 +49,19 @@ module ActiveRecord schema = new schema.instance_eval(&block) - unless info[:version].blank? - initialize_schema_migrations_table - assume_migrated_upto_version(info[:version], schema.migrations_path) - end + initialize_schema_migrations_table + assume_migrated_upto_version(info[:version], schema.migrations_path) unless info[:version].blank? + end + + def self.migration(version, name="", options={}) + name, options = "", name if name.is_a?(Hash) + + table = Arel::Table.new(ActiveRecord::Migrator.schema_migrations_table_name) + table.insert( + table["version"] => version, + table["name"] => name, + table["migrated_at"] => Time.now + ) end end end diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index e30b481fe1..a53dce0cf4 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -24,6 +24,7 @@ module ActiveRecord def dump(stream) header(stream) + migrations(stream) tables(stream) trailer(stream) stream @@ -62,6 +63,15 @@ HEADER stream.puts "end" end + def migrations(stream) + rows = @connection.select_all("SELECT * FROM #{@connection.quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name)}") + rows.each do |migration| + line = %Q(migration "#{migration['version']}") + line << %Q(, "#{migration['name']}") unless migration['name'].blank? + stream.puts line + end + end + def tables(stream) @connection.tables.sort.each do |tbl| next if ['schema_migrations', ignore_tables].flatten.any? do |ignored| -- cgit v1.2.3 From b07c2c0fd3130bb69cf8d846e46762a7c3972107 Mon Sep 17 00:00:00 2001 From: Josh Susser Date: Sat, 20 Mar 2010 19:46:17 -0700 Subject: clear schema_migrations in Schema.define --- activerecord/lib/active_record/schema.rb | 4 +++- activerecord/lib/active_record/schema_dumper.rb | 8 +++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/schema.rb b/activerecord/lib/active_record/schema.rb index c9b5539e4f..4b846f2e27 100644 --- a/activerecord/lib/active_record/schema.rb +++ b/activerecord/lib/active_record/schema.rb @@ -46,10 +46,12 @@ module ActiveRecord # ... # end def self.define(info={}, &block) + Base.connection.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) + initialize_schema_migrations_table + schema = new schema.instance_eval(&block) - initialize_schema_migrations_table assume_migrated_upto_version(info[:version], schema.migrations_path) unless info[:version].blank? end diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index a53dce0cf4..794a354917 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -35,12 +35,9 @@ module ActiveRecord def initialize(connection) @connection = connection @types = @connection.native_database_types - @version = Migrator::current_version rescue nil end def header(stream) - define_params = @version ? ":version => #{@version}" : "" - stream.puts <
Date: Wed, 1 Dec 2010 11:56:21 -0800 Subject: tests mostly pass adjust to work with instance-based migations migrated_at can't be null why must people have last names? it's killing me! --- .../active_record/connection_adapters/abstract/schema_statements.rb | 4 ++-- activerecord/lib/active_record/schema.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') 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 ccb6fe3be2..de7d358df9 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -464,7 +464,7 @@ module ActiveRecord end unless migrated.include?(version) - execute "INSERT INTO #{sm_table} (version) VALUES ('#{version}')" + execute "INSERT INTO #{sm_table} (version,migrated_at) VALUES ('#{version}','#{Time.now.to_s(:db)}')" end inserted = Set.new @@ -472,7 +472,7 @@ module ActiveRecord if inserted.include?(v) raise "Duplicate migration #{v}. Please renumber your migrations to resolve the conflict." elsif v < version - execute "INSERT INTO #{sm_table} (version) VALUES ('#{v}')" + execute "INSERT INTO #{sm_table} (version,migrated_at) VALUES ('#{v}','#{Time.now.to_s(:db)}')" inserted << v end end diff --git a/activerecord/lib/active_record/schema.rb b/activerecord/lib/active_record/schema.rb index 4b846f2e27..9a47fd3b84 100644 --- a/activerecord/lib/active_record/schema.rb +++ b/activerecord/lib/active_record/schema.rb @@ -55,7 +55,7 @@ module ActiveRecord assume_migrated_upto_version(info[:version], schema.migrations_path) unless info[:version].blank? end - def self.migration(version, name="", options={}) + def migration(version, name="", options={}) name, options = "", name if name.is_a?(Hash) table = Arel::Table.new(ActiveRecord::Migrator.schema_migrations_table_name) -- cgit v1.2.3 From 3ec212e3c9c815e9993cbea409c60774ea75cd30 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 1 Dec 2010 17:08:01 -0800 Subject: rolling out migrated_at until I can fix the build --- .../connection_adapters/abstract/schema_statements.rb | 18 +++--------------- activerecord/lib/active_record/migration.rb | 18 +++++++----------- activerecord/lib/active_record/schema.rb | 19 ++++--------------- activerecord/lib/active_record/schema_dumper.rb | 16 ++++------------ 4 files changed, 18 insertions(+), 53 deletions(-) (limited to 'activerecord/lib/active_record') 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 de7d358df9..4e770c37da 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -422,21 +422,9 @@ module ActiveRecord def initialize_schema_migrations_table sm_table = ActiveRecord::Migrator.schema_migrations_table_name - if table_exists?(sm_table) - cols = columns(sm_table).collect { |col| col.name } - unless cols.include?("migrated_at") - add_column sm_table, :migrated_at, :datetime - update "UPDATE #{quote_table_name(sm_table)} SET migrated_at = '#{quoted_date(Time.now)}' WHERE migrated_at IS NULL" - change_column sm_table, :migrated_at, :datetime, :null => false - end - unless cols.include?("name") - add_column sm_table, :name, :string, :null => false, :default => "" - end - else + unless table_exists?(sm_table) create_table(sm_table, :id => false) do |schema_migrations_table| schema_migrations_table.column :version, :string, :null => false - schema_migrations_table.column :name, :string, :null => false, :default => "" - schema_migrations_table.column :migrated_at, :datetime, :null => false end add_index sm_table, :version, :unique => true, :name => "#{Base.table_name_prefix}unique_schema_migrations#{Base.table_name_suffix}" @@ -464,7 +452,7 @@ module ActiveRecord end unless migrated.include?(version) - execute "INSERT INTO #{sm_table} (version,migrated_at) VALUES ('#{version}','#{Time.now.to_s(:db)}')" + execute "INSERT INTO #{sm_table} (version) VALUES ('#{version}')" end inserted = Set.new @@ -472,7 +460,7 @@ module ActiveRecord if inserted.include?(v) raise "Duplicate migration #{v}. Please renumber your migrations to resolve the conflict." elsif v < version - execute "INSERT INTO #{sm_table} (version,migrated_at) VALUES ('#{v}','#{Time.now.to_s(:db)}')" + execute "INSERT INTO #{sm_table} (version) VALUES ('#{v}')" inserted << v end end diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index d2ebf656cb..f6321f1499 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -628,7 +628,7 @@ module ActiveRecord raise UnknownMigrationVersionError.new(@target_version) if target.nil? unless (up? && migrated.include?(target.version.to_i)) || (down? && !migrated.include?(target.version.to_i)) target.migrate(@direction) - record_version_state_after_migrating(target) + record_version_state_after_migrating(target.version) end end @@ -664,7 +664,7 @@ module ActiveRecord begin ddl_transaction do migration.migrate(@direction) - record_version_state_after_migrating(migration) + record_version_state_after_migrating(migration.version) end rescue => e canceled_msg = Base.connection.supports_ddl_transactions? ? "this and " : "" @@ -690,20 +690,16 @@ module ActiveRecord end private - def record_version_state_after_migrating(target) + def record_version_state_after_migrating(version) table = Arel::Table.new(self.class.schema_migrations_table_name) @migrated_versions ||= [] if down? - @migrated_versions.delete(target.version) - table.where(table["version"].eq(target.version.to_s)).delete + @migrated_versions.delete(version) + table.where(table["version"].eq(version.to_s)).delete else - @migrated_versions.push(target.version).sort! - table.insert( - table["version"] => target.version.to_s, - table["name"] => File.basename(target.filename,'.rb').gsub(/^\d+_/,''), - table["migrated_at"] => Time.now - ) + @migrated_versions.push(version).sort! + table.insert table["version"] => version.to_s end end diff --git a/activerecord/lib/active_record/schema.rb b/activerecord/lib/active_record/schema.rb index 9a47fd3b84..c6bb5c1961 100644 --- a/activerecord/lib/active_record/schema.rb +++ b/activerecord/lib/active_record/schema.rb @@ -46,24 +46,13 @@ module ActiveRecord # ... # end def self.define(info={}, &block) - Base.connection.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) - initialize_schema_migrations_table - schema = new schema.instance_eval(&block) - assume_migrated_upto_version(info[:version], schema.migrations_path) unless info[:version].blank? - end - - def migration(version, name="", options={}) - name, options = "", name if name.is_a?(Hash) - - table = Arel::Table.new(ActiveRecord::Migrator.schema_migrations_table_name) - table.insert( - table["version"] => version, - table["name"] => name, - table["migrated_at"] => Time.now - ) + unless info[:version].blank? + initialize_schema_migrations_table + assume_migrated_upto_version(info[:version], schema.migrations_path) + end end end end diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index 794a354917..e30b481fe1 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -24,7 +24,6 @@ module ActiveRecord def dump(stream) header(stream) - migrations(stream) tables(stream) trailer(stream) stream @@ -35,9 +34,12 @@ module ActiveRecord def initialize(connection) @connection = connection @types = @connection.native_database_types + @version = Migrator::current_version rescue nil end def header(stream) + define_params = @version ? ":version => #{@version}" : "" + stream.puts <
Date: Wed, 1 Dec 2010 18:00:24 -0800 Subject: no need for self --- .../associations/class_methods/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/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index 3db80d341f..4dd11a7366 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -52,7 +52,7 @@ module ActiveRecord def find_parent_in(other_join_dependency) other_join_dependency.join_parts.detect do |join_part| - self.parent == join_part + parent == join_part end end -- cgit v1.2.3 From 96eec090dfd50326146b2f690408fefec50c5111 Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Thu, 2 Dec 2010 15:36:05 +1300 Subject: Work around a strange piece of Syck behaviour where it checks Model#respond_to? before initializing the object. Things like YAML.load(YAML.dump(@post)) won't work without this. --- 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 67f70c434e..4f4a0a5fee 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -54,7 +54,7 @@ module ActiveRecord protected def attribute_method?(attr_name) - attr_name == 'id' || @attributes.include?(attr_name) + attr_name == 'id' || (defined?(@attributes) && @attributes.include?(attr_name)) end end end -- cgit v1.2.3 From deb90d9485516832d86afcf6e6810e1c98c836ab Mon Sep 17 00:00:00 2001 From: Alex Rothenberg Date: Tue, 23 Nov 2010 09:47:41 -0500 Subject: made in_clause_length default nil (no limit) --- .../lib/active_record/connection_adapters/abstract/database_limits.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb index a130c330dd..29ac9341ec 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb @@ -37,9 +37,9 @@ module ActiveRecord 16 end - # the maximum number of elements in an IN (x,y,z) clause + # the maximum number of elements in an IN (x,y,z) clause. nil means no limit def in_clause_length - 65535 + nil end # the maximum length of an SQL query -- cgit v1.2.3 From 15633519f7fbe5450e4b232e556deca3340eb88d Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 2 Dec 2010 13:53:59 -0800 Subject: removing some calls to insert on arel --- .../associations/has_and_belongs_to_many_association.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb index f6f291a039..367104ec1b 100644 --- a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb +++ b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb @@ -49,7 +49,7 @@ module ActiveRecord timestamps = record_timestamp_columns(record) timezone = record.send(:current_time_from_proper_timezone) if timestamps.any? - attributes = Hash[columns.map do |column| + attributes = columns.map do |column| name = column.name value = case name.to_s when @reflection.primary_key_name.to_s @@ -62,9 +62,10 @@ module ActiveRecord @owner.send(:quote_value, record[name], column) if record.has_attribute?(name) end [relation[name], value] unless value.nil? - end] + end - relation.insert(attributes) + stmt = relation.compile_insert Hash[attributes] + @owner.connection.insert stmt.to_sql end true -- cgit v1.2.3 From 6673d88f6f234ab493ad314f930901ce3a288da8 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 2 Dec 2010 14:01:37 -0800 Subject: avoiding deprecated methods in arel --- activerecord/lib/active_record/migration.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index f6321f1499..b4b9dfab88 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -699,7 +699,8 @@ module ActiveRecord table.where(table["version"].eq(version.to_s)).delete else @migrated_versions.push(version).sort! - table.insert table["version"] => version.to_s + stmt = table.compile_insert table["version"] => version.to_s + Base.connection.insert stmt.to_sql end end -- cgit v1.2.3 From 42c51b8527e49ae2d7a0f6cc009e53865b7910c1 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 2 Dec 2010 17:59:55 -0200 Subject: Doesn't need to sort, lets users of attribute_names sort them if they want --- activerecord/lib/active_record/base.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index b972b193e4..6573cd5e89 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1455,9 +1455,9 @@ MSG @attributes.has_key?(attr_name.to_s) end - # Returns an array of names for the attributes available on this object sorted alphabetically. + # Returns an array of names for the attributes available on this object. def attribute_names - @attributes.keys.sort + @attributes.keys end # Returns the value of the attribute identified by attr_name after it has been typecast (for example, -- cgit v1.2.3 From 21eadc1b3f2eb818a4833381ee0a6cfa205f2955 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 2 Dec 2010 20:05:06 -0200 Subject: Base#[] and Base#[]= are aliases so implement them as aliases :) --- activerecord/lib/active_record/base.rb | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 6573cd5e89..ba7f6f0129 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1460,19 +1460,6 @@ MSG @attributes.keys end - # Returns the value of the attribute identified by attr_name after it has been typecast (for example, - # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). - # (Alias for the protected read_attribute method). - def [](attr_name) - read_attribute(attr_name) - end - - # Updates the attribute identified by attr_name with the specified +value+. - # (Alias for the protected write_attribute method). - def []=(attr_name, value) - write_attribute(attr_name, value) - end - # Allows you to set all the attributes at once by passing in a hash with keys # matching the attribute names (which again matches the column names). # @@ -1873,6 +1860,17 @@ MSG include Aggregations, Transactions, Reflection, Serialization NilClass.add_whiner(self) if NilClass.respond_to?(:add_whiner) + + # Returns the value of the attribute identified by attr_name after it has been typecast (for example, + # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). + # (Alias for the protected read_attribute method). + alias [] read_attribute + + # Updates the attribute identified by attr_name with the specified +value+. + # (Alias for the protected write_attribute method). + alias []= write_attribute + + public :[], :[]= end end -- cgit v1.2.3 From 9f0133fbf4465d97559d97ff04c67775b8379b1c Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 2 Dec 2010 14:38:33 -0800 Subject: refactor `self.class` to a variable --- 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 75dba0206d..fad83cde09 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -250,7 +250,8 @@ module ActiveRecord def update(attribute_names = @attributes.keys) attributes_with_values = arel_attributes_values(false, false, attribute_names) return 0 if attributes_with_values.empty? - self.class.unscoped.where(self.class.arel_table[self.class.primary_key].eq(id)).arel.update(attributes_with_values) + klass = self.class + klass.unscoped.where(klass.arel_table[klass.primary_key].eq(id)).arel.update(attributes_with_values) end # Creates a record with values matching those of the instance attributes -- cgit v1.2.3 From 12b9920a15d93ead97bad83c30fd3a15bc7b074a Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 2 Dec 2010 14:43:08 -0800 Subject: removing calls to deprecated methods --- 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 fad83cde09..9ac8fcb176 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -251,7 +251,8 @@ module ActiveRecord attributes_with_values = arel_attributes_values(false, false, attribute_names) return 0 if attributes_with_values.empty? klass = self.class - klass.unscoped.where(klass.arel_table[klass.primary_key].eq(id)).arel.update(attributes_with_values) + stmt = klass.unscoped.where(klass.arel_table[klass.primary_key].eq(id)).arel.compile_update(attributes_with_values) + klass.connection.update stmt.to_sql end # Creates a record with values matching those of the instance attributes -- cgit v1.2.3 From ead0c6eed35c71cc990f8c5b6d98e20c6072c136 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 2 Dec 2010 14:49:02 -0800 Subject: removing more calls to deprecated methods --- activerecord/lib/active_record/associations/has_many_association.rb | 5 +++-- activerecord/lib/active_record/counter_cache.rb | 3 ++- activerecord/lib/active_record/relation.rb | 3 ++- 3 files changed, 7 insertions(+), 4 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 685d818ab3..4ff61fff45 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -67,9 +67,10 @@ module ActiveRecord @reflection.klass.delete(records.map { |record| record.id }) else relation = Arel::Table.new(@reflection.table_name) - relation.where(relation[@reflection.primary_key_name].eq(@owner.id). + stmt = relation.where(relation[@reflection.primary_key_name].eq(@owner.id). and(relation[@reflection.klass.primary_key].in(records.map { |r| r.id })) - ).update(relation[@reflection.primary_key_name] => nil) + ).compile_update(relation[@reflection.primary_key_name] => nil) + @owner.connection.update stmt.to_sql @owner.class.update_counters(@owner.id, cached_counter_attribute_name => -records.size) if has_cached_counter? end diff --git a/activerecord/lib/active_record/counter_cache.rb b/activerecord/lib/active_record/counter_cache.rb index ed0d4aef7f..8180bf0987 100644 --- a/activerecord/lib/active_record/counter_cache.rb +++ b/activerecord/lib/active_record/counter_cache.rb @@ -30,9 +30,10 @@ module ActiveRecord reflection = belongs_to.find { |e| e.class_name == expected_name } counter_name = reflection.counter_cache_column - self.unscoped.where(arel_table[self.primary_key].eq(object.id)).arel.update({ + stmt = unscoped.where(arel_table[primary_key].eq(object.id)).arel.compile_update({ arel_table[counter_name] => object.send(association).count }) + connection.update stmt.to_sql end return true end diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index bebdd1292c..646bf8f4be 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -156,7 +156,8 @@ module ActiveRecord else # Apply limit and order only if they're both present if @limit_value.present? == @order_values.present? - arel.update(Arel::SqlLiteral.new(@klass.send(:sanitize_sql_for_assignment, updates))) + stmt = arel.compile_update(Arel::SqlLiteral.new(@klass.send(:sanitize_sql_for_assignment, updates))) + @klass.connection.update stmt.to_sql else except(:limit, :order).update_all(updates) end -- cgit v1.2.3 From 8c9b5e413ff9bab8607377223dd42a0ff4375405 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 2 Dec 2010 15:06:43 -0800 Subject: removing more calls to deprecated methods --- activerecord/lib/active_record/locking/optimistic.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb index c0e1dda2bd..e5065de7fb 100644 --- a/activerecord/lib/active_record/locking/optimistic.rb +++ b/activerecord/lib/active_record/locking/optimistic.rb @@ -87,11 +87,13 @@ module ActiveRecord begin relation = self.class.unscoped - affected_rows = relation.where( + stmt = relation.where( relation.table[self.class.primary_key].eq(quoted_id).and( relation.table[lock_col].eq(quote_value(previous_value)) ) - ).arel.update(arel_attributes_values(false, false, attribute_names)) + ).arel.compile_update(arel_attributes_values(false, false, attribute_names)) + + affected_rows = connection.update stmt.to_sql unless affected_rows == 1 raise ActiveRecord::StaleObjectError, "Attempted to update a stale object: #{self.class.name}" -- cgit v1.2.3 From b0fc912f1b829391760b50107dad365fa87c744f Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 2 Dec 2010 15:50:34 -0800 Subject: avoid deprecate api --- activerecord/lib/active_record/relation.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 646bf8f4be..3009bb70c1 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -271,7 +271,14 @@ module ActiveRecord # If you need to destroy dependent associations or call your before_* or # +after_destroy+ callbacks, use the +destroy_all+ method instead. def delete_all(conditions = nil) - conditions ? where(conditions).delete_all : arel.delete.tap { reset } + if conditions + where(conditions).delete_all + else + statement = arel.compile_delete + affected = @klass.connection.delete statement.to_sql + reset + affected + end end # Deletes the row with a primary key matching the +id+ argument, using a -- cgit v1.2.3 From 9a3e29e126d9daf6175b4d2be50112d1c8771d17 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 2 Dec 2010 15:56:55 -0800 Subject: remove calls to deprecated methods --- .../associations/has_and_belongs_to_many_association.rb | 5 +++-- activerecord/lib/active_record/migration.rb | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb index 367104ec1b..e2ce9aefcf 100644 --- a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb +++ b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb @@ -76,9 +76,10 @@ module ActiveRecord records.each { |record| @owner.connection.delete(interpolate_sql(sql, record)) } else relation = Arel::Table.new(@reflection.options[:join_table]) - relation.where(relation[@reflection.primary_key_name].eq(@owner.id). + stmt = relation.where(relation[@reflection.primary_key_name].eq(@owner.id). and(relation[@reflection.association_foreign_key].in(records.map { |x| x.id }.compact)) - ).delete + ).compile_delete + @owner.connection.delete stmt.to_sql end end diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index b4b9dfab88..d80416149e 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -696,7 +696,8 @@ module ActiveRecord @migrated_versions ||= [] if down? @migrated_versions.delete(version) - table.where(table["version"].eq(version.to_s)).delete + stmt = table.where(table["version"].eq(version.to_s)).compile_delete + Base.connection.delete stmt.to_sql else @migrated_versions.push(version).sort! stmt = table.compile_insert table["version"] => version.to_s -- cgit v1.2.3 From 47737681fdfe4986dc7426b174f81d2b8daca991 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 3 Dec 2010 11:44:11 -0800 Subject: in the middle of refactoring --- activerecord/lib/active_record/migration.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index d80416149e..4dc67a0905 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -518,6 +518,7 @@ module ActiveRecord when target_version.nil? up(migrations_path, target_version) when current_version == 0 && target_version == 0 + [] when current_version > target_version down(migrations_path, target_version) else @@ -647,6 +648,7 @@ module ActiveRecord # skip the last migration if we're headed down, but not ALL the way down runnable.pop if down? && target + ran = [] runnable.each do |migration| Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger @@ -666,11 +668,13 @@ module ActiveRecord migration.migrate(@direction) record_version_state_after_migrating(migration.version) end + ran << migration rescue => e canceled_msg = Base.connection.supports_ddl_transactions? ? "this and " : "" raise StandardError, "An error has occurred, #{canceled_msg}all later migrations canceled:\n\n#{e}", e.backtrace end end + ran end def migrations -- cgit v1.2.3 From d21f38aaa204ee8df81bd34a6dad3d6de8ad63d9 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 3 Dec 2010 15:33:59 -0800 Subject: use the columns hash for primary key lookup --- activerecord/lib/active_record/relation/finder_methods.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 1da7411589..51ba17c9be 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -290,7 +290,7 @@ module ActiveRecord def find_one(id) id = id.id if ActiveRecord::Base === id - column = primary_key.column + column = columns_hash[primary_key.name.to_s] substitute = connection.substitute_for(column, @bind_values) relation = where(primary_key.eq(substitute)) -- cgit v1.2.3 From 3e842559427746eb9051ce5ee3cd36caeff303a3 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 3 Dec 2010 22:31:05 -0200 Subject: attributes_before_type_cast are just the value of @attributes --- activerecord/lib/active_record/attribute_methods/before_type_cast.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/attribute_methods/before_type_cast.rb b/activerecord/lib/active_record/attribute_methods/before_type_cast.rb index 23195b02f7..f7e5ef853f 100644 --- a/activerecord/lib/active_record/attribute_methods/before_type_cast.rb +++ b/activerecord/lib/active_record/attribute_methods/before_type_cast.rb @@ -13,7 +13,7 @@ module ActiveRecord # Returns a hash of attributes before typecasting and deserialization. def attributes_before_type_cast - Hash[attribute_names.map { |name| [name, read_attribute_before_type_cast(name)] }] + @attributes end private -- cgit v1.2.3 From a11ddf3ee2d2db0378c241a1fd0648b74ff48e20 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 3 Dec 2010 22:46:45 -0200 Subject: Fix indentation here --- .../active_record/attribute_methods/before_type_cast.rb | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/attribute_methods/before_type_cast.rb b/activerecord/lib/active_record/attribute_methods/before_type_cast.rb index f7e5ef853f..bde11d0494 100644 --- a/activerecord/lib/active_record/attribute_methods/before_type_cast.rb +++ b/activerecord/lib/active_record/attribute_methods/before_type_cast.rb @@ -17,14 +17,15 @@ module ActiveRecord end private - # Handle *_before_type_cast for method_missing. - def attribute_before_type_cast(attribute_name) - if attribute_name == 'id' - read_attribute_before_type_cast(self.class.primary_key) - else - read_attribute_before_type_cast(attribute_name) - end + + # Handle *_before_type_cast for method_missing. + def attribute_before_type_cast(attribute_name) + if attribute_name == 'id' + read_attribute_before_type_cast(self.class.primary_key) + else + read_attribute_before_type_cast(attribute_name) end + end end end end -- cgit v1.2.3 From c4809d9984ab5d20759075a96ddea6096ab93802 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 3 Dec 2010 22:41:54 -0200 Subject: use map instead of each --- activerecord/lib/active_record/base.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index ba7f6f0129..f54c9d118d 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1500,9 +1500,7 @@ MSG # Returns a hash of all the attributes with their names as keys and the values of the attributes as values. def attributes - attrs = {} - attribute_names.each { |name| attrs[name] = read_attribute(name) } - attrs + Hash[attribute_names.map { |name| [name, read_attribute(name)] }] end # Returns an #inspect-like string for the value of the -- cgit v1.2.3 From 20ba81e47d04b0ffd510c4de9c65a439b22a00b2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 3 Dec 2010 22:45:02 -0200 Subject: We can use the keys of the @attributes hash here and avoid a method call --- 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 f54c9d118d..b55aaddbd7 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1500,7 +1500,7 @@ MSG # Returns a hash of all the attributes with their names as keys and the values of the attributes as values. def attributes - Hash[attribute_names.map { |name| [name, read_attribute(name)] }] + Hash[@attributes.map { |name, _| [name, read_attribute(name)] }] end # Returns an #inspect-like string for the value of the -- cgit v1.2.3 From 70ab4502749d23464f06d50779aeea0b3275d67c Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 7 Dec 2010 14:01:37 -0800 Subject: cleaning up custom_join_sql method --- activerecord/lib/active_record/relation/query_methods.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 0483950db7..2933d427f0 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -163,13 +163,15 @@ module ActiveRecord end def custom_join_sql(joins) - arel = table.select_manager + joins = joins.reject { |join| join.blank? } - joins.each do |join| - next if join.blank? + return if joins.empty? - @implicit_readonly = true + @implicit_readonly = true + arel = table.select_manager + + joins.each do |join| case join when Array join = Arel.sql(join.join(' ')) if array_of_strings?(join) -- cgit v1.2.3 From ef79658bd143a9243eefa90db2f9ce300f18dd0d Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 7 Dec 2010 14:47:21 -0800 Subject: save the AR reference rather than delegating --- .../active_record/associations/class_methods/join_dependency.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index c578845878..9f171f891d 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -6,9 +6,10 @@ module ActiveRecord module Associations module ClassMethods class JoinDependency # :nodoc: - attr_reader :join_parts, :reflections, :table_aliases + attr_reader :join_parts, :reflections, :table_aliases, :active_record def initialize(base, associations, joins) + @active_record = base @table_joins = joins || '' @join_parts = [JoinBase.new(base)] @associations = {} @@ -45,7 +46,7 @@ module ActiveRecord def count_aliases_from_table_joins(name) # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase - quoted_name = join_base.active_record.connection.quote_table_name(name.downcase).downcase + quoted_name = active_record.connection.quote_table_name(name.downcase).downcase join_sql = @table_joins.downcase join_sql.blank? ? 0 : # Table names @@ -61,11 +62,11 @@ module ActiveRecord records = rows.map { |model| primary_id = model[primary_key] parent = parents[primary_id] ||= join_base.instantiate(model) - construct(parent, @associations, join_associations.dup, model) + construct(parent, @associations, join_associations, model) parent }.uniq - remove_duplicate_results!(join_base.active_record, records, @associations) + remove_duplicate_results!(active_record, records, @associations) records end -- cgit v1.2.3 From ddbd2039615ca4376a46a97a17612732f24568cd Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 7 Dec 2010 15:23:29 -0800 Subject: reduce string objects, reduce method calls --- .../active_record/associations/class_methods/join_dependency.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index 9f171f891d..34928bc764 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -10,7 +10,7 @@ module ActiveRecord def initialize(base, associations, joins) @active_record = base - @table_joins = joins || '' + @table_joins = joins @join_parts = [JoinBase.new(base)] @associations = {} @reflections = [] @@ -45,12 +45,13 @@ module ActiveRecord end def count_aliases_from_table_joins(name) + return 0 unless @table_joins + # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase quoted_name = active_record.connection.quote_table_name(name.downcase).downcase join_sql = @table_joins.downcase - join_sql.blank? ? 0 : - # Table names - join_sql.scan(/join(?:\s+\w+)?\s+#{quoted_name}\son/).size + + # Table names + join_sql.scan(/join(?:\s+\w+)?\s+#{quoted_name}\son/).size + # Table aliases join_sql.scan(/join(?:\s+\w+)?\s+\S+\s+#{quoted_name}\son/).size end -- cgit v1.2.3 From d6133209ce54bac430e63ec512251eae182b79e1 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 7 Dec 2010 15:23:50 -0800 Subject: arel is lazy about column information, so no need to pass it around --- .../associations/class_methods/join_dependency/join_base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_base.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_base.rb index 97003c1457..67567f06df 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_base.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_base.rb @@ -13,7 +13,7 @@ module ActiveRecord end def table - Arel::Table.new(table_name, :engine => arel_engine, :columns => active_record.columns) + Arel::Table.new(table_name, arel_engine) end def aliased_table_name -- cgit v1.2.3 From 2d9d6cd4c263f639adf8e26c7d95e7772e0c4eb7 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 7 Dec 2010 16:48:59 -0800 Subject: passing the ast to JoinDependency --- .../associations/class_methods/join_dependency.rb | 13 +++++++++++-- activerecord/lib/active_record/relation/finder_methods.rb | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index 34928bc764..86d43f21d3 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -45,11 +45,20 @@ module ActiveRecord end def count_aliases_from_table_joins(name) - return 0 unless @table_joins + return 0 if !@table_joins || Arel::Table === @table_joins + return count_aliases_from_string(@table_joins.downcase, name) if String === @table_joins + + @table_joins.grep(Arel::Table).find_all { |table| + table.name.downcase == name + }.length + @table_joins.grep(String).map { |s| + count_aliases_from_string(s, name) + }.sum + end + + def count_aliases_from_string(join_sql, name) # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase quoted_name = active_record.connection.quote_table_name(name.downcase).downcase - join_sql = @table_joins.downcase # Table names join_sql.scan(/join(?:\s+\w+)?\s+#{quoted_name}\son/).size + # Table aliases diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 51ba17c9be..906ad7699c 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -196,7 +196,7 @@ module ActiveRecord def construct_relation_for_association_calculations including = (@eager_load_values + @includes_values).uniq - join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, including, arel.join_sql) + join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, including, arel.froms.first) relation = except(:includes, :eager_load, :preload) apply_join_dependency(relation, join_dependency) end -- cgit v1.2.3 From d98cb5153dad97cde82ec91a1993043cfa9bc0e4 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 7 Dec 2010 17:05:15 -0800 Subject: JoinDependency is always created with an AST now --- .../associations/class_methods/join_dependency.rb | 14 ++++++++++---- activerecord/lib/active_record/relation/query_methods.rb | 16 +++++++++++++++- 2 files changed, 25 insertions(+), 5 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index 86d43f21d3..928e8152a5 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -49,10 +49,16 @@ module ActiveRecord return count_aliases_from_string(@table_joins.downcase, name) if String === @table_joins - @table_joins.grep(Arel::Table).find_all { |table| - table.name.downcase == name - }.length + @table_joins.grep(String).map { |s| - count_aliases_from_string(s, name) + @table_joins.grep(Arel::Nodes::Join).map { |join| + right = join.right + case right + when Arel::Table + right.name.downcase == name ? 1 : 0 + when String + count_aliases_from_string(right.downcase, name) + else + 0 + end }.sum end diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 2933d427f0..194ce881e0 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -185,6 +185,20 @@ module ActiveRecord arel.join_sql end + def custom_join_ast(joins) + joins = joins.reject { |join| join.blank? } + + return if joins.empty? + + @implicit_readonly = true + + head = table.create_string_join(table, joins.shift) + + joins.inject(head) do |ast, join| + ast.right = table.create_string_join(ast.right, join) + end + end + def build_arel arel = table @@ -256,7 +270,7 @@ module ActiveRecord non_association_joins = (joins - association_joins - stashed_association_joins) custom_joins = custom_join_sql(non_association_joins) - join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, custom_joins) + join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, custom_join_ast(non_association_joins)) join_dependency.graft(*stashed_association_joins) -- cgit v1.2.3 From 1d96d44da318faab8d213f330aebcecdbec52f5d Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 7 Dec 2010 18:54:04 -0800 Subject: passing the ast to a table when the relation is a table --- .../associations/class_methods/join_dependency.rb | 2 -- .../lib/active_record/relation/query_methods.rb | 23 +++++++++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index 928e8152a5..d508c3b7aa 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -47,8 +47,6 @@ module ActiveRecord def count_aliases_from_table_joins(name) return 0 if !@table_joins || Arel::Table === @table_joins - return count_aliases_from_string(@table_joins.downcase, name) if String === @table_joins - @table_joins.grep(Arel::Nodes::Join).map { |join| right = join.right case right diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 194ce881e0..df41f756ce 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -185,18 +185,30 @@ module ActiveRecord arel.join_sql end - def custom_join_ast(joins) + def custom_join_ast(table, joins) joins = joins.reject { |join| join.blank? } return if joins.empty? @implicit_readonly = true + joins.map! do |join| + case join + when Array + join = Arel.sql(join.join(' ')) if array_of_strings?(join) + when String + join = Arel.sql(join) + end + join + end + head = table.create_string_join(table, joins.shift) joins.inject(head) do |ast, join| ast.right = table.create_string_join(ast.right, join) end + + head end def build_arel @@ -269,8 +281,9 @@ module ActiveRecord non_association_joins = (joins - association_joins - stashed_association_joins) custom_joins = custom_join_sql(non_association_joins) + ast = custom_join_ast(relation, non_association_joins) - join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, custom_join_ast(non_association_joins)) + join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, ast) join_dependency.graft(*stashed_association_joins) @@ -280,7 +293,11 @@ module ActiveRecord relation = association.join_to(relation) end - relation.join(custom_joins) + if Arel::Table === relation + relation.from(ast || relation) + else + relation.join(custom_joins) + end end def build_select(arel, selects) -- cgit v1.2.3 From 2fd385d47163149ec74029731bc29370fa768735 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 8 Dec 2010 10:29:52 -0800 Subject: reducing use of custom joins --- activerecord/lib/active_record/relation/query_methods.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index df41f756ce..705bf21eae 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -296,7 +296,12 @@ module ActiveRecord if Arel::Table === relation relation.from(ast || relation) else - relation.join(custom_joins) + if relation.froms.length > 0 && ast + ast.left = relation.froms.first + relation.from ast + else + relation.join(custom_joins) + end end end -- cgit v1.2.3 From ddd6dee04343d3731b2f2fc558501c3707cde8fb Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 8 Dec 2010 10:35:26 -0800 Subject: further reducing dependence on custom_joins --- activerecord/lib/active_record/relation/query_methods.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 705bf21eae..3a2cbc8dda 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -299,6 +299,8 @@ module ActiveRecord if relation.froms.length > 0 && ast ast.left = relation.froms.first relation.from ast + elsif relation.froms.length == 0 && ast + relation.from(ast) else relation.join(custom_joins) end -- cgit v1.2.3 From 3499f882cc62e891057f806cf9a09a84f97a5e5c Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 8 Dec 2010 10:54:24 -0800 Subject: renaming variables, making the join_ast method private --- .../lib/active_record/relation/query_methods.rb | 78 ++++++++-------------- 1 file changed, 27 insertions(+), 51 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 3a2cbc8dda..f9e5d7d925 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -162,29 +162,32 @@ module ActiveRecord @arel ||= build_arel end - def custom_join_sql(joins) - joins = joins.reject { |join| join.blank? } + def build_arel + arel = table - return if joins.empty? + arel = build_joins(arel, @joins_values) unless @joins_values.empty? - @implicit_readonly = true + arel = collapse_wheres(arel, (@where_values - ['']).uniq) - arel = table.select_manager + arel = arel.having(*@having_values.uniq.reject{|h| h.blank?}) unless @having_values.empty? - joins.each do |join| - case join - when Array - join = Arel.sql(join.join(' ')) if array_of_strings?(join) - when String - join = Arel.sql(join) - end + arel = arel.take(@limit_value) if @limit_value + arel = arel.skip(@offset_value) if @offset_value - arel.join(join) - end + arel = arel.group(*@group_values.uniq.reject{|g| g.blank?}) unless @group_values.empty? - arel.join_sql + arel = arel.order(*@order_values.uniq.reject{|o| o.blank?}) unless @order_values.empty? + + arel = build_select(arel, @select_values.uniq) + + arel = arel.from(@from_value) if @from_value + arel = arel.lock(@lock_value) if @lock_value + + arel end + private + def custom_join_ast(table, joins) joins = joins.reject { |join| join.blank? } @@ -211,32 +214,6 @@ module ActiveRecord head end - def build_arel - arel = table - - arel = build_joins(arel, @joins_values) unless @joins_values.empty? - - arel = collapse_wheres(arel, (@where_values - ['']).uniq) - - arel = arel.having(*@having_values.uniq.reject{|h| h.blank?}) unless @having_values.empty? - - arel = arel.take(@limit_value) if @limit_value - arel = arel.skip(@offset_value) if @offset_value - - arel = arel.group(*@group_values.uniq.reject{|g| g.blank?}) unless @group_values.empty? - - arel = arel.order(*@order_values.uniq.reject{|o| o.blank?}) unless @order_values.empty? - - arel = build_select(arel, @select_values.uniq) - - arel = arel.from(@from_value) if @from_value - arel = arel.lock(@lock_value) if @lock_value - - arel - end - - private - def collapse_wheres(arel, wheres) equalities = wheres.grep(Arel::Nodes::Equality) @@ -280,10 +257,9 @@ module ActiveRecord stashed_association_joins = joins.grep(ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation) non_association_joins = (joins - association_joins - stashed_association_joins) - custom_joins = custom_join_sql(non_association_joins) - ast = custom_join_ast(relation, non_association_joins) + join_ast = custom_join_ast(relation, non_association_joins) - join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, ast) + join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, join_ast) join_dependency.graft(*stashed_association_joins) @@ -294,15 +270,15 @@ module ActiveRecord end if Arel::Table === relation - relation.from(ast || relation) + relation.from(join_ast || relation) else - if relation.froms.length > 0 && ast - ast.left = relation.froms.first - relation.from ast - elsif relation.froms.length == 0 && ast - relation.from(ast) + if relation.froms.length > 0 && join_ast + join_ast.left = relation.froms.first + relation.from join_ast + elsif relation.froms.length == 0 && join_ast + relation.from(join_ast) else - relation.join(custom_joins) + relation end end end -- cgit v1.2.3 From 17d72dd19fc7f979ae17097c3ee1e0b5c1d75fb7 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 8 Dec 2010 11:02:15 -0800 Subject: adding a fixme comment --- activerecord/lib/active_record/relation/query_methods.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index f9e5d7d925..6886c7538b 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -265,6 +265,7 @@ module ActiveRecord @implicit_readonly = true unless association_joins.empty? && stashed_association_joins.empty? + # FIXME: refactor this to build an AST join_dependency.join_associations.each do |association| relation = association.join_to(relation) end -- cgit v1.2.3 From f4223cc7abeeae5f4849eab27951faa55f3c6996 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 8 Dec 2010 11:18:26 -0800 Subject: arel ignores the columns parameter --- .../associations/class_methods/join_dependency/join_association.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index 4dd11a7366..2c20e304d0 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -67,8 +67,7 @@ module ActiveRecord def table @table ||= Arel::Table.new( - table_name, :as => aliased_table_name, - :engine => arel_engine, :columns => active_record.columns + table_name, :as => aliased_table_name, :engine => arel_engine ) end -- cgit v1.2.3 From b8d57a0400f95abe1b87634e9cada8868ff0a22e Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 8 Dec 2010 11:50:16 -0800 Subject: have table_aliases call count_aliases to set the default value --- .../lib/active_record/associations/class_methods/join_dependency.rb | 4 +++- .../associations/class_methods/join_dependency/join_association.rb | 4 ---- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index d508c3b7aa..13576e1aec 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -14,7 +14,9 @@ module ActiveRecord @join_parts = [JoinBase.new(base)] @associations = {} @reflections = [] - @table_aliases = Hash.new(0) + @table_aliases = Hash.new do |h,name| + h[name] = count_aliases_from_table_joins(name) + end @table_aliases[base.table_name] = 1 build(associations) end diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index 2c20e304d0..15c1e7de55 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -77,10 +77,6 @@ module ActiveRecord protected def aliased_table_name_for(name, suffix = nil) - if @join_dependency.table_aliases[name].zero? - @join_dependency.table_aliases[name] = @join_dependency.count_aliases_from_table_joins(name) - end - if !@join_dependency.table_aliases[name].zero? # We need an alias name = active_record.connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}#{suffix}" @join_dependency.table_aliases[name] += 1 -- cgit v1.2.3 From de4bd472c3298f0455de8e3862c31900184f3c31 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 8 Dec 2010 11:54:45 -0800 Subject: remove code that could never be executed --- .../associations/class_methods/join_dependency/join_association.rb | 4 ---- 1 file changed, 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index 15c1e7de55..9c43e9edd7 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -80,10 +80,6 @@ module ActiveRecord if !@join_dependency.table_aliases[name].zero? # We need an alias name = active_record.connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}#{suffix}" @join_dependency.table_aliases[name] += 1 - if @join_dependency.table_aliases[name] == 1 # First time we've seen this name - # Also need to count the aliases from the table_aliases to avoid incorrect count - @join_dependency.table_aliases[name] += @join_dependency.count_aliases_from_table_joins(name) - end table_index = @join_dependency.table_aliases[name] name = name[0..active_record.connection.table_alias_length-3] + "_#{table_index}" if table_index > 1 else -- cgit v1.2.3 From dcc0c9a8bb49d956476a7165f3eef6699ec4628b Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 8 Dec 2010 12:05:02 -0800 Subject: dry up calls to table_aliases --- .../class_methods/join_dependency/join_association.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index 9c43e9edd7..bf0190e40a 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -77,13 +77,15 @@ module ActiveRecord protected def aliased_table_name_for(name, suffix = nil) - if !@join_dependency.table_aliases[name].zero? # We need an alias + aliases = @join_dependency.table_aliases + + if !aliases[name].zero? # We need an alias name = active_record.connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}#{suffix}" - @join_dependency.table_aliases[name] += 1 - table_index = @join_dependency.table_aliases[name] + aliases[name] += 1 + table_index = aliases[name] name = name[0..active_record.connection.table_alias_length-3] + "_#{table_index}" if table_index > 1 else - @join_dependency.table_aliases[name] += 1 + aliases[name] += 1 end name -- cgit v1.2.3 From c69bd59a9cc7c0de3d6db7f8c90e73778516debf Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 8 Dec 2010 12:09:00 -0800 Subject: only call active_record once --- .../associations/class_methods/join_dependency/join_association.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index bf0190e40a..09094f3ed5 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -80,10 +80,12 @@ module ActiveRecord aliases = @join_dependency.table_aliases if !aliases[name].zero? # We need an alias - name = active_record.connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}#{suffix}" + connection = active_record.connection + + name = connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}#{suffix}" aliases[name] += 1 table_index = aliases[name] - name = name[0..active_record.connection.table_alias_length-3] + "_#{table_index}" if table_index > 1 + name = name[0, connection.table_alias_length-3] + "_#{table_index}" if table_index > 1 else aliases[name] += 1 end -- cgit v1.2.3 From 45ea60eee7e6284768b78d51dbed4a2913aa18dd Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 8 Dec 2010 12:11:43 -0800 Subject: fewer method calls, fewer code branches --- .../class_methods/join_dependency/join_association.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index 09094f3ed5..25511a092f 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -79,17 +79,16 @@ module ActiveRecord def aliased_table_name_for(name, suffix = nil) aliases = @join_dependency.table_aliases - if !aliases[name].zero? # We need an alias + if aliases[name] != 0 # We need an alias connection = active_record.connection name = connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}#{suffix}" - aliases[name] += 1 - table_index = aliases[name] + table_index = aliases[name] + 1 name = name[0, connection.table_alias_length-3] + "_#{table_index}" if table_index > 1 - else - aliases[name] += 1 end + aliases[name] += 1 + name end -- cgit v1.2.3 From 53bbbcc6638a9df86e74e4e420840f076e7c2994 Mon Sep 17 00:00:00 2001 From: Ivan Evtukhovich Date: Thu, 9 Dec 2010 00:41:47 +0300 Subject: Fix doc about nested transaction rollback Because AR::Rollback do not reraise and inner transaction is not "real" nothing rollback at all --- activerecord/lib/active_record/transactions.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index 654c475aed..181280baaa 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -141,7 +141,8 @@ module ActiveRecord # end # end # - # User.find(:all) # => empty + # User.find(:all) # => Return both Kotori and Nemu, because inner transaction do not rollback + # # without :requiers_new => true option, and Rollback exception do not reraise # # It is also possible to requires a sub-transaction by passing # :requires_new => true. If anything goes wrong, the -- cgit v1.2.3 From e924814b28d655242a49f543cf453d55712071b1 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 8 Dec 2010 13:40:10 -0800 Subject: just allocate the table in initialize --- .../class_methods/join_dependency/join_association.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index 25511a092f..b063d927b9 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -42,6 +42,9 @@ module ActiveRecord # depends on the state of the join dependency, but we want it to work the same way # every time. allocate_aliases + @table = Arel::Table.new( + table_name, :as => aliased_table_name, :engine => arel_engine + ) end def ==(other) @@ -65,12 +68,7 @@ module ActiveRecord joining_relation.joins(self) end - def table - @table ||= Arel::Table.new( - table_name, :as => aliased_table_name, :engine => arel_engine - ) - end - + attr_reader :table # More semantic name given we are talking about associations alias_method :target_table, :table -- cgit v1.2.3 From d0467e08e54a84fc4672c508716615aa0177994a Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 3 Dec 2010 13:12:59 +0100 Subject: Allow to run migrations from more than one directory --- .../abstract/schema_statements.rb | 6 ++- activerecord/lib/active_record/migration.rb | 57 +++++++++++++--------- activerecord/lib/active_record/schema.rb | 6 +-- 3 files changed, 40 insertions(+), 29 deletions(-) (limited to 'activerecord/lib/active_record') 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 4e770c37da..3eb81b0dfa 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -442,12 +442,14 @@ module ActiveRecord end end - def assume_migrated_upto_version(version, migrations_path = ActiveRecord::Migrator.migrations_path) + def assume_migrated_upto_version(version, migrations_paths = ActiveRecord::Migrator.migrations_paths) + migrations_paths = [migrations_paths] unless migrations_paths.kind_of?(Array) version = version.to_i sm_table = quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name) migrated = select_values("SELECT version FROM #{sm_table}").map { |v| v.to_i } - versions = Dir["#{migrations_path}/[0-9]*_*.rb"].map do |filename| + paths = migrations_paths.map {|p| "#{p}/[0-9]*_*.rb" } + versions = Dir[*paths].map do |filename| filename.split('/').last.split('_').first.to_i end diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 4dc67a0905..130b43cc15 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -511,39 +511,40 @@ module ActiveRecord class Migrator#:nodoc: class << self - attr_writer :migrations_path + attr_writer :migrations_paths + alias :migrations_path= :migrations_paths= - def migrate(migrations_path, target_version = nil) + def migrate(migrations_paths, target_version = nil) case when target_version.nil? - up(migrations_path, target_version) + up(migrations_paths, target_version) when current_version == 0 && target_version == 0 [] when current_version > target_version - down(migrations_path, target_version) + down(migrations_paths, target_version) else - up(migrations_path, target_version) + up(migrations_paths, target_version) end end - def rollback(migrations_path, steps=1) - move(:down, migrations_path, steps) + def rollback(migrations_paths, steps=1) + move(:down, migrations_paths, steps) end - def forward(migrations_path, steps=1) - move(:up, migrations_path, steps) + def forward(migrations_paths, steps=1) + move(:up, migrations_paths, steps) end - def up(migrations_path, target_version = nil) - self.new(:up, migrations_path, target_version).migrate + def up(migrations_paths, target_version = nil) + self.new(:up, migrations_paths, target_version).migrate end - def down(migrations_path, target_version = nil) - self.new(:down, migrations_path, target_version).migrate + def down(migrations_paths, target_version = nil) + self.new(:down, migrations_paths, target_version).migrate end - def run(direction, migrations_path, target_version) - self.new(direction, migrations_path, target_version).run + def run(direction, migrations_paths, target_version) + self.new(direction, migrations_paths, target_version).run end def schema_migrations_table_name @@ -569,12 +570,20 @@ module ActiveRecord name.table_name rescue "#{ActiveRecord::Base.table_name_prefix}#{name}#{ActiveRecord::Base.table_name_suffix}" end + def migrations_paths + @migrations_paths ||= ['db/migrate'] + # just to not break things if someone uses: migration_path = some_string + @migrations_paths.kind_of?(Array) ? @migrations_paths : [@migrations_paths] + end + def migrations_path - @migrations_path ||= 'db/migrate' + migrations_paths.first end - def migrations(path) - files = Dir["#{path}/[0-9]*_*.rb"] + def migrations(paths) + paths = [paths] unless paths.kind_of?(Array) + + files = Dir[*paths.map { |p| "#{p}/[0-9]*_*.rb" }] seen = Hash.new false @@ -598,22 +607,22 @@ module ActiveRecord private - def move(direction, migrations_path, steps) - migrator = self.new(direction, migrations_path) + def move(direction, migrations_paths, steps) + migrator = self.new(direction, migrations_paths) start_index = migrator.migrations.index(migrator.current_migration) if start_index finish = migrator.migrations[start_index + steps] version = finish ? finish.version : 0 - send(direction, migrations_path, version) + send(direction, migrations_paths, version) end end end - def initialize(direction, migrations_path, target_version = nil) + def initialize(direction, migrations_paths, target_version = nil) raise StandardError.new("This database does not yet support migrations") unless Base.connection.supports_migrations? Base.connection.initialize_schema_migrations_table - @direction, @migrations_path, @target_version = direction, migrations_path, target_version + @direction, @migrations_paths, @target_version = direction, migrations_paths, target_version end def current_version @@ -679,7 +688,7 @@ module ActiveRecord def migrations @migrations ||= begin - migrations = self.class.migrations(@migrations_path) + migrations = self.class.migrations(@migrations_paths) down? ? migrations.reverse : migrations end end diff --git a/activerecord/lib/active_record/schema.rb b/activerecord/lib/active_record/schema.rb index c6bb5c1961..d815ab05ac 100644 --- a/activerecord/lib/active_record/schema.rb +++ b/activerecord/lib/active_record/schema.rb @@ -30,8 +30,8 @@ module ActiveRecord # ActiveRecord::Schema is only supported by database adapters that also # support migrations, the two features being very similar. class Schema < Migration - def migrations_path - ActiveRecord::Migrator.migrations_path + def migrations_paths + ActiveRecord::Migrator.migrations_paths end # Eval the given block. All methods available to the current connection @@ -51,7 +51,7 @@ module ActiveRecord unless info[:version].blank? initialize_schema_migrations_table - assume_migrated_upto_version(info[:version], schema.migrations_path) + assume_migrated_upto_version(info[:version], schema.migrations_paths) end end end -- cgit v1.2.3 From c9d23214aefcf0bcebb56fce53eefa4598cbb64d Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 3 Dec 2010 13:41:51 +0100 Subject: Allow to run migrations from more than one directory in rake tasks --- activerecord/lib/active_record/railties/databases.rake | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 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 1fbc8a1d32..316e0d9a3b 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -2,7 +2,7 @@ namespace :db do task :load_config => :rails_env do require 'active_record' ActiveRecord::Base.configurations = Rails.application.config.database_configuration - ActiveRecord::Migrator.migrations_path = Rails.application.paths["db/migrate"].first + ActiveRecord::Migrator.migrations_paths = Rails.application.paths["db/migrate"].to_a end namespace :create do @@ -140,7 +140,7 @@ namespace :db do desc "Migrate the database (options: VERSION=x, VERBOSE=false)." task :migrate => :environment do ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true - ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_path, ENV["VERSION"] ? ENV["VERSION"].to_i : nil) + ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, ENV["VERSION"] ? ENV["VERSION"].to_i : nil) Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end @@ -163,7 +163,7 @@ namespace :db do task :up => :environment do version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil raise "VERSION is required" unless version - ActiveRecord::Migrator.run(:up, ActiveRecord::Migrator.migrations_path, version) + ActiveRecord::Migrator.run(:up, ActiveRecord::Migrator.migrations_paths, version) Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end @@ -171,7 +171,7 @@ namespace :db do task :down => :environment do version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil raise "VERSION is required" unless version - ActiveRecord::Migrator.run(:down, ActiveRecord::Migrator.migrations_path, version) + ActiveRecord::Migrator.run(:down, ActiveRecord::Migrator.migrations_paths, version) Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end @@ -209,14 +209,14 @@ namespace :db do desc 'Rolls the schema back to the previous version (specify steps w/ STEP=n).' task :rollback => :environment do step = ENV['STEP'] ? ENV['STEP'].to_i : 1 - ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_path, step) + ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_paths, step) Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end # desc 'Pushes the schema to the next version (specify steps w/ STEP=n).' task :forward => :environment do step = ENV['STEP'] ? ENV['STEP'].to_i : 1 - ActiveRecord::Migrator.forward(ActiveRecord::Migrator.migrations_path, step) + ActiveRecord::Migrator.forward(ActiveRecord::Migrator.migrations_paths, step) Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end @@ -261,7 +261,7 @@ namespace :db do # desc "Raises an error if there are pending migrations" task :abort_if_pending_migrations => :environment do if defined? ActiveRecord - pending_migrations = ActiveRecord::Migrator.new(:up, ActiveRecord::Migrator.migrations_path).pending_migrations + pending_migrations = ActiveRecord::Migrator.new(:up, ActiveRecord::Migrator.migrations_paths).pending_migrations if pending_migrations.any? puts "You have #{pending_migrations.size} pending migrations:" @@ -501,7 +501,7 @@ namespace :railties do puts "Copied migration #{migration.basename} from #{name}" end - ActiveRecord::Migration.copy( ActiveRecord::Migrator.migrations_path, railties, + ActiveRecord::Migration.copy( ActiveRecord::Migrator.migrations_paths.first, railties, :on_skip => on_skip, :on_copy => on_copy) end end -- cgit v1.2.3 From 23ba7e456dd0302aeaddb50d14e1f595c82ca6c8 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 4 Dec 2010 08:33:06 +0100 Subject: properly load database config in database rake tasks, to properly set migrations_paths --- activerecord/lib/active_record/railties/databases.rake | 14 +++++++------- 1 file changed, 7 insertions(+), 7 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 316e0d9a3b..f1e21bea3f 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -138,7 +138,7 @@ namespace :db do desc "Migrate the database (options: VERSION=x, VERBOSE=false)." - task :migrate => :environment do + 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) Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby @@ -146,7 +146,7 @@ namespace :db do namespace :migrate do # desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).' - task :redo => :environment do + task :redo => [:environment, :load_config] do if ENV["VERSION"] Rake::Task["db:migrate:down"].invoke Rake::Task["db:migrate:up"].invoke @@ -160,7 +160,7 @@ namespace :db do task :reset => ["db:drop", "db:create", "db:migrate"] # desc 'Runs the "up" for a given migration VERSION.' - task :up => :environment do + task :up => [:environment, :load_config] do version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil raise "VERSION is required" unless version ActiveRecord::Migrator.run(:up, ActiveRecord::Migrator.migrations_paths, version) @@ -168,7 +168,7 @@ namespace :db do end # desc 'Runs the "down" for a given migration VERSION.' - task :down => :environment do + task :down => [:environment, :load_config] do version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil raise "VERSION is required" unless version ActiveRecord::Migrator.run(:down, ActiveRecord::Migrator.migrations_paths, version) @@ -176,7 +176,7 @@ namespace :db do end desc "Display status of migrations" - task :status => :environment do + task :status => [:environment, :load_config] do config = ActiveRecord::Base.configurations[Rails.env || 'development'] ActiveRecord::Base.establish_connection(config) unless ActiveRecord::Base.connection.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name) @@ -207,14 +207,14 @@ namespace :db do end desc 'Rolls the schema back to the previous version (specify steps w/ STEP=n).' - task :rollback => :environment do + task :rollback => [:environment, :load_config] do step = ENV['STEP'] ? ENV['STEP'].to_i : 1 ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_paths, step) Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end # desc 'Pushes the schema to the next version (specify steps w/ STEP=n).' - task :forward => :environment do + task :forward => [:environment, :load_config] do step = ENV['STEP'] ? ENV['STEP'].to_i : 1 ActiveRecord::Migrator.forward(ActiveRecord::Migrator.migrations_paths, step) Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby -- cgit v1.2.3 From 7ecee054a322e214e4f285b1a8327751bd79a418 Mon Sep 17 00:00:00 2001 From: Jeff Dean Date: Fri, 3 Dec 2010 23:16:45 -0700 Subject: Setting the id of a belongs_to object updates all referenced objects [#2989 state:resolved] --- activerecord/lib/active_record/associations.rb | 37 ++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 0d9171d876..4711522b00 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1223,12 +1223,14 @@ module ActiveRecord if reflection.options[:polymorphic] association_accessor_methods(reflection, BelongsToPolymorphicAssociation) + association_foreign_type_setter_method(reflection) else association_accessor_methods(reflection, BelongsToAssociation) association_constructor_method(:build, reflection, BelongsToAssociation) association_constructor_method(:create, reflection, BelongsToAssociation) end + association_foreign_key_setter_method(reflection) add_counter_cache_callbacks(reflection) if options[:counter_cache] add_touch_callbacks(reflection, options[:touch]) if options[:touch] @@ -1555,6 +1557,41 @@ module ActiveRecord end end + def association_foreign_key_setter_method(reflection) + setters = reflect_on_all_associations(:belongs_to).map do |belongs_to_reflection| + if belongs_to_reflection.primary_key_name == reflection.primary_key_name + "association_instance_set(:#{belongs_to_reflection.name}, nil);" + end + end.compact.join + + class_eval <<-FILE, __FILE__, __LINE__ + 1 + def #{reflection.primary_key_name}=(new_id) + write_attribute :#{reflection.primary_key_name}, new_id + if #{reflection.primary_key_name}_changed? + #{ setters } + end + end + FILE + end + + def association_foreign_type_setter_method(reflection) + setters = reflect_on_all_associations(:belongs_to).map do |belongs_to_reflection| + if belongs_to_reflection.options[:foreign_type] == reflection.options[:foreign_type] + "association_instance_set(:#{belongs_to_reflection.name}, nil);" + end + end.compact.join + + field = reflection.options[:foreign_type] + class_eval <<-FILE, __FILE__, __LINE__ + 1 + def #{field}=(new_id) + write_attribute :#{field}, new_id + if #{field}_changed? + #{ setters } + end + end + FILE + end + def add_counter_cache_callbacks(reflection) cache_column = reflection.counter_cache_column -- cgit v1.2.3 From 6c5b734e6a529284bab4c7bdca770d390b8b9084 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 8 Dec 2010 15:37:13 -0800 Subject: removing method to prevent warnings --- activerecord/lib/active_record/associations.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 4711522b00..cdc8f25119 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1564,6 +1564,10 @@ module ActiveRecord end end.compact.join + if method_defined?(:"#{reflection.primary_key_name}=") + undef_method :"#{reflection.primary_key_name}=" + end + class_eval <<-FILE, __FILE__, __LINE__ + 1 def #{reflection.primary_key_name}=(new_id) write_attribute :#{reflection.primary_key_name}, new_id -- cgit v1.2.3 From 7a237d56aa38c51987af0fd52d001989c4f3da07 Mon Sep 17 00:00:00 2001 From: Aditya Sanghi Date: Mon, 29 Nov 2010 18:13:17 +0530 Subject: Ensure that boolean false is properly serialized [#6079 state:resolved] --- activerecord/lib/active_record/attribute_methods/read.rb | 3 ++- activerecord/lib/active_record/base.rb | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index ad5a3e7562..506f6e878f 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -85,7 +85,8 @@ module ActiveRecord def _read_attribute(attr_name) attr_name = attr_name.to_s attr_name = self.class.primary_key if attr_name == 'id' - if value = @attributes[attr_name] + value = @attributes[attr_name] + unless value.nil? if column = column_for_attribute(attr_name) if unserializable_attribute?(attr_name, column) unserialize_attribute(attr_name) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index b55aaddbd7..7b9ce21ceb 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1680,7 +1680,7 @@ MSG if include_readonly_attributes || (!include_readonly_attributes && !self.class.readonly_attributes.include?(name)) value = read_attribute(name) - if value && self.class.serialized_attributes.key?(name) + if !value.nil? && self.class.serialized_attributes.key?(name) value = YAML.dump value end attrs[self.class.arel_table[name]] = value -- cgit v1.2.3 From 5df72a238e9fcb18daf6ab6e6dc9051c9106d7bb Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 4 Dec 2010 17:12:57 +0100 Subject: Rake tasks for managing database while development and testing of engines Some of the engines needs database. As engine needs to be run inside Rails application, migrations and other database operations are run from dummy application. To make that process simple I changed db tasks to look for migrations in both engine's and application's db/migrate directory. You can run all of the database tasks from test/dummy or directly from engine with prefix app, like: rake app:db:migrate rake app:db:migrate:redo --- .../lib/active_record/railties/databases.rake | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 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 f1e21bea3f..2e73cd4f1d 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -1,4 +1,4 @@ -namespace :db do +db_namespace = namespace :db do task :load_config => :rails_env do require 'active_record' ActiveRecord::Base.configurations = Rails.application.config.database_configuration @@ -141,18 +141,18 @@ namespace :db do 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) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby + db_namespace["schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end namespace :migrate do # desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).' task :redo => [:environment, :load_config] do if ENV["VERSION"] - Rake::Task["db:migrate:down"].invoke - Rake::Task["db:migrate:up"].invoke + db_namespace["migrate:down"].invoke + db_namespace["migrate:up"].invoke else - Rake::Task["db:rollback"].invoke - Rake::Task["db:migrate"].invoke + db_namespace["rollback"].invoke + db_namespace["migrate"].invoke end end @@ -164,7 +164,7 @@ namespace :db do version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil raise "VERSION is required" unless version ActiveRecord::Migrator.run(:up, ActiveRecord::Migrator.migrations_paths, version) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby + db_namespace["schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end # desc 'Runs the "down" for a given migration VERSION.' @@ -172,7 +172,7 @@ namespace :db do version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil raise "VERSION is required" unless version ActiveRecord::Migrator.run(:down, ActiveRecord::Migrator.migrations_paths, version) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby + db_namespace["schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end desc "Display status of migrations" @@ -210,14 +210,14 @@ namespace :db do task :rollback => [:environment, :load_config] do step = ENV['STEP'] ? ENV['STEP'].to_i : 1 ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_paths, step) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby + db_namespace["schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end # desc 'Pushes the schema to the next version (specify steps w/ STEP=n).' task :forward => [:environment, :load_config] do step = ENV['STEP'] ? ENV['STEP'].to_i : 1 ActiveRecord::Migrator.forward(ActiveRecord::Migrator.migrations_paths, step) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby + db_namespace["schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end # desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.' @@ -321,12 +321,12 @@ namespace :db do namespace :schema do desc "Create a db/schema.rb file that can be portably used against any DB supported by AR" - task :dump => :environment do + task :dump => :load_config do require 'active_record/schema_dumper' File.open(ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb", "w") do |file| ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file) end - Rake::Task["db:schema:dump"].reenable + db_namespace["schema:dump"].reenable end desc "Load a schema.rb file into the database" @@ -383,7 +383,7 @@ namespace :db do task :load => 'db:test:purge' do ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test']) ActiveRecord::Schema.verbose = false - Rake::Task["db:schema:load"].invoke + db_namespace["schema:load"].invoke end # desc "Recreate the test database from the current environment's database schema" @@ -457,7 +457,7 @@ namespace :db do # desc 'Check for pending migrations and load the test schema' task :prepare => 'db:abort_if_pending_migrations' do if defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank? - Rake::Task[{ :sql => "db:test:clone_structure", :ruby => "db:test:load" }[ActiveRecord::Base.schema_format]].invoke + db_namespace[{ :sql => "test:clone_structure", :ruby => "test:load" }[ActiveRecord::Base.schema_format]].invoke end end end -- cgit v1.2.3 From 07b0e59988beb1b29bdfadd02f0d015eae9191cf Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 8 Dec 2010 17:31:20 -0800 Subject: use sort_by --- .../lib/active_record/associations/class_methods/join_dependency.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index 13576e1aec..1856395f2d 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -151,7 +151,7 @@ module ActiveRecord build(association, parent, join_type) end when Hash - associations.keys.sort{|a,b|a.to_s<=>b.to_s}.each do |name| + associations.keys.sort_by { |a| a.to_s }.each do |name| join_association = build(name, parent, join_type) build(associations[name], join_association, join_type) end -- cgit v1.2.3 From 7b9f634e15bfc3f92f4ac7e18537443a55306c10 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 8 Dec 2010 23:29:25 +0100 Subject: Refactor db:load:config to automatically pick additional migrations if ENGINE_PATH is available --- activerecord/lib/active_record/railties/databases.rake | 6 ++++++ 1 file changed, 6 insertions(+) (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 2e73cd4f1d..a4fc18148e 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -3,6 +3,12 @@ db_namespace = namespace :db do require 'active_record' ActiveRecord::Base.configurations = Rails.application.config.database_configuration ActiveRecord::Migrator.migrations_paths = Rails.application.paths["db/migrate"].to_a + + if defined?(ENGINE_PATH) && engine = Rails::Engine.find(ENGINE_PATH) + if engine.paths["db/migrate"].existent + ActiveRecord::Migrator.migrations_paths += engine.paths["db/migrate"].to_a + end + end end namespace :create do -- cgit v1.2.3 From e12810178cebc0c40a90b4aba3976537852b71b4 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 9 Dec 2010 18:04:44 +0100 Subject: Use Array.wrap instead of using ternary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- .../active_record/connection_adapters/abstract/schema_statements.rb | 2 +- activerecord/lib/active_record/migration.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') 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 3eb81b0dfa..d4aefada22 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -443,7 +443,7 @@ module ActiveRecord end def assume_migrated_upto_version(version, migrations_paths = ActiveRecord::Migrator.migrations_paths) - migrations_paths = [migrations_paths] unless migrations_paths.kind_of?(Array) + migrations_paths = Array.wrap(migrations_paths) version = version.to_i sm_table = quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name) diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 130b43cc15..ea9950de08 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -573,7 +573,7 @@ module ActiveRecord def migrations_paths @migrations_paths ||= ['db/migrate'] # just to not break things if someone uses: migration_path = some_string - @migrations_paths.kind_of?(Array) ? @migrations_paths : [@migrations_paths] + Array.wrap(@migrations_paths) end def migrations_path @@ -581,7 +581,7 @@ module ActiveRecord end def migrations(paths) - paths = [paths] unless paths.kind_of?(Array) + paths = Array.wrap(paths) files = Dir[*paths.map { |p| "#{p}/[0-9]*_*.rb" }] -- cgit v1.2.3 From bba3dacc3dc6ac379209f2eda0da5d2dd93d6b04 Mon Sep 17 00:00:00 2001 From: "Robert Pankowecki (Gavdi)" Date: Fri, 26 Nov 2010 19:16:13 +0100 Subject: Simplifies observer implementation [#6065 state:resolved] --- activerecord/lib/active_record/observer.rb | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/observer.rb b/activerecord/lib/active_record/observer.rb index 022cf109af..f0da4202bf 100644 --- a/activerecord/lib/active_record/observer.rb +++ b/activerecord/lib/active_record/observer.rb @@ -89,51 +89,29 @@ module ActiveRecord # singletons and that call instantiates and registers them. # class Observer < ActiveModel::Observer - class_attribute :observed_methods - self.observed_methods = [].freeze def initialize super observed_descendants.each { |klass| add_observer!(klass) } end - def self.method_added(method) - method = method.to_sym - - if ActiveRecord::Callbacks::CALLBACKS.include?(method) - self.observed_methods += [method] - self.observed_methods.freeze - end - end - protected def observed_descendants observed_classes.sum([]) { |klass| klass.descendants } end - def observe_callbacks? - self.class.observed_methods.any? - end - def add_observer!(klass) super - define_callbacks klass if observe_callbacks? + define_callbacks klass end def define_callbacks(klass) - existing_methods = klass.instance_methods.map { |m| m.to_sym } observer = self - observer_name = observer.class.name.underscore.gsub('/', '__') - self.class.observed_methods.each do |method| - callback = :"_notify_#{observer_name}_for_#{method}" - unless existing_methods.include? callback - klass.send(:define_method, callback) do # def _notify_user_observer_for_before_save - observer.update(method, self) # observer.update(:before_save, self) - end # end - klass.send(method, callback) # before_save :_notify_user_observer_for_before_save - end + ActiveRecord::Callbacks::CALLBACKS.each do |callback| + next unless respond_to?(callback) + klass.send(callback){|record| observer.send(callback, record)} end end end -- cgit v1.2.3 From 3cbf5d9794cc49783fcbcb160cdd908981ee8f84 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 9 Dec 2010 11:13:00 -0800 Subject: removing useless lasgn --- .../associations/class_methods/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/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index b063d927b9..024ce4114b 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -136,7 +136,7 @@ module ActiveRecord conditions << process_conditions(options[:conditions], aliased_table_name) end - relation = relation.on(*conditions) + relation.on(*conditions) end def join_has_and_belongs_to_many_to(relation) -- cgit v1.2.3 From 6110b0c54dde6251f7501e6421a7002a99779537 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 9 Dec 2010 11:14:54 -0800 Subject: fixing documentation, thanks Ivan Evtuhovich --- activerecord/lib/active_record/transactions.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index 654c475aed..f8c6c7b53e 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -141,7 +141,8 @@ module ActiveRecord # end # end # - # User.find(:all) # => empty + # User.find(:all) # => Returns Kotori and Nemu, because + # AcriveRecord::Rollback do not re-raise # # It is also possible to requires a sub-transaction by passing # :requires_new => true. If anything goes wrong, the -- cgit v1.2.3 From b2a042570cf55c716e44865cf6388f9079a86690 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 9 Dec 2010 13:26:41 -0800 Subject: just use core methods --- activerecord/lib/active_record/observer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/observer.rb b/activerecord/lib/active_record/observer.rb index f0da4202bf..a09c392f9d 100644 --- a/activerecord/lib/active_record/observer.rb +++ b/activerecord/lib/active_record/observer.rb @@ -98,7 +98,7 @@ module ActiveRecord protected def observed_descendants - observed_classes.sum([]) { |klass| klass.descendants } + observed_classes.map { |klass| klass.descendants }.flatten end def add_observer!(klass) -- cgit v1.2.3 From 0e8280b19322bd3fdd7e18fc6ba35d45e986e611 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 9 Dec 2010 13:37:15 -0800 Subject: reuse the superclass methods for shorter codes --- activerecord/lib/active_record/observer.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/observer.rb b/activerecord/lib/active_record/observer.rb index a09c392f9d..8b011ad9af 100644 --- a/activerecord/lib/active_record/observer.rb +++ b/activerecord/lib/active_record/observer.rb @@ -90,15 +90,11 @@ module ActiveRecord # class Observer < ActiveModel::Observer - def initialize - super - observed_descendants.each { |klass| add_observer!(klass) } - end - protected - def observed_descendants - observed_classes.map { |klass| klass.descendants }.flatten + def observed_classes + klasses = super + klasses + klasses.map { |klass| klass.descendants }.flatten end def add_observer!(klass) -- cgit v1.2.3 From 12f67a70697212b55cde66f89ccd4caf0e9f4dad Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 9 Dec 2010 15:31:09 -0800 Subject: use inject rather than lasgn --- .../class_methods/join_dependency/join_association.rb | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index 024ce4114b..5e37542416 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -121,14 +121,13 @@ module ActiveRecord # If the target table is an STI model then we must be sure to only include records of # its type and its sub-types. unless active_record.descends_from_active_record? - sti_column = target_table[active_record.inheritance_column] - + sti_column = target_table[active_record.inheritance_column] + subclasses = active_record.descendants sti_condition = sti_column.eq(active_record.sti_name) - active_record.descendants.each do |subclass| - sti_condition = sti_condition.or(sti_column.eq(subclass.sti_name)) - end - conditions << sti_condition + conditions << subclasses.inject(sti_condition) { |attr,subclass| + attr.or(sti_column.eq(subclass.sti_name)) + } end # If the reflection has conditions, add them -- cgit v1.2.3 From 06ba9eaa62f756b70217f4d1e277c37e835343d4 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 9 Dec 2010 15:54:07 -0800 Subject: move join creation a little closer to where it is used --- .../associations/class_methods/join_dependency/join_association.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index 5e37542416..b0091c613d 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -116,8 +116,6 @@ module ActiveRecord end def join_target_table(relation, *conditions) - relation = relation.join(target_table, join_type) - # If the target table is an STI model then we must be sure to only include records of # its type and its sub-types. unless active_record.descends_from_active_record? @@ -135,7 +133,9 @@ module ActiveRecord conditions << process_conditions(options[:conditions], aliased_table_name) end - relation.on(*conditions) + join = relation.join(target_table, join_type) + + join.on(*conditions) end def join_has_and_belongs_to_many_to(relation) -- cgit v1.2.3 From 3d01ef6dd1ed83b44702d117b4c1c658dfa8ba75 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 10 Dec 2010 02:14:58 +0100 Subject: require core_ext/array/wrap in active_record/migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activerecord/lib/active_record/migration.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index ea9950de08..640111096d 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -1,3 +1,5 @@ +require "active_support/core_ext/array/wrap" + module ActiveRecord # Exception that can be raised to stop migrations from going backwards. class IrreversibleMigration < ActiveRecordError -- cgit v1.2.3 From 88bc49f2f7560d1afb53f480720a809e101e8f7a Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 11:17:59 -0800 Subject: dealing with an AST manager, not a relation, so fix the variable names --- .../lib/active_record/relation/query_methods.rb | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 6886c7538b..1e6a928da3 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -163,7 +163,7 @@ module ActiveRecord end def build_arel - arel = table + arel = table.from table arel = build_joins(arel, @joins_values) unless @joins_values.empty? @@ -247,7 +247,7 @@ module ActiveRecord end end - def build_joins(relation, joins) + def build_joins(manager, joins) joins = joins.map {|j| j.respond_to?(:strip) ? j.strip : j}.uniq association_joins = joins.find_all do |join| @@ -257,7 +257,7 @@ module ActiveRecord stashed_association_joins = joins.grep(ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation) non_association_joins = (joins - association_joins - stashed_association_joins) - join_ast = custom_join_ast(relation, non_association_joins) + join_ast = custom_join_ast(manager.froms.first, non_association_joins) join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, join_ast) @@ -267,19 +267,19 @@ module ActiveRecord # FIXME: refactor this to build an AST join_dependency.join_associations.each do |association| - relation = association.join_to(relation) + manager = association.join_to(manager) end - if Arel::Table === relation - relation.from(join_ast || relation) + if Arel::Table === manager + manager.from(join_ast || manager) else - if relation.froms.length > 0 && join_ast - join_ast.left = relation.froms.first - relation.from join_ast - elsif relation.froms.length == 0 && join_ast - relation.from(join_ast) + if manager.froms.length > 0 && join_ast + join_ast.left = manager.froms.first + manager.from join_ast + elsif manager.froms.length == 0 && join_ast + manager.from(join_ast) else - relation + manager end end end -- cgit v1.2.3 From 82944b95a909965ddec189058fb2040dcf0aa54a Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 11:24:05 -0800 Subject: eliminate lasgns --- .../lib/active_record/relation/query_methods.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 1e6a928da3..b2f741026b 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -165,23 +165,23 @@ module ActiveRecord def build_arel arel = table.from table - arel = build_joins(arel, @joins_values) unless @joins_values.empty? + build_joins(arel, @joins_values) unless @joins_values.empty? - arel = collapse_wheres(arel, (@where_values - ['']).uniq) + collapse_wheres(arel, (@where_values - ['']).uniq) - arel = arel.having(*@having_values.uniq.reject{|h| h.blank?}) unless @having_values.empty? + arel.having(*@having_values.uniq.reject{|h| h.blank?}) unless @having_values.empty? - arel = arel.take(@limit_value) if @limit_value - arel = arel.skip(@offset_value) if @offset_value + arel.take(@limit_value) if @limit_value + arel.skip(@offset_value) if @offset_value - arel = arel.group(*@group_values.uniq.reject{|g| g.blank?}) unless @group_values.empty? + arel.group(*@group_values.uniq.reject{|g| g.blank?}) unless @group_values.empty? - arel = arel.order(*@order_values.uniq.reject{|o| o.blank?}) unless @order_values.empty? + arel.order(*@order_values.uniq.reject{|o| o.blank?}) unless @order_values.empty? - arel = build_select(arel, @select_values.uniq) + build_select(arel, @select_values.uniq) - arel = arel.from(@from_value) if @from_value - arel = arel.lock(@lock_value) if @lock_value + arel.from(@from_value) if @from_value + arel.lock(@lock_value) if @lock_value arel end -- cgit v1.2.3 From 4dec00a9d8262d85b733aa3bd5b68d2b7de950a7 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 11:30:22 -0800 Subject: manager will always be a manager --- activerecord/lib/active_record/relation/query_methods.rb | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index b2f741026b..a98b650524 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -270,17 +270,13 @@ module ActiveRecord manager = association.join_to(manager) end - if Arel::Table === manager - manager.from(join_ast || manager) + if manager.froms.length > 0 && join_ast + join_ast.left = manager.froms.first + manager.from join_ast + elsif manager.froms.length == 0 && join_ast + manager.from(join_ast) else - if manager.froms.length > 0 && join_ast - join_ast.left = manager.froms.first - manager.from join_ast - elsif manager.froms.length == 0 && join_ast - manager.from(join_ast) - else - manager - end + manager end end -- cgit v1.2.3 From ec72b6b3ec1b78c22189ee475c1af2fdab317489 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 11:33:24 -0800 Subject: froms should never equal 0 --- activerecord/lib/active_record/relation/query_methods.rb | 2 -- 1 file changed, 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index a98b650524..145ae6ca97 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -273,8 +273,6 @@ module ActiveRecord if manager.froms.length > 0 && join_ast join_ast.left = manager.froms.first manager.from join_ast - elsif manager.froms.length == 0 && join_ast - manager.from(join_ast) else manager end -- cgit v1.2.3 From 7d8fd5723600c1290177e665cfd8136031f8abd1 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 11:37:55 -0800 Subject: no more manager manipulation if there is no custom join ast --- activerecord/lib/active_record/relation/query_methods.rb | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 145ae6ca97..08b61c9752 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -270,12 +270,11 @@ module ActiveRecord manager = association.join_to(manager) end - if manager.froms.length > 0 && join_ast - join_ast.left = manager.froms.first - manager.from join_ast - else - manager - end + return manager unless join_ast + + join_ast.left = manager.froms.first + manager.from join_ast + manager end def build_select(arel, selects) -- cgit v1.2.3 From 6e15a7fa3c42e183541a893196d83a83cfc20553 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 11:46:02 -0800 Subject: only quote the table name once per call --- .../associations/class_methods/join_dependency.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index 1856395f2d..b6d85a7c7d 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -15,7 +15,7 @@ module ActiveRecord @associations = {} @reflections = [] @table_aliases = Hash.new do |h,name| - h[name] = count_aliases_from_table_joins(name) + h[name] = count_aliases_from_table_joins(name.downcase) end @table_aliases[base.table_name] = 1 build(associations) @@ -49,13 +49,16 @@ module ActiveRecord def count_aliases_from_table_joins(name) return 0 if !@table_joins || Arel::Table === @table_joins + # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase + quoted_name = active_record.connection.quote_table_name(name).downcase + @table_joins.grep(Arel::Nodes::Join).map { |join| right = join.right case right when Arel::Table right.name.downcase == name ? 1 : 0 when String - count_aliases_from_string(right.downcase, name) + count_aliases_from_string(right.downcase, quoted_name) else 0 end @@ -63,12 +66,10 @@ module ActiveRecord end def count_aliases_from_string(join_sql, name) - # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase - quoted_name = active_record.connection.quote_table_name(name.downcase).downcase # Table names - join_sql.scan(/join(?:\s+\w+)?\s+#{quoted_name}\son/).size + + join_sql.scan(/join(?:\s+\w+)?\s+#{name}\son/).size + # Table aliases - join_sql.scan(/join(?:\s+\w+)?\s+\S+\s+#{quoted_name}\son/).size + join_sql.scan(/join(?:\s+\w+)?\s+\S+\s+#{name}\son/).size end def instantiate(rows) -- cgit v1.2.3 From 73d4d6704ec2a5b11e32d7f421f4614ac83d8384 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 13:20:03 -0800 Subject: avoid *args on join_target_table --- .../class_methods/join_dependency/join_association.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index b0091c613d..5c062e874e 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -115,7 +115,9 @@ module ActiveRecord active_record.send(:sanitize_sql, condition, table_name) end - def join_target_table(relation, *conditions) + def join_target_table(relation, condition) + conditions = [condition] + # If the target table is an STI model then we must be sure to only include records of # its type and its sub-types. unless active_record.descends_from_active_record? @@ -247,9 +249,9 @@ module ActiveRecord join_target_table( relation, target_table["#{reflection.options[:as]}_id"]. - eq(parent_table[parent.primary_key]), + eq(parent_table[parent.primary_key]).and( target_table["#{reflection.options[:as]}_type"]. - eq(parent.active_record.base_class.name) + eq(parent.active_record.base_class.name)) ) end -- cgit v1.2.3 From f528389a5580227f4d173bf4915a98b71befb32e Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 13:26:58 -0800 Subject: use alias nodes to represent table aliases --- .../associations/class_methods/join_dependency/join_association.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index 5c062e874e..ff6a9993b0 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -142,9 +142,8 @@ module ActiveRecord def join_has_and_belongs_to_many_to(relation) join_table = Arel::Table.new( - options[:join_table], :engine => arel_engine, - :as => @aliased_join_table_name - ) + options[:join_table] + ).alias(@aliased_join_table_name) fk = options[:foreign_key] || reflection.active_record.to_s.foreign_key klass_fk = options[:association_foreign_key] || reflection.klass.to_s.foreign_key -- cgit v1.2.3 From e07772556a2167e44158f367beb3a45e6a55671f Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 13:28:50 -0800 Subject: use table alias nodes rather than Table nodes --- .../associations/class_methods/join_dependency/join_association.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index ff6a9993b0..98536d23bc 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -181,9 +181,8 @@ module ActiveRecord def join_has_many_through_to(relation) join_table = Arel::Table.new( - through_reflection.klass.table_name, :engine => arel_engine, - :as => @aliased_join_table_name - ) + through_reflection.klass.table_name + ).alias @aliased_join_table_name jt_conditions = [] jt_foreign_key = first_key = second_key = nil -- cgit v1.2.3 From d38644f4a9eead2f9d9ed96e10fb67430de31789 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Sat, 11 Dec 2010 00:52:33 +0100 Subject: reviews commit 53bbbcc --- activerecord/lib/active_record/transactions.rb | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index 181280baaa..443f318067 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -131,7 +131,7 @@ module ActiveRecord # # +transaction+ calls can be nested. By default, this makes all database # statements in the nested transaction block become part of the parent - # transaction. For example: + # transaction. For example, the following behavior may be surprising: # # User.transaction do # User.create(:username => 'Kotori') @@ -141,13 +141,15 @@ module ActiveRecord # end # end # - # User.find(:all) # => Return both Kotori and Nemu, because inner transaction do not rollback - # # without :requiers_new => true option, and Rollback exception do not reraise + # creates both "Kotori" and "Nemu". Reason is the ActiveRecord::Rollback + # exception in the nested block does not issue a ROLLBACK. Since these exceptions + # are captured in transaction blocks, the parent block does not see it and the + # real transaction is committed. # - # It is also possible to requires a sub-transaction by passing - # :requires_new => true. If anything goes wrong, the - # database rolls back to the beginning of the sub-transaction - # without rolling back the parent transaction. For example: + # In order to get a ROLLBACK for the nested transaction you may ask for a real + # sub-transaction by passing :requires_new => true. If anything goes wrong, + # the database rolls back to the beginning of the sub-transaction without rolling + # back the parent transaction. If we add it to the previous example: # # User.transaction do # User.create(:username => 'Kotori') @@ -157,12 +159,12 @@ module ActiveRecord # end # end # - # User.find(:all) # => Returns only Kotori + # only "Kotori" is created. (This works on MySQL and PostgreSQL, but not on SQLite3.) # # Most databases don't support true nested transactions. At the time of # writing, the only database that we're aware of that supports true nested # transactions, is MS-SQL. Because of this, Active Record emulates nested - # transactions by using savepoints. See + # transactions by using savepoints on MySQL and PostgreSQL. See # http://dev.mysql.com/doc/refman/5.0/en/savepoints.html # for more information about savepoints. # -- cgit v1.2.3 From cea73f82ad65bf8bca707f6f8f3afd86f3e82bdb Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 14:02:14 -0800 Subject: just mutate the ast, fewer lasgns --- activerecord/lib/active_record/relation/query_methods.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 08b61c9752..dce9ac4808 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -225,14 +225,13 @@ module ActiveRecord test = eqls.inject(eqls.shift) do |memo, expr| memo.or(expr) end - arel = arel.where(test) + arel.where(test) end (wheres - equalities).each do |where| where = Arel.sql(where) if String === where - arel = arel.where(Arel::Nodes::Grouping.new(where)) + arel.where(Arel::Nodes::Grouping.new(where)) end - arel end def build_where(opts, other = []) -- cgit v1.2.3 From 0042054ea873a8d25d9bbdc4c7fe0febe1b76042 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 14:44:42 -0800 Subject: remove lasgn since AST is mutated --- .../class_methods/join_dependency/join_association.rb | 10 ++++++++-- activerecord/lib/active_record/relation/query_methods.rb | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index 98536d23bc..4839068f6d 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -135,9 +135,15 @@ module ActiveRecord conditions << process_conditions(options[:conditions], aliased_table_name) end - join = relation.join(target_table, join_type) + ands = relation.create_and(conditions) - join.on(*conditions) + join = relation.create_join( + relation.froms.first, + target_table, + relation.create_on(ands), + join_type) + + relation.from join end def join_has_and_belongs_to_many_to(relation) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index dce9ac4808..51a39be065 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -266,7 +266,7 @@ module ActiveRecord # FIXME: refactor this to build an AST join_dependency.join_associations.each do |association| - manager = association.join_to(manager) + association.join_to(manager) end return manager unless join_ast -- cgit v1.2.3 From b1447d902c39a4b324cb0dc54b80fecc0fe7e34e Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 15:13:51 -0800 Subject: explicitly set prefix --- .../associations/class_methods/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/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index 4839068f6d..f1b923e98b 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -22,7 +22,7 @@ module ActiveRecord attr_reader :aliased_prefix, :aliased_table_name delegate :options, :through_reflection, :source_reflection, :to => :reflection - delegate :table, :table_name, :to => :parent, :prefix => true + delegate :table, :table_name, :to => :parent, :prefix => :parent def initialize(reflection, join_dependency, parent = nil) reflection.check_validity! -- cgit v1.2.3 From 59ec13155581918fe934890ff7d9e6c2c03dc92e Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 15:27:10 -0800 Subject: move ivar to initialize, use triple dot rather than minus --- .../associations/class_methods/join_dependency/join_association.rb | 2 +- .../lib/active_record/connection_adapters/abstract/schema_statements.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index f1b923e98b..c552603097 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -37,6 +37,7 @@ module ActiveRecord @join_dependency = join_dependency @parent = parent @join_type = Arel::InnerJoin + @aliased_prefix = "t#{ join_dependency.join_parts.size }" # This must be done eagerly upon initialisation because the alias which is produced # depends on the state of the join dependency, but we want it to work the same way @@ -97,7 +98,6 @@ module ActiveRecord private def allocate_aliases - @aliased_prefix = "t#{ join_dependency.join_parts.size }" @aliased_table_name = aliased_table_name_for(table_name) if reflection.macro == :has_and_belongs_to_many 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 d4aefada22..5b9c48bafa 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -12,7 +12,7 @@ module ActiveRecord # Truncates a table alias according to the limits of the current adapter. def table_alias_for(table_name) - table_name[0..table_alias_length-1].gsub(/\./, '_') + table_name[0...table_alias_length].gsub(/\./, '_') end # def tables(name = nil) end -- cgit v1.2.3 From b3ae67dbb91a79f0f58528ba0ba4ffe592db1924 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 16:26:43 -0800 Subject: reduce method calls --- 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 a07c321960..fe4b518826 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -248,7 +248,7 @@ module ActiveRecord end def has_inverse? - !@options[:inverse_of].nil? + @options[:inverse_of] end def inverse_of -- cgit v1.2.3 From 59bd9c2a3793febffb919f1555156208825d4a9c Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 17:01:15 -0800 Subject: combine regexp --- .../lib/active_record/associations/class_methods/join_dependency.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index b6d85a7c7d..6be947df41 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -66,10 +66,8 @@ module ActiveRecord end def count_aliases_from_string(join_sql, name) - # Table names - join_sql.scan(/join(?:\s+\w+)?\s+#{name}\son/).size + - # Table aliases - join_sql.scan(/join(?:\s+\w+)?\s+\S+\s+#{name}\son/).size + # Table names + table aliases + join_sql.scan(/join(?:\s+\w+)?\s+(\S+\s+)?#{name}\son/).size end def instantiate(rows) -- cgit v1.2.3 From ad47b7bcc11aae7745b39354292b089ae18a8cfc Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 17:03:32 -0800 Subject: just use the regexp directly --- .../associations/class_methods/join_dependency.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index 6be947df41..5a0ff942ca 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -58,18 +58,16 @@ module ActiveRecord when Arel::Table right.name.downcase == name ? 1 : 0 when String - count_aliases_from_string(right.downcase, quoted_name) + # Table names + table aliases + right.downcase.scan( + /join(?:\s+\w+)?\s+(\S+\s+)?#{quoted_name}\son/ + ).size else 0 end }.sum end - def count_aliases_from_string(join_sql, name) - # Table names + table aliases - join_sql.scan(/join(?:\s+\w+)?\s+(\S+\s+)?#{name}\son/).size - end - def instantiate(rows) primary_key = join_base.aliased_primary_key parents = {} -- cgit v1.2.3 From bda16eb0920780509467bcf051d1a01639357903 Mon Sep 17 00:00:00 2001 From: Chiel Wester Date: Mon, 13 Dec 2010 15:06:23 +0100 Subject: Only call save on belongs_to associations if the record has changed or any nested associations have changed (resolves #3353) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activerecord/lib/active_record/autosave_association.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index c3dda29d03..4a18719551 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -363,7 +363,7 @@ module ActiveRecord if autosave && association.marked_for_destruction? association.destroy elsif autosave != false - saved = association.save(:validate => !autosave) if association.new_record? || autosave + saved = association.save(:validate => !autosave) if association.new_record? || (autosave && association.changed_for_autosave?) if association.updated? association_id = association.send(reflection.options[:primary_key] || :id) -- cgit v1.2.3 From 63480d234df401d678bb7c5a8cef662e3222d841 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 13 Dec 2010 13:21:18 -0800 Subject: stop delegating inserts to ARel, use the INSERT SQL ourselves --- activerecord/lib/active_record/relation.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 3009bb70c1..7ecba1c43a 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -11,7 +11,6 @@ module ActiveRecord include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to => :to_a - delegate :insert, :to => :arel attr_reader :table, :klass, :loaded attr_accessor :extensions @@ -28,6 +27,19 @@ module ActiveRecord @extensions = [] end + def insert(values) + im = arel.compile_insert values + im.into @table + primary_key_name = @klass.primary_key + primary_key_value = Hash === values ? values[primary_key_name] : nil + + @klass.connection.insert( + im.to_sql, + 'SQL', + primary_key_name, + primary_key_value) + end + def new(*args, &block) scoping { @klass.new(*args, &block) } end -- cgit v1.2.3 From c02fd2acc575f3e90da12d4915390a80a48b7c8e Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2010 11:25:47 -0800 Subject: taking advantage of the JoinSource node in the SQL AST --- .../associations/class_methods/join_dependency.rb | 20 ++++++------------- .../join_dependency/join_association.rb | 1 - .../lib/active_record/relation/finder_methods.rb | 2 +- .../lib/active_record/relation/query_methods.rb | 23 +++++++--------------- 4 files changed, 14 insertions(+), 32 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index 5a0ff942ca..a74d0a4ca8 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -47,24 +47,16 @@ module ActiveRecord end def count_aliases_from_table_joins(name) - return 0 if !@table_joins || Arel::Table === @table_joins + return 0 if Arel::Table === @table_joins # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase quoted_name = active_record.connection.quote_table_name(name).downcase - @table_joins.grep(Arel::Nodes::Join).map { |join| - right = join.right - case right - when Arel::Table - right.name.downcase == name ? 1 : 0 - when String - # Table names + table aliases - right.downcase.scan( - /join(?:\s+\w+)?\s+(\S+\s+)?#{quoted_name}\son/ - ).size - else - 0 - end + @table_joins.map { |join| + # Table names + table aliases + join.left.downcase.scan( + /join(?:\s+\w+)?\s+(\S+\s+)?#{quoted_name}\son/ + ).size }.sum end diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index c552603097..694778008b 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -138,7 +138,6 @@ module ActiveRecord ands = relation.create_and(conditions) join = relation.create_join( - relation.froms.first, target_table, relation.create_on(ands), join_type) diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 906ad7699c..8bc28c06cb 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -187,7 +187,7 @@ module ActiveRecord def find_with_associations including = (@eager_load_values + @includes_values).uniq - join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, including, nil) + join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, including, []) rows = construct_relation_for_association_find(join_dependency).to_a join_dependency.instantiate(rows) rescue ThrowResult diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 51a39be065..67a94cec85 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -191,27 +191,19 @@ module ActiveRecord def custom_join_ast(table, joins) joins = joins.reject { |join| join.blank? } - return if joins.empty? + return [] if joins.empty? @implicit_readonly = true - joins.map! do |join| + joins.map do |join| case join when Array join = Arel.sql(join.join(' ')) if array_of_strings?(join) when String join = Arel.sql(join) end - join + table.create_string_join(join) end - - head = table.create_string_join(table, joins.shift) - - joins.inject(head) do |ast, join| - ast.right = table.create_string_join(ast.right, join) - end - - head end def collapse_wheres(arel, wheres) @@ -256,9 +248,9 @@ module ActiveRecord stashed_association_joins = joins.grep(ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation) non_association_joins = (joins - association_joins - stashed_association_joins) - join_ast = custom_join_ast(manager.froms.first, non_association_joins) + join_list = custom_join_ast(manager, non_association_joins) - join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, join_ast) + join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, join_list) join_dependency.graft(*stashed_association_joins) @@ -269,10 +261,9 @@ module ActiveRecord association.join_to(manager) end - return manager unless join_ast + return manager unless join_list - join_ast.left = manager.froms.first - manager.from join_ast + join_list.each { |j| manager.from j } manager end -- cgit v1.2.3 From b68407f7f013ce3b08d1273ac3c2ffd7a8a510c9 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2010 12:34:04 -0800 Subject: bucketing based on join type --- .../lib/active_record/relation/query_methods.rb | 25 +++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 67a94cec85..ef14f48a8f 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -239,16 +239,25 @@ module ActiveRecord end def build_joins(manager, joins) - joins = joins.map {|j| j.respond_to?(:strip) ? j.strip : j}.uniq - - association_joins = joins.find_all do |join| - [Hash, Array, Symbol].include?(join.class) && !array_of_strings?(join) + buckets = joins.group_by do |join| + case join + when String + 'string_join' + when Hash, Symbol, Array + 'association_join' + when ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation + 'stashed_join' + else + raise 'unknown class: %s' % join.class.name + end end - stashed_association_joins = joins.grep(ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation) - - non_association_joins = (joins - association_joins - stashed_association_joins) - join_list = custom_join_ast(manager, non_association_joins) + association_joins = buckets['association_join'] || [] + stashed_association_joins = buckets['stashed_join'] || [] + string_joins = (buckets['string_join'] || []).map { |x| + x.strip + }.uniq + join_list = custom_join_ast(manager, string_joins) join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, join_list) -- cgit v1.2.3 From 80ff64a947b4acd3835faab36e3b7f44ade10170 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2010 14:49:33 -0800 Subject: just copy the joins to the list --- .../lib/active_record/associations/has_many_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/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb index d0c8af1801..6ad51e2fb4 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -54,7 +54,7 @@ module ActiveRecord end def construct_find_options!(options) - options[:joins] = construct_joins(options[:joins]) + options[:joins] = [construct_joins] + Array.wrap(options[:joins]) options[:include] = @reflection.source_reflection.options[:include] if options[:include].nil? && @reflection.source_reflection.options[:include] end -- cgit v1.2.3 From 18402b5d649658a4046769a6d74b76a6731f7c94 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2010 14:57:03 -0800 Subject: supporting arel AST nodes when building join statements --- .../associations/through_association_scope.rb | 32 ++++++++++++---------- .../lib/active_record/relation/query_methods.rb | 18 ++++++++++-- 2 files changed, 32 insertions(+), 18 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index acddfda924..48386ee124 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -55,33 +55,35 @@ module ActiveRecord end def construct_joins(custom_joins = nil) - polymorphic_join = nil + right = @reflection.through_reflection.klass.arel_table + left = @reflection.klass.arel_table + + conditions = [] + if @reflection.source_reflection.macro == :belongs_to reflection_primary_key = @reflection.klass.primary_key source_primary_key = @reflection.source_reflection.primary_key_name if @reflection.options[:source_type] - polymorphic_join = "AND %s.%s = %s" % [ - @reflection.through_reflection.quoted_table_name, "#{@reflection.source_reflection.options[:foreign_type]}", - @owner.class.quote_value(@reflection.options[:source_type]) - ] + column = @reflection.source_reflection.options[:foreign_type] + conditions << + right[column].eq(@reflection.options[:source_type]) end else reflection_primary_key = @reflection.source_reflection.primary_key_name source_primary_key = @reflection.through_reflection.klass.primary_key if @reflection.source_reflection.options[:as] - polymorphic_join = "AND %s.%s = %s" % [ - @reflection.quoted_table_name, "#{@reflection.source_reflection.options[:as]}_type", - @owner.class.quote_value(@reflection.through_reflection.klass.name) - ] + column = "#{@reflection.source_reflection.options[:as]}_type" + conditions << + left[column].eq(@reflection.through_reflection.klass.name) end end - "INNER JOIN %s ON %s.%s = %s.%s %s #{@reflection.options[:joins]} #{custom_joins}" % [ - @reflection.through_reflection.quoted_table_name, - @reflection.quoted_table_name, reflection_primary_key, - @reflection.through_reflection.quoted_table_name, source_primary_key, - polymorphic_join - ] + conditions << + left[reflection_primary_key].eq(right[source_primary_key]) + + right.create_join( + right, + right.create_on(right.create_and(conditions))) end # Construct attributes for associate pointing to owner. diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index ef14f48a8f..8e50f4a9bc 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -247,6 +247,8 @@ module ActiveRecord 'association_join' when ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation 'stashed_join' + when Arel::Nodes::Join + 'join_node' else raise 'unknown class: %s' % join.class.name end @@ -254,12 +256,22 @@ module ActiveRecord association_joins = buckets['association_join'] || [] stashed_association_joins = buckets['stashed_join'] || [] + join_nodes = buckets['join_node'] || [] string_joins = (buckets['string_join'] || []).map { |x| x.strip }.uniq + join_list = custom_join_ast(manager, string_joins) - join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, join_list) + join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new( + @klass, + association_joins, + join_list + ) + + join_nodes.each do |join| + join_dependency.table_aliases[join.left.name.downcase] = 1 + end join_dependency.graft(*stashed_association_joins) @@ -270,9 +282,9 @@ module ActiveRecord association.join_to(manager) end - return manager unless join_list + manager.join_sources.concat join_nodes + manager.join_sources.concat join_list - join_list.each { |j| manager.from j } manager end -- cgit v1.2.3 From aa4d03fcfc42453b5553c001d24933365effe5f0 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2010 15:03:06 -0800 Subject: construct_joins no longer needs an argument --- .../lib/active_record/associations/through_association_scope.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_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index 48386ee124..f6b242168c 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -54,7 +54,7 @@ module ActiveRecord custom_select || @reflection.options[:select] || "#{distinct}#{@reflection.quoted_table_name}.*" end - def construct_joins(custom_joins = nil) + def construct_joins right = @reflection.through_reflection.klass.arel_table left = @reflection.klass.arel_table -- cgit v1.2.3 From 2f0708e97405fa55e641dd2eac8805f12f878f5a Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2010 15:24:25 -0800 Subject: build SQL AST nodes rather than generate strings --- .../associations/through_association_scope.rb | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index f6b242168c..8d701248af 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -23,25 +23,23 @@ module ActiveRecord # Build SQL conditions from attributes, qualified by table name. def construct_conditions - table_name = @reflection.through_reflection.quoted_table_name + table = @reflection.through_reflection.klass.arel_table conditions = construct_quoted_owner_attributes(@reflection.through_reflection).map do |attr, value| - "#{table_name}.#{attr} = #{value}" + table[attr].eq(value) end - conditions << sql_conditions if sql_conditions - "(" + conditions.join(') AND (') + ")" + conditions << Arel.sql(sql_conditions) if sql_conditions + table.create_and(conditions) end # Associate attributes pointing to owner, quoted. def construct_quoted_owner_attributes(reflection) if as = reflection.options[:as] - { "#{as}_id" => owner_quoted_id, - "#{as}_type" => reflection.klass.quote_value( - @owner.class.base_class.name.to_s, - reflection.klass.columns_hash["#{as}_type"]) } + { "#{as}_id" => @owner.id, + "#{as}_type" => @owner.class.base_class.name } elsif reflection.macro == :belongs_to - { reflection.klass.primary_key => @owner.class.quote_value(@owner[reflection.primary_key_name]) } + { reflection.klass.primary_key => @owner[reflection.primary_key_name] } else - { reflection.primary_key_name => owner_quoted_id } + { reflection.primary_key_name => @owner.id } end end -- cgit v1.2.3 From a64bf22a718bcc8d1a33234ab8a7cdd91c6d537b Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2010 15:27:06 -0800 Subject: class names are already strings, so we do not need to call to_s on the strings that are already strings --- .../lib/active_record/associations/through_association_scope.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_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index 8d701248af..6b7faa9fc3 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -88,7 +88,7 @@ module ActiveRecord def construct_owner_attributes(reflection) if as = reflection.options[:as] { "#{as}_id" => @owner.id, - "#{as}_type" => @owner.class.base_class.name.to_s } + "#{as}_type" => @owner.class.base_class.name } else { reflection.primary_key_name => @owner.id } end @@ -102,7 +102,7 @@ module ActiveRecord join_attributes = construct_owner_attributes(@reflection.through_reflection).merge(@reflection.source_reflection.primary_key_name => associate.id) if @reflection.options[:source_type] - join_attributes.merge!(@reflection.source_reflection.options[:foreign_type] => associate.class.base_class.name.to_s) + join_attributes.merge!(@reflection.source_reflection.options[:foreign_type] => associate.class.base_class.name) end if @reflection.through_reflection.options[:conditions].is_a?(Hash) -- cgit v1.2.3 From 5d37ff6bb2b1f948034bf06e450f2fdb8195c4e5 Mon Sep 17 00:00:00 2001 From: Ernie Miller Date: Mon, 3 May 2010 20:47:42 -0400 Subject: Fix hm:t to self table aliasing in construct_scope --- .../active_record/associations/through_association_scope.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index 6b7faa9fc3..a55bf6323e 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -21,9 +21,17 @@ module ActiveRecord construct_owner_attributes(@reflection) end + def aliased_through_table + name = @reflection.through_reflection.table_name + + @reflection.table_name == name ? + @reflection.through_reflection.klass.arel_table.alias(name + "_join") : + @reflection.through_reflection.klass.arel_table + end + # Build SQL conditions from attributes, qualified by table name. def construct_conditions - table = @reflection.through_reflection.klass.arel_table + table = aliased_through_table conditions = construct_quoted_owner_attributes(@reflection.through_reflection).map do |attr, value| table[attr].eq(value) end @@ -53,7 +61,7 @@ module ActiveRecord end def construct_joins - right = @reflection.through_reflection.klass.arel_table + right = aliased_through_table left = @reflection.klass.arel_table conditions = [] -- cgit v1.2.3 From eba76640862d071d89c846f8624d1e651d872794 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sun, 12 Dec 2010 16:35:27 +0000 Subject: Respect the default_scope on a join model when reading a through association --- .../lib/active_record/associations/has_many_through_association.rb | 2 +- .../lib/active_record/associations/has_one_through_association.rb | 2 +- .../lib/active_record/associations/through_association_scope.rb | 7 +++++++ 3 files changed, 9 insertions(+), 2 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 6ad51e2fb4..781aa7ef62 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -81,7 +81,7 @@ module ActiveRecord def find_target return [] unless target_reflection_has_associated_record? - with_scope(@scope) { @reflection.klass.find(:all) } + scoped.all end def has_cached_counter? diff --git a/activerecord/lib/active_record/associations/has_one_through_association.rb b/activerecord/lib/active_record/associations/has_one_through_association.rb index 7f28abf464..e8cf73976b 100644 --- a/activerecord/lib/active_record/associations/has_one_through_association.rb +++ b/activerecord/lib/active_record/associations/has_one_through_association.rb @@ -33,7 +33,7 @@ module ActiveRecord private def find_target - with_scope(@scope) { @reflection.klass.find(:first) } + scoped.first end end end diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index a55bf6323e..2ecd0f054a 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -3,6 +3,13 @@ module ActiveRecord module Associations module ThroughAssociationScope + def scoped + with_scope(@scope) do + @reflection.klass.scoped & + @reflection.through_reflection.klass.scoped + end + end + protected def construct_find_scope -- cgit v1.2.3 From 4cd3302279f4ab5af642a1cd4e601b676ba6278b Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 15 Dec 2010 11:12:33 -0800 Subject: make sure that join nodes are uniq --- activerecord/lib/active_record/relation/query_methods.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 8e50f4a9bc..6660df302b 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -282,7 +282,7 @@ module ActiveRecord association.join_to(manager) end - manager.join_sources.concat join_nodes + manager.join_sources.concat join_nodes.uniq manager.join_sources.concat join_list manager -- cgit v1.2.3 From fe0db2b80588446b34f5f89bbe73f04b88fb06c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vi=CC=81ctor=20Marti=CC=81nez?= Date: Thu, 30 Sep 2010 19:14:47 +0200 Subject: to_xml doesn't work in such case: Event.select('title as t').to_xml [#4840 state:resolved] NilClass.type is no longer defined in Ruby 1.9 and causes ActiveRecord::Base.to_xml to fail with message: undefined method `type' for nil:NilClass --- activerecord/lib/active_record/serializers/xml_serializer.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/serializers/xml_serializer.rb b/activerecord/lib/active_record/serializers/xml_serializer.rb index 15abf8bac7..0746908131 100644 --- a/activerecord/lib/active_record/serializers/xml_serializer.rb +++ b/activerecord/lib/active_record/serializers/xml_serializer.rb @@ -226,8 +226,14 @@ module ActiveRecord #:nodoc: class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute #:nodoc: def compute_type - type = @serializable.class.serialized_attributes.has_key?(name) ? - super : @serializable.class.columns_hash[name].type + case + when @serializable.class.serialized_attributes.has_key?(name) + type = super + when @serializable.class.columns_hash.has_key?(name) + type = @serializable.class.columns_hash[name].type + else + type = NilClass + end case type when :text -- cgit v1.2.3 From 96bae30538951367a82235785e7dba3577b50a5a Mon Sep 17 00:00:00 2001 From: Pavel Gorbokon Date: Wed, 24 Nov 2010 10:17:49 +0200 Subject: Replace rudimentary named_scope with scope. [#6052 state:resolved] * rename method names (actually in tests) * rename instance variable @_named_scopes_cache to @_scopes_cache * rename references in doc comments * don't touch CHANGELOG :) --- .../active_record/associations/association_collection.rb | 16 ++++++++-------- activerecord/lib/active_record/base.rb | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index abb17a11c6..11a7a725e5 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -102,7 +102,7 @@ module ActiveRecord def reset reset_target! - reset_named_scopes_cache! + reset_scopes_cache! @loaded = false end @@ -160,7 +160,7 @@ module ActiveRecord load_target delete(@target) reset_target! - reset_named_scopes_cache! + reset_scopes_cache! end # Calculate sum using SQL, not Enumerable @@ -253,7 +253,7 @@ module ActiveRecord load_target destroy(@target).tap do reset_target! - reset_named_scopes_cache! + reset_scopes_cache! end end @@ -409,9 +409,9 @@ module ActiveRecord if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method)) super elsif @reflection.klass.scopes[method] - @_named_scopes_cache ||= {} - @_named_scopes_cache[method] ||= {} - @_named_scopes_cache[method][args] ||= with_scope(@scope) { @reflection.klass.send(method, *args) } + @_scopes_cache ||= {} + @_scopes_cache[method] ||= {} + @_scopes_cache[method][args] ||= with_scope(@scope) { @reflection.klass.send(method, *args) } else with_scope(@scope) do if block_given? @@ -442,8 +442,8 @@ module ActiveRecord @target = Array.new end - def reset_named_scopes_cache! - @_named_scopes_cache = {} + def reset_scopes_cache! + @_scopes_cache = {} end def find_target diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 7b9ce21ceb..d0f33c1d18 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -852,8 +852,8 @@ module ActiveRecord #:nodoc: # limit(10) # Fires "SELECT * FROM posts LIMIT 10" # } # - # It is recommended to use block form of unscoped because chaining unscoped with named_scope - # does not work. Assuming that published is a named_scope following two statements are same. + # It is recommended to use block form of unscoped because chaining unscoped with scope + # does not work. Assuming that published is a scope following two statements are same. # # Post.unscoped.published # Post.published -- cgit v1.2.3 From 6bfa846a2cc950bbb3d8b30f076589a60f38b821 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 15 Dec 2010 14:01:33 -0800 Subject: dry up compute type in attribute --- .../active_record/serializers/xml_serializer.rb | 26 +++++++++------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/serializers/xml_serializer.rb b/activerecord/lib/active_record/serializers/xml_serializer.rb index 0746908131..8c4adf7116 100644 --- a/activerecord/lib/active_record/serializers/xml_serializer.rb +++ b/activerecord/lib/active_record/serializers/xml_serializer.rb @@ -226,23 +226,17 @@ module ActiveRecord #:nodoc: class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute #:nodoc: def compute_type - case - when @serializable.class.serialized_attributes.has_key?(name) - type = super - when @serializable.class.columns_hash.has_key?(name) - type = @serializable.class.columns_hash[name].type - else - type = NilClass - end + klass = @serializable.class + type = if klass.serialized_attributes.key?(name) + super + elsif klass.columns_hash.key?(name) + klass.columns_hash[name].type + else + NilClass + end - case type - when :text - :string - when :time - :datetime - else - type - end + { :text => :string, + :time => :datetime }[type] || type end protected :compute_type end -- cgit v1.2.3 From 09ddca67acbb88e2fdd7300670839cbf647b2694 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Thu, 16 Dec 2010 00:40:03 +0000 Subject: Fix problem with duplicated records when a :uniq :through association is preloaded [#2447 state:resolved] --- activerecord/lib/active_record/association_preload.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb index 5eb1071ba2..f2094283a2 100644 --- a/activerecord/lib/active_record/association_preload.rb +++ b/activerecord/lib/active_record/association_preload.rb @@ -251,6 +251,7 @@ module ActiveRecord through_record_id = through_record[reflection.through_reflection_primary_key].to_s add_preloaded_records_to_collection(id_to_record_map[through_record_id], reflection.name, through_record.send(source)) end + records.each { |record| record.send(reflection.name).target.uniq! } if options[:uniq] end else -- cgit v1.2.3 From 14b880fd035fcdf807051398674c9aa89bd3b4d3 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Wed, 15 Dec 2010 23:27:15 +0000 Subject: Fix various issues with the :primary_key option in :through associations [#2421 state:resolved] --- .../associations/through_association_scope.rb | 26 ++++++++-------------- activerecord/lib/active_record/reflection.rb | 6 ++++- 2 files changed, 14 insertions(+), 18 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index 2ecd0f054a..5dc5b0c048 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -39,22 +39,22 @@ module ActiveRecord # Build SQL conditions from attributes, qualified by table name. def construct_conditions table = aliased_through_table - conditions = construct_quoted_owner_attributes(@reflection.through_reflection).map do |attr, value| + conditions = construct_owner_attributes(@reflection.through_reflection).map do |attr, value| table[attr].eq(value) end conditions << Arel.sql(sql_conditions) if sql_conditions table.create_and(conditions) end - # Associate attributes pointing to owner, quoted. - def construct_quoted_owner_attributes(reflection) + # Associate attributes pointing to owner + def construct_owner_attributes(reflection) if as = reflection.options[:as] - { "#{as}_id" => @owner.id, + { "#{as}_id" => @owner[reflection.active_record_primary_key], "#{as}_type" => @owner.class.base_class.name } elsif reflection.macro == :belongs_to { reflection.klass.primary_key => @owner[reflection.primary_key_name] } else - { reflection.primary_key_name => @owner.id } + { reflection.primary_key_name => @owner[reflection.active_record_primary_key] } end end @@ -74,7 +74,8 @@ module ActiveRecord conditions = [] if @reflection.source_reflection.macro == :belongs_to - reflection_primary_key = @reflection.klass.primary_key + reflection_primary_key = @reflection.source_reflection.options[:primary_key] || + @reflection.klass.primary_key source_primary_key = @reflection.source_reflection.primary_key_name if @reflection.options[:source_type] column = @reflection.source_reflection.options[:foreign_type] @@ -83,7 +84,8 @@ module ActiveRecord end else reflection_primary_key = @reflection.source_reflection.primary_key_name - source_primary_key = @reflection.through_reflection.klass.primary_key + source_primary_key = @reflection.source_reflection.options[:primary_key] || + @reflection.through_reflection.klass.primary_key if @reflection.source_reflection.options[:as] column = "#{@reflection.source_reflection.options[:as]}_type" conditions << @@ -99,16 +101,6 @@ module ActiveRecord right.create_on(right.create_and(conditions))) end - # Construct attributes for associate pointing to owner. - def construct_owner_attributes(reflection) - if as = reflection.options[:as] - { "#{as}_id" => @owner.id, - "#{as}_type" => @owner.class.base_class.name } - else - { reflection.primary_key_name => @owner.id } - end - end - # Construct attributes for :through pointing to owner and associate. def construct_join_attributes(associate) # TODO: revisit this to allow it for deletion, supposing dependent option is supported diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index fe4b518826..b9caa64a0e 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -205,7 +205,11 @@ module ActiveRecord end def association_foreign_key - @association_foreign_key ||= @options[:association_foreign_key] || class_name.foreign_key + @association_foreign_key ||= options[:association_foreign_key] || class_name.foreign_key + end + + def active_record_primary_key + @active_record_primary_key ||= options[:primary_key] || active_record.primary_key end def counter_cache_column -- cgit v1.2.3 From 40b15f9f389b9394b22cf36567269e54c66c9fc8 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 16 Dec 2010 22:20:42 +0100 Subject: ActiveRecord::Base.joins should allow single nil argument [#6181 state:resolved] --- activerecord/lib/active_record/relation/query_methods.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 6660df302b..0ab55ae864 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -63,7 +63,7 @@ module ActiveRecord end def joins(*args) - return self if args.blank? + return self if args.compact.blank? relation = clone -- cgit v1.2.3 From bcf4e4f2b02157cecc1f1727a95cdf5bfa471771 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 18 Dec 2010 13:38:05 -0800 Subject: Added ActiveRecord::Base#has_secure_password (via ActiveModel::SecurePassword) to encapsulate dead-simple password usage with SHA2 encryption and salting --- 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 d0f33c1d18..858ccebbfa 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1851,6 +1851,7 @@ MSG include ActiveModel::MassAssignmentSecurity include Callbacks, ActiveModel::Observing, Timestamp include Associations, AssociationPreload, NamedScope + include ActiveModel::SecurePassword # AutosaveAssociation needs to be included before Transactions, because we want # #save_with_autosave_associations to be wrapped inside a transaction. -- cgit v1.2.3 From 435bccda930e4dde3d0fafca958e1c8330b4c3ca Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sun, 19 Dec 2010 15:58:58 -0800 Subject: Replace AD::Callbacks.to_prepare with AD::Reloader.to_prepare MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activerecord/lib/active_record/railtie.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index dfe255ad7c..ba455ea79d 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -82,7 +82,7 @@ module ActiveRecord ActiveSupport.on_load(:active_record) do instantiate_observers - ActionDispatch::Callbacks.to_prepare(:activerecord_instantiate_observers) do + ActionDispatch::Reloader.to_prepare(:activerecord_instantiate_observers) do ActiveRecord::Base.instantiate_observers end end -- cgit v1.2.3 From e683ab7c390f26e110387822c7ffb5ac6aafebca Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sun, 19 Dec 2010 16:00:01 -0800 Subject: Use AD::Reloader.to_cleanup for reloading [#2873 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activerecord/lib/active_record/railtie.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index ba455ea79d..61fb0ae468 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -69,11 +69,9 @@ module ActiveRecord end initializer "active_record.set_dispatch_hooks", :before => :set_clear_dependencies_hook do |app| - unless app.config.cache_classes - ActiveSupport.on_load(:active_record) do - ActionDispatch::Callbacks.after do - ActiveRecord::Base.clear_reloadable_connections! - end + ActiveSupport.on_load(:active_record) do + ActionDispatch::Reloader.to_cleanup do + ActiveRecord::Base.clear_reloadable_connections! end end end -- cgit v1.2.3 From 0cbfd6c28d327304432f7d0c067662b5c1e41a78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Mon, 20 Dec 2010 12:41:49 +0100 Subject: Small changes on AD::Reloader. --- activerecord/lib/active_record/railtie.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index 61fb0ae468..2accf0a48f 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -80,7 +80,7 @@ module ActiveRecord ActiveSupport.on_load(:active_record) do instantiate_observers - ActionDispatch::Reloader.to_prepare(:activerecord_instantiate_observers) do + ActionDispatch::Reloader.to_prepare do ActiveRecord::Base.instantiate_observers end end -- cgit v1.2.3