Created
February 27, 2009 17:37
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From b7894c95720d13ec7d955fb3675294db5aedf987 Mon Sep 17 00:00:00 2001 | |
From: Luke Redpath <contact@lukeredpath.co.uk> | |
Date: Fri, 27 Feb 2009 17:35:41 +0000 | |
Subject: [PATCH] Initial attempt at adding a :scope option to has_many :through. | |
This allows you to have has_many :through collections that go | |
through a named scope on your join model. This should make it | |
clearer: http://gist.github.com/71585 | |
--- | |
activerecord/lib/active_record/associations.rb | 3 ++- | |
.../associations/has_many_through_association.rb | 11 +++++++++++ | |
.../has_many_through_associations_test.rb | 11 +++++++++++ | |
activerecord/test/models/post.rb | 2 ++ | |
activerecord/test/models/tagging.rb | 2 ++ | |
activerecord/test/schema/schema.rb | 1 + | |
6 files changed, 29 insertions(+), 1 deletions(-) | |
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb | |
index 6e88c89..7ab3a88 100755 | |
--- a/activerecord/lib/active_record/associations.rb | |
+++ b/activerecord/lib/active_record/associations.rb | |
@@ -1462,7 +1462,8 @@ module ActiveRecord | |
:finder_sql, :counter_sql, | |
:before_add, :after_add, :before_remove, :after_remove, | |
:extend, :readonly, | |
- :validate | |
+ :validate, | |
+ :scope | |
] | |
def create_has_many_reflection(association_id, options, &extension) | |
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 d5d188a..b8f197f 100644 | |
--- a/activerecord/lib/active_record/associations/has_many_through_association.rb | |
+++ b/activerecord/lib/active_record/associations/has_many_through_association.rb | |
@@ -125,8 +125,19 @@ module ActiveRecord | |
"#{table_name}.#{attr} = #{value}" | |
end | |
conditions << sql_conditions if sql_conditions | |
+ conditions << through_scope_conditions if through_scope_conditions | |
"(" + conditions.join(') AND (') + ")" | |
end | |
+ | |
+ def through_scope_conditions | |
+ return unless @reflection.options[:scope] | |
+ if scope_proxy = @reflection.through_reflection.klass.send(@reflection.options[:scope]) | |
+ scope_proxy.proxy_options[:conditions].inject([]) do |scope_conditions, (key, value)| | |
+ scope_conditions << "#{@reflection.through_reflection.quoted_table_name}.#{key} = #{value}" | |
+ scope_conditions | |
+ end | |
+ end | |
+ end | |
def construct_from | |
@reflection.quoted_table_name | |
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 1e5d1a0..b9538f7 100644 | |
--- a/activerecord/test/cases/associations/has_many_through_associations_test.rb | |
+++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb | |
@@ -249,4 +249,15 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase | |
author.author_favorites.create(:favorite_author_id => 3) | |
assert_equal post.author.author_favorites, post.author_favorites | |
end | |
+ | |
+ def test_has_many_association_through_a_scoped_association | |
+ author = authors(:mary) | |
+ post = Post.create!(:author => author, :title => "TITLE", :body => "BODY") | |
+ tag_one = Tag.create!(:name => 'ruby') | |
+ tag_two = Tag.create!(:name => 'rails') | |
+ post.taggings.flagged.create(:tag => tag_one) | |
+ post.taggings.create(:tag => tag_two) | |
+ assert post.taggings.first.flagged? | |
+ assert_equal [tag_one], post.flagged_tags | |
+ end | |
end | |
diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb | |
index 374e536..ce665f2 100644 | |
--- a/activerecord/test/models/post.rb | |
+++ b/activerecord/test/models/post.rb | |
@@ -58,6 +58,8 @@ class Post < ActiveRecord::Base | |
has_many :invalid_taggings, :as => :taggable, :class_name => "Tagging", :conditions => 'taggings.id < 0' | |
has_many :invalid_tags, :through => :invalid_taggings, :source => :tag | |
+ | |
+ has_many :flagged_tags, :through => :taggings, :source => :tag, :scope => :flagged | |
has_many :categorizations, :foreign_key => :category_id | |
has_many :authors, :through => :categorizations | |
diff --git a/activerecord/test/models/tagging.rb b/activerecord/test/models/tagging.rb | |
index a1fa1a9..3e04dc8 100644 | |
--- a/activerecord/test/models/tagging.rb | |
+++ b/activerecord/test/models/tagging.rb | |
@@ -7,4 +7,6 @@ class Tagging < ActiveRecord::Base | |
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 :taggable, :polymorphic => true, :counter_cache => true | |
+ | |
+ named_scope :flagged, :conditions => {:flagged => true} | |
end | |
\ No newline at end of file | |
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb | |
index 74a8939..4610f67 100644 | |
--- a/activerecord/test/schema/schema.rb | |
+++ b/activerecord/test/schema/schema.rb | |
@@ -414,6 +414,7 @@ ActiveRecord::Schema.define do | |
t.column :super_tag_id, :integer | |
t.column :taggable_type, :string | |
t.column :taggable_id, :integer | |
+ t.column :flagged, :boolean | |
end | |
create_table :tags, :force => true do |t| | |
-- | |
1.5.6.4 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment