README.md
# Kindergarten
[![Build Status](https://secure.travis-ci.org/coffeeaddict/kindergarten.png)](http://travis-ci.org/coffeeaddict/kindergarten)
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/coffeeaddict/kindergarten)
A way to achieve modularity and modular security with a sandbox on steroids.
## Introduction
### Modules
A Kindergarten could be seen as collection of service objects, each
representing a 'play area' (think: doll area, lego table, etc. etc.).
Within the realm of kindergarten, the service objects are refered to as
modules.
### Sandboxing
The modules are plugged into the kindergarten and can be governed, both per
module and kindergarten wide. There are governesses looking for, and preventing
trouble.
Each module is not just exposed as-is; it is sandboxed. Which means that they
must specify which methods are to be played with.
### Child
What good would a kindergarten with a sandbox full of toys be without a child?
In a Rails context; the most logical choise for a child would be
the ```current_user```.
## Installation
Add this line to your application's Gemfile:
gem 'kindergarten'
And then execute:
$ bundle
Or install it yourself as:
$ gem install kindergarten
## Usage
```ruby
# define a child
child = User.find(2)
# define a module (perimeter) for the child to play in
class MyPlayModule < Kindergarten::Perimeter
# every module must have a purpose.
# The purpose also serves as a namespace
#
purpose :playing
# use can-can rules to govern the perimeter
govern do
can :watch, Television
cannot :watch, CableTV
can :eat, Candy do |candy|
child.quotum.allows(candy)
end
end
# define exposed methods
expose :watch_tv, :eat
def watch_tv(tv)
guard(:watch, tv)
child.watch(tv)
sleep(:four)
end
def eat(candy)
guard(:eat, candy)
child.eat(candy)
end
def sleep(len) # not_accessible_from_outside
child.sleep(len)
end
# or expose methods in an 'annotation like way'
expose :method
# method that does nothing at all
def method
end
end
# load the child (any object) and the module into a sandbox
sandbox = Kindergarten.sandbox(child)
sandbox.load_module(MyPlayPerimeter)
# you can now call the sandboxed methods on the sandbox
sandbox.playing.watch_tv(CableTV.new) # fails with Kindergarten::AccessDenied
30.times do
sandbox.playing.eat(Liquorice.new) # fails after a while
end
sandbox.playing.sleep(:long) # fails with NoMethodError
sandbox.allows?(:watch, Television)
# => true
```
You are not restricted to only one perimeter/module - that would be most
boring...
Infact, the above is the essence of things - but there is much much more fun
hidden inside the Kindergarten. More will follow on the Wiki
## Contributing
1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Added some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request