Skip to content

Latest commit

 

History

History
178 lines (120 loc) · 7.66 KB

README.rdoc

File metadata and controls

178 lines (120 loc) · 7.66 KB

This project is no longer under development. Visit github.com/phifty/gom

CouchModel

The intent of CouchModel is, to provide an easy interface handle CouchDB documents. It also comes with a ActiveModel implementation to integrate into an Rails 3 application.

The current version is under development and open for everyone to find bugs and post them into the issue tracker.

The code has been tested Ruby 1.8.7 and 1.9.1, CouchDB 0.10.0 and Rails 3.0.0.beta4.

Dependencies

Basically, the ruby standard library (1.9.1) if the only requirement. If you still using Ruby 1.8, the json gem is required.

If the activemodel gem is installed, CouchModel automatically provides an interface to Rails 3.

To run the test suite, rspec (tested with 1.2.9) is required. A CouchDB instance is only required for the integration tests (task spec:integration).

Installation

The gem is part of the gemcutter archive. It can be installed by simply type

gem install couchmodel

Defining a model

To define a model, it’s necessary to create a subclass of CouchModel::Base

class User < CouchModel::Base

  setup_database :url               => "http://localhost:5984/test",
                 :create_if_missing => true,
                 :delete_if_exists  => false,
                 :push_design       => true

  key_accessor :name
  key_accessor :email
  key_accessor :language, :default => "en"
  key_accessor :birthday, :type => :date

end

The setup_database method defines a database for the model. The url option is required and specifies the url of the database in the scheme [scheme]://[host]:[port]/[database_name]. If the option create_if_missing is set to true, CouchModel will try to create the database when the model is initialized. If the option delete_if_exists is specified, the database will be deleted and re-created. The option push_design will make CouchModel upload the design document assigned to the model during it’s initialization process. If the option create_if_missing is not specified or false, the database setup be done manually by calling CouchModel::Configuration.setup_databases and CouchModel::Configuration.setup_designs.

The method key_accessor defined access methods to the given keys of the CouchDB document. It’s also possible to use key_reader and key_writer here. If the :default option is passed, the key will get a default value assigned during initialization of the class. The :type option specifies the type of the attribute. Currently the types :integer, :string, :date and :time are supported.

Design documents

Each defined model has a realted design document, that keeps all the views for that model. Via the command

CouchModel::Configuration.design_directory = "[directory]"

a directory is specfied that keeps all the design document. CouchModel will watch out for a file with the name [design directory]/[model_name].design and will use it as the related design document. If no such file exists, a design document will be created (but not saved to the file). The design ducument can be asscessed via Model.design.

A design document should look like this

id:        "test_design"
language:  "javascript"
views:
  view_name_1:
    map:
      function(document) {
        ...
      };
    reduce:
      function(key, values, rereduce) {
        ...
      };
  view_name_2:
    keys: [ "key_one", "key_two" ]
  ...

It will create the methods Model.view_name_1 and Model.view_name_2, which returns the result of the related view. It’s also possible to pass some extra options like startkey or key to these methods.

The view can be defined by write down a map and a reduce function or provide the keys array. If the keys array is given, CouchModel will generate a map function that emits the given array of document keys. The reduce function will be set to null.

CouchModel also creates by default a class view. This view simply selects all documents from the corresponding model and is assigned to the method Model.all.

Associations

CouchModel provides support for simple association definition. Currently, the method belongs_to and has_many are implmented.

class User < CouchModel::Base

  ...

  belongs_to :session, :class_name => "UserSession"

  has_many :memberships,
           :class_name => "Membership",
           :view_name  => :by_user_id_and_created_at
           :query      => proc { |created_at| { :startkey => [ self.id, (create_at || nil) ], :endkey => [ self.id, (created_at || { }) ] } }

end

In this example, the belongs_to adds a key_accessor named session_id to the user and also generates getters and setters for the session object itself (session and session=).

The has_many acts as a wrapper for the specified view. The previously defined view by_user_id_and_created_at emits membership-documents by thier user_id and the created_at date. Basically, the association can be accessed by a reader method. Options for querying the view can be passed by a hash.

user.membership(:startkey => [ ... ], :endkey => [ ... ], :descending => false)

The possible keys for that query hash can be taken from wiki.apache.org/couchdb/HTTP_view_API (Section Querying Options).

If a :query option is defined (like in the example above), the given method is used to generate this query hash. When querying a view, the first arguments will be passed to that method and the result of the generator-method will be merged with the additionally given query hash.

user.membership(created_at, :returns => :rows)

The :returns option extends the possible keys defined by CouchDB. If not given or specified as :models, CouchModel will try to cast the returned rows into model classes. It also automatically passes the :include_docs option to CouchDB. If this option is specified as :rows, a collection of CouchModel::Row objects is returned that wraps the CouchDB result rows. That’s maybe useful for views with a reduce function.

Rails integration

The following steps has been tested with the first beta version of Rails 3 (activemodel-3.0.0.beta).

First of all, the couchmodel gem has to added to the dependencies. This can be done by adding

gem "couchmodel", :require => "couch_model"

to the Gemfile.

The configuration can be done by creating an initializer. Here is an example file (e.g. config/initializer/couch_model.rb).

CouchModel::Configuration.design_directory = File.join(Rails.root, "app", "models", "designs")

DATABASE = {
  :test        => { :url => "http://localhost:5984/test",        :setup_on_initialization => true, :delete_if_exists => true  }
  :development => { :url => "http://localhost:5984/development", :setup_on_initialization => true, :delete_if_exists => false },
  :production  => { :url => "http://localhost:5984/production",  :setup_on_initialization => true, :delete_if_exists => false }
}[Rails.env.to_sym] unless defined?(DATABASE)

This example uses an sub-directory of app/models to search for the design documents. It also defined a constant named DATABASE that is initialized with the right database setup for the each environment. This constant can then be used to define the models.

class User < CouchModel::Base

  setup_database DATABASE

  ...

end

Support

Apart from contribution, support via Flattr is welcome.