aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/CHANGELOG23
-rw-r--r--activerecord/lib/active_record/association_preload.rb12
-rw-r--r--activerecord/lib/active_record/associations/association_collection.rb109
-rw-r--r--activerecord/lib/active_record/associations/association_proxy.rb11
-rw-r--r--activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb4
-rw-r--r--activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb12
-rw-r--r--activerecord/lib/active_record/associations/has_many_association.rb4
-rw-r--r--activerecord/lib/active_record/associations/has_many_through_association.rb17
-rw-r--r--activerecord/lib/active_record/associations/through_association.rb4
-rw-r--r--activerecord/lib/active_record/autosave_association.rb2
-rw-r--r--activerecord/lib/active_record/base.rb6
-rw-r--r--activerecord/lib/active_record/nested_attributes.rb2
-rw-r--r--activerecord/test/cases/associations/eager_test.rb8
-rw-r--r--activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb2
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb1
-rw-r--r--activerecord/test/cases/associations/has_many_through_associations_test.rb7
-rw-r--r--activerecord/test/cases/associations/has_one_associations_test.rb8
-rw-r--r--activerecord/test/cases/base_test.rb6
-rw-r--r--activerecord/test/cases/connection_pool_test.rb10
-rw-r--r--activerecord/test/models/company.rb15
-rw-r--r--activerecord/test/models/post.rb7
-rw-r--r--activerecord/test/models/project.rb17
-rw-r--r--activerecord/test/models/tagging.rb1
23 files changed, 171 insertions, 117 deletions
diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG
index e49915a8cd..72bbeeec61 100644
--- a/activerecord/CHANGELOG
+++ b/activerecord/CHANGELOG
@@ -50,8 +50,27 @@
(for example, add_name_to_users) use the reversible migration's `change`
method instead of the ordinary `up` and `down` methods. [Prem Sichanugrist]
-* Removed support for interpolated SQL conditions. Please use scoping
-along with attribute conditionals as a replacement.
+* Removed support for interpolating string SQL conditions on associations. Instead, you should
+ use a proc, like so:
+
+ Before:
+
+ has_many :things, :conditions => 'foo = #{bar}'
+
+ After:
+
+ has_many :things, :conditions => proc { "foo = #{bar}" }
+
+ Inside the proc, 'self' is the object which is the owner of the association, unless you are
+ eager loading the association, in which case 'self' is the class which the association is within.
+
+ You can have any "normal" conditions inside the proc, so the following will work too:
+
+ has_many :things, :conditions => proc { ["foo = ?", bar] }
+
+ Previously :insert_sql and :delete_sql on has_and_belongs_to_many association allowed you to call
+ 'record' to get the record being inserted or deleted. This is now passed as an argument to
+ the proc.
* Added ActiveRecord::Base#has_secure_password (via ActiveModel::SecurePassword) to encapsulate dead-simple password usage with BCrypt encryption and salting [DHH]. Example:
diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb
index b83c00e9f8..52d2c49836 100644
--- a/activerecord/lib/active_record/association_preload.rb
+++ b/activerecord/lib/active_record/association_preload.rb
@@ -399,10 +399,18 @@ module ActiveRecord
end
end
+ def process_conditions(conditions, klass = self)
+ if conditions.respond_to?(:to_proc)
+ conditions = instance_eval(&conditions)
+ end
+
+ klass.send(:sanitize_sql, conditions)
+ end
+
def append_conditions(reflection, preload_options)
[
- ("(#{reflection.sanitized_conditions})" if reflection.sanitized_conditions),
- ("(#{sanitize_sql preload_options[:conditions]})" if preload_options[:conditions]),
+ ('(' + process_conditions(reflection.options[:conditions], reflection.klass) + ')' if reflection.options[:conditions]),
+ ('(' + process_conditions(preload_options[:conditions]) + ')' if preload_options[:conditions]),
].compact.map { |x| Arel.sql x }
end
diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb
index 3e3237c348..ca350f51c9 100644
--- a/activerecord/lib/active_record/associations/association_collection.rb
+++ b/activerecord/lib/active_record/associations/association_collection.rb
@@ -56,14 +56,21 @@ module ActiveRecord
end
def build(attributes = {}, &block)
- if attributes.is_a?(Array)
- attributes.collect { |attr| build(attr, &block) }
- else
- build_record(attributes) do |record|
- block.call(record) if block_given?
- set_owner_attributes(record)
- end
+ build_or_create(attributes, :build, &block)
+ end
+
+ def create(attributes = {}, &block)
+ unless @owner.persisted?
+ raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
end
+
+ build_or_create(attributes, :create, &block)
+ end
+
+ def create!(attrs = {}, &block)
+ record = create(attrs, &block)
+ Array.wrap(record).each(&:save!)
+ record
end
# Add +records+ to this association. Returns +self+ so method calls may be chained.
@@ -75,7 +82,7 @@ module ActiveRecord
transaction do
records.flatten.each do |record|
raise_on_type_mismatch(record)
- add_record_to_target_with_callbacks(record) do |r|
+ add_to_target(record) do |r|
result &&= insert_record(record) unless @owner.new_record?
end
end
@@ -191,24 +198,6 @@ module ActiveRecord
delete_or_destroy(records, :destroy)
end
- def create(attrs = {})
- if attrs.is_a?(Array)
- attrs.collect { |attr| create(attr) }
- else
- create_record(attrs) do |record|
- yield(record) if block_given?
- insert_record(record, false)
- end
- end
- end
-
- def create!(attrs = {})
- create_record(attrs) do |record|
- yield(record) if block_given?
- insert_record(record, true)
- end
- end
-
# Returns the size of the collection by executing a SELECT COUNT(*)
# query if the collection hasn't been loaded, and calling
# <tt>collection.size</tt> if it has.
@@ -348,17 +337,21 @@ module ActiveRecord
target
end
- def add_record_to_target_with_callbacks(record)
- callback(:before_add, record)
- yield(record) if block_given?
- @target ||= [] unless loaded?
- if @reflection.options[:uniq] && index = @target.index(record)
- @target[index] = record
- else
- @target << record
+ def add_to_target(record)
+ transaction do
+ callback(:before_add, record)
+ yield(record) if block_given?
+
+ if @reflection.options[:uniq] && index = @target.index(record)
+ @target[index] = record
+ else
+ @target << record
+ end
+
+ callback(:after_add, record)
+ set_inverse_instance(record)
end
- callback(:after_add, record)
- set_inverse_instance(record)
+
record
end
@@ -374,17 +367,15 @@ module ActiveRecord
def custom_counter_sql
if @reflection.options[:counter_sql]
- counter_sql = @reflection.options[:counter_sql]
+ interpolate(@reflection.options[:counter_sql])
else
# replace the SELECT clause with COUNT(*), preserving any hints within /* ... */
- counter_sql = @reflection.options[:finder_sql].sub(/SELECT\b(\/\*.*?\*\/ )?(.*)\bFROM\b/im) { "SELECT #{$1}COUNT(*) FROM" }
+ interpolate(@reflection.options[:finder_sql]).sub(/SELECT\b(\/\*.*?\*\/ )?(.*)\bFROM\b/im) { "SELECT #{$1}COUNT(*) FROM" }
end
-
- interpolate_sql(counter_sql)
end
def custom_finder_sql
- interpolate_sql(@reflection.options[:finder_sql])
+ interpolate(@reflection.options[:finder_sql])
end
def find_target
@@ -421,26 +412,26 @@ module ActiveRecord
end + existing
end
- # Do the relevant stuff to insert the given record into the association collection. The
- # force param specifies whether or not an exception should be raised on failure. The
- # validate param specifies whether validation should be performed (if force is false).
- def insert_record(record, force = true, validate = true)
- raise NotImplementedError
- end
+ def build_or_create(attributes, method)
+ records = Array.wrap(attributes).map do |attrs|
+ record = build_record(attrs)
+
+ add_to_target(record) do
+ yield(record) if block_given?
+ insert_record(record) if method == :create
+ end
+ end
- def save_record(record, force, validate)
- force ? record.save! : record.save(:validate => validate)
+ attributes.is_a?(Array) ? records : records.first
end
- def create_record(attributes, &block)
- ensure_owner_is_persisted!
- transaction { build_record(attributes, &block) }
+ # Do the relevant stuff to insert the given record into the association collection.
+ def insert_record(record, validate = true)
+ raise NotImplementedError
end
- def build_record(attributes, &block)
- attributes = scoped.scope_for_create.merge(attributes)
- record = @reflection.build_association(attributes)
- add_record_to_target_with_callbacks(record, &block)
+ def build_record(attributes)
+ @reflection.build_association(scoped.scope_for_create.merge(attributes))
end
def delete_or_destroy(records, method)
@@ -482,12 +473,6 @@ module ActiveRecord
@owner.class.send(full_callback_name.to_sym) || []
end
- def ensure_owner_is_persisted!
- unless @owner.persisted?
- raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
- end
- end
-
# Should we deal with assoc.first or assoc.last by issuing an independent query to
# the database, or by getting the target, and then taking the first/last item from that?
#
diff --git a/activerecord/lib/active_record/associations/association_proxy.rb b/activerecord/lib/active_record/associations/association_proxy.rb
index 2832f49c23..fc03a4b619 100644
--- a/activerecord/lib/active_record/associations/association_proxy.rb
+++ b/activerecord/lib/active_record/associations/association_proxy.rb
@@ -184,7 +184,8 @@ module ActiveRecord
def association_scope
scope = target_klass.unscoped
scope = scope.create_with(creation_attributes)
- scope = scope.apply_finder_options(@reflection.options.slice(:conditions, :readonly, :include))
+ scope = scope.apply_finder_options(@reflection.options.slice(:readonly, :include))
+ scope = scope.where(interpolate(@reflection.options[:conditions]))
if select = select_value
scope = scope.select(select)
end
@@ -240,8 +241,12 @@ module ActiveRecord
!loaded? && (!@owner.new_record? || foreign_key_present?) && target_klass
end
- def interpolate_sql(sql, record = nil)
- @owner.send(:interpolate_sql, sql, record)
+ def interpolate(sql, record = nil)
+ if sql.respond_to?(:to_proc)
+ @owner.send(:instance_exec, record, &sql)
+ else
+ sql
+ end
end
def select_value
diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb
index 856d826d67..aaa475109e 100644
--- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb
+++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb
@@ -108,6 +108,10 @@ module ActiveRecord
end
def process_conditions(conditions, table_name)
+ if conditions.respond_to?(:to_proc)
+ conditions = instance_eval(&conditions)
+ end
+
Arel.sql(sanitize_sql(conditions, table_name))
end
diff --git a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
index b0ccab2de6..b9c9919e7a 100644
--- a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
+++ b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
@@ -11,13 +11,11 @@ module ActiveRecord
protected
- def insert_record(record, force = true, validate = true)
- if record.new_record?
- return false unless save_record(record, force, validate)
- end
+ def insert_record(record, validate = true)
+ return if record.new_record? && !record.save(:validate => validate)
if @reflection.options[:insert_sql]
- @owner.connection.insert(interpolate_sql(@reflection.options[:insert_sql], record))
+ @owner.connection.insert(interpolate(@reflection.options[:insert_sql], record))
else
stmt = join_table.compile_insert(
join_table[@reflection.foreign_key] => @owner.id,
@@ -27,7 +25,7 @@ module ActiveRecord
@owner.connection.insert stmt.to_sql
end
- true
+ record
end
def association_scope
@@ -42,7 +40,7 @@ module ActiveRecord
def delete_records(records, method)
if sql = @reflection.options[:delete_sql]
- records.each { |record| @owner.connection.delete(interpolate_sql(sql, record)) }
+ records.each { |record| @owner.connection.delete(interpolate(sql, record)) }
else
relation = join_table
stmt = relation.where(relation[@reflection.foreign_key].eq(@owner.id).
diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb
index 0b246587c0..543b073393 100644
--- a/activerecord/lib/active_record/associations/has_many_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_association.rb
@@ -8,9 +8,9 @@ module ActiveRecord
class HasManyAssociation < AssociationCollection #:nodoc:
protected
- def insert_record(record, force = false, validate = true)
+ def insert_record(record, validate = true)
set_owner_attributes(record)
- save_record(record, force, validate)
+ record.save(:validate => validate)
end
private
diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb
index f299f51466..9f74d57c4d 100644
--- a/activerecord/lib/active_record/associations/has_many_through_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_through_association.rb
@@ -22,12 +22,21 @@ module ActiveRecord
end
end
+ def <<(*records)
+ unless @owner.new_record?
+ records.flatten.each do |record|
+ raise_on_type_mismatch(record)
+ record.save! if record.new_record?
+ end
+ end
+
+ super
+ end
+
protected
- def insert_record(record, force = true, validate = true)
- if record.new_record?
- return unless save_record(record, force, validate)
- end
+ def insert_record(record, validate = true)
+ return if record.new_record? && !record.save(:validate => validate)
through_association = @owner.send(@reflection.through_reflection.name)
through_association.create!(construct_join_attributes(record))
diff --git a/activerecord/lib/active_record/associations/through_association.rb b/activerecord/lib/active_record/associations/through_association.rb
index ab593d09b9..0550bae408 100644
--- a/activerecord/lib/active_record/associations/through_association.rb
+++ b/activerecord/lib/active_record/associations/through_association.rb
@@ -119,14 +119,14 @@ module ActiveRecord
scope = scope.where(@reflection.through_reflection.klass.send(:type_condition))
end
- scope = scope.where(@reflection.source_reflection.options[:conditions])
+ scope = scope.where(interpolate(@reflection.source_reflection.options[:conditions]))
scope.where(through_conditions)
end
# If there is a hash of conditions then we make sure the keys are scoped to the
# through table name if left ambiguous.
def through_conditions
- conditions = @reflection.through_reflection.options[:conditions]
+ conditions = interpolate(@reflection.through_reflection.options[:conditions])
if conditions.is_a?(Hash)
Hash[conditions.map { |key, value|
diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb
index c52af23fbd..95357ee5dc 100644
--- a/activerecord/lib/active_record/autosave_association.rb
+++ b/activerecord/lib/active_record/autosave_association.rb
@@ -312,7 +312,7 @@ module ActiveRecord
association.destroy(record)
elsif autosave != false && (@new_record_before_save || record.new_record?)
if autosave
- saved = association.send(:insert_record, record, false, false)
+ saved = association.send(:insert_record, record, false)
else
association.send(:insert_record, record)
end
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 16bdd7bb58..3d48ab89ac 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -1790,12 +1790,6 @@ MSG
self.class.connection.quote(value, column)
end
- # Interpolate custom SQL string in instance context.
- # Optional record argument is meant for custom insert_sql.
- def interpolate_sql(sql, record = nil)
- instance_eval("%@#{sql.gsub('@', '\@')}@", __FILE__, __LINE__)
- end
-
# Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done
# by calling new on the column type or aggregation type (through composed_of) object with these parameters.
# So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate
diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb
index 16023defe3..fc68d7254a 100644
--- a/activerecord/lib/active_record/nested_attributes.rb
+++ b/activerecord/lib/active_record/nested_attributes.rb
@@ -413,7 +413,7 @@ module ActiveRecord
if target_record
existing_record = target_record
else
- association.send(:add_record_to_target_with_callbacks, existing_record)
+ association.send(:add_to_target, existing_record)
end
end
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index 3074648d59..42dd612083 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -668,6 +668,14 @@ class EagerAssociationTest < ActiveRecord::TestCase
assert_equal people(:david, :susan), Person.find(:all, :include => [:readers, :primary_contact, :number1_fan], :conditions => "number1_fans_people.first_name like 'M%'", :order => 'people.id', :limit => 2, :offset => 0)
end
+ def test_preload_with_interpolation
+ post = Post.includes(:comments_with_interpolated_conditions).find(posts(:welcome).id)
+ assert_equal [comments(:greetings)], post.comments_with_interpolated_conditions
+
+ post = Post.joins(:comments_with_interpolated_conditions).find(posts(:welcome).id)
+ assert_equal [comments(:greetings)], post.comments_with_interpolated_conditions
+ end
+
def test_polymorphic_type_condition
post = Post.find(posts(:thinking).id, :include => :taggings)
assert post.taggings.include?(taggings(:thinking_general))
diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
index 5dd2c9861e..dc382c3007 100644
--- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
@@ -72,7 +72,7 @@ class DeveloperWithCounterSQL < ActiveRecord::Base
:join_table => "developers_projects",
:association_foreign_key => "project_id",
:foreign_key => "developer_id",
- :counter_sql => 'SELECT COUNT(*) AS count_all FROM projects INNER JOIN developers_projects ON projects.id = developers_projects.project_id WHERE developers_projects.developer_id =#{id}'
+ :counter_sql => proc { "SELECT COUNT(*) AS count_all FROM projects INNER JOIN developers_projects ON projects.id = developers_projects.project_id WHERE developers_projects.developer_id =#{id}" }
end
class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 23b777ac6d..ad774eb9ce 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -279,7 +279,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_counting_using_finder_sql
assert_equal 2, Firm.find(4).clients_using_sql.count
- assert_equal 2, Firm.find(4).clients_using_multiline_sql.count
end
def test_belongs_to_sanity
diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb
index c58068ef75..73b1d6c500 100644
--- a/activerecord/test/cases/associations/has_many_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -711,4 +711,11 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
post.author_addresses.delete(address)
assert post[:author_count].nil?
end
+
+ def test_interpolated_conditions
+ post = posts(:welcome)
+ assert !post.tags.empty?
+ assert_equal post.tags, post.interpolated_tags
+ assert_equal post.tags, post.interpolated_tags_2
+ end
end
diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb
index dbf6dfe20d..6b73a35905 100644
--- a/activerecord/test/cases/associations/has_one_associations_test.rb
+++ b/activerecord/test/cases/associations/has_one_associations_test.rb
@@ -243,6 +243,14 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
firm.destroy
end
+ def test_finding_with_interpolated_condition
+ firm = Firm.find(:first)
+ superior = firm.clients.create(:name => 'SuperiorCo')
+ superior.rating = 10
+ superior.save
+ assert_equal 10, firm.clients_with_interpolated_conditions.first.rating
+ end
+
def test_assignment_before_child_saved
firm = Firm.find(1)
firm.account = a = Account.new("credit_limit" => 1000)
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 6a61dcdb47..0ad20bb9bc 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -1295,12 +1295,6 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal res6, res7
end
- def test_interpolate_sql
- assert_nothing_raised { Category.new.send(:interpolate_sql, 'foo@bar') }
- assert_nothing_raised { Category.new.send(:interpolate_sql, 'foo bar) baz') }
- assert_nothing_raised { Category.new.send(:interpolate_sql, 'foo bar} baz') }
- end
-
def test_scoped_find_conditions
scoped_developers = Developer.send(:with_scope, :find => { :conditions => 'salary > 90000' }) do
Developer.find(:all, :conditions => 'id < 5')
diff --git a/activerecord/test/cases/connection_pool_test.rb b/activerecord/test/cases/connection_pool_test.rb
index 0c545b7e9d..7ac14fa8d6 100644
--- a/activerecord/test/cases/connection_pool_test.rb
+++ b/activerecord/test/cases/connection_pool_test.rb
@@ -6,6 +6,16 @@ module ActiveRecord
def setup
# Keep a duplicate pool so we do not bother others
@pool = ConnectionPool.new ActiveRecord::Base.connection_pool.spec
+
+ if in_memory_db?
+ # Separate connections to an in-memory database create an entirely new database,
+ # with an empty schema etc, so we just stub out this schema on the fly.
+ @pool.with_connection do |connection|
+ connection.create_table :posts do |t|
+ t.integer :cololumn
+ end
+ end
+ end
end
def test_pool_caches_columns
diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb
index 3e219fbe4a..e0b30efd51 100644
--- a/activerecord/test/models/company.rb
+++ b/activerecord/test/models/company.rb
@@ -48,19 +48,16 @@ class Firm < Company
has_many :dependent_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id", :dependent => :destroy
has_many :exclusively_dependent_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id", :dependent => :delete_all
has_many :limited_clients, :class_name => "Client", :limit => 1
+ has_many :clients_with_interpolated_conditions, :class_name => "Client", :conditions => proc { "rating > #{rating}" }
has_many :clients_like_ms, :conditions => "name = 'Microsoft'", :class_name => "Client", :order => "id"
has_many :clients_like_ms_with_hash_conditions, :conditions => { :name => 'Microsoft' }, :class_name => "Client", :order => "id"
- has_many :clients_using_sql, :class_name => "Client", :finder_sql => 'SELECT * FROM companies WHERE client_of = #{id}'
- has_many :clients_using_multiline_sql, :class_name => "Client", :finder_sql => '
- SELECT
- companies.*
- FROM companies WHERE companies.client_of = #{id}'
+ has_many :clients_using_sql, :class_name => "Client", :finder_sql => proc { "SELECT * FROM companies WHERE client_of = #{id}" }
has_many :clients_using_counter_sql, :class_name => "Client",
- :finder_sql => 'SELECT * FROM companies WHERE client_of = #{id}',
- :counter_sql => 'SELECT COUNT(*) FROM companies WHERE client_of = #{id}'
+ :finder_sql => proc { "SELECT * FROM companies WHERE client_of = #{id} " },
+ :counter_sql => proc { "SELECT COUNT(*) FROM companies WHERE client_of = #{id}" }
has_many :clients_using_zero_counter_sql, :class_name => "Client",
- :finder_sql => 'SELECT * FROM companies WHERE client_of = #{id}',
- :counter_sql => 'SELECT 0 FROM companies WHERE client_of = #{id}'
+ :finder_sql => proc { "SELECT * FROM companies WHERE client_of = #{id}" },
+ :counter_sql => proc { "SELECT 0 FROM companies WHERE client_of = #{id}" }
has_many :no_clients_using_counter_sql, :class_name => "Client",
:finder_sql => 'SELECT * FROM companies WHERE client_of = 1000',
:counter_sql => 'SELECT COUNT(*) FROM companies WHERE client_of = 1000'
diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb
index fd8cd2244a..5f29196790 100644
--- a/activerecord/test/models/post.rb
+++ b/activerecord/test/models/post.rb
@@ -41,6 +41,9 @@ class Post < ActiveRecord::Base
has_many :author_categorizations, :through => :author, :source => :categorizations
has_many :author_addresses, :through => :author
+ has_many :comments_with_interpolated_conditions, :class_name => 'Comment',
+ :conditions => proc { ["#{"#{aliased_table_name}." rescue ""}body = ?", 'Thank you for the welcome'] }
+
has_one :very_special_comment
has_one :very_special_comment_with_post, :class_name => "VerySpecialComment", :include => :post
has_many :special_comments
@@ -57,6 +60,10 @@ class Post < ActiveRecord::Base
end
end
+ has_many :interpolated_taggings, :class_name => 'Tagging', :as => :taggable, :conditions => proc { "1 = #{1}" }
+ has_many :interpolated_tags, :through => :taggings
+ has_many :interpolated_tags_2, :through => :interpolated_taggings, :source => :tag
+
has_many :taggings_with_delete_all, :class_name => 'Tagging', :as => :taggable, :dependent => :delete_all
has_many :taggings_with_destroy, :class_name => 'Tagging', :as => :taggable, :dependent => :destroy
diff --git a/activerecord/test/models/project.rb b/activerecord/test/models/project.rb
index 8a53a8f803..efe1ce67da 100644
--- a/activerecord/test/models/project.rb
+++ b/activerecord/test/models/project.rb
@@ -7,14 +7,15 @@ class Project < ActiveRecord::Base
has_and_belongs_to_many :developers_named_david, :class_name => "Developer", :conditions => "name = 'David'", :uniq => true
has_and_belongs_to_many :developers_named_david_with_hash_conditions, :class_name => "Developer", :conditions => { :name => 'David' }, :uniq => true
has_and_belongs_to_many :salaried_developers, :class_name => "Developer", :conditions => "salary > 0"
- has_and_belongs_to_many :developers_with_finder_sql, :class_name => "Developer", :finder_sql => 'SELECT t.*, j.* FROM developers_projects j, developers t WHERE t.id = j.developer_id AND j.project_id = #{id} ORDER BY t.id'
- has_and_belongs_to_many :developers_with_multiline_finder_sql, :class_name => "Developer", :finder_sql => '
- SELECT
- t.*, j.*
- FROM
- developers_projects j,
- developers t WHERE t.id = j.developer_id AND j.project_id = #{id} ORDER BY t.id'
- has_and_belongs_to_many :developers_by_sql, :class_name => "Developer", :delete_sql => "DELETE FROM developers_projects WHERE project_id = \#{id} AND developer_id = \#{record.id}"
+ has_and_belongs_to_many :developers_with_finder_sql, :class_name => "Developer", :finder_sql => proc { "SELECT t.*, j.* FROM developers_projects j, developers t WHERE t.id = j.developer_id AND j.project_id = #{id} ORDER BY t.id" }
+ has_and_belongs_to_many :developers_with_multiline_finder_sql, :class_name => "Developer", :finder_sql => proc {
+ "SELECT
+ t.*, j.*
+ FROM
+ developers_projects j,
+ developers t WHERE t.id = j.developer_id AND j.project_id = #{id} ORDER BY t.id"
+ }
+ has_and_belongs_to_many :developers_by_sql, :class_name => "Developer", :delete_sql => proc { |record| "DELETE FROM developers_projects WHERE project_id = #{id} AND developer_id = #{record.id}" }
has_and_belongs_to_many :developers_with_callbacks, :class_name => "Developer", :before_add => Proc.new {|o, r| o.developers_log << "before_adding#{r.id || '<new>'}"},
:after_add => Proc.new {|o, r| o.developers_log << "after_adding#{r.id || '<new>'}"},
:before_remove => Proc.new {|o, r| o.developers_log << "before_removing#{r.id}"},
diff --git a/activerecord/test/models/tagging.rb b/activerecord/test/models/tagging.rb
index 33ffc623d7..231d2b5890 100644
--- a/activerecord/test/models/tagging.rb
+++ b/activerecord/test/models/tagging.rb
@@ -6,6 +6,7 @@ class Tagging < ActiveRecord::Base
belongs_to :tag, :include => :tagging
belongs_to :super_tag, :class_name => 'Tag', :foreign_key => 'super_tag_id'
belongs_to :invalid_tag, :class_name => 'Tag', :foreign_key => 'tag_id'
+ belongs_to :interpolated_tag, :class_name => 'Tag', :foreign_key => :tag_id, :conditions => proc { "1 = #{1}" }
belongs_to :taggable, :polymorphic => true, :counter_cache => true
has_many :things, :through => :taggable
end