diff options
author | Jon Leighton <j@jonathanleighton.com> | 2010-10-19 00:27:40 +0100 |
---|---|---|
committer | Jon Leighton <j@jonathanleighton.com> | 2010-10-19 00:27:40 +0100 |
commit | 9ec07348749675110843c44f680da79223218db2 (patch) | |
tree | e4a356d2b6ee95232097fac21df5a04118dcc014 /activerecord/lib/active_record/reflection.rb | |
parent | 78b8c51cb3b0c629152f3bbaf6d8bcf988cc936e (diff) | |
download | rails-9ec07348749675110843c44f680da79223218db2.tar.gz rails-9ec07348749675110843c44f680da79223218db2.tar.bz2 rails-9ec07348749675110843c44f680da79223218db2.zip |
Properly support conditions on any of the reflections involved in a nested through association
Diffstat (limited to 'activerecord/lib/active_record/reflection.rb')
-rw-r--r-- | activerecord/lib/active_record/reflection.rb | 53 |
1 files changed, 50 insertions, 3 deletions
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index ee63fcfce2..d8bd6c9873 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -253,6 +253,10 @@ module ActiveRecord def through_reflection_chain [self] end + + def through_conditions + [Array.wrap(options[:conditions])] + end def through_reflection_primary_key_name end @@ -378,9 +382,9 @@ module ActiveRecord # TODO: Documentation def through_reflection_chain @through_reflection_chain ||= begin - if source_reflection.through_reflection - # If the source reflection goes through another reflection, then the chain must start - # by getting us to the source reflection. + if source_reflection.source_reflection + # If the source reflection has its own source reflection, then the chain must start + # by getting us to that source reflection. chain = source_reflection.through_reflection_chain else # If the source reflection does not go through another reflection, then we can get @@ -396,6 +400,49 @@ module ActiveRecord end end + # Consider the following example: + # + # class Person + # has_many :articles + # has_many :comment_tags, :through => :articles + # end + # + # class Article + # has_many :comments + # has_many :comment_tags, :through => :comments, :source => :tags + # end + # + # class Comment + # has_many :tags + # end + # + # There may be conditions on Person.comment_tags, Article.comment_tags and/or Comment.tags, + # but only Comment.tags will be represented in the through_reflection_chain. So this method + # creates an array of conditions corresponding to the through_reflection_chain. Each item in + # the through_conditions array corresponds to an item in the through_reflection_chain, and is + # itself an array of conditions from an arbitrary number of relevant reflections. + def through_conditions + @through_conditions ||= begin + # Initialize the first item - which corresponds to this reflection - either by recursing + # into the souce reflection (if it is itself a through reflection), or by grabbing the + # source reflection conditions. + if source_reflection.source_reflection + conditions = source_reflection.through_conditions + else + conditions = [Array.wrap(source_reflection.options[:conditions])] + end + + # Add to it the conditions from this reflection if necessary. + conditions.first << options[:conditions] if options[:conditions] + + # Recursively fill out the rest of the array from the through reflection + conditions += through_reflection.through_conditions + + # And return + conditions + end + end + def nested? through_reflection_chain.length > 2 end |