README.md in cistern-0.2.1 vs README.md in cistern-0.2.2

- old
+ new

@@ -1,35 +1,192 @@ # Cistern [![Build Status](https://secure.travis-ci.org/lanej/cistern.png)](http://travis-ci.org/lanej/cistern) +[![Dependencies](https://gemnasium.com/lanej/cistern.png)](https://gemnasium.com/lanej/cistern.png) -TODO: Write a gem description +Cistern helps you consistenly build your API clients and faciliates building mock support. -## Installation +## Usage -Add this line to your application's Gemfile: +### Service - gem 'cistern' +This represents the remote service that you are wrapping. If the service name is 'foo' then a good name is 'Foo::Client'. -And then execute: +Service initialization will only accept parameters enumerated by ```requires``` and ```recognizes```. ```model```, ```collection```, and ```request``` enumerate supported features and require them directly within the context of the ```model_path``` and ```request_path```. - $ bundle +```Mock.data``` is commonly used to store mock data. It is often easiest to use identity to raw response mappings within the ```Mock.data``` hash. -Or install it yourself as: +```ruby - $ gem install cistern +class Foo::Client < Cistern::Service -## Usage + model_path "foo/models" + request_path "foo/requests" -TODO: Write usage instructions here + model :bar + collection :bars + request :create_bar + request :get_bar + request :get_bars + requires :hmac_id, :hmac_secret + recognizes :host + + class Real + def initialize(options={}) + # setup connection + end + end + + class Mock + def self.data + @data ||= { + :bars => {}, + } + end + + def self.reset! + @data = nil + end + + def data + self.class.data + end + def initialize(options={}) + # setup mock data + end + end +end + +``` + +### Model + +```connection``` represents the associated ```Foo::Client``` instance. + +```ruby + +class Foo::Client::Bar < Cistern::Model + identity :id + + attribute :flavor + attribute :keypair_id, aliases: "keypair", squash: "id" + attribute :private_ips, type: :array + + def destroy + params = { + "id" => self.identity + } + self.connection.destroy_bar(params).body["request"] + end + + def save + requires :keypair_id + + params = { + "keypair" => self.keypair_id, + "bar" => { + "flavor" => self.flavor, + }, + } + + if new_record? + request_attributes = connection.create_bar(params).body["request"] + merge_attributes(new_attributes) + end + end +end + +``` + +### Collection + +```model``` tells Cistern which class is contained within the collection. ```Cistern::Collection``` inherits from ```Array``` and lazy loads where applicable. + +```ruby + +class Foo::Client::Bars < Cistern::Collection + + model Foo::Client::Bar + + def all(params = {}) + response = connection.get_bars(params) + + data = self.clone.load(response.body["bars"]) + + collection.attributes.clear + collection.merge_attributes(data) + end + + def discover(provisioned_id, options={}) + params = { + "provisioned_id" => provisioned_id, + } + params.merge!("location" => options[:location]) if options.key?(:location) + + connection.requests.new(connection.discover_bar(params).body["request"]) + end + + def get(id) + if data = connection.get_bar("id" => id).body["bar"] + new(data) + else + nil + end + end +end + +``` + +### Request + +```ruby + +module Foo + class Client + class Real + def create_bar(options={}) + request( + :body => {"bar" => options}, + :method => :post, + :path => '/bar' + ) + end + end # Real + + class Mock + def create_bar(options={}) + id = Foo.random_hex(6) + + bar = { + "id" => id + }.merge(options) + + self.data[:bars][id]= bar + + response( + :body => {"bar" => bar}, + :status => 201, + :path => '/bar', + ) + end + end # Mock + end # Client +end # Foo + +``` + +## Examples + +* [zendesk2](https://github.com/lanej/zendesk2) + ## Releasing $ gem bump -trv (major|minor|patch) ## 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`) -. Create new Pull Request +5. Create new Pull Request