= ActiveCollection Lazy-loaded Array-like collections of records. Compatible with will_paginate. == Example A quick example: If you have a model class Beer < ActiveRecord::Base end You can make ActiveCollections of Beers like so: class BeerCollection < ActiveCollection::Base end Or a more complex version: class BeerCollection < ActiveCollection::Base scope :geolocation scope :by_brewery order_by "distance ASC" def names map(&:name) end protected def geolocation if params[:lat] && params[:lng] { :origin => [params[:lat], params[:lng]], :within => params[:radius] || 50 } end end def by_brewery if params[:brewery_id] { :conditions => { :brewery_id => params[:brewery_id] } } end end end And you would use it like so: beers = BeerCollection.new(:lat => 38.1234, :lng => -117.6543) # All of these are lazy loaded only when they're needed. beers.size # => Beer.count(:origin => [38.1234, -117.6543], :within => 50) beers.each # => Beer.all(:origin => [38.1234, -117.6543], :within => 50, :order => "distance ASC") and yields each record ==== Custom conditions You can specify anything you want for conditions using the scope, find_scope, and count_scope class methods. Conditions on the fly is on my road map. brewery_beers = BeerCollection.new(:brewery_id => 1) brewery_beers.to_a # Beer.all(:conditions => {:brewery_id => 1}) => [Beer, Beer, Beer, ...] brewery_beers.size # Does not load count, just takes the size of the loaded collection. brewery_beers.names # => ["La Folie", "1554", ...] ==== Pagination ActiveCollections are fully will_paginate compliant. paginated_beers = brewery_beers.paginate paginated_beers.size # => size of this page only (doesn't query if already loaded) paginated_beers.total_entries # => size of the entire collection without paging. (performs a database lookup if it can't be inferred by the collection size) paginated_beers.total_pages paginated_beers.next_page_collection # => new BeerCollection for page 2. Again, lazily-loaded. ==== Includes Specify eager loading for a collection. beers.include(:brewery) # => new collection that will eager load Brewery association when it loads. Includes can also be specified in the class along with order. Anything specified on the class will combine using active record's rules (merge includes, overwrite order). class BeerCollection < ActiveCollection::Base includes :brewery => :owner order_by "name asc" # ... end == Usage I tend to use this in my index action in a controller by just passing in params. def index @beers = BeerCollection.new(params) end It will automatically take care of paging. You can also pass the collection itself to the index named route to pass along the params necessary to link to the collection. beers_path(@beers) # => Includes the right options for paging and any specified order or search query. == Coming Soon ==== Search Integration This can already be done by overloading load_collection and load_count in your collection. I have sphinx and solr searching integrated on another project but I've yet to abstract it. Probably will work something like this: BeerCollection.new(:q => "search term") and then you specify searchability like so: class BeerCollection < ActiveCollection::Base # It could possibly auto-configure by looking at what search libraries are loaded. # Note: this doesn't exist yet. search_on :q, :using => :thinking_sphinx end ==== Geolocation Integration This can already be done as shown above, but I'd like it to be knowledgeable of the available geolocation libraries like Geokit and also support local search with solr and sphinx. == Copyright Copyright (c) 2009 Martin Emde. See LICENSE for details.