31
Halcyon

Halcyon Atl RUG Presentation

Embed Size (px)

DESCRIPTION

My presentation on Halcyon, the JSON web app framework.

Citation preview

Page 1: Halcyon Atl RUG Presentation

Halcyon

Page 2: Halcyon Atl RUG Presentation

I WORK

occasionally

Page 3: Halcyon Atl RUG Presentation

HALCYON

web app framework

Page 4: Halcyon Atl RUG Presentation

HALCYON

JSON

HTTP

Rack

Merb

light weight data transport layer

cross-platform communications layer

app/server abstraction layer

core extensions & router

Page 5: Halcyon Atl RUG Presentation

JSON

similar to XML

easy to read & write (unlike XML)

serializable

cross platform

Page 6: Halcyon Atl RUG Presentation

HTTP

cross platform

request/response model

REST

uniform resource identifiers

Page 7: Halcyon Atl RUG Presentation

Rack

small core

simple rules

powerful abstractions

Jim Weirich

Page 8: Halcyon Atl RUG Presentation

Merb

modular

active community, ever increasing code quality

well documented

easy

Page 9: Halcyon Atl RUG Presentation

GETTING STARTED

installation, initialization,running, and customization

Page 10: Halcyon Atl RUG Presentation

Installation

$ sudo gem install --source=http://halcyon.rubyforge.org/latest/

or

$ git clone git://github.com/mtodd/halcyon.git$ cd halcyon; rake install

$ sudo gem install json

Page 11: Halcyon Atl RUG Presentation

Initialization

$ cd ~/Projects/$ halcyon init app_name

Page 12: Halcyon Atl RUG Presentation

Running

$ cd ~/Projects/app_name/$ halcyon run -p 4647

or

$ thin start -p 4647as of Thin 0.8.0

Page 13: Halcyon Atl RUG Presentation

Customization

CONTROLLERS

ROUTES

CLIENTS

found in app/inherits from Application

found in config/initializer.rbwill be config/initializers/routes.rb

found in lib/client.rbsimplifies calling actions' URLs

Page 14: Halcyon Atl RUG Presentation

Controllers

class Foo < Application def random ok rand(10) end def greet ok "Hello #{params[:name]}!" end end

app/foo.rb

Page 15: Halcyon Atl RUG Presentation

Routes

class Halcyon::Application route do |r| r.match('/hello/:name').to(:controller => 'foo') r.match('/rand').to(:controller => 'foo', :action => 'random') # defines /:controller/:action/:id and family # r.default_routes end end

config/initialize.rb

Page 16: Halcyon Atl RUG Presentation

Clients

class AppAgent < Halcyon::Client def greet(name) get("/hello/#{name}")[:body] end def random get('/rand')[:body] end end

lib/client.rb

Page 17: Halcyon Atl RUG Presentation

Run & Test

RUN

TEST

$ halcyon start -p 4647

$ irb -rubygems -r lib/client>> client = AppAgent.new( "http://localhost:4647/")=> #<AppAgent>>> client.rand=> 4>> client.greet("Matt")=> "Hello Matt!">> client.get("/foo")=> {:status=>404,:body=>"Not Found"}

Page 18: Halcyon Atl RUG Presentation

Run & Test Interactively

OR $ halcyon irb>> get "/rand"=> {:status=>200,:body=>7}>> get "/hello/Matt"=> {:status=>200,:body=>"Hello Matt!"}>> client.get("/foo")=> {:status=>404,:body=>"Not Found"}

Page 19: Halcyon Atl RUG Presentation

ADVANCED TOPICS

databases, Rack magic

Page 20: Halcyon Atl RUG Presentation

DATABASES – ORM agnostic

ActiveRecord

DataMapper

Sequel

ET AL

in config/initialize.rbclass Halcyon::Application startup do |config| # connect to DB of your choice here. # define in $global_variable (bleh) # or Constant. end end

Page 21: Halcyon Atl RUG Presentation

RACK MAGIC

API Handler

Cascade

Content-Type

Reloader

Referrer

routes matching pattern deferred

finds the first app that can handle request

change the content type for all responses

reload classes when modified

track referrers

Page 22: Halcyon Atl RUG Presentation

class ApiHandler def initialize(app, api); @app, @api = app, api; end def call(env) req = Merb::Request.new(env) if request.path =~ %r{^/api/(.*)} @api.call(env) else @app.call(env) end endenduse ApiHandler, Halcyon::Runner.newrun Merb::Rack::Application.new

RACK MAGIC – API Handler

Page 23: Halcyon Atl RUG Presentation

Similar to previous example, only using Rack::Cascade.

run Rack::Cascade, [ Halcyon::Runner.new, Merb::Rack::Application.new]

Just define routes so that the Halcyon app won't preventthe Merb app from ever running.(Require /api/ in front of all routes for Halcyon, forinstance.)

RACK MAGIC – Cascade

Page 24: Halcyon Atl RUG Presentation

# http://hokstad.com/rewriting-content-types-with-rack.html

class RewriteContentType def initialize(app, map); @app, @map = app, map; end def call(env) res = @app.call(env) type = res[1]["Content-Type"] res[1]["Content-Type"] = @map[type] if @map.has_key?(type) res endend

use RewriteContentType, {'application/json'=>'text/plain'}run Halcyon::Runner.new

RACK MAGIC – Content Type

Page 25: Halcyon Atl RUG Presentation

Automatically reload modified requirements.

# uncomment for pretty web exception rendering# use Rack::ShowExceptionsuse Rack::Reloaderrun Halcyon::Runner.new

Simple as that.

RACK MAGIC – Reloader

Page 26: Halcyon Atl RUG Presentation

Keep a log of referring links (if even set), or any other recordable data.

http://hokstad.com/latest-referrers-using-rack-and-ruby.html

Why reinvent the wheel?

RACK MAGIC – Referrer

Page 27: Halcyon Atl RUG Presentation

DEMO

Page 28: Halcyon Atl RUG Presentation

QUESTIONS?

Page 29: Halcyon Atl RUG Presentation

RESOURCES

HOMEPAGE

GIT REPO

DOCS

IRC

Jan Lenhardt's MountainWest CouchDB Talk

http://halcyon.rubyforge.org/

http://github.com/mtodd/halcyon

http://halcyon.rubyforge.org/docs/

freenode.net #halcyon

http://mtnwestrubyconf2008.confreaks.com/10lehnardt.html

Page 30: Halcyon Atl RUG Presentation

FIN

Page 31: Halcyon Atl RUG Presentation

SEE ALSO

CouchDB

Jan Lenhardt's MountainWest CouchDB Talk

http://couchdb.com/

http://mtnwestrubyconf2008.confreaks.com/10lehnardt.html