Building A Framework On Rack
Upcoming SlideShare
Loading in...5
×
 

Building A Framework On Rack

on

  • 2,990 views

Describes a high-level evaluation of why one would end up actually implementing a framework, how one should approach it, why one would do it, and then actually shows some examples of writing a ...

Describes a high-level evaluation of why one would end up actually implementing a framework, how one should approach it, why one would do it, and then actually shows some examples of writing a Rack-based web application development framework called "Fuck".

Statistics

Views

Total Views
2,990
Views on SlideShare
2,969
Embed Views
21

Actions

Likes
3
Downloads
38
Comments
1

3 Embeds 21

http://www.slideshare.net 16
http://maraby.org 3
http://localhost:4871 2

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Building A Framework On Rack Building A Framework On Rack Presentation Transcript

  • Building a Framework on Rack Wednesday, August 12, 2009
  • Wednesday, August 12, 2009
  • Fornication You’ve probably heard about my fornication-themed framework called... Wednesday, August 12, 2009
  • Wednesday, August 12, 2009
  • Fuck Wednesday, August 12, 2009
  • writing a fucking framework It was the most appropriate name for a simple fuckin framework! Wednesday, August 12, 2009
  • 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
  • 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
  • A need to develop similar types of web applications... Yep... pretty damn simple. Wednesday, August 12, 2009
  • ...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
  • An exercise in You’re tired or think MVC just doesn’t cut it (it challenging doesn’t) and think you can come up with something that solves the problem better... expectations Wednesday, August 12, 2009
  • Or you’re just itching a mental scratch.... An exercise mental masturbation Wednesday, August 12, 2009
  • 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
  • We need to find out what we’re abstracting What are we abstracting? Wednesday, August 12, 2009
  • 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
  • Non-application logic Configuration Templating ORMs assembling the working pieces of a stack request routing et al Wednesday, August 12, 2009
  • Reusable components, tools, and helpers Wednesday, August 12, 2009
  • 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
  • a fuckin resource: responds with: all read one accepts: create new update one delete one Wednesday, August 12, 2009
  • CRUD Wednesday, August 12, 2009
  • 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
  • So what are we aiming for with the Fuck framework? An overly simple abstraction of a RESTful CRUD interface Wednesday, August 12, 2009
  • 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
  • Including: Threats Recipes Ask for some simple objects we could easily Posts ser ve purely RESTfully like WeeDB which stores generic key-value pairs Values (serialized JSON data) People Nouns Verbs Cities (called Atlanta) Wednesday, August 12, 2009
  • 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
  • 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
  • Specialty Domain You’re solving a special problem that other frameworks don’t, right? Wednesday, August 12, 2009
  • Unfamiliar Expectations Developers don’t know what to expect from your framework... What content type does it default to? Does it support forms? Wednesday, August 12, 2009
  • Maintenance community & email bug fixes & issue tracking heckling (j/k) speaking opportunities feature improvement testing Wednesday, August 12, 2009
  • Why? One last sanity check Wednesday, August 12, 2009
  • Why doesn’t Rails work for our needs? Wednesday, August 12, 2009
  • Why doesn’t Sinatra work for our needs? Wednesday, August 12, 2009
  • Why doesn’t work anything for our needs? Wednesday, August 12, 2009
  • How? So how do we do it? This is after all the crux of the talk Wednesday, August 12, 2009
  • 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
  • Simplest possible implementation of the solution but no simpler Wednesday, August 12, 2009
  • For Example: Only resources These are essentially what Fuck is designed around Only RESTfully IO includes templating and DB persistence BUT specifically requests and responses No explicit routes No explicit configuration No assumptions about IO Wednesday, August 12, 2009
  • 100 LOC Keep 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
  • How do we reuse existing tools? This is a talk about building a framework on Rack, after all Wednesday, August 12, 2009
  • Rack abstracts server integration into a simple, consistent interface This is why Rack was written initially Wednesday, August 12, 2009
  • 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
  • Rack has many great libraries, middleware, and guides freely available already Rack::Cache Rack::JSONP Rack::Bug CloudKit Get audience to name some middleware they’ve found useful or interesting Wednesday, August 12, 2009
  • Rack is constantly improving and many popular frameworks use it internallyRails 2.3+ is built on top of Rack and supports Metal endpoints (Rack apps) Sinatra, Ramaze, Halcyon, Mack, etc Wednesday, August 12, 2009
  • How do we write it? So how do we even begin to know how to write a framework? Wednesday, August 12, 2009
  • YOU’RE DOING IT WRONG WRONG WRONG WRONG WRONG Stop, you retard... WRONG 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
  • How do we test it? Wednesday, August 12, 2009
  • We write our tests first. TATFT Wednesday, August 12, 2009
  • It allows us to exercise the API before Our opportunity to design the API implementing it... Wednesday, August 12, 2009
  • ...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
  • 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
  • But lets wait until the end of the talk to see... ... Wednesday, August 12, 2009
  • How do we get it to run? No need for JBoss ser vers and all that bullshit... Essentially calls Mongrel and then loads the environment Wednesday, August 12, 2009
  • rackup -p 3000 config.ru Wednesday, August 12, 2009
  • config.ru require 'fuck' require 'posts' run Fuck Fuck the class responds to the class method #call to handle requests (it figures out what resource to defer to) Wednesday, August 12, 2009
  • How do we release it? Wednesday, August 12, 2009
  • RubyGems Talk about the Gem spec and simple Rakefile to make this simple Rip Mention the GitHub restriction Rip, developed by Chris Wanstrath of GitHub, looks very promising; specifically the branching and sharing Wednesday, August 12, 2009
  • Wednesday, August 12, 2009
  • Implementing the Framework Wednesday, August 12, 2009
  • Tests TATFT Wednesday, August 12, 2009
  • class Posts < Fuck::Resource Simplistic CRUD with a nonsensical def all implementation 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}" end end Wednesday, August 12, 2009
  • Dependencies for testing require 'rubygems' require 'fuck' # set load path first require 'rack/mock' require 'stringio' require 'test/spec' # or whatever Wednesday, August 12, 2009
  • A mock request is essentially the environment hash of the request (PATH_INFO et al) env = Rack::MockRequest.env_for( "/posts", "REQUEST_METHOD" => "GET") This sets off the resource Fuck.call(env) routing Response is minimal #=> [status, headers, body] required response for Rack Wednesday, August 12, 2009
  • Slightly specific to test/spec wrote this a few months ago and would probably pick context or shoulda or rspec now... 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 Didn’t mention this but wrote a helper method for sending a mock request for all of the HTTP verbs Wednesday, August 12, 2009
  • Let’s get to the actual framework already! Framework But we’ll add tests for each feature we start to implement Wednesday, August 12, 2009
  • The initial routing handler... Base Wednesday, August 12, 2009
  • find_handler finds the resource class (Posts) require 'rack' yay for minimal dependencies that will handle the request class Fuck stripped down but we definitely respond with class << self proper status codes and PATH_INFO = %r{/?(w+)(/(w+))?} # matches /posts and /posts/1 log to rack.errors 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 Would probably just require now instead of end autoload because thread- end safety concerns autoload :Resource, "fuck/resource" end Wednesday, August 12, 2009
  • The actual request handlers; essentially a resource controller, for instance Resources Wednesday, August 12, 2009
  • 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 find_method figures out what request method is being used and whether an def find_method(request_method) ID was set or not in order to determine # determine the type of request (GET, PUT, POST, to call the :all, :create, :read, :update, DELETE, etc) or :delete methods... 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 end end Wednesday, August 12, 2009
  • Wednesday, August 12, 2009
  • Wednesday, August 12, 2009
  • Wednesday, August 12, 2009