From 368063eab6b7ec0389dddfaf8503214118dfc915 Mon Sep 17 00:00:00 2001 From: Mark Catley Date: Mon, 28 Jul 2008 00:23:39 +1200 Subject: [PATCH] Added the ability to use a model which has a polymorphic belongs_to relationship in a conditions hash. --- activerecord/lib/active_record/base.rb | 31 +++++++++++++++++++++++++++++++ activerecord/test/cases/finder_test.rb | 11 +++++------ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 4f5d72a..18e112b 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1992,6 +1992,36 @@ module ActiveRecord #:nodoc: end expanded_attrs end + + # Accepts a hash of SQL conditions and replaces those attributes + # that correspond to a polymorphic +belongs_to+ relationship + # with their id and type attributes expanded. + # Given: + # class Tagging < ActiveRecord::Base + # belongs_to :taggable, :polymorphic => true + # end + # Then: + # { :taggable => Post.find(1) } + # # => { :taggable_id => 1, :taggable_type => "Post" } + def expand_hash_conditions_for_polymorphics(attrs) + expanded_attrs = {} + attrs.each do |attr, value| + if polymorphic_belongs_to? attr, value + expanded_attrs["#{attr}_id"] = value.id + expanded_attrs["#{attr}_type"] = value.class.to_s + else + expanded_attrs[attr] = value + end + end + expanded_attrs + end + + def polymorphic_belongs_to? attr, value + association = reflect_on_association attr.to_sym + polymorphic = association + polymorphic &&= association.macro == :belongs_to + polymorphic &&= association.options[:polymorphic] + end # Sanitizes a hash of attribute/value pairs into SQL conditions for a WHERE clause. # { :name => "foo'bar", :group_id => 4 } @@ -2009,6 +2039,7 @@ module ActiveRecord #:nodoc: # # => "address_street='123 abc st.' and address_city='chicago'" def sanitize_sql_hash_for_conditions(attrs, table_name = quoted_table_name) attrs = expand_hash_conditions_for_aggregates(attrs) + attrs = expand_hash_conditions_for_polymorphics(attrs) conditions = attrs.map do |attr, value| unless value.is_a?(Hash) diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index b97db73..628e2a2 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -13,7 +13,7 @@ require 'models/job' require 'models/categorization' class FinderTest < ActiveRecord::TestCase - fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :customers + fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :customers, :taggings def test_find assert_equal(topics(:first).title, Topic.find(1).title) @@ -246,6 +241,10 @@ class FinderTest < ActiveRecord::TestCase assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :author_name => "David", :title => "The First Topic", :replies_count => 1, :approved => true }) } end + def test_find_on_hash_conditions_through_polymorphic_association + assert Tagging.find(1, :conditions => { :taggable => Post.find(1) }) + assert_raises(ActiveRecord::RecordNotFound) { Tagging.find(1, :conditions => { :taggable => Post.find(3) }) } + end def test_condition_interpolation assert_kind_of Firm, Company.find(:first, :conditions => ["name = '%s'", "37signals"]) -- 1.5.5.1