diff options
author | Dmitry Polushkin <dmitry.polushkin@gmail.com> | 2011-10-01 20:49:14 +0100 |
---|---|---|
committer | Dmitry Polushkin <dmitry.polushkin@gmail.com> | 2011-10-01 20:49:14 +0100 |
commit | 19965402b2f868c79d78269ca17cb6282f271382 (patch) | |
tree | 8635415f386595650c27469d6b6d04335121d070 /activerecord/lib/active_record | |
parent | 9d54f8994d09db5435d6c234430ae13333928fb9 (diff) | |
parent | ec53b802dab9b676dcc9b53e542bcd840983b7a2 (diff) | |
download | rails-19965402b2f868c79d78269ca17cb6282f271382.tar.gz rails-19965402b2f868c79d78269ca17cb6282f271382.tar.bz2 rails-19965402b2f868c79d78269ca17cb6282f271382.zip |
Merge branch 'master' of git://github.com/rails/rails
Diffstat (limited to 'activerecord/lib/active_record')
9 files changed, 58 insertions, 25 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 9e7d609d19..0952ea2829 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1575,7 +1575,7 @@ module ActiveRecord # has_and_belongs_to_many :categories, :join_table => "prods_cats" # has_and_belongs_to_many :categories, :readonly => true # has_and_belongs_to_many :active_projects, :join_table => 'developers_projects', :delete_sql => - # 'DELETE FROM developers_projects WHERE active=1 AND developer_id = #{id} AND project_id = #{record.id}' + # "DELETE FROM developers_projects WHERE active=1 AND developer_id = #{id} AND project_id = #{record.id}" def has_and_belongs_to_many(name, options = {}, &extension) Builder::HasAndBelongsToMany.build(self, name, options, &extension) end diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb index 9e6d9e73c5..6cc401e6cc 100644 --- a/activerecord/lib/active_record/associations/association_scope.rb +++ b/activerecord/lib/active_record/associations/association_scope.rb @@ -42,10 +42,6 @@ module ActiveRecord select_value ||= options[:uniq] && "DISTINCT #{reflection.quoted_table_name}.*" end - if reflection.macro == :has_and_belongs_to_many - select_value ||= reflection.klass.arel_table[Arel.star] - end - select_value end @@ -68,7 +64,12 @@ module ActiveRecord end if reflection.source_macro == :belongs_to - key = reflection.association_primary_key + if reflection.options[:polymorphic] + key = reflection.association_primary_key(klass) + else + key = reflection.association_primary_key + end + foreign_key = reflection.foreign_key else key = reflection.foreign_key diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb index 58c9648ce8..97f531d064 100644 --- a/activerecord/lib/active_record/associations/belongs_to_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_association.rb @@ -45,7 +45,11 @@ module ActiveRecord end def replace_keys(record) - owner[reflection.foreign_key] = record && record[reflection.association_primary_key] + if record + owner[reflection.foreign_key] = record[reflection.association_primary_key(record.class)] + else + owner[reflection.foreign_key] = nil + end end def foreign_key_present? diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index 6ba3d45aff..3181ca9a32 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -46,7 +46,7 @@ module ActiveRecord delegate :select, :find, :first, :last, :build, :create, :create!, - :concat, :delete_all, :destroy_all, :delete, :destroy, :uniq, + :concat, :replace, :delete_all, :destroy_all, :delete, :destroy, :uniq, :sum, :count, :size, :length, :empty?, :any?, :many?, :include?, :to => :@association diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb index ed71b5e7d4..a404a5edd7 100644 --- a/activerecord/lib/active_record/attribute_methods/primary_key.rb +++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb @@ -66,7 +66,6 @@ module ActiveRecord @primary_key ||= '' self.original_primary_key = @primary_key value &&= value.to_s - connection_pool.primary_keys[table_name] = value self.primary_key = block_given? ? instance_eval(&block) : value end end diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 558b341c06..78159d13d4 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -707,6 +707,10 @@ module ActiveRecord #:nodoc: # Returns an array of column objects for the table associated with this class. def columns + if defined?(@primary_key) + connection_pool.primary_keys[table_name] ||= primary_key + end + connection_pool.columns[table_name] end diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 89179779e3..120ff0cac6 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -211,11 +211,9 @@ module ActiveRecord @association_foreign_key ||= options[:association_foreign_key] || class_name.foreign_key end - def association_primary_key - @association_primary_key ||= - options[:primary_key] || - !options[:polymorphic] && klass.primary_key || - 'id' + # klass option is necessary to support loading polymorphic associations + def association_primary_key(klass = nil) + options[:primary_key] || (klass || self.klass).primary_key end def active_record_primary_key @@ -463,17 +461,15 @@ module ActiveRecord # We want to use the klass from this reflection, rather than just delegate straight to # the source_reflection, because the source_reflection may be polymorphic. We still # need to respect the source_reflection's :primary_key option, though. - def association_primary_key - @association_primary_key ||= begin - # Get the "actual" source reflection if the immediate source reflection has a - # source reflection itself - source_reflection = self.source_reflection - while source_reflection.source_reflection - source_reflection = source_reflection.source_reflection - end - - source_reflection.options[:primary_key] || klass.primary_key + def association_primary_key(klass = self.klass) + # Get the "actual" source reflection if the immediate source reflection has a + # source reflection itself + source_reflection = self.source_reflection + while source_reflection.source_reflection + source_reflection = source_reflection.source_reflection end + + source_reflection.options[:primary_key] || klass.primary_key end # Gets an array of possible <tt>:through</tt> source reflection names: diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index a11b7a3864..670ba0987d 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -37,6 +37,35 @@ module ActiveRecord relation end + # Works in two unique ways. + # + # First: takes a block so it can be used just like Array#select. + # + # Model.scoped.select { |m| m.field == value } + # + # This will build an array of objects from the database for the scope, + # converting them into an array and iterating through them using Array#select. + # + # Second: Modifies the SELECT statement for the query so that only certain + # fields are retrieved: + # + # >> Model.select(:field) + # => [#<Model field:value>] + # + # Although in the above example it looks as though this method returns an + # array, it actually returns a relation object and can have other query + # methods appended to it, such as the other methods in ActiveRecord::QueryMethods. + # + # This method will also take multiple parameters: + # + # >> Model.select(:field, :other_field, :and_one_more) + # => [#<Model field: "value", other_field: "value", and_one_more: "value">] + # + # Any attributes that do not have fields retrieved by a select + # will return `nil` when the getter method for that attribute is used: + # + # >> Model.select(:field).first.other_field + # => nil def select(value = Proc.new) if block_given? to_a.select {|*block_args| value.call(*block_args) } diff --git a/activerecord/lib/active_record/serializers/xml_serializer.rb b/activerecord/lib/active_record/serializers/xml_serializer.rb index cbfa1ad609..0e7f57aa43 100644 --- a/activerecord/lib/active_record/serializers/xml_serializer.rb +++ b/activerecord/lib/active_record/serializers/xml_serializer.rb @@ -179,7 +179,7 @@ module ActiveRecord #:nodoc: class XmlSerializer < ActiveModel::Serializers::Xml::Serializer #:nodoc: def initialize(*args) super - options[:except] |= Array.wrap(@serializable.class.inheritance_column) + options[:except] = Array.wrap(options[:except]) | Array.wrap(@serializable.class.inheritance_column) end class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute #:nodoc: |