Skip to content
Lasse Skindstad Ebert edited this page Aug 23, 2014 · 3 revisions

Querying Your Data

In the Mappers section, we learned that you can get at an instance of a mapper using Perpetuity[MyClass].

All of our query methods will be on this object.

Declare the classes

Each of the examples in this document will be using the following classes:

class Article
  def initialize attributes={}
    attributes.each { |attr, value| instance_variable_set("@#{attr}", value) }
  end
end

class ArticleMapper < Perpetuity::Mapper
  map Article

  attribute :title
  attribute :body
  attribute :published_at
  attribute :tags

  id { title.downcase.gsub(/\W+/, '-') }
end

Inserting Objects

Objects are inserted using the #insert method:

article = Article.new(title: 'The Hobbit is a True Story')
Perpetuity[Article].insert article

This will insert an article with the title "The Hobbit is a True Story" and the id "the-hobbit-is-a-true-story" into the Article collection of the database.

Retrieving objects

The simplest way to retrieve a single object from the database is using the #find method, which takes an ID:

article = Perpetuity[Article].find(article_id)

Objects are retrieved from the database using the #select method with a block, similar to an array:

published_articles = Perpetuity[Article].select { |article| article.published_at < Time.now }

Please note that the object yielded to the block is not an actual Article object. You cannot invoke Article instance methods on it. It is a DSL object that allows you to compare attributes of the object to known values for selection. The selection criteria are as follows:

mapper = Perpetuity[Article]
article              = mapper.select { |article| article.title == 'The Hobbit is a True Story' }.first
published_articles   = mapper.select { |article| article.published_at <= Time.now }
unpublished_articles = mapper.select { |article| article.published_at > Time.now }
lotr_articles        = mapper.select { |article| article.body =~ /hobbit/i }
lotr_articles        = mapper.select { |article| article.tags.in ['lotr', 'hobbit', 'precious'] }
excluded_articles    = mapper.select { |article| article.id.not_equal?(article_id) }

Ideally, you would want to define methods on your mappers for things like this:

class ArticleMapper < Perpetuity::Mapper
  map Article

  attribute :title
  attribute :body
  attribute :published_at

  def published
    select { |article| article.published_at < Time.now }
  end

  def search(text)
    terms = /#{Regexp.escape(text)}/
    select { |article| (article.title =~ terms) | (article.body =~ terms) }
  end
end

Updating objects

You can update objects with the save message on the mapper, passing in the object as a parameter:

article.title = 'I Aim to Misbehave'
Perpetuity[Article].save article

That will modify the title (assuming we have a #title= on the article) and tell Perpetuity to reserialize it and update the existing persisted version of it.

Deleting Objects

If you have an object that has been persisted to the database, you can delete it with the #delete message.

Perpetuity[Article].delete draft_article