activerecord 3.1.12 → 3.2.22.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +804 -338
- data/README.rdoc +3 -3
- data/examples/performance.rb +20 -1
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/associations/alias_tracker.rb +3 -6
- data/lib/active_record/associations/association.rb +13 -45
- data/lib/active_record/associations/association_scope.rb +3 -15
- data/lib/active_record/associations/belongs_to_association.rb +1 -1
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +2 -1
- data/lib/active_record/associations/builder/association.rb +6 -4
- data/lib/active_record/associations/builder/belongs_to.rb +7 -4
- data/lib/active_record/associations/builder/collection_association.rb +2 -2
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +5 -6
- data/lib/active_record/associations/builder/singular_association.rb +3 -16
- data/lib/active_record/associations/collection_association.rb +65 -32
- data/lib/active_record/associations/collection_proxy.rb +8 -41
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +1 -0
- data/lib/active_record/associations/has_many_association.rb +11 -7
- data/lib/active_record/associations/has_many_through_association.rb +19 -9
- data/lib/active_record/associations/has_one_association.rb +23 -13
- data/lib/active_record/associations/join_dependency/join_association.rb +6 -1
- data/lib/active_record/associations/join_dependency.rb +3 -3
- data/lib/active_record/associations/preloader/through_association.rb +3 -3
- data/lib/active_record/associations/preloader.rb +14 -10
- data/lib/active_record/associations/through_association.rb +8 -4
- data/lib/active_record/associations.rb +92 -76
- data/lib/active_record/attribute_assignment.rb +221 -0
- data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +32 -0
- data/lib/active_record/attribute_methods/dirty.rb +21 -11
- data/lib/active_record/attribute_methods/primary_key.rb +62 -25
- data/lib/active_record/attribute_methods/read.rb +73 -83
- data/lib/active_record/attribute_methods/serialization.rb +120 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
- data/lib/active_record/attribute_methods/write.rb +32 -6
- data/lib/active_record/attribute_methods.rb +231 -30
- data/lib/active_record/autosave_association.rb +44 -26
- data/lib/active_record/base.rb +227 -1708
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +150 -148
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +85 -29
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +7 -34
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +10 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +7 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +39 -28
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +48 -19
- data/lib/active_record/connection_adapters/abstract_adapter.rb +77 -42
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +676 -0
- data/lib/active_record/connection_adapters/column.rb +37 -11
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +133 -581
- data/lib/active_record/connection_adapters/mysql_adapter.rb +136 -693
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +209 -97
- data/lib/active_record/connection_adapters/schema_cache.rb +69 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -6
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +62 -35
- data/lib/active_record/counter_cache.rb +9 -4
- data/lib/active_record/dynamic_finder_match.rb +12 -0
- data/lib/active_record/dynamic_matchers.rb +84 -0
- data/lib/active_record/errors.rb +11 -1
- data/lib/active_record/explain.rb +86 -0
- data/lib/active_record/explain_subscriber.rb +25 -0
- data/lib/active_record/fixtures/file.rb +65 -0
- data/lib/active_record/fixtures.rb +57 -86
- data/lib/active_record/identity_map.rb +3 -4
- data/lib/active_record/inheritance.rb +174 -0
- data/lib/active_record/integration.rb +60 -0
- data/lib/active_record/locking/optimistic.rb +33 -26
- data/lib/active_record/locking/pessimistic.rb +23 -1
- data/lib/active_record/log_subscriber.rb +8 -4
- data/lib/active_record/migration/command_recorder.rb +8 -8
- data/lib/active_record/migration.rb +68 -35
- data/lib/active_record/model_schema.rb +368 -0
- data/lib/active_record/nested_attributes.rb +60 -24
- data/lib/active_record/persistence.rb +57 -11
- data/lib/active_record/query_cache.rb +6 -6
- data/lib/active_record/querying.rb +58 -0
- data/lib/active_record/railtie.rb +37 -29
- data/lib/active_record/railties/controller_runtime.rb +3 -1
- data/lib/active_record/railties/databases.rake +213 -117
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +26 -0
- data/lib/active_record/reflection.rb +7 -15
- data/lib/active_record/relation/batches.rb +7 -4
- data/lib/active_record/relation/calculations.rb +55 -16
- data/lib/active_record/relation/delegation.rb +49 -0
- data/lib/active_record/relation/finder_methods.rb +16 -11
- data/lib/active_record/relation/predicate_builder.rb +8 -6
- data/lib/active_record/relation/query_methods.rb +75 -9
- data/lib/active_record/relation/spawn_methods.rb +48 -7
- data/lib/active_record/relation.rb +78 -32
- data/lib/active_record/result.rb +10 -4
- data/lib/active_record/sanitization.rb +194 -0
- data/lib/active_record/schema_dumper.rb +12 -5
- data/lib/active_record/scoping/default.rb +142 -0
- data/lib/active_record/scoping/named.rb +200 -0
- data/lib/active_record/scoping.rb +152 -0
- data/lib/active_record/serialization.rb +1 -43
- data/lib/active_record/serializers/xml_serializer.rb +4 -45
- data/lib/active_record/session_store.rb +18 -16
- data/lib/active_record/store.rb +52 -0
- data/lib/active_record/test_case.rb +11 -7
- data/lib/active_record/timestamp.rb +17 -3
- data/lib/active_record/transactions.rb +27 -6
- data/lib/active_record/translation.rb +22 -0
- data/lib/active_record/validations/associated.rb +5 -4
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record/validations.rb +1 -1
- data/lib/active_record/version.rb +3 -3
- data/lib/active_record.rb +38 -3
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb +12 -3
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -1
- data/lib/rails/generators/active_record/model/templates/migration.rb +3 -5
- data/lib/rails/generators/active_record/model/templates/model.rb +5 -0
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +1 -5
- metadata +49 -28
- data/lib/active_record/named_scope.rb +0 -200
@@ -5,7 +5,6 @@ require 'active_support/core_ext/object/blank'
|
|
5
5
|
require 'active_support/core_ext/string/conversions'
|
6
6
|
require 'active_support/core_ext/module/remove_method'
|
7
7
|
require 'active_support/core_ext/class/attribute'
|
8
|
-
require 'active_support/deprecation'
|
9
8
|
|
10
9
|
module ActiveRecord
|
11
10
|
class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc:
|
@@ -71,7 +70,7 @@ module ActiveRecord
|
|
71
70
|
end
|
72
71
|
end
|
73
72
|
|
74
|
-
class HasManyThroughNestedAssociationsAreReadonly < ActiveRecordError #:nodoc
|
73
|
+
class HasManyThroughNestedAssociationsAreReadonly < ActiveRecordError #:nodoc:
|
75
74
|
def initialize(owner, reflection)
|
76
75
|
super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.")
|
77
76
|
end
|
@@ -106,6 +105,7 @@ module ActiveRecord
|
|
106
105
|
|
107
106
|
# See ActiveRecord::Associations::ClassMethods for documentation.
|
108
107
|
module Associations # :nodoc:
|
108
|
+
extend ActiveSupport::Autoload
|
109
109
|
extend ActiveSupport::Concern
|
110
110
|
|
111
111
|
# These classes will be loaded when associations are created.
|
@@ -114,7 +114,6 @@ module ActiveRecord
|
|
114
114
|
autoload :SingularAssociation, 'active_record/associations/singular_association'
|
115
115
|
autoload :CollectionAssociation, 'active_record/associations/collection_association'
|
116
116
|
autoload :CollectionProxy, 'active_record/associations/collection_proxy'
|
117
|
-
autoload :AssociationCollection, 'active_record/associations/collection_proxy'
|
118
117
|
|
119
118
|
autoload :BelongsToAssociation, 'active_record/associations/belongs_to_association'
|
120
119
|
autoload :BelongsToPolymorphicAssociation, 'active_record/associations/belongs_to_polymorphic_association'
|
@@ -136,11 +135,13 @@ module ActiveRecord
|
|
136
135
|
autoload :HasAndBelongsToMany, 'active_record/associations/builder/has_and_belongs_to_many'
|
137
136
|
end
|
138
137
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
138
|
+
eager_autoload do
|
139
|
+
autoload :Preloader, 'active_record/associations/preloader'
|
140
|
+
autoload :JoinDependency, 'active_record/associations/join_dependency'
|
141
|
+
autoload :AssociationScope, 'active_record/associations/association_scope'
|
142
|
+
autoload :AliasTracker, 'active_record/associations/alias_tracker'
|
143
|
+
autoload :JoinHelper, 'active_record/associations/join_helper'
|
144
|
+
end
|
144
145
|
|
145
146
|
# Clears out the association cache.
|
146
147
|
def clear_association_cache #:nodoc:
|
@@ -193,11 +194,31 @@ module ActiveRecord
|
|
193
194
|
# * <tt>Project#portfolio, Project#portfolio=(portfolio), Project#portfolio.nil?</tt>
|
194
195
|
# * <tt>Project#project_manager, Project#project_manager=(project_manager), Project#project_manager.nil?,</tt>
|
195
196
|
# * <tt>Project#milestones.empty?, Project#milestones.size, Project#milestones, Project#milestones<<(milestone),</tt>
|
196
|
-
# <tt>Project#milestones.delete(milestone), Project#milestones.find(milestone_id), Project#milestones.
|
197
|
+
# <tt>Project#milestones.delete(milestone), Project#milestones.find(milestone_id), Project#milestones.all(options),</tt>
|
197
198
|
# <tt>Project#milestones.build, Project#milestones.create</tt>
|
198
199
|
# * <tt>Project#categories.empty?, Project#categories.size, Project#categories, Project#categories<<(category1),</tt>
|
199
200
|
# <tt>Project#categories.delete(category1)</tt>
|
200
201
|
#
|
202
|
+
# === Overriding generated methods
|
203
|
+
#
|
204
|
+
# Association methods are generated in a module that is included into the model class,
|
205
|
+
# which allows you to easily override with your own methods and call the original
|
206
|
+
# generated method with +super+. For example:
|
207
|
+
#
|
208
|
+
# class Car < ActiveRecord::Base
|
209
|
+
# belongs_to :owner
|
210
|
+
# belongs_to :old_owner
|
211
|
+
# def owner=(new_owner)
|
212
|
+
# self.old_owner = self.owner
|
213
|
+
# super
|
214
|
+
# end
|
215
|
+
# end
|
216
|
+
#
|
217
|
+
# If your model class is <tt>Project</tt>, the module is
|
218
|
+
# named <tt>Project::GeneratedFeatureMethods</tt>. The GeneratedFeatureMethods module is
|
219
|
+
# included in the model class immediately after the (anonymous) generated attributes methods
|
220
|
+
# module, meaning an association will override the methods for an attribute with the same name.
|
221
|
+
#
|
201
222
|
# === A word of warning
|
202
223
|
#
|
203
224
|
# Don't create associations that have the same name as instance methods of
|
@@ -471,9 +492,9 @@ module ActiveRecord
|
|
471
492
|
# === Association Join Models
|
472
493
|
#
|
473
494
|
# Has Many associations can be configured with the <tt>:through</tt> option to use an
|
474
|
-
# explicit join model to retrieve the data.
|
475
|
-
# +has_and_belongs_to_many+ association.
|
476
|
-
# callbacks, and extra attributes on the join model.
|
495
|
+
# explicit join model to retrieve the data. This operates similarly to a
|
496
|
+
# +has_and_belongs_to_many+ association. The advantage is that you're able to add validations,
|
497
|
+
# callbacks, and extra attributes on the join model. Consider the following schema:
|
477
498
|
#
|
478
499
|
# class Author < ActiveRecord::Base
|
479
500
|
# has_many :authorships
|
@@ -530,7 +551,7 @@ module ActiveRecord
|
|
530
551
|
# @group.avatars # selects all avatars by going through the User join model.
|
531
552
|
#
|
532
553
|
# An important caveat with going through +has_one+ or +has_many+ associations on the
|
533
|
-
# join model is that these associations are *read-only*.
|
554
|
+
# join model is that these associations are *read-only*. For example, the following
|
534
555
|
# would not work following the previous example:
|
535
556
|
#
|
536
557
|
# @group.avatars << Avatar.new # this would work if User belonged_to Avatar rather than the other way around
|
@@ -598,7 +619,7 @@ module ActiveRecord
|
|
598
619
|
# === Polymorphic Associations
|
599
620
|
#
|
600
621
|
# Polymorphic associations on models are not restricted on what types of models they
|
601
|
-
# can be associated with.
|
622
|
+
# can be associated with. Rather, they specify an interface that a +has_many+ association
|
602
623
|
# must adhere to.
|
603
624
|
#
|
604
625
|
# class Asset < ActiveRecord::Base
|
@@ -612,7 +633,7 @@ module ActiveRecord
|
|
612
633
|
# @asset.attachable = @post
|
613
634
|
#
|
614
635
|
# This works by using a type column in addition to a foreign key to specify the associated
|
615
|
-
# record.
|
636
|
+
# record. In the Asset example, you'd need an +attachable_id+ integer column and an
|
616
637
|
# +attachable_type+ string column.
|
617
638
|
#
|
618
639
|
# Using polymorphic associations in combination with single table inheritance (STI) is
|
@@ -668,7 +689,7 @@ module ActiveRecord
|
|
668
689
|
#
|
669
690
|
# Consider the following loop using the class above:
|
670
691
|
#
|
671
|
-
#
|
692
|
+
# Post.all.each do |post|
|
672
693
|
# puts "Post: " + post.title
|
673
694
|
# puts "Written by: " + post.author.name
|
674
695
|
# puts "Last comment on: " + post.comments.first.created_on
|
@@ -677,7 +698,7 @@ module ActiveRecord
|
|
677
698
|
# To iterate over these one hundred posts, we'll generate 201 database queries. Let's
|
678
699
|
# first just optimize it for retrieving the author:
|
679
700
|
#
|
680
|
-
#
|
701
|
+
# Post.includes(:author).each do |post|
|
681
702
|
#
|
682
703
|
# This references the name of the +belongs_to+ association that also used the <tt>:author</tt>
|
683
704
|
# symbol. After loading the posts, find will collect the +author_id+ from each one and load
|
@@ -686,7 +707,7 @@ module ActiveRecord
|
|
686
707
|
#
|
687
708
|
# We can improve upon the situation further by referencing both associations in the finder with:
|
688
709
|
#
|
689
|
-
#
|
710
|
+
# Post.includes(:author, :comments).each do |post|
|
690
711
|
#
|
691
712
|
# This will load all comments with a single query. This reduces the total number of queries
|
692
713
|
# to 3. More generally the number of queries will be 1 plus the number of associations
|
@@ -694,7 +715,7 @@ module ActiveRecord
|
|
694
715
|
#
|
695
716
|
# To include a deep hierarchy of associations, use a hash:
|
696
717
|
#
|
697
|
-
#
|
718
|
+
# Post.includes(:author, {:comments => {:author => :gravatar}}).each do |post|
|
698
719
|
#
|
699
720
|
# That'll grab not only all the comments but all their authors and gravatar pictures.
|
700
721
|
# You can mix and match symbols, arrays and hashes in any combination to describe the
|
@@ -722,13 +743,13 @@ module ActiveRecord
|
|
722
743
|
# <tt>:order => "author.name DESC"</tt> will work but <tt>:order => "name DESC"</tt> will not.
|
723
744
|
#
|
724
745
|
# If you do want eager load only some members of an association it is usually more natural
|
725
|
-
# to
|
746
|
+
# to include an association which has conditions defined on it:
|
726
747
|
#
|
727
748
|
# class Post < ActiveRecord::Base
|
728
749
|
# has_many :approved_comments, :class_name => 'Comment', :conditions => ['approved = ?', true]
|
729
750
|
# end
|
730
751
|
#
|
731
|
-
# Post.
|
752
|
+
# Post.includes(:approved_comments)
|
732
753
|
#
|
733
754
|
# This will load posts and eager load the +approved_comments+ association, which contains
|
734
755
|
# only those comments that have been approved.
|
@@ -740,10 +761,10 @@ module ActiveRecord
|
|
740
761
|
# has_many :most_recent_comments, :class_name => 'Comment', :order => 'id DESC', :limit => 10
|
741
762
|
# end
|
742
763
|
#
|
743
|
-
# Picture.
|
764
|
+
# Picture.includes(:most_recent_comments).first.most_recent_comments # => returns all associated comments.
|
744
765
|
#
|
745
766
|
# When eager loaded, conditions are interpolated in the context of the model class, not
|
746
|
-
# the model instance.
|
767
|
+
# the model instance. Conditions are lazily interpolated before the actual model exists.
|
747
768
|
#
|
748
769
|
# Eager loading is supported with polymorphic associations.
|
749
770
|
#
|
@@ -753,7 +774,7 @@ module ActiveRecord
|
|
753
774
|
#
|
754
775
|
# A call that tries to eager load the addressable model
|
755
776
|
#
|
756
|
-
# Address.
|
777
|
+
# Address.includes(:addressable)
|
757
778
|
#
|
758
779
|
# This will execute one query to load the addresses and load the addressables with one
|
759
780
|
# query per addressable type.
|
@@ -767,47 +788,47 @@ module ActiveRecord
|
|
767
788
|
# == Table Aliasing
|
768
789
|
#
|
769
790
|
# Active Record uses table aliasing in the case that a table is referenced multiple times
|
770
|
-
# in a join.
|
791
|
+
# in a join. If a table is referenced only once, the standard table name is used. The
|
771
792
|
# second time, the table is aliased as <tt>#{reflection_name}_#{parent_table_name}</tt>.
|
772
793
|
# Indexes are appended for any more successive uses of the table name.
|
773
794
|
#
|
774
|
-
# Post.
|
795
|
+
# Post.joins(:comments)
|
775
796
|
# # => SELECT ... FROM posts INNER JOIN comments ON ...
|
776
|
-
# Post.
|
797
|
+
# Post.joins(:special_comments) # STI
|
777
798
|
# # => SELECT ... FROM posts INNER JOIN comments ON ... AND comments.type = 'SpecialComment'
|
778
|
-
# Post.
|
799
|
+
# Post.joins(:comments, :special_comments) # special_comments is the reflection name, posts is the parent table name
|
779
800
|
# # => SELECT ... FROM posts INNER JOIN comments ON ... INNER JOIN comments special_comments_posts
|
780
801
|
#
|
781
802
|
# Acts as tree example:
|
782
803
|
#
|
783
|
-
# TreeMixin.
|
804
|
+
# TreeMixin.joins(:children)
|
784
805
|
# # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
|
785
|
-
# TreeMixin.
|
806
|
+
# TreeMixin.joins(:children => :parent)
|
786
807
|
# # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
|
787
808
|
# INNER JOIN parents_mixins ...
|
788
|
-
# TreeMixin.
|
809
|
+
# TreeMixin.joins(:children => {:parent => :children})
|
789
810
|
# # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
|
790
811
|
# INNER JOIN parents_mixins ...
|
791
812
|
# INNER JOIN mixins childrens_mixins_2
|
792
813
|
#
|
793
814
|
# Has and Belongs to Many join tables use the same idea, but add a <tt>_join</tt> suffix:
|
794
815
|
#
|
795
|
-
# Post.
|
816
|
+
# Post.joins(:categories)
|
796
817
|
# # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
|
797
|
-
# Post.
|
818
|
+
# Post.joins(:categories => :posts)
|
798
819
|
# # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
|
799
820
|
# INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
|
800
|
-
# Post.
|
821
|
+
# Post.joins(:categories => {:posts => :categories})
|
801
822
|
# # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
|
802
823
|
# INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
|
803
824
|
# INNER JOIN categories_posts categories_posts_join INNER JOIN categories categories_posts_2
|
804
825
|
#
|
805
|
-
# If you wish to specify your own custom joins using
|
826
|
+
# If you wish to specify your own custom joins using <tt>joins</tt> method, those table
|
806
827
|
# names will take precedence over the eager associations:
|
807
828
|
#
|
808
|
-
# Post.
|
829
|
+
# Post.joins(:comments).joins("inner join comments ...")
|
809
830
|
# # => SELECT ... FROM posts INNER JOIN comments_posts ON ... INNER JOIN comments ...
|
810
|
-
# Post.
|
831
|
+
# Post.joins(:comments, :special_comments).joins("inner join comments ...")
|
811
832
|
# # => SELECT ... FROM posts INNER JOIN comments comments_posts ON ...
|
812
833
|
# INNER JOIN comments special_comments_posts ...
|
813
834
|
# INNER JOIN comments ...
|
@@ -849,7 +870,7 @@ module ActiveRecord
|
|
849
870
|
# == Bi-directional associations
|
850
871
|
#
|
851
872
|
# When you specify an association there is usually an association on the associated model
|
852
|
-
# that specifies the same relationship in reverse.
|
873
|
+
# that specifies the same relationship in reverse. For example, with the following models:
|
853
874
|
#
|
854
875
|
# class Dungeon < ActiveRecord::Base
|
855
876
|
# has_many :traps
|
@@ -866,9 +887,9 @@ module ActiveRecord
|
|
866
887
|
#
|
867
888
|
# The +traps+ association on +Dungeon+ and the +dungeon+ association on +Trap+ are
|
868
889
|
# the inverse of each other and the inverse of the +dungeon+ association on +EvilWizard+
|
869
|
-
# is the +evil_wizard+ association on +Dungeon+ (and vice-versa).
|
890
|
+
# is the +evil_wizard+ association on +Dungeon+ (and vice-versa). By default,
|
870
891
|
# Active Record doesn't know anything about these inverse relationships and so no object
|
871
|
-
# loading
|
892
|
+
# loading optimization is possible. For example:
|
872
893
|
#
|
873
894
|
# d = Dungeon.first
|
874
895
|
# t = d.traps.first
|
@@ -878,8 +899,8 @@ module ActiveRecord
|
|
878
899
|
#
|
879
900
|
# The +Dungeon+ instances +d+ and <tt>t.dungeon</tt> in the above example refer to
|
880
901
|
# the same object data from the database, but are actually different in-memory copies
|
881
|
-
# of that data.
|
882
|
-
# Active Record about inverse relationships and it will optimise object loading.
|
902
|
+
# of that data. Specifying the <tt>:inverse_of</tt> option on associations lets you tell
|
903
|
+
# Active Record about inverse relationships and it will optimise object loading. For
|
883
904
|
# example, if we changed our model definitions to:
|
884
905
|
#
|
885
906
|
# class Dungeon < ActiveRecord::Base
|
@@ -1039,7 +1060,7 @@ module ActiveRecord
|
|
1039
1060
|
# === Example
|
1040
1061
|
#
|
1041
1062
|
# Example: A Firm class declares <tt>has_many :clients</tt>, which will add:
|
1042
|
-
# * <tt>Firm#clients</tt> (similar to <tt>Clients.
|
1063
|
+
# * <tt>Firm#clients</tt> (similar to <tt>Clients.all :conditions => ["firm_id = ?", id]</tt>)
|
1043
1064
|
# * <tt>Firm#clients<<</tt>
|
1044
1065
|
# * <tt>Firm#clients.delete</tt>
|
1045
1066
|
# * <tt>Firm#clients=</tt>
|
@@ -1062,7 +1083,7 @@ module ActiveRecord
|
|
1062
1083
|
# specify it with this option.
|
1063
1084
|
# [:conditions]
|
1064
1085
|
# Specify the conditions that the associated objects must meet in order to be included as a +WHERE+
|
1065
|
-
# SQL fragment, such as <tt>price > 5 AND name LIKE 'B%'</tt>.
|
1086
|
+
# SQL fragment, such as <tt>price > 5 AND name LIKE 'B%'</tt>. Record creations from
|
1066
1087
|
# the association are scoped if a hash is used.
|
1067
1088
|
# <tt>has_many :posts, :conditions => {:published => true}</tt> will create published
|
1068
1089
|
# posts with <tt>@blog.posts.create</tt> or <tt>@blog.posts.build</tt>.
|
@@ -1077,10 +1098,11 @@ module ActiveRecord
|
|
1077
1098
|
# Specify the method that returns the primary key used for the association. By default this is +id+.
|
1078
1099
|
# [:dependent]
|
1079
1100
|
# If set to <tt>:destroy</tt> all the associated objects are destroyed
|
1080
|
-
# alongside this object by calling their +destroy+ method.
|
1081
|
-
# objects are deleted *without* calling their +destroy+ method.
|
1101
|
+
# alongside this object by calling their +destroy+ method. If set to <tt>:delete_all</tt> all associated
|
1102
|
+
# objects are deleted *without* calling their +destroy+ method. If set to <tt>:nullify</tt> all associated
|
1082
1103
|
# objects' foreign keys are set to +NULL+ *without* calling their +save+ callbacks. If set to
|
1083
|
-
# <tt>:restrict</tt> this object
|
1104
|
+
# <tt>:restrict</tt> this object raises an <tt>ActiveRecord::DeleteRestrictionError</tt> exception and
|
1105
|
+
# cannot be deleted if it has any associated objects.
|
1084
1106
|
#
|
1085
1107
|
# If using with the <tt>:through</tt> option, the association on the join model must be
|
1086
1108
|
# a +belongs_to+, and the records which get deleted are the join records, rather than
|
@@ -1088,7 +1110,8 @@ module ActiveRecord
|
|
1088
1110
|
#
|
1089
1111
|
# [:finder_sql]
|
1090
1112
|
# Specify a complete SQL statement to fetch the association. This is a good way to go for complex
|
1091
|
-
# associations that depend on multiple tables.
|
1113
|
+
# associations that depend on multiple tables. May be supplied as a string or a proc where interpolation is
|
1114
|
+
# required. Note: When this option is used, +find_in_collection+
|
1092
1115
|
# is _not_ added.
|
1093
1116
|
# [:counter_sql]
|
1094
1117
|
# Specify a complete SQL statement to fetch the size of the association. If <tt>:finder_sql</tt> is
|
@@ -1163,11 +1186,14 @@ module ActiveRecord
|
|
1163
1186
|
# has_many :tags, :as => :taggable
|
1164
1187
|
# has_many :reports, :readonly => true
|
1165
1188
|
# has_many :subscribers, :through => :subscriptions, :source => :user
|
1166
|
-
# has_many :subscribers, :class_name => "Person", :finder_sql =>
|
1167
|
-
#
|
1168
|
-
#
|
1169
|
-
#
|
1170
|
-
#
|
1189
|
+
# has_many :subscribers, :class_name => "Person", :finder_sql => Proc.new {
|
1190
|
+
# %Q{
|
1191
|
+
# SELECT DISTINCT *
|
1192
|
+
# FROM people p, post_subscriptions ps
|
1193
|
+
# WHERE ps.post_id = #{id} AND ps.person_id = p.id
|
1194
|
+
# ORDER BY p.first_name
|
1195
|
+
# }
|
1196
|
+
# }
|
1171
1197
|
def has_many(name, options = {}, &extension)
|
1172
1198
|
Builder::HasMany.build(self, name, options, &extension)
|
1173
1199
|
end
|
@@ -1229,7 +1255,8 @@ module ActiveRecord
|
|
1229
1255
|
# If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
|
1230
1256
|
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method.
|
1231
1257
|
# If set to <tt>:nullify</tt>, the associated object's foreign key is set to +NULL+.
|
1232
|
-
# Also, association is assigned.
|
1258
|
+
# Also, association is assigned. If set to <tt>:restrict</tt> this object raises an
|
1259
|
+
# <tt>ActiveRecord::DeleteRestrictionError</tt> exception and cannot be deleted if it has any associated object.
|
1233
1260
|
# [:foreign_key]
|
1234
1261
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
1235
1262
|
# of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_one+ association
|
@@ -1245,7 +1272,7 @@ module ActiveRecord
|
|
1245
1272
|
# you want to do a join but not include the joined columns. Do not forget to include the
|
1246
1273
|
# primary and foreign keys, otherwise it will raise an error.
|
1247
1274
|
# [:through]
|
1248
|
-
# Specifies a Join Model through which to perform the query.
|
1275
|
+
# Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt>,
|
1249
1276
|
# <tt>:primary_key</tt>, and <tt>:foreign_key</tt> are ignored, as the association uses the
|
1250
1277
|
# source reflection. You can only use a <tt>:through</tt> query through a <tt>has_one</tt>
|
1251
1278
|
# or <tt>belongs_to</tt> association on the join model.
|
@@ -1267,7 +1294,7 @@ module ActiveRecord
|
|
1267
1294
|
# By default, only save the associated object if it's a new record.
|
1268
1295
|
# [:inverse_of]
|
1269
1296
|
# Specifies the name of the <tt>belongs_to</tt> association on the associated object
|
1270
|
-
# that is the inverse of this <tt>has_one</tt> association.
|
1297
|
+
# that is the inverse of this <tt>has_one</tt> association. Does not work in combination
|
1271
1298
|
# with <tt>:through</tt> or <tt>:as</tt> options.
|
1272
1299
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
1273
1300
|
#
|
@@ -1325,7 +1352,7 @@ module ActiveRecord
|
|
1325
1352
|
#
|
1326
1353
|
# [:class_name]
|
1327
1354
|
# Specify the class name of the association. Use it only if that name can't be inferred
|
1328
|
-
# from the association name. So <tt>
|
1355
|
+
# from the association name. So <tt>belongs_to :author</tt> will by default be linked to the Author class, but
|
1329
1356
|
# if the real class name is Person, you'll have to specify it with this option.
|
1330
1357
|
# [:conditions]
|
1331
1358
|
# Specify the conditions that the associated object must meet in order to be included as a +WHERE+
|
@@ -1385,7 +1412,7 @@ module ActiveRecord
|
|
1385
1412
|
# will be updated with the current time in addition to the updated_at/on attribute.
|
1386
1413
|
# [:inverse_of]
|
1387
1414
|
# Specifies the name of the <tt>has_one</tt> or <tt>has_many</tt> association on the associated
|
1388
|
-
# object that is the inverse of this <tt>belongs_to</tt> association.
|
1415
|
+
# object that is the inverse of this <tt>belongs_to</tt> association. Does not work in
|
1389
1416
|
# combination with the <tt>:polymorphic</tt> options.
|
1390
1417
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
1391
1418
|
#
|
@@ -1405,15 +1432,15 @@ module ActiveRecord
|
|
1405
1432
|
end
|
1406
1433
|
|
1407
1434
|
# Specifies a many-to-many relationship with another class. This associates two classes via an
|
1408
|
-
# intermediate join table.
|
1435
|
+
# intermediate join table. Unless the join table is explicitly specified as an option, it is
|
1409
1436
|
# guessed using the lexical order of the class names. So a join between Developer and Project
|
1410
1437
|
# will give the default join table name of "developers_projects" because "D" outranks "P".
|
1411
|
-
# Note that this precedence is calculated using the <tt><</tt> operator for String.
|
1438
|
+
# Note that this precedence is calculated using the <tt><</tt> operator for String. This
|
1412
1439
|
# means that if the strings are of different lengths, and the strings are equal when compared
|
1413
1440
|
# up to the shortest length, then the longer string is considered of higher
|
1414
|
-
# lexical precedence than the shorter one.
|
1441
|
+
# lexical precedence than the shorter one. For example, one would expect the tables "paper_boxes" and "papers"
|
1415
1442
|
# to generate a join table name of "papers_paper_boxes" because of the length of the name "paper_boxes",
|
1416
|
-
# but it in fact generates a join table name of "paper_boxes_papers".
|
1443
|
+
# but it in fact generates a join table name of "paper_boxes_papers". Be aware of this caveat, and use the
|
1417
1444
|
# custom <tt>:join_table</tt> option if you need to.
|
1418
1445
|
#
|
1419
1446
|
# The join table should not have a primary key or a model associated with it. You must manually generate the
|
@@ -1489,8 +1516,8 @@ module ActiveRecord
|
|
1489
1516
|
# * <tt>Developer#projects.size</tt>
|
1490
1517
|
# * <tt>Developer#projects.find(id)</tt>
|
1491
1518
|
# * <tt>Developer#projects.exists?(...)</tt>
|
1492
|
-
# * <tt>Developer#projects.build</tt> (similar to <tt>Project.new("
|
1493
|
-
# * <tt>Developer#projects.create</tt> (similar to <tt>c = Project.new("
|
1519
|
+
# * <tt>Developer#projects.build</tt> (similar to <tt>Project.new("developer_id" => id)</tt>)
|
1520
|
+
# * <tt>Developer#projects.create</tt> (similar to <tt>c = Project.new("developer_id" => id); c.save; c</tt>)
|
1494
1521
|
# The declaration may include an options hash to specialize the behavior of the association.
|
1495
1522
|
#
|
1496
1523
|
# === Options
|
@@ -1515,7 +1542,7 @@ module ActiveRecord
|
|
1515
1542
|
# the association will use "project_id" as the default <tt>:association_foreign_key</tt>.
|
1516
1543
|
# [:conditions]
|
1517
1544
|
# Specify the conditions that the associated object must meet in order to be included as a +WHERE+
|
1518
|
-
# SQL fragment, such as <tt>authorized = 1</tt>.
|
1545
|
+
# SQL fragment, such as <tt>authorized = 1</tt>. Record creations from the association are
|
1519
1546
|
# scoped if a hash is used.
|
1520
1547
|
# <tt>has_many :posts, :conditions => {:published => true}</tt> will create published posts with <tt>@blog.posts.create</tt>
|
1521
1548
|
# or <tt>@blog.posts.build</tt>.
|
@@ -1575,17 +1602,6 @@ module ActiveRecord
|
|
1575
1602
|
def has_and_belongs_to_many(name, options = {}, &extension)
|
1576
1603
|
Builder::HasAndBelongsToMany.build(self, name, options, &extension)
|
1577
1604
|
end
|
1578
|
-
|
1579
|
-
protected
|
1580
|
-
|
1581
|
-
def preload_associations(records, associations, options = {}) #:nodoc:
|
1582
|
-
ActiveSupport::Deprecation.warn(
|
1583
|
-
"preload_associations(records, associations, options = {}) is deprecated. Use " \
|
1584
|
-
"ActiveRecord::Associations::Preloader.new(records, associations, options = {}).run " \
|
1585
|
-
"instead."
|
1586
|
-
)
|
1587
|
-
Preloader.new(records, associations, options).run
|
1588
|
-
end
|
1589
1605
|
end
|
1590
1606
|
end
|
1591
1607
|
end
|