Building A Framework On Rack
-
Upload
matt-todd -
Category
Technology
-
view
1.921 -
download
2
description
Transcript of Building A Framework On Rack
![Page 1: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/1.jpg)
Building aFramework
on RackWednesday, August 12, 2009
![Page 2: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/2.jpg)
Wednesday, August 12, 2009
![Page 3: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/3.jpg)
FornicationYou’ve probably heard about my fornication-themed framework called...
Wednesday, August 12, 2009
![Page 4: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/4.jpg)
Wednesday, August 12, 2009
![Page 5: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/5.jpg)
Fuck
Wednesday, August 12, 2009
![Page 6: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/6.jpg)
writing afucking
frameworkIt was the most appropriate name for a simple fuckin framework!
Wednesday, August 12, 2009
![Page 7: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/7.jpg)
What?I know what I want, but let’s establish what we’re after...
We need to ask some important questions before we get lost in glee and fascination
We’ll start with...
Wednesday, August 12, 2009
![Page 8: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/8.jpg)
What is the problem we’re solving?
Clearly there’s a reason we need this framework... we’re solving a problem, but what is the problem?
Wednesday, August 12, 2009
![Page 9: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/9.jpg)
A need to develop similar types of web applications...
Yep... pretty damn simple.
Wednesday, August 12, 2009
![Page 10: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/10.jpg)
...that another framework doesn’t already do better
One option, though a plugin could probably be better used, or simply using Sinatra or Rack directly
Wednesday, August 12, 2009
![Page 11: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/11.jpg)
An exercise in challenging expectations
You’re tired or think MVC just doesn’t cut it (it doesn’t)
and think you can come up with something that solves the problem better...
Wednesday, August 12, 2009
![Page 12: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/12.jpg)
An exerciseOr you’re just itching a mental scratch....
mental masturbation
Wednesday, August 12, 2009
![Page 13: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/13.jpg)
Abstracting out a solution’s pattern
Most successful frameworks
abstract a working solution
to a generic framework
because their solution solved both a specific and a general problem
Wednesday, August 12, 2009
![Page 14: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/14.jpg)
What are we abstracting?
We need to find out what we’re abstracting
Wednesday, August 12, 2009
![Page 15: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/15.jpg)
The hard parts in our solution’s pattern
like the distributed stuff in Mack
or handling uploads, testing, and RESTful routes and routes in general in Rails
Wednesday, August 12, 2009
![Page 16: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/16.jpg)
Non-application logicConfigurationTemplatingORMs
assembling the working pieces of a stack
request routing et al
Wednesday, August 12, 2009
![Page 17: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/17.jpg)
Reusable components, tools, and helpers
Wednesday, August 12, 2009
![Page 18: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/18.jpg)
What should the API look like? if we could use the API
before writing it or testing it, what would it look like?
pseudo-code
Wednesday, August 12, 2009
![Page 19: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/19.jpg)
a fuckin resource: responds with: all read one accepts: create new update one delete one
Wednesday, August 12, 2009
![Page 20: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/20.jpg)
CRUD
Wednesday, August 12, 2009
![Page 21: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/21.jpg)
What applications will it have? How will we use our
framework?
For example, the application the framework will be abstracted out of?
Aurora, JSON-based auth server
Wednesday, August 12, 2009
![Page 22: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/22.jpg)
An overly simple abstraction of a RESTful CRUD interface
So what are we aiming for with the Fuck framework?
Wednesday, August 12, 2009
![Page 23: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/23.jpg)
Any object we want to manage RESTfully
CloudKit does something like this, but it’s all automatic
We want to define the data IO (essentially)
Wednesday, August 12, 2009
![Page 24: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/24.jpg)
Including:
ThreatsRecipesPostsValuesPeopleNounsVerbsCities (called Atlanta)
Ask for some simple objects we could easily serve purely RESTfully
like WeeDB which stores generic key-value pairs (serialized JSON data)
Wednesday, August 12, 2009
![Page 25: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/25.jpg)
How about a Key-Value store web interface?
If we have time we can write an application that stores to Redis via a Fuck Resource
doubtful, though
Wednesday, August 12, 2009
![Page 26: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/26.jpg)
What problems have we created?
There always comes some responsibility with writing and sharing a framework
ASSUMING we’re sharing it as OSS, right? RIGHT?!
Wednesday, August 12, 2009
![Page 27: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/27.jpg)
Specialty DomainYou’re solving a special problem that other frameworks don’t, right?
Wednesday, August 12, 2009
![Page 28: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/28.jpg)
Unfamiliar ExpectationsDevelopers don’t know what to expect from your framework...
What content type does it default to?
Does it support forms?
Wednesday, August 12, 2009
![Page 29: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/29.jpg)
Maintenancecommunity & emailbug fixes & issue trackingheckling (j/k)speaking opportunitiesfeature improvementtesting
Wednesday, August 12, 2009
![Page 30: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/30.jpg)
Why?One last sanity check
Wednesday, August 12, 2009
![Page 31: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/31.jpg)
Why doesn’t Rails work for our needs?
Wednesday, August 12, 2009
![Page 32: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/32.jpg)
Why doesn’t Sinatra work for our needs?
Wednesday, August 12, 2009
![Page 33: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/33.jpg)
Why doesn’t work for our needs?
anything
Wednesday, August 12, 2009
![Page 34: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/34.jpg)
How?So how do we do it?
This is after all the crux of the talk
Wednesday, August 12, 2009
![Page 35: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/35.jpg)
How simple can we make it?
We still need to ask the right questions...
So how can we make the framework as simple as possible?
And why?
Wednesday, August 12, 2009
![Page 36: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/36.jpg)
Simplest possible implementation of the solution but no simpler
Wednesday, August 12, 2009
![Page 37: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/37.jpg)
For Example:
Only resourcesOnly RESTfullyNo explicit routesNo explicit configurationNo assumptions about IO
These are essentially what Fuck is designed around
IO includes templating and DB persistence
BUT specifically requests and responses
Wednesday, August 12, 2009
![Page 38: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/38.jpg)
100 LOCKeep the code as small, lean, and clean as possible...
100 LOC is a little arbitrary and meaningless, but it’s small...
Can we meaningfully create a framework in 100 LOC? Yep.
Wednesday, August 12, 2009
![Page 39: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/39.jpg)
How do we reuse existing tools? This is a talk about
building a framework on Rack, after all
Wednesday, August 12, 2009
![Page 40: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/40.jpg)
Rack abstracts server integration into a simple, consistent interface This is why Rack was
written initially
Wednesday, August 12, 2009
![Page 41: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/41.jpg)
Rack provides a simple DSL for injecting logic in the call cycle through middleware
Why we don’t worry about auth, caching, et al
Wednesday, August 12, 2009
![Page 42: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/42.jpg)
Rack has many great libraries, middleware, and guides freely available already
Rack::CacheRack::JSONPRack::BugCloudKit
Get audience to name some middleware they’ve found useful or interesting
Wednesday, August 12, 2009
![Page 43: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/43.jpg)
Rack is constantly improving and many popular frameworks use it internally
Rails 2.3+ is built on top of Rack and supports Metal endpoints (Rack apps)
Sinatra, Ramaze, Halcyon, Mack, etc
Wednesday, August 12, 2009
![Page 44: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/44.jpg)
How do we write it?So how do we even begin to know how to write a framework?
Wednesday, August 12, 2009
![Page 45: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/45.jpg)
WRONGYOU’RE DOING IT
WRONGWRONGWRONGWRONGWRONGWRONGWRONG
Stop, you retard...
you’re doing it wrong!
You write the tests first!
This will answer so many questions early on about how to write it!
Wednesday, August 12, 2009
![Page 46: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/46.jpg)
How do we test it?
Wednesday, August 12, 2009
![Page 47: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/47.jpg)
We write our tests first. TATFT
Wednesday, August 12, 2009
![Page 48: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/48.jpg)
It allows us to exercise the API before implementing it...
Our opportunity to design the API
Wednesday, August 12, 2009
![Page 49: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/49.jpg)
...and ensures our expectations are met as we implement. Failing tests are always a
good way to bring attention to problematic or incomplete portions of the library/framework
Wednesday, August 12, 2009
![Page 50: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/50.jpg)
How do we write it?Now we can think about writing it once we’ve established or at least started our tests...
TDD/BDD works great!
Wednesday, August 12, 2009
![Page 51: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/51.jpg)
...But lets wait until the end of the talk to see...
Wednesday, August 12, 2009
![Page 52: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/52.jpg)
How do we get it to run?
No need for JBoss servers and all that bullshit...
Essentially calls Mongrel and then loads the environment
Wednesday, August 12, 2009
![Page 53: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/53.jpg)
rackup -p 3000 config.ru
Wednesday, August 12, 2009
![Page 54: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/54.jpg)
require 'fuck'require 'posts'
run Fuck
config.ru
Fuck the class responds to the class method #call to handle requests (it figures out what resource to defer to)
Wednesday, August 12, 2009
![Page 55: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/55.jpg)
How do we release it?
Wednesday, August 12, 2009
![Page 56: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/56.jpg)
RubyGemsRip
Talk about the Gem spec and simple Rakefile to make this simple
Mention the GitHub restriction
Rip, developed by Chris Wanstrath of GitHub, looks very promising ; specifically the branching and sharing
Wednesday, August 12, 2009
![Page 57: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/57.jpg)
Wednesday, August 12, 2009
![Page 58: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/58.jpg)
Implementingthe Framework
Wednesday, August 12, 2009
![Page 59: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/59.jpg)
Tests TATFT
Wednesday, August 12, 2009
![Page 60: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/60.jpg)
class Posts < Fuck::Resource def all respond "Fuckin A!" end def create respond params["a"] end def read(id) respond "You asked for #{id}?" end def update(id) respond params["a"] end def delete(id) respond "You asked me to delete #{id}" endend
Simplistic CRUD with a nonsensical implementation
Wednesday, August 12, 2009
![Page 61: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/61.jpg)
require 'rubygems'
require 'fuck' # set load path first
require 'rack/mock'require 'stringio'
require 'test/spec' # or whatever
Dependencies for testing
Wednesday, August 12, 2009
![Page 62: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/62.jpg)
env = Rack::MockRequest.env_for( "/posts", "REQUEST_METHOD" => "GET")
Fuck.call(env)#=> [status, headers, body]
A mock request is essentially the environment hash of the request (PATH_INFO et al)
This sets off the resource routing
Response is minimal required response for Rack
Wednesday, August 12, 2009
![Page 63: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/63.jpg)
context "Fuck can route" do specify "to list all of the resources" do status, headers, body = get("/posts") status.should == 200 body.should =~ /Fuckin A!/ end end
Slightly specific totest/spec
wrote this a few months ago and would probably pick context or shoulda or rspec now...
Didn’t mention this but wrote a helper method for sending a mock request for all of the HTTP verbs
Wednesday, August 12, 2009
![Page 64: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/64.jpg)
FrameworkLet’s get to the actual framework already!
But we’ll add tests for each feature we start to implement
Wednesday, August 12, 2009
![Page 65: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/65.jpg)
BaseThe initial routing handler...
Wednesday, August 12, 2009
![Page 66: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/66.jpg)
require 'rack'
class Fuck class << self PATH_INFO = %r{/?(\w+)(/(\w+))?} # matches /posts and /posts/1 def call(env) if handler = find_handler(env["PATH_INFO"], env["QUERY_STRING"]) handler.call(env) # dispatch the request else # not found end rescue Exception => e # internal server error end def find_handler(path_info, query_string) # determine the resource from the path info # /posts => Posts end end autoload :Resource, "fuck/resource"end
find_handler finds the resource class (Posts) that will handle the request
stripped down but we definitely respond with proper status codes and log to rack.errors
Would probably just require now instead of autoload because thread-safety concerns
yay for minimal dependencies
Wednesday, August 12, 2009
![Page 67: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/67.jpg)
Resources
The actual request handlers;
essentially a resource controller, for instance
Wednesday, August 12, 2009
![Page 68: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/68.jpg)
class Fuck class Resource DEFAULT_HEADERS = {"Content-Type" => "text/html"} attr_accessor :params def initialize(id, params); @id, @params = id, params; end def call(env) request_method = find_method(env["REQUEST_METHOD"]) || :not_implemented return not_implemented unless self.respond_to?(request_method) send(request_method, *[@id].compact) or not_found rescue Exception => e # internal server error end def find_method(request_method) # determine the type of request (GET, PUT, POST, DELETE, etc) end def respond(body = "OK", options = {}, headers = {}) # prepares a Rack-compatible response: [status, headers, body] end def not_found; respond("Not Found", :status => 404); end def not_implemented; respond("Not Implemented", :status => 501); end endend
find_method figures out what request method is being used and whether an ID was set or not in order to determine to call the :all, :create, :read, :update, or :delete methods...
Wednesday, August 12, 2009
![Page 69: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/69.jpg)
Wednesday, August 12, 2009
![Page 70: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/70.jpg)
Wednesday, August 12, 2009
![Page 71: Building A Framework On Rack](https://reader033.fdocuments.net/reader033/viewer/2022060109/555278ddb4c905115b8b48d3/html5/thumbnails/71.jpg)
Wednesday, August 12, 2009