README.md in yeti-0.1.1 vs README.md in yeti-0.1.2

- old
+ new

@@ -18,10 +18,156 @@ $ gem install yeti ## Usage -TODO: Write usage instructions here +### Yeti::Context + +The context object allows to communicate application state coming from the +controllers. First, let's create a Context class tuned to your application +logic. + +```ruby +class Context < Yeti::Context + def initialize(hash) + super hash + @section = hash.fetch :section + end + + def in_admin? + section==:admin + + def api_call? + section==:api + end +end +``` + +Typical usage in controller: + +```ruby +class Admin::BaseController < ApplicationController +private + def current_context + Context.new account_id: session[:account_id, section: :admin + end +end +class Admin::UsersController < Admin::BaseController + def index + @users = UserSearch.new context, params + end + + def show + @user = UserViewer.new context, params[:id] + end + + def new + user + end + + def create + if user.update_attributes params[:user] + redirect_to action: :index, notice: t(:successfully_created) + else + flash.now[:error] = t(:please_fix_errors_and_retry) + render :new + end + end + + def edit + user + end + + def update + if user.update_attributes params[:user] + redirect_to action: :index, notice: t(:successfully_updated) + else + flash.now[:error] = t(:please_fix_errors_and_retry) + render :edit + end + end + + def user + @user ||= UserEditor.new context, params[:id] + end +end +``` + +The presenters can then use the context to restrict search results, change +validation, etc. The context object is also useful to track current account in +order to apply permissions or know who is performing the action. + +Let's say you have a Account model: + +```ruby +class Account < ActiveRecord::Base + def guest? + false + end +end +``` + +of course it could be using Sequel, Mongoid or the ORM of your liking. Then you +can define your context class this way: + +```ruby +class Context < Yeti::Context + class NoAccount < Yeti::Context::NoAccount + def guest? + true + end + end + delegate :guest?, to: :account + +private + + def find_account_by_id(id) + Account.find_by_id id + end + + def no_account + NoAccount.new + end +end +``` + +And with that setup you get: + +```ruby +existing_account_id = 1 +invalid_id = 2 +Context.new.guest? #=> true +Context.new(account_id: existing_account_id).guest? #=> false +Context.new(account_id: invalid_id).guest? #=> true +``` + +No more passing tons of variables from presenters to presenters, the context +object regroups and unify this communication while being easy to test in +isolation. + +### Yeti::Search + +The search object aims to simplify creating pages with numerous filters. + +Let's say you have the following Sequel model: + +```ruby +class User < Sequel::Model +end +``` + +then you can create UserSearch like this: + +```ruby +class UserSearch < Yeti::Search +private + def paginated_results + User.search(search).paginate page, per_page + end +end +``` + +### Yeti::Editor ## Contributing 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`)