Skip to content

Sources Configuration

floere edited this page Dec 16, 2011 · 32 revisions

Sources

Sources tell an index where to get its data.

Quick Example

Picky sources simply need an #each method that returns objects.

Picky::Index.new(:books) do
  source { ActiveRecordBookModel.order('isbn ASC') }
end

Each Method

Picky gets its data from traversing the data through the #each method of whatever you give it as source.

The returned object needs to respond to methods called like the categories

For example, this could be an ActiveRecord object.

Picky::Index.new(:books) do
  source { Book.order('title DESC') }
  category :title
  category :isbn, :from => :historic_isbn_method_name
end

In this case, each returned book should offer the #title and #historic_isbn_method_name methods.

Use the from option if you want to name the category differently from the method you get it from.

Source Method

As you’ve seen, you tell the Picky::Index where to get the data by calling source inside the index definition. There’s two ways:

  • with a block (delayed execution when the index is indexing)
  • without a block (execution as soon as the index definition is evaluated)

What’s the difference?

Picky::Index.new(:books) do
  source { Book.order('title DESC') }
end

This will be executed each time the books are indexed.

Picky::Index.new(:books) do
  source Book.order('title DESC').all
end

This will be executed each time the index definition is read. So once for all indexing.

Examples

Simple Array

Picky::Index.new(:books) do
  source do
    [Book.new(1, 'title 1'), Book.new(2, 'title 2')]
  end
  category :title
end

ActiveRecord

Picky::Index.new(:books) do
  source { Book.order('isbn ASC') }
  category :title
  category :isbn
end

Other ORMs will work in a similar way.

CSV

class CSVBooks

  def initialize file, options = {}
    @file, @options = file, options
  end

  Book = Struct.new(:id, :title, :author)

  def each
    CSV.foreach(@file, @options) do |row|
      yield Book.new(*row)
    end
  end

end

Picky::Index.new(:books) do
  source { CSVBooks.new(File.expand_path('../books.csv', __FILE__), col_sep: "\t") }
  category :title
  category :author
end

RSS

class RSSItems

  def each &block
    require 'rss'
    require 'open-uri'
    rss_feed = "http://florianhanke.com/blog/atom.xml"
    rss_content = ""
    open rss_feed do |f|
       rss_content = f.read
    end
    rss = RSS::Parser.parse rss_content, true
    rss.items.each &block
  rescue
    # Don't call block, no data.
  end

end

Index.new :rss do
  source     RSSItems.new
  key_format :to_s # String key format since the ids are non-Integer.
  category   :title
  # More categories here...
end

Advanced Examples

Aggregating

Getting data from relations:

  class Book < ActiveRecord::Base
 
    has_many :categories

    def category_names_from_categories
      categories.map(&:name).join(" ")
    end

  end

  Index.new :aggregated do
    source     { Book.all }
    category   :category, :from => :category_names_from_categories
  end