Class Zetetic::Acts::UnionCollection
In: vendor/plugins/acts_as_network/lib/zetetic/acts/network.rb
Parent: Array


UnionCollection provides useful application-space functionality for emulating set unions acrosss ActiveRecord collections.

A UnionCollection can be initialized with zero or more sets, although generally it must contain at least two to do anything useful. Once initialized, the UnionCollection itself will act as an array containing all of the records from each of its member sets. The following will create a union object containing the unique results of each individual find

  union =
    Person.find(:all, :conditions => "id <= 1"),                # set 0
    Person.find(:all, :conditions => "id >= 10 AND id <= 15"),  # set 1
    Person.find(:all, :conditions => "id >= 20")                # set 2

UnionCollection‘s more interesting feature is how it will intelligently forward ActiveRecord method calls to its member sets. This allows you to execute find operations directly on a UnionCollection, that will be executed on one or more of the member sets. Given the prior definition calling

  union.find(:all, :conditions => "id <= 1 OR id >= 20")

would return an array containing all the records from set 0 and set 2 (set 1 would be implicity excluded by the :conditions),


would return a single entry fetched from set 2 if george‘s id was >= 20,


would retrieve the record from set 2 with id == 30, and


would throw an ActiveRecord::RecordNotFound exception because that id is specifically excluded from the union‘s member sets.

UnionCollection operates according to the following rules:

  • find :first - will search the sets in order and return the first record that matches the find criteria.
  • find :all - will search the sets, returning a UnionCollection containing the all matching results. This UnionCollection can, of course, be searched further
  • find(ids) - will look through all member sets in search of records with the given ids. ActiveRecord::RecordNotFound will be raised unless all the IDs are located.
  • find_by_* - works as expected, behaving like find :first
  • find_all_by_* - works as expected like find :all


find   new  

Public Class methods

UnionCollection should be initialized with a list of ActiveRecord collections

  union =
    Person.find(:all, :conditions => "id <= 1"),      # dynamic find set
    Person.managers                                   # an model association


    # File vendor/plugins/acts_as_network/lib/zetetic/acts/network.rb, line 72
72:       def initialize(*sets)
73:         @sets = sets || []
74:         @sets.compact!     # remove nil elements
75:         @sets.each{|set| self.concat set unless set.nil?} unless @sets.nil?
76:         uniq!
77:       end

Public Instance methods

Emulates the ActiveRecord::base.find method. Accepts all the same arguments and options

  union.find(:first, :conditions => ["name = ?", "George"])


    # File vendor/plugins/acts_as_network/lib/zetetic/acts/network.rb, line 84
84:       def find(*args)
85:         case args.first
86:           when :first then find_initial(:find, *args)
87:           when :all   then find_all(:find, *args)
88:           else             find_from_ids(:find, *args)
89:         end
90:       end