Project

gom

0.0
No commit activity in last 3 years
No release in over 3 years
Core package of the General Object Mapper.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

>= 1.2
>= 2

Runtime

>= 0.3.0
 Project Readme

Generic Object Mapper¶ ↑

The Generic Object Mapper maps ruby objects to different storage engines and vice versa. The interface is designed to be small and try to avoid any unnecessary dependencies between GOM and your code. On the other side, the storage engine is plugged-in via an adapter interface. Currently, the following adapters are provided.

Configuration¶ ↑

At the beginning of your program the storage configuration should be done with the GOM::Storage.configure command.

GOM::Storage.configure {
  storage {
    name :storage_name
    adapter :filesystem
    directory "/var/project-name/data"
  }
}

Look at the adapter pages to see the adapter-specific configuration values.

How to use¶ ↑

Setup the system¶ ↑

First step after the configuration has been read is to setup the whole storage system. This can be done by

GOM::Storage.setup

The call should be done during the initialization of your application and triggers each storage adapter to do his own setup. To shutdown the system and trigger final clean ups simply call

GOM::Storage.teardown

Storing an object¶ ↑

To store an object just pass it to GOM::Storage.store.

class Book

  attr_accessor :author_name
  attr_accessor :pages

end

book = Book.new
book.author_name = "Mr. Storyteller"
book.pages = 1253

GOM::Storage.store book, :storage_name

The storage name doesn’t has to be specified. If it’s missing, the object’s previously used storage or the default storage is used.

There is no base class needed for your model class. GOM inspects your object, reads all the instance variables and passes the values to the specified storage adapter. The first time an object is stored, an id is generated and assigned to the object. This id can be determined by calling GOM::Object.id.

book_id = GOM::Object.id book
# book_id => "storage_name:1234..."

Fetching an object¶ ↑

Once an object is stored, it can be easily brought back to life by using it’s id to fetch it from the storage.

book = GOM::Storage.fetch book_id

The storage name is encoded (prefixed) in the id and doesn’t has to be specified. The classname of the object was also saved during the storage and the fetch method instantiates a new object using the constructor. If the constructor requires arguments, nil will be passed for each of them. The internal state (the instance variables) will be overwritten anyway.

Removing an object¶ ↑

To remove an object from the storage, simply pass it to GOM::Storage.remove.

GOM::Storage.remove book

It’s also possible to use just the id to remove the assigned object.

GOM::Storage.remove book_id

Relations¶ ↑

GOM does make a distinction between object properties and object relations. The properties are more atomic values that can be stored in a key/value-way and relations are links to more complex objects. Since in Ruby everything is an object, it’s necessary to mark the relations. This is done by the following way.

class Book

  attr_accessor :author

end

class Author

  attr_accessor :name

end

author = Author.new
author.name = "Mr. Storyteller"

book = Book.new
book.author = GOM::Object.reference author

The GOM::Object.reference call creates a proxy to the referenced object, that passes every call to it. For example, the call

book.author.name

will return the instance variable @name (“Mr. Storyteller”) from the author object.

Views¶ ↑

Views are a kind of prepared queries to the data store. They are initialized during the setup and provide collections of results at runtime. There are several kinds of views.

Class views¶ ↑

There are views simply providing a collection of all objects of a specified class. They are defined at the storage configuration.

GOM::Storage.configure {
  storage {
    name :storage_name
    adapter :filesystem
    directory "/var/project-name/data"
    view {
      name :users
      type :class
      model_class User
    }
  }
}

The example defines a class view for all objects of the class User. The result can be fetched via…

users = GOM::Storage.collection :storage_name, :users

Collections can be handled like (read-only) ruby-arrays and the data will be fetched by the first read access to that array.

Map/Reduce views¶ ↑

These views are also defined in the storage configuration.

GOM::Storage.configure {
  storage {
    name :storage_name
    adapter :couchdb
    view {
      name :active_user_count
      type :map_reduce
      map_function """
        function(document) {
          if (document['model_class'] == 'User' && document['active']) {
            emit(document['_id'], 1);
          }
        }
      """
      reduce_function """
        function(keys, values, rereduce) {
          return sum(values);
        }
      """
    }
  }
}

The example defines a map/reduce view that results in a single row with the count of all active users. This row can be fetched by…

rows = GOM::Storage.collection :storage_name, :active_user_count
rows.first.value # => 123

If no reduce method is given, GOM will try to map the fetched data back to ruby-objects. The definition would be…

GOM::Storage.configure {
  storage {
    name :storage_name
    adapter :couchdb
    view {
      name :active_users
      type :map_reduce
      map_function """
        function(document) {
          if (document['model_class'] == 'User') {
            emit(document['_id'], null);
          }
        }
      """
    }
  }
}

…and the fetch is done by…

active_users = GOM::Storage.collection :storage_name, :active_users

Development¶ ↑

Development has been done test-driven and the code follows at most the Clean Code paradigms. Code smells has been removed by using the reek code smell detector.

This project is still experimental and under development. Any bug report and contribution is welcome!

Support¶ ↑

Apart from contribution, support via Flattr is welcome.