Ohm-Contrib: Quick Start

ohm ohm-contrib redis

10|05|2010

Since Ohm-Contrib was released on May 11, 2010, a lot of changes, cool features, and small removals have happened. This blog post is an attempt to summarize what's available and most useful, although I won't attempt to make this an exhaustive reference in any way.

Timestamping

This is probably the most simple yet useful plugin currently in Ohm::Contrib. Using it is actually pretty simple:

require "ohm"
require "ohm/contrib"

class Post < Ohm::Model
  include Ohm::Timestamping
end

Post.new.created_at == nil
# => true

Post.new.updated == nil
# => true

Post.create.created_at.to_s == Time.now.utc.to_s
# => true

Typecasting

Probably one of the most useful yet heavy in the sense that it attempts to solve something a bit more difficult than what the other plugins solve.

Using it is rather simple though:

require "ohm"
require "ohm/contrib"

class Product < Ohm::Model
  include Ohm::Typecast
  include Ohm::Timestamping

  attribute :price, Decimal
  attribute :discount, Decimal

  typecast :created_at, Time
  typecast :updated_at, Time
end

As you can see, you can either declare an attribute with a type from the get go, but you may also do it later using the typecast function.

p = Product.create(:price => "99.50", :discount = "0.50")
p.price * p.discount == 49.75
# => true

p.created_at.respond_to?(:strftime)
# => true

Callbacks

I don't think I even have to explain why this is important: popularized by Martin Fowler in his article entitled CallSuper hooks, a.k.a. callbacks have been an intimate part of our models of late.

require "ohm"
require "ohm/contrib"

class Order < Ohm::Model
  include Ohm::Callbacks

  attribute :status

  before :create, :initialize_status

private
  def initialize_status
    self.status = "Pending"
  end

  def after_save
    OrderMailer.deliver(self)
  end
end

As you can see, you may choose to use macro style callbacks, or instance style ones. The following are all the callbacks available to you:

  1. before_validate and after_validate
  2. before_create and after_create
  3. before_save and after_save
  4. before_update and after_update
  5. before_delete and after_delete

The Newest Addition: Ohm::Scope

This is pretty useful, and the usecase pretty much came about in a fairly large project (twice actually, with different converging styles arrived at independently).

require "ohm"
require "ohm/contrib"

class Product < Ohm::Model
end

class Order < Ohm::Model
  include Ohm::Scope

  attribute :status
  index :status

  reference :product, Product
  reference :user, User

  scope do
    def pending
      find(:status => "Pending")
    end

    def paid
      find(:status =>"Paid")
    end

    def product(product)
      find(:product_id => product.id).first
    end
  end
end

class User < Ohm::Model
  collection :orders, Order
end

ipod = Product.create
ipad = Product.create

u = User.create
u.orders.add(Order.create(:status => "Pending", :product => ipod))
u.orders.add(Order.create(:status => "Paid", :product => ipad))

u.orders.pending.include?(ipod)
# => true

u.orders.paid.include?(ipad)
# => true

u.orders.pending.product(ipod) == Order[1]
# => true

u.orders.pending.product(ipad) == nil
# => true

There's more!

Aside from the ones mentioned here, there are also a lot of validation routines, and some marginally helpful, but still handy plugins.

If you want to see more checkout the documentation.

blog comments powered by Disqus