CurlyMustache

ActiveModel implementation for various data stores. In other words, it provides an ActiveRecord like library for data stores other than relational databases. Out of the box, it works with Memcached, Redis, Tokyo Tyrant, Cassandra and Amazon SDB.

github.com/cjbottaro/curly_mustache

Installation

sudo gem install curly_mustache

CurlyMustache depends on activemodel-3.0.0beta1 and activesupport-3.0.0beta1 which are unfortunately in a state of great flux and are thus very buggy. I’m hosting patched versions that are known to work with CurlyMustache here:

activesupport-3.0.0beta1

activemodel-3.0.0beta1

Features

  • Basic ActiveRecord-like CRUD operations (new, create, destroy, find, save).

  • Validations (via ActiveModel).

  • Callbacks (via ActiveModel).

  • Attribute change tracking (via ActiveModel::Dirty).

  • Easy creation of new types.

  • Easy creation of new adapters (to connect to different data stores).

  • 100% rcov(erage)!

Quickstart

If your data store speaks Memcached, then you just need to use the :memcached adapter.

CurlyMustache::Base.establish_connection :adapter => :memcached,
                                         :servers => %w[one.example.com:11211 two.example.com:11211]

class User < CurlyMustache::Base
  attribute :name,          :string
  attribute :login_count,   :integer
  attribute :birthday,      :time

  validates_presence_of :name
  after_validation :capitalize_name

  def capitalize_name
    self.name = name.capitalize
  end
end

user = User.new :name => "chris"
user.new_record?                      # => true
user.id                               # => nil
user.name                             # => "chris"
user.birthday                         # => nil
user.birthday = "03/11/1980"
user.birthday_changed?                # => true
user.birthday.class                   # => Time
user.birthday                         # => "Tue Mar 11 00:00:00 -0600 1980"
user.save!
user.id                               # => "676cef021584904876af7c4b3e42afb5"

user = User.find(user.id)
user.name                             # => "Chris"

user.destroy
User.find(user.id)                    # => CurlyMustache::RecordNotFound

end

The memcache adapter uses memcache-client. Whatever other options you pass to establish_connection will be passed to the constructor for it.

Types

Five types are defined for you: string, integer, float, time, boolean. It is easy to define new types or modify existing ones. See Read more

Callbacks

The following callbacks are available:

before_validation_on_create    after_validation_on_create
before_validation_on_update    after_validation_on_update
before_validation              after_validation
before_create                  after_create
before_update                  after_update
before_save                    after_save
before_destroy                 after_destroy
                               after_find

Adapters

You can use the Memcached adapter with any data stores that speak memcached. There is also the Cassandra adapter and soon to be SDB adapter and Tokyo Tyrant table type adapter.

You can create your own adapters by subclassing CurlyMustache::Adapters::Abstract and implementing a few methods.

Serializing

If you need to serialize your model’s attributes before sending them to the adapter, it’s done by overriding send_attributes. For deserialization, override recv_attributes.

This is how data flows in and out of the data store…

---------------------     --------------------------     ---------------      --------------
| record.attributes | ==> | record.send_attributes | ==> | adapter.put |  ==> | data store |
---------------------     --------------------------     ---------------      --------------

---------------------     --------------------------     ---------------      --------------
| record.attributes | <== | record.recv_attributes | <== | adapter.get |  <== | data store |
---------------------     --------------------------     ---------------      --------------

Author

Christopher J. Bottaro - cjbottaro