hanswurst: Be a couch potato and play different roles

Hanswurst is a library that uses couch potato to create arbitrary objects that may have different roles. The roles determine the properties and they can be mixed and matched at will.

Installation

hanswurst is only tested with ruby 1.9.2 and above.

Install it as a gem:

sudo gem install hanswurst

or in rvm:

gem install hanswurst

Example:

first you have to build your roles as normal couch potato classes

class Person
  include CouchPotato::Persistence

  property :last_name
  property :first_name

  def name()
    "#{firstname} #{lastname}"
  end

  validates_presence_of :last_name
end

class Product
  include CouchPotato::Persistence

  property :price
  property :in_stock
end

then you may use them as you like

hw = Hanswurst.new
hw << {:person => Person} # first role then class
hw.person.first_name = 'Diederich'
hw.person.last_name = 'Hessling' # an RoleNotValid error is raised if hw.person.last_name is missing

# you may also use some syntatic sugar with 'as', the following does the same thing as above
hw = Hanswurst.new :person => Person.new(:first_name => 'Diederich', :last_name => 'Hessling') 

# this is also possible
hw.product = Product.new :price => 20, :in_stock => 1  

id = CouchPotato.database.save_document hw

later...

hw = CouchPotato.database.load_document id

hw.person.first_name  # => 'Diederich'
hw.person.name # => 'Diederich Hessling'
hw.product.price       # => 20

you may also set roles as properties of other roles

class Address
  include CouchPotato::Persistence

  property :street
  property :zip
  property :city
end

class Person
  include CouchPotato::Persistence

  property :address_privat
  property :address_work

  # gets invalid unless address_privat / address_work are instances of Address
  validates :address_privat, :hanswurst => {:class => Address}
  validates :address_work, :hanswurst => {:class => Address}

  property :last_name
  property :first_name
end

hw = Hanswurst.new :employee => Person.new(:last_name => 'Hessling')
emp = hw.employee
emp.address_privat = Address.new :city => 'Berlin'
emp.address_work = Address.new :city => 'Potsdam'

as comfort you might delegate to some roles property

class Address
  include CouchPotato::Persistence

  property :street
  property :zip
  property :city
end

class Person
  include CouchPotato::Persistence
  include Hanswurst::Delegates

  property :address

  delegates [:street,:zip,:city] => :address
end

hw = Hanswurst.new :employee => Person.new(:last_name => 'Hessling'), :address => Address.new
emp = hw.employee
emp.city = 'Berlin' # => sets emp.addess.city = 'Berlin'
emp.city # => gets emp.addess.city

you might also share dependancies

class Address
  include CouchPotato::Persistence

  property :street
  property :zip
  property :city
end

class Person
  include CouchPotato::Persistence
  include Hanswurst::Shares

  shares :address_privat => Address
  shares :address_work => Address

  property :last_name
  property :first_name
end

hw = Hanswurst.new :employee => Person.new(:last_name => 'Hessling')
hw.address_privat.city = 'Berlin'
hw.address_work.city = 'Potsdam'

All views are attached to the hanswurst design document You may create general views:

Hanswurst.view :all, :key => :created_at

or views specific for a role

Hanswurst.view_for :employee, :all, :key => :created_at

# execute them this way
CouchPotato.database.view Hanswurst.employee_all

the same works with lists.

You may subclass Hanswurst to do further separation and mix the native properties of Hanswursts / its subclasses with the roles properties.

Contributing to hanswurst

  • Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
  • Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
  • Fork the project
  • Start a feature/bugfix branch
  • Commit and push until you are happy with your contribution
  • Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
  • Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.

Copyright (c) 2012 Marc Rene Arns. See LICENSE.txt for further details.