aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/associations.rb
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2005-11-03 09:06:42 +0000
committerDavid Heinemeier Hansson <david@loudthinking.com>2005-11-03 09:06:42 +0000
commit8c512a1caffa11d1522cef5d2a35e2888c608581 (patch)
tree4fc18e0b02824638eb87d815231f470b9523231a /activerecord/lib/active_record/associations.rb
parentf109bfb765fd54ef8bb94751c671a097089d7f53 (diff)
downloadrails-8c512a1caffa11d1522cef5d2a35e2888c608581.tar.gz
rails-8c512a1caffa11d1522cef5d2a35e2888c608581.tar.bz2
rails-8c512a1caffa11d1522cef5d2a35e2888c608581.zip
Added extension capabilities to has_many and has_and_belongs_to_many proxies [DHH]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@2861 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'activerecord/lib/active_record/associations.rb')
-rwxr-xr-xactiverecord/lib/active_record/associations.rb34
1 files changed, 30 insertions, 4 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 9b3296b3e4..5a9dc21a78 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -120,6 +120,30 @@ module ActiveRecord
# Should any of the before_add callbacks throw an exception, the object does not get added to the collection. Same with
# the before_remove callbacks, if an exception is thrown the object doesn't get removed.
#
+ # === Association extensions
+ #
+ # The proxy objects that controls the access to associations can be extended through anonymous modules. This is especially
+ # beneficial for adding new finders, creators, and other factory-type methods that are only used as part of this associatio.
+ # Example:
+ #
+ # class Account < ActiveRecord::Base
+ # has_many :people, :extend => Module.new {
+ # def find_or_create_by_name(name)
+ # first_name, *last_name = name.split
+ # last_name = last_name.join " "
+ #
+ # find_by_first_name_and_last_name(first_name, last_name) ||
+ # create({ :first_name => first_name, :last_name => last_name })
+ # end
+ # }
+ # end
+ #
+ # person = Account.find(:first).people.find_or_create_by_name("David Heinemeier Hansson")
+ # person.first_name # => "David"
+ # person.last_name # => "Heinemeier Hansson"
+ #
+ # Note that the anoymous module must be declared using brackets, not do/end (due to order of evaluation).
+ #
# == Caching
#
# All of the methods are built on a simple caching principle that will keep the result of the last query around unless specifically
@@ -282,6 +306,7 @@ module ActiveRecord
# associations that depend on multiple tables. Note: When this option is used, +find_in_collection+ is _not_ added.
# * <tt>:counter_sql</tt> - specify a complete SQL statement to fetch the size of the association. If +:finder_sql+ is
# specified but +:counter_sql+, +:counter_sql+ will be generated by replacing SELECT ... FROM with SELECT COUNT(*) FROM.
+ # * <tt>:extend</tt> - anonymous module for extending the proxy, see "Association extensions".
#
# Option examples:
# has_many :comments, :order => "posted_on"
@@ -296,7 +321,7 @@ module ActiveRecord
options.assert_valid_keys(
:foreign_key, :class_name, :exclusively_dependent, :dependent,
:conditions, :order, :finder_sql, :counter_sql,
- :before_add, :after_add, :before_remove, :after_remove
+ :before_add, :after_add, :before_remove, :after_remove, :extend
)
association_name, association_class_name, association_class_primary_key_name =
@@ -380,7 +405,7 @@ module ActiveRecord
# has_one :last_comment, :class_name => "Comment", :order => "posted_on"
# has_one :project_manager, :class_name => "Person", :conditions => "role = 'project_manager'"
def has_one(association_id, options = {})
- options.assert_valid_keys(:class_name, :foreign_key, :remote, :conditions, :order, :dependent, :counter_cache)
+ options.assert_valid_keys(:class_name, :foreign_key, :remote, :conditions, :order, :dependent, :counter_cache, :extend)
association_name, association_class_name, association_class_primary_key_name =
associate_identification(association_id, options[:class_name], options[:foreign_key], false)
@@ -460,7 +485,7 @@ module ActiveRecord
# belongs_to :valid_coupon, :class_name => "Coupon", :foreign_key => "coupon_id",
# :conditions => 'discounts > #{payments_count}'
def belongs_to(association_id, options = {})
- options.assert_valid_keys(:class_name, :foreign_key, :remote, :conditions, :order, :dependent, :counter_cache)
+ options.assert_valid_keys(:class_name, :foreign_key, :remote, :conditions, :order, :dependent, :counter_cache, :extend)
association_name, association_class_name, class_primary_key_name =
associate_identification(association_id, options[:class_name], options[:foreign_key], false)
@@ -569,6 +594,7 @@ module ActiveRecord
# classes with a manual one
# * <tt>:insert_sql</tt> - overwrite the default generated SQL used to add links between the associated classes
# with a manual one
+ # * <tt>:extend</tt> - anonymous module for extending the proxy, see "Association extensions".
#
# Option examples:
# has_and_belongs_to_many :projects
@@ -580,7 +606,7 @@ module ActiveRecord
options.assert_valid_keys(
:class_name, :table_name, :foreign_key, :association_foreign_key, :conditions,
:join_table, :finder_sql, :delete_sql, :insert_sql, :order, :uniq, :before_add, :after_add,
- :before_remove, :after_remove
+ :before_remove, :after_remove, :extend
)
association_name, association_class_name, association_class_primary_key_name =