aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2005-11-06 19:05:42 +0000
committerDavid Heinemeier Hansson <david@loudthinking.com>2005-11-06 19:05:42 +0000
commitc8dd66fdcdc2170982fea8a1782c1728f79e3d41 (patch)
treebd7c1141fe7c23511080661cb723894858a2c3cd /activerecord/lib/active_record
parent0073a759f14c406316062ef6e27f1de5f9ad6cdc (diff)
downloadrails-c8dd66fdcdc2170982fea8a1782c1728f79e3d41.tar.gz
rails-c8dd66fdcdc2170982fea8a1782c1728f79e3d41.tar.bz2
rails-c8dd66fdcdc2170982fea8a1782c1728f79e3d41.zip
Made association extensions use simpler block syntax
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@2895 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'activerecord/lib/active_record')
-rwxr-xr-xactiverecord/lib/active_record/associations.rb45
-rw-r--r--activerecord/lib/active_record/reflection.rb8
2 files changed, 42 insertions, 11 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 5a9dc21a78..d4bc2ed9ef 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -127,7 +127,7 @@ module ActiveRecord
# Example:
#
# class Account < ActiveRecord::Base
- # has_many :people, :extend => Module.new {
+ # has_many :people do
# def find_or_create_by_name(name)
# first_name, *last_name = name.split
# last_name = last_name.join " "
@@ -135,14 +135,32 @@ module ActiveRecord
# find_by_first_name_and_last_name(first_name, last_name) ||
# create({ :first_name => first_name, :last_name => last_name })
# end
- # }
+ # 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).
+ # If you need to share the same extensions between many associations, you can use a named extension module. Example:
+ #
+ # module FindOrCreateByNameExtension
+ # 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
+ #
+ # class Account < ActiveRecord::Base
+ # has_many :people, :extend => FindOrCreateByNameExtension
+ # end
+ #
+ # class Company < ActiveRecord::Base
+ # has_many :people, :extend => FindOrCreateByNameExtension
+ # end
#
# == Caching
#
@@ -306,7 +324,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".
+ # * <tt>:extend</tt> - specify a named module for extending the proxy, see "Association extensions".
#
# Option examples:
# has_many :comments, :order => "posted_on"
@@ -317,13 +335,15 @@ module ActiveRecord
# 'FROM people p, post_subscriptions ps ' +
# 'WHERE ps.post_id = #{id} AND ps.person_id = p.id ' +
# 'ORDER BY p.first_name'
- def has_many(association_id, options = {})
+ def has_many(association_id, options = {}, &extension)
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, :extend
)
+ options[:extend] = create_extension_module(association_id, extension) if block_given?
+
association_name, association_class_name, association_class_primary_key_name =
associate_identification(association_id, options[:class_name], options[:foreign_key])
@@ -602,13 +622,15 @@ module ActiveRecord
# has_and_belongs_to_many :categories, :join_table => "prods_cats"
# 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}'
- def has_and_belongs_to_many(association_id, options = {})
+ def has_and_belongs_to_many(association_id, options = {}, &extension)
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, :extend
)
+ options[:extend] = create_extension_module(association_id, extension) if block_given?
+
association_name, association_class_name, association_class_primary_key_name =
associate_identification(association_id, options[:class_name], options[:foreign_key])
@@ -1004,7 +1026,16 @@ module ActiveRecord
def condition_word(sql)
sql =~ /where/i ? " AND " : "WHERE "
end
- end
+ def create_extension_module(association_id, extension)
+ extension_module_name = "#{self.to_s}#{association_id.to_s.camelize}AssociationExtension"
+
+ silence_warnings do
+ Object.const_set(extension_module_name, Module.new(&extension))
+ end
+
+ extension_module_name.constantize
+ end
+ end
end
end
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb
index de5a01c9be..affbb65ca6 100644
--- a/activerecord/lib/active_record/reflection.rb
+++ b/activerecord/lib/active_record/reflection.rb
@@ -21,12 +21,12 @@ module ActiveRecord
base.module_eval <<-"end_eval"
class << self
alias_method :#{association_type}_without_reflection, :#{association_type}
-
- def #{association_type}_with_reflection(association_id, options = {})
- #{association_type}_without_reflection(association_id, options)
+
+ def #{association_type}_with_reflection(association_id, options = {}, &block)
+ #{association_type}_without_reflection(association_id, options, &block)
reflect_on_all_associations << AssociationReflection.new(:#{association_type}, association_id, options, self)
end
-
+
alias_method :#{association_type}, :#{association_type}_with_reflection
end
end_eval