diff options
author | Jeremy Kemper <jeremy@bitsweat.net> | 2009-01-10 12:14:44 -0800 |
---|---|---|
committer | Jeremy Kemper <jeremy@bitsweat.net> | 2009-01-10 12:14:44 -0800 |
commit | 223a1d9451c88800e9fcc93a726fdebec99e2650 (patch) | |
tree | 207b0b671778ac7a0e00829f6f642256b261cb28 /activerecord/lib/active_record/associations.rb | |
parent | 13c6c3cfc59ff0b400b294dce15f32752b0fb5f5 (diff) | |
parent | 9fe69b225cfbf12c02ee1433adf3a5aa17bcdf59 (diff) | |
download | rails-223a1d9451c88800e9fcc93a726fdebec99e2650.tar.gz rails-223a1d9451c88800e9fcc93a726fdebec99e2650.tar.bz2 rails-223a1d9451c88800e9fcc93a726fdebec99e2650.zip |
Merge branch 'master' into savepoints
Diffstat (limited to 'activerecord/lib/active_record/associations.rb')
-rwxr-xr-x | activerecord/lib/active_record/associations.rb | 97 |
1 files changed, 60 insertions, 37 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 3fbbea43ed..86616abf52 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -22,7 +22,7 @@ module ActiveRecord through_reflection = reflection.through_reflection source_reflection_names = reflection.source_reflection_names source_associations = reflection.through_reflection.klass.reflect_on_all_associations.collect { |a| a.name.inspect } - super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence :connector => 'or'} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => <name>'. Is it one of #{source_associations.to_sentence :connector => 'or'}?") + super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence :two_words_connector => ' or ', :last_word_connector => ', or '} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => <name>'. Is it one of #{source_associations.to_sentence :two_words_connector => ' or ', :last_word_connector => ', or '}?") end end @@ -153,7 +153,7 @@ module ActiveRecord # #others.destroy_all | X | X | X # #others.find(*args) | X | X | X # #others.find_first | X | | - # #others.exist? | X | X | X + # #others.exists? | X | X | X # #others.uniq | X | X | X # #others.reset | X | X | X # @@ -652,7 +652,7 @@ module ActiveRecord # Returns the number of associated objects. # [collection.find(...)] # Finds an associated object according to the same rules as ActiveRecord::Base.find. - # [collection.exist?(...)] + # [collection.exists?(...)] # Checks whether an associated object with the given conditions exists. # Uses the same rules as ActiveRecord::Base.exists?. # [collection.build(attributes = {}, ...)] @@ -682,7 +682,7 @@ module ActiveRecord # * <tt>Firm#clients.empty?</tt> (similar to <tt>firm.clients.size == 0</tt>) # * <tt>Firm#clients.size</tt> (similar to <tt>Client.count "firm_id = #{id}"</tt>) # * <tt>Firm#clients.find</tt> (similar to <tt>Client.find(id, :conditions => "firm_id = #{id}")</tt>) - # * <tt>Firm#clients.exist?(:name => 'ACME')</tt> (similar to <tt>Client.exist?(:name => 'ACME', :firm_id => firm.id)</tt>) + # * <tt>Firm#clients.exists?(:name => 'ACME')</tt> (similar to <tt>Client.exists?(:name => 'ACME', :firm_id => firm.id)</tt>) # * <tt>Firm#clients.build</tt> (similar to <tt>Client.new("firm_id" => id)</tt>) # * <tt>Firm#clients.create</tt> (similar to <tt>c = Client.new("firm_id" => id); c.save; c</tt>) # The declaration can also include an options hash to specialize the behavior of the association. @@ -1107,7 +1107,7 @@ module ActiveRecord # Finds an associated object responding to the +id+ and that # meets the condition that it has to be associated with this object. # Uses the same rules as ActiveRecord::Base.find. - # [collection.exist?(...)] + # [collection.exists?(...)] # Checks whether an associated object with the given conditions exists. # Uses the same rules as ActiveRecord::Base.exists?. # [collection.build(attributes = {})] @@ -1133,7 +1133,7 @@ module ActiveRecord # * <tt>Developer#projects.empty?</tt> # * <tt>Developer#projects.size</tt> # * <tt>Developer#projects.find(id)</tt> - # * <tt>Developer#clients.exist?(...)</tt> + # * <tt>Developer#clients.exists?(...)</tt> # * <tt>Developer#projects.build</tt> (similar to <tt>Project.new("project_id" => id)</tt>) # * <tt>Developer#projects.create</tt> (similar to <tt>c = Project.new("project_id" => id); c.save; c</tt>) # The declaration may include an options hash to specialize the behavior of the association. @@ -1216,11 +1216,11 @@ module ActiveRecord # callbacks will be executed after the association is wiped out. old_method = "destroy_without_habtm_shim_for_#{reflection.name}" class_eval <<-end_eval unless method_defined?(old_method) - alias_method :#{old_method}, :destroy_without_callbacks - def destroy_without_callbacks - #{reflection.name}.clear - #{old_method} - end + alias_method :#{old_method}, :destroy_without_callbacks # alias_method :destroy_without_habtm_shim_for_posts, :destroy_without_callbacks + def destroy_without_callbacks # def destroy_without_callbacks + #{reflection.name}.clear # posts.clear + #{old_method} # destroy_without_habtm_shim_for_posts + end # end end_eval add_association_callbacks(reflection.name, options) @@ -1453,7 +1453,7 @@ module ActiveRecord dependent_conditions << sanitize_sql(reflection.options[:conditions]) if reflection.options[:conditions] dependent_conditions << extra_conditions if extra_conditions dependent_conditions = dependent_conditions.collect {|where| "(#{where})" }.join(" AND ") - + dependent_conditions = dependent_conditions.gsub('@', '\@') case reflection.options[:dependent] when :destroy method_name = "has_many_dependent_destroy_for_#{reflection.name}".to_sym @@ -1463,22 +1463,22 @@ module ActiveRecord before_destroy method_name when :delete_all module_eval %Q{ - before_destroy do |record| - delete_all_has_many_dependencies(record, - "#{reflection.name}", - #{reflection.class_name}, - "#{dependent_conditions}") - end + before_destroy do |record| # before_destroy do |record| + delete_all_has_many_dependencies(record, # delete_all_has_many_dependencies(record, + "#{reflection.name}", # "posts", + #{reflection.class_name}, # Post, + %@#{dependent_conditions}@) # %@...@) # this is a string literal like %(...) + end # end } when :nullify module_eval %Q{ - before_destroy do |record| - nullify_has_many_dependencies(record, - "#{reflection.name}", - #{reflection.class_name}, - "#{reflection.primary_key_name}", - "#{dependent_conditions}") - end + before_destroy do |record| # before_destroy do |record| + nullify_has_many_dependencies(record, # nullify_has_many_dependencies(record, + "#{reflection.name}", # "posts", + #{reflection.class_name}, # Post, + "#{reflection.primary_key_name}", # "user_id", + %@#{dependent_conditions}@) # %@...@) # this is a string literal like %(...) + end # end } else raise ArgumentError, "The :dependent option expects either :destroy, :delete_all, or :nullify (#{reflection.options[:dependent].inspect})" @@ -1731,6 +1731,11 @@ module ActiveRecord return sanitize_sql(sql) end + def tables_in_string(string) + return [] if string.blank? + string.scan(/([\.a-zA-Z_]+).?\./).flatten + end + def conditions_tables(options) # look in both sets of conditions conditions = [scope(:find, :conditions), options[:conditions]].inject([]) do |all, cond| @@ -1741,37 +1746,55 @@ module ActiveRecord else all << cond end end - conditions.join(' ').scan(/([\.a-zA-Z_]+).?\./).flatten + tables_in_string(conditions.join(' ')) end def order_tables(options) order = [options[:order], scope(:find, :order) ].join(", ") return [] unless order && order.is_a?(String) - order.scan(/([\.a-zA-Z_]+).?\./).flatten + tables_in_string(order) end def selects_tables(options) select = options[:select] return [] unless select && select.is_a?(String) - select.scan(/"?([\.a-zA-Z_]+)"?.?\./).flatten + tables_in_string(select) + end + + def joined_tables(options) + scope = scope(:find) + joins = options[:joins] + merged_joins = scope && scope[:joins] && joins ? merge_joins(scope[:joins], joins) : (joins || scope && scope[:joins]) + [table_name] + case merged_joins + when Symbol, Hash, Array + if array_of_strings?(merged_joins) + tables_in_string(merged_joins.join(' ')) + else + join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, merged_joins, nil) + join_dependency.join_associations.collect {|join_association| [join_association.aliased_join_table_name, join_association.aliased_table_name]}.flatten.compact + end + else + tables_in_string(merged_joins) + end end # Checks if the conditions reference a table other than the current model table - def include_eager_conditions?(options, tables = nil) - ((tables || conditions_tables(options)) - [table_name]).any? + def include_eager_conditions?(options, tables = nil, joined_tables = nil) + ((tables || conditions_tables(options)) - (joined_tables || joined_tables(options))).any? end # Checks if the query order references a table other than the current model's table. - def include_eager_order?(options, tables = nil) - ((tables || order_tables(options)) - [table_name]).any? + def include_eager_order?(options, tables = nil, joined_tables = nil) + ((tables || order_tables(options)) - (joined_tables || joined_tables(options))).any? end - def include_eager_select?(options) - (selects_tables(options) - [table_name]).any? + def include_eager_select?(options, joined_tables = nil) + (selects_tables(options) - (joined_tables || joined_tables(options))).any? end def references_eager_loaded_tables?(options) - include_eager_order?(options) || include_eager_conditions?(options) || include_eager_select?(options) + joined_tables = joined_tables(options) + include_eager_order?(options, nil, joined_tables) || include_eager_conditions?(options, nil, joined_tables) || include_eager_select?(options, joined_tables) end def using_limitable_reflections?(reflections) @@ -2148,7 +2171,7 @@ module ActiveRecord aliased_table_name, foreign_key, parent.aliased_table_name, - parent.primary_key + reflection.options[:primary_key] || parent.primary_key ] end when :belongs_to @@ -2175,7 +2198,7 @@ module ActiveRecord protected def aliased_table_name_for(name, suffix = nil) - if !parent.table_joins.blank? && parent.table_joins.to_s.downcase =~ %r{join(\s+\w+)?\s+#{name.downcase}\son} + if !parent.table_joins.blank? && parent.table_joins.to_s.downcase =~ %r{join(\s+\w+)?\s+#{active_record.connection.quote_table_name name.downcase}\son} @join_dependency.table_aliases[name] += 1 end |