= 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.
http://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}[http://dl.dropbox.com/u/167916/stochasticbytes/activesupport-3.0.0.beta1.gem]
{activemodel-3.0.0beta1}[http://dl.dropbox.com/u/167916/stochasticbytes/activemodel-3.0.0.beta1.gem]
== 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[http://github.com/mperham/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}[link:/classes/CurlyMustache/Attributes/Types.html]
== 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}[link:/classes/CurlyMustache/Adapters/Memcached.html] with any data stores that speak memcached. There is also the {Cassandra adapter}[link:/classes/CurlyMustache/Adapters/Cassandra.html] 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}[link:/classes/CurlyMustache/Connection/InstanceMethods.html#M000078]. For deserialization, override {recv_attributes}[/classes/CurlyMustache/Connection/InstanceMethods.html#M000079].
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}[http://github.com/cjbottaro]