Skip to content

MikeSofaer/vanna

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

73 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

#Vanna

Vanna is a replacement for ActionController::Base, build around the basic concept that all web requests should operate as logical clients of a JSON API. This should be transparent to the web developer, and development should still be possible in the standard pattern of write a test, write the controller code, build a template, repeat.

The main differences are:

  • controllers return their data directly
  • controllers are tested by calling them directly
  • html-specific behavior (like redirects) happen in explicit post-process blocks

See My Blabs post for a theoretical discussion.

#Setup: ##Gemfile

gem 'vanna', :git => 'git:https://github.com/MikeSofaer/vanna.git'

##ApplicationController

Change 'ActionController::Base' to 'Vanna::Base'

It you want to use Devise, do this:

include Devise::Controllers::Helpers

And then you can do this:

before_filter :authenticate_user!

#Usage

##Controllers

Controllers normally return hashes of the data you want to render. Don't call render from inside a controller. If a controller uses params, use (opts=params) in the signature, so it can be called from other controllers. Use other controller methods to construct the full page dictionary

##Redirects

Your happy path redirects work by putting a line in your controller telling Vanna what to do after a successful POST.

redirect_on :create, :to => :index

For more complex logic, you write a post-processor block:

post_process :html do
  def post_create(json_response)
    Response.new(:status => 302, :location => path_in_another_controller(json_response[:some_id])
  end
end

##Views

Just like normal ERB views, but instead of instance variables, you get the top level hash elements as locals, so all templates act like partials.

Since there are no instance variables, anything that needs to be available in a partial has to be passed through.

#Example

##Controller

class PersonasController < ApplicationController
  def index
    {:main => {"personas" => Persona.all}}
  end
  def show(opts = params)
    persona = Persona.named(opts["persona"]).first
    sidebar = catchphrases("personas" => persona["partners"])
    {:persona =>persona, :sidebar => sidebar}
  end
  def catchphrases(opts=params)
    names = opts["personas"]
    Persona.named(names).map{|p| p["catchphrase"]}
  end
end

#Thanks Thanks to Affine Systems(https://affinesystems.com) for sponsoring some of the development of this library.

About

An opinion on APi-driven web application program flow

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages