SlideShare a Scribd company logo
1 of 71
Download to read offline
All I Really Need to Know*
I Learned by Writing My
Own Web Framework
Ben Scofield               7 November 2008
                                  Rubyconf




* about Ruby and the web
All I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web Framework
DSLs
                  DSL




                        Intimidate
                            and
                         Frighten
flickr: cwsteeds
All I Need to Know I Learned by Writing My Own Web Framework
Rails
Rails




        your custom
         framework
Starter Projects
Hello World
main() {
    printf(quot;hello, worldnquot;);
}


-module(hello).

-export([hello/0]).

hello() ->
   io:format(quot;Hello World!~nquot;, []).


      PROGRAM HELLO
      PRINT*, 'Hello World!'
      END
main = putStrLn quot;Hello Worldquot;

Imports System.Console

Class HelloWorld

    Public Shared Sub Main()
        WriteLine(quot;Hello, world!quot;)
    End Sub

End Class

!greeting.
+!greeting : true <- .print(quot;Hello Worldquot;).
Applications
To-do lists
DIY Blog
Frameworks?
PHP Framework   (based on Rails)
NOT FOR PRODUCTION!
well, maybe for production
but really:

NOT FOR PRODUCTION!
Frameworks
ActionMailer
   ActionPack
  ActiveRecord
Ruby on Rails
ActiveResource
 ActiveSupport
    Railties
request => response
Sequel
   ActiveRecord
persistence layer
    DataMapper
        Og
ERB
     Liquid
    Amrita2
templating layer
     Erubis
    Markaby
      HAML
Ramaze
       Waves
   ActionPack
the middle layer
    Merb Core
     Sinatra
     Camping
ActionMailer
 Merb Helpers
   utilities
ActiveSupport
   Railties
Tools
Rack
Mack
   CGI
            Coset
  SCGI
          Camping
  LSWS
          Halcyon
Mongrel
          Maveric
WEBrick
          Sinatra
FastCGI
          Vintage
 Fuzed
           Ramaze
  Thin
            Waves
   Ebb
             Merb
mod_rack
Rack::Lint
    Rack::URLMap
   Rack::Deflater
 Rack::CommonLogger
   middlewares
Rack::ShowExceptions
   Rack::Reloader
    Rack::Static
     Rack::Cache
Rack::Request
     utility
Rack::Response
Other Layers
Sequel
   ActiveRecord
persistence layer
    DataMapper
        Og
ERB
     Liquid
    Amrita2
templating layer
     Erubis
    Markaby
      HAML
Start at the End
Vision
REST and Resources
fully-formed web applications
       built on resources
fully-formed        web applications
     built on resources
All I Need to Know I Learned by Writing My Own Web Framework
Birth of Athena
Dionysus
ask me after if you don’t get the joke
Project
Extraction   flickr: 95579828@N00
All I Need to Know I Learned by Writing My Own Web Framework
class Habit < Athena::Resource
  def get
    @habit = Habit.find(@id)
  end

  # ...
end


RouteMap = {
  :get => {
     //habit/new/ => {:resource => :habit, :template => :new},
     //habit/(d+)/ => {:resource => :habit},
     //habit/(d+)/edit/ => {:resource => :habit, :template => :edit}
  },
  :put => {
     //habit/(d+)/ => {:resource => :habit}
  },
  :delete => {
     //habit/(d+)/ => {:resource => :habit}
  },
  :post => {
     //habit// => {:resource => :habit}
  }
}
Results
All I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web Framework
puts quot;Starting Athena applicationquot;

require 'active_record'
require File.expand_path(File.join('./vendor/athena/lib/athena'))
puts quot;... Framework loadedquot;

Athena.require_all_libs_relative_to('resources')
puts quot;... Resources loadedquot;

use Rack::Static, :urls => ['/images', '/stylesheets'], :root => 'public'
run Athena::Application.new
puts quot;... Application startednnquot;

puts quot;^C to stop the applicationquot;
module Athena
  class Application
    def self.root
      File.join(File.dirname(__FILE__), '..', '..', '..', '..')
    end

    def self.route_map
      @route_map ||= {
        :get     => {},
        :post    => {},
        :put     => {},
        :delete => {}
      }
      @route_map
    end

    def call(environment)
      request = Rack::Request.new(environment)
      request_method = request.params['_method'] ? # ...

      matching_route = Athena::Application.route_map # ...

      if matching_route
        resource = matching_route.last[:class].new(request, request_method)
        resource.template = matching_route.last[:template]
        return resource.output
      else
        raise Athena::BadRequest
      end
    end
  end
end
module Athena
  class Resource
    extend Athena::Persistence
    attr_accessor :template

    def self.inherited(f)
      unless f == Athena::SingletonResource
        url_name = f.name.downcase
        routing = url_name + id_pattern
        url_pattern = /^/#{routing}$/

        Athena::Application.route_map[:get][/^/#{routing}/edit$/] = # ...
        Athena::Application.route_map[:post][/^/#{url_name}$/]     = # ...
        # ...
      end
    end

    def self.default_resource
      Athena::Application.route_map[:get][/^/$/] = {:class => # ...
    end

    def self.id_pattern
      '/(d+)'
    end

    def   get;      raise   Athena::MethodNotAllowed;   end
    def   put;      raise   Athena::MethodNotAllowed;   end
    def   post;     raise   Athena::MethodNotAllowed;   end
    def   delete;   raise   Athena::MethodNotAllowed;   end

    # ...
  end
end
class Habit < Athena::Resource
  persist(ActiveRecord::Base) do
    validates_presence_of :name
  end

  def get
    @habit = Habit.find_by_id(@id) || Habit.new_record
  end

  def post
    @habit = Habit.new_record(@params['habit'])
    @habit.save!
  end

  def put
    @habit = Habit.find(@id)
    @habit.update_attributes!(@params['habit'])
  end

  def delete
    Habit.find(@id).destroy
  end
end
class Habits < Athena::SingletonResource
  default_resource

  def get
    @habits = Habit.all
  end

  def post
    @results = @params['habits'].map do |hash|
      Habit.new_record(hash).save
    end
  end

  def put
    @results = @params['habits'].map do |id, hash|
      Habit.find(id).update_attributes(hash)
    end
  end

  def delete
    Habit.find(:all,
      :conditions => ['id IN (?)', @params['habit_ids']]
    ).map(&:destroy)
  end
end
module Athena
  module Persistence
    def self.included(base)
      base.class_eval do
        @@persistence_class = nil
      end
    end

    def persist(klass, &block)
      pklass = Class.new(klass)

     pklass.class_eval(&block)
     pklass.class_eval quot;set_table_name '#{self.name}'.tableizequot;
     eval quot;Persistent#{self.name} = pklassquot;

      @@persistence_class = pklass
      @@persistence_class.establish_connection(
        YAML::load(IO.read(File.join(Athena::Application.root, # ...
      )
    end

    def new_record(*args)
      self.persistence_class.new(*args)
    end

    def persistence_class
      @@persistence_class
    end

   # ...
Lessons About the Web
HTTP status codes   http://thoughtpad.net/alan-dean/http-headers-status.gif
207
Multi-Status
207
sucks
 Multi-Status
rack::cache
http://tomayko.com/src/rack-cache/
Lessons About Ruby
module Athena
    class Application
      # ...

      def process_params(params)
        nested_pattern = /^(.+?)[(.*])/
        processed = {}
        params.each do |k, v|
          if k =~ nested_pattern
            scanned = k.scan(nested_pattern).flatten
            first = scanned.first
            last = scanned.last.sub(/]/, '')
            if last == ''
              processed[first] ||= []
              processed[first] << v
            else
              processed[first] ||= {}
              processed[first][last] = v
              processed[first] = process_params(processed[first])
            end
          else
            processed[k] = v
          end
        end
        processed.delete('_method')
        processed
      end

      # ...
    end


Form Parameters
  end
module Athena
     module Persistence
       def self.included(base)
         base.class_eval do
           @@persistence_class = nil
         end
       end

       def persist(klass, &block)
         pklass = Class.new(klass)

        pklass.class_eval(&block)
        pklass.class_eval quot;set_table_name '#{self.name}'.tableizequot;
        eval quot;Persistent#{self.name} = pklassquot;

         @@persistence_class = pklass
         @@persistence_class.establish_connection(
           YAML::load(IO.read(File.join(Athena::Application.root, # ...
         )
       end

       def new_record(*args)
         self.persistence_class.new(*args)
       end

       def persistence_class
         @@persistence_class
       end

      # ...

Dynamic class creation
Tangled classes   flickr: randomurl
module Athena
     module Persistence
       # ...

       def method_missing(name, *args)
         return self.persistence_class.send(name, *args)
       rescue ActiveRecord::ActiveRecordError => e
         raise e
       rescue
         super
       end
     end
   end




Exception Propagation
this session has been a LIE
More to learn   flickr: glynnis
... always   flickr: mointrigue
http://github.com/bscofield/athena
           (under construction)
Thank you!
    Questions?

 Ben Scofield
 Development Director, Viget Labs

 http://www.viget.com/extend | http://www.culann.com
 ben.scofield@viget.com      | bscofield@gmail.com

More Related Content

What's hot

symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207patter
 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkJeremy Kendall
 
With a Mighty Hammer
With a Mighty HammerWith a Mighty Hammer
With a Mighty HammerBen Scofield
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Developmentjsmith92
 
And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...Codemotion
 
PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overviewjsmith92
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworksdiego_k
 
Using Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databasesUsing Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databasesRaimonds Simanovskis
 
And the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportAnd the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportBen Scofield
 
Scala ActiveRecord
Scala ActiveRecordScala ActiveRecord
Scala ActiveRecordscalaconfjp
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your AppLuca Mearelli
 
Django - 次の一歩 gumiStudy#3
Django - 次の一歩 gumiStudy#3Django - 次の一歩 gumiStudy#3
Django - 次の一歩 gumiStudy#3makoto tsuyuki
 
Let's write secure Drupal code! DUG Belgium - 08/08/2019
Let's write secure Drupal code! DUG Belgium - 08/08/2019Let's write secure Drupal code! DUG Belgium - 08/08/2019
Let's write secure Drupal code! DUG Belgium - 08/08/2019Balázs Tatár
 
More tips n tricks
More tips n tricksMore tips n tricks
More tips n tricksbcoca
 
Ansible leveraging 2.0
Ansible leveraging 2.0Ansible leveraging 2.0
Ansible leveraging 2.0bcoca
 
How to develop modern web application framework
How to develop modern web application frameworkHow to develop modern web application framework
How to develop modern web application frameworktechmemo
 
Let's write secure drupal code! - Drupal Camp Pannonia 2019
Let's write secure drupal code! - Drupal Camp Pannonia 2019Let's write secure drupal code! - Drupal Camp Pannonia 2019
Let's write secure drupal code! - Drupal Camp Pannonia 2019Balázs Tatár
 

What's hot (20)

Lithium Best
Lithium Best Lithium Best
Lithium Best
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro Framework
 
With a Mighty Hammer
With a Mighty HammerWith a Mighty Hammer
With a Mighty Hammer
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
 
And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...
 
PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overview
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
 
Using Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databasesUsing Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databases
 
And the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportAnd the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack Support
 
Scala ActiveRecord
Scala ActiveRecordScala ActiveRecord
Scala ActiveRecord
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your App
 
Django - 次の一歩 gumiStudy#3
Django - 次の一歩 gumiStudy#3Django - 次の一歩 gumiStudy#3
Django - 次の一歩 gumiStudy#3
 
Let's write secure Drupal code! DUG Belgium - 08/08/2019
Let's write secure Drupal code! DUG Belgium - 08/08/2019Let's write secure Drupal code! DUG Belgium - 08/08/2019
Let's write secure Drupal code! DUG Belgium - 08/08/2019
 
More tips n tricks
More tips n tricksMore tips n tricks
More tips n tricks
 
Ansible leveraging 2.0
Ansible leveraging 2.0Ansible leveraging 2.0
Ansible leveraging 2.0
 
Silex Cheat Sheet
Silex Cheat SheetSilex Cheat Sheet
Silex Cheat Sheet
 
How to develop modern web application framework
How to develop modern web application frameworkHow to develop modern web application framework
How to develop modern web application framework
 
Let's write secure drupal code! - Drupal Camp Pannonia 2019
Let's write secure drupal code! - Drupal Camp Pannonia 2019Let's write secure drupal code! - Drupal Camp Pannonia 2019
Let's write secure drupal code! - Drupal Camp Pannonia 2019
 

Similar to All I Need to Know I Learned by Writing My Own Web Framework

Integrating Flex And Rails With Ruby Amf
Integrating Flex And Rails With Ruby AmfIntegrating Flex And Rails With Ruby Amf
Integrating Flex And Rails With Ruby Amfrailsconf
 
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo EditionLithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo EditionNate Abele
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the FinishYehuda Katz
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
Adventurous Merb
Adventurous MerbAdventurous Merb
Adventurous MerbMatt Todd
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksNate Abele
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slidesharetomcopeland
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐいHisateru Tanaka
 
Great Developers Steal
Great Developers StealGreat Developers Steal
Great Developers StealBen Scofield
 
Ruby Isn't Just About Rails
Ruby Isn't Just About RailsRuby Isn't Just About Rails
Ruby Isn't Just About RailsAdam Wiggins
 
Hacking with ruby2ruby
Hacking with ruby2rubyHacking with ruby2ruby
Hacking with ruby2rubyMarc Chung
 
Practical PHP 5.3
Practical PHP 5.3Practical PHP 5.3
Practical PHP 5.3Nate Abele
 
JavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best PracticesJavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best PracticesSiarhei Barysiuk
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
 
Express Presentation
Express PresentationExpress Presentation
Express Presentationaaronheckmann
 
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011Nick Sieger
 

Similar to All I Need to Know I Learned by Writing My Own Web Framework (20)

Flex With Rubyamf
Flex With RubyamfFlex With Rubyamf
Flex With Rubyamf
 
Integrating Flex And Rails With Ruby Amf
Integrating Flex And Rails With Ruby AmfIntegrating Flex And Rails With Ruby Amf
Integrating Flex And Rails With Ruby Amf
 
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo EditionLithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
DataMapper
DataMapperDataMapper
DataMapper
 
Adventurous Merb
Adventurous MerbAdventurous Merb
Adventurous Merb
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate Frameworks
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
Great Developers Steal
Great Developers StealGreat Developers Steal
Great Developers Steal
 
Ruby Isn't Just About Rails
Ruby Isn't Just About RailsRuby Isn't Just About Rails
Ruby Isn't Just About Rails
 
Hacking with ruby2ruby
Hacking with ruby2rubyHacking with ruby2ruby
Hacking with ruby2ruby
 
Rails 4.0
Rails 4.0Rails 4.0
Rails 4.0
 
Practical PHP 5.3
Practical PHP 5.3Practical PHP 5.3
Practical PHP 5.3
 
JavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best PracticesJavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best Practices
 
Having Fun with Play
Having Fun with PlayHaving Fun with Play
Having Fun with Play
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
Express Presentation
Express PresentationExpress Presentation
Express Presentation
 
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
 

More from Ben Scofield

How to Be Awesome in 2.5 Steps
How to Be Awesome in 2.5 StepsHow to Be Awesome in 2.5 Steps
How to Be Awesome in 2.5 StepsBen Scofield
 
Building Cloud Castles - LRUG
Building Cloud Castles - LRUGBuilding Cloud Castles - LRUG
Building Cloud Castles - LRUGBen Scofield
 
Open Source: A Call to Arms
Open Source: A Call to ArmsOpen Source: A Call to Arms
Open Source: A Call to ArmsBen Scofield
 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud CastlesBen Scofield
 
Intentionality: Choice and Mastery
Intentionality: Choice and MasteryIntentionality: Choice and Mastery
Intentionality: Choice and MasteryBen Scofield
 
Mastery or Mediocrity
Mastery or MediocrityMastery or Mediocrity
Mastery or MediocrityBen Scofield
 
Mind Control - DevNation Atlanta
Mind Control - DevNation AtlantaMind Control - DevNation Atlanta
Mind Control - DevNation AtlantaBen Scofield
 
Understanding Mastery
Understanding MasteryUnderstanding Mastery
Understanding MasteryBen Scofield
 
Mind Control: Psychology for the Web
Mind Control: Psychology for the WebMind Control: Psychology for the Web
Mind Control: Psychology for the WebBen Scofield
 
The State of NoSQL
The State of NoSQLThe State of NoSQL
The State of NoSQLBen Scofield
 
NoSQL @ CodeMash 2010
NoSQL @ CodeMash 2010NoSQL @ CodeMash 2010
NoSQL @ CodeMash 2010Ben Scofield
 
NoSQL: Death to Relational Databases(?)
NoSQL: Death to Relational Databases(?)NoSQL: Death to Relational Databases(?)
NoSQL: Death to Relational Databases(?)Ben Scofield
 
Charlotte.rb - "Comics" Is Hard
Charlotte.rb - "Comics" Is HardCharlotte.rb - "Comics" Is Hard
Charlotte.rb - "Comics" Is HardBen Scofield
 
The Future of Data
The Future of DataThe Future of Data
The Future of DataBen Scofield
 
WindyCityRails - "Comics" Is Hard
WindyCityRails - "Comics" Is HardWindyCityRails - "Comics" Is Hard
WindyCityRails - "Comics" Is HardBen Scofield
 
"Comics" Is Hard: Alternative Databases
"Comics" Is Hard: Alternative Databases"Comics" Is Hard: Alternative Databases
"Comics" Is Hard: Alternative DatabasesBen Scofield
 
Mind Control on the Web
Mind Control on the WebMind Control on the Web
Mind Control on the WebBen Scofield
 
How the Geeks Inherited the Earth
How the Geeks Inherited the EarthHow the Geeks Inherited the Earth
How the Geeks Inherited the EarthBen Scofield
 

More from Ben Scofield (20)

How to Be Awesome in 2.5 Steps
How to Be Awesome in 2.5 StepsHow to Be Awesome in 2.5 Steps
How to Be Awesome in 2.5 Steps
 
Building Cloud Castles - LRUG
Building Cloud Castles - LRUGBuilding Cloud Castles - LRUG
Building Cloud Castles - LRUG
 
Thinking Small
Thinking SmallThinking Small
Thinking Small
 
Open Source: A Call to Arms
Open Source: A Call to ArmsOpen Source: A Call to Arms
Open Source: A Call to Arms
 
Ship It
Ship ItShip It
Ship It
 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud Castles
 
Intentionality: Choice and Mastery
Intentionality: Choice and MasteryIntentionality: Choice and Mastery
Intentionality: Choice and Mastery
 
Mastery or Mediocrity
Mastery or MediocrityMastery or Mediocrity
Mastery or Mediocrity
 
Mind Control - DevNation Atlanta
Mind Control - DevNation AtlantaMind Control - DevNation Atlanta
Mind Control - DevNation Atlanta
 
Understanding Mastery
Understanding MasteryUnderstanding Mastery
Understanding Mastery
 
Mind Control: Psychology for the Web
Mind Control: Psychology for the WebMind Control: Psychology for the Web
Mind Control: Psychology for the Web
 
The State of NoSQL
The State of NoSQLThe State of NoSQL
The State of NoSQL
 
NoSQL @ CodeMash 2010
NoSQL @ CodeMash 2010NoSQL @ CodeMash 2010
NoSQL @ CodeMash 2010
 
NoSQL: Death to Relational Databases(?)
NoSQL: Death to Relational Databases(?)NoSQL: Death to Relational Databases(?)
NoSQL: Death to Relational Databases(?)
 
Charlotte.rb - "Comics" Is Hard
Charlotte.rb - "Comics" Is HardCharlotte.rb - "Comics" Is Hard
Charlotte.rb - "Comics" Is Hard
 
The Future of Data
The Future of DataThe Future of Data
The Future of Data
 
WindyCityRails - "Comics" Is Hard
WindyCityRails - "Comics" Is HardWindyCityRails - "Comics" Is Hard
WindyCityRails - "Comics" Is Hard
 
"Comics" Is Hard: Alternative Databases
"Comics" Is Hard: Alternative Databases"Comics" Is Hard: Alternative Databases
"Comics" Is Hard: Alternative Databases
 
Mind Control on the Web
Mind Control on the WebMind Control on the Web
Mind Control on the Web
 
How the Geeks Inherited the Earth
How the Geeks Inherited the EarthHow the Geeks Inherited the Earth
How the Geeks Inherited the Earth
 

Recently uploaded

Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Adtran
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfDaniel Santiago Silva Capera
 
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDEADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDELiveplex
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfinfogdgmi
 
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesMd Hossain Ali
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8DianaGray10
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...DianaGray10
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?IES VE
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPathCommunity
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureEric D. Schabell
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IES VE
 
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfJamie (Taka) Wang
 
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsIgniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsSafe Software
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024D Cloud Solutions
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Commit University
 
VoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXVoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXTarek Kalaji
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-pyJamie (Taka) Wang
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesDavid Newbury
 

Recently uploaded (20)

Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
 
20150722 - AGV
20150722 - AGV20150722 - AGV
20150722 - AGV
 
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDEADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdf
 
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation Developers
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability Adventure
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
 
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
 
201610817 - edge part1
201610817 - edge part1201610817 - edge part1
201610817 - edge part1
 
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsIgniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
 
VoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXVoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBX
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-py
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond Ontologies
 

All I Need to Know I Learned by Writing My Own Web Framework

  • 1. All I Really Need to Know* I Learned by Writing My Own Web Framework Ben Scofield 7 November 2008 Rubyconf * about Ruby and the web
  • 4. DSLs DSL Intimidate and Frighten flickr: cwsteeds
  • 7. Rails your custom framework
  • 10. main() { printf(quot;hello, worldnquot;); } -module(hello). -export([hello/0]). hello() -> io:format(quot;Hello World!~nquot;, []). PROGRAM HELLO PRINT*, 'Hello World!' END
  • 11. main = putStrLn quot;Hello Worldquot; Imports System.Console Class HelloWorld Public Shared Sub Main() WriteLine(quot;Hello, world!quot;) End Sub End Class !greeting. +!greeting : true <- .print(quot;Hello Worldquot;).
  • 16. PHP Framework (based on Rails)
  • 18. well, maybe for production
  • 19. but really: NOT FOR PRODUCTION!
  • 21. ActionMailer ActionPack ActiveRecord Ruby on Rails ActiveResource ActiveSupport Railties
  • 23. Sequel ActiveRecord persistence layer DataMapper Og
  • 24. ERB Liquid Amrita2 templating layer Erubis Markaby HAML
  • 25. Ramaze Waves ActionPack the middle layer Merb Core Sinatra Camping
  • 26. ActionMailer Merb Helpers utilities ActiveSupport Railties
  • 27. Tools
  • 28. Rack
  • 29. Mack CGI Coset SCGI Camping LSWS Halcyon Mongrel Maveric WEBrick Sinatra FastCGI Vintage Fuzed Ramaze Thin Waves Ebb Merb
  • 31. Rack::Lint Rack::URLMap Rack::Deflater Rack::CommonLogger middlewares Rack::ShowExceptions Rack::Reloader Rack::Static Rack::Cache
  • 32. Rack::Request utility Rack::Response
  • 34. Sequel ActiveRecord persistence layer DataMapper Og
  • 35. ERB Liquid Amrita2 templating layer Erubis Markaby HAML
  • 39. fully-formed web applications built on resources
  • 40. fully-formed web applications built on resources
  • 43. Dionysus ask me after if you don’t get the joke
  • 45. Extraction flickr: 95579828@N00
  • 47. class Habit < Athena::Resource def get @habit = Habit.find(@id) end # ... end RouteMap = { :get => { //habit/new/ => {:resource => :habit, :template => :new}, //habit/(d+)/ => {:resource => :habit}, //habit/(d+)/edit/ => {:resource => :habit, :template => :edit} }, :put => { //habit/(d+)/ => {:resource => :habit} }, :delete => { //habit/(d+)/ => {:resource => :habit} }, :post => { //habit// => {:resource => :habit} } }
  • 51. puts quot;Starting Athena applicationquot; require 'active_record' require File.expand_path(File.join('./vendor/athena/lib/athena')) puts quot;... Framework loadedquot; Athena.require_all_libs_relative_to('resources') puts quot;... Resources loadedquot; use Rack::Static, :urls => ['/images', '/stylesheets'], :root => 'public' run Athena::Application.new puts quot;... Application startednnquot; puts quot;^C to stop the applicationquot;
  • 52. module Athena class Application def self.root File.join(File.dirname(__FILE__), '..', '..', '..', '..') end def self.route_map @route_map ||= { :get => {}, :post => {}, :put => {}, :delete => {} } @route_map end def call(environment) request = Rack::Request.new(environment) request_method = request.params['_method'] ? # ... matching_route = Athena::Application.route_map # ... if matching_route resource = matching_route.last[:class].new(request, request_method) resource.template = matching_route.last[:template] return resource.output else raise Athena::BadRequest end end end end
  • 53. module Athena class Resource extend Athena::Persistence attr_accessor :template def self.inherited(f) unless f == Athena::SingletonResource url_name = f.name.downcase routing = url_name + id_pattern url_pattern = /^/#{routing}$/ Athena::Application.route_map[:get][/^/#{routing}/edit$/] = # ... Athena::Application.route_map[:post][/^/#{url_name}$/] = # ... # ... end end def self.default_resource Athena::Application.route_map[:get][/^/$/] = {:class => # ... end def self.id_pattern '/(d+)' end def get; raise Athena::MethodNotAllowed; end def put; raise Athena::MethodNotAllowed; end def post; raise Athena::MethodNotAllowed; end def delete; raise Athena::MethodNotAllowed; end # ... end end
  • 54. class Habit < Athena::Resource persist(ActiveRecord::Base) do validates_presence_of :name end def get @habit = Habit.find_by_id(@id) || Habit.new_record end def post @habit = Habit.new_record(@params['habit']) @habit.save! end def put @habit = Habit.find(@id) @habit.update_attributes!(@params['habit']) end def delete Habit.find(@id).destroy end end
  • 55. class Habits < Athena::SingletonResource default_resource def get @habits = Habit.all end def post @results = @params['habits'].map do |hash| Habit.new_record(hash).save end end def put @results = @params['habits'].map do |id, hash| Habit.find(id).update_attributes(hash) end end def delete Habit.find(:all, :conditions => ['id IN (?)', @params['habit_ids']] ).map(&:destroy) end end
  • 56. module Athena module Persistence def self.included(base) base.class_eval do @@persistence_class = nil end end def persist(klass, &block) pklass = Class.new(klass) pklass.class_eval(&block) pklass.class_eval quot;set_table_name '#{self.name}'.tableizequot; eval quot;Persistent#{self.name} = pklassquot; @@persistence_class = pklass @@persistence_class.establish_connection( YAML::load(IO.read(File.join(Athena::Application.root, # ... ) end def new_record(*args) self.persistence_class.new(*args) end def persistence_class @@persistence_class end # ...
  • 58. HTTP status codes http://thoughtpad.net/alan-dean/http-headers-status.gif
  • 63. module Athena class Application # ... def process_params(params) nested_pattern = /^(.+?)[(.*])/ processed = {} params.each do |k, v| if k =~ nested_pattern scanned = k.scan(nested_pattern).flatten first = scanned.first last = scanned.last.sub(/]/, '') if last == '' processed[first] ||= [] processed[first] << v else processed[first] ||= {} processed[first][last] = v processed[first] = process_params(processed[first]) end else processed[k] = v end end processed.delete('_method') processed end # ... end Form Parameters end
  • 64. module Athena module Persistence def self.included(base) base.class_eval do @@persistence_class = nil end end def persist(klass, &block) pklass = Class.new(klass) pklass.class_eval(&block) pklass.class_eval quot;set_table_name '#{self.name}'.tableizequot; eval quot;Persistent#{self.name} = pklassquot; @@persistence_class = pklass @@persistence_class.establish_connection( YAML::load(IO.read(File.join(Athena::Application.root, # ... ) end def new_record(*args) self.persistence_class.new(*args) end def persistence_class @@persistence_class end # ... Dynamic class creation
  • 65. Tangled classes flickr: randomurl
  • 66. module Athena module Persistence # ... def method_missing(name, *args) return self.persistence_class.send(name, *args) rescue ActiveRecord::ActiveRecordError => e raise e rescue super end end end Exception Propagation
  • 67. this session has been a LIE
  • 68. More to learn flickr: glynnis
  • 69. ... always flickr: mointrigue
  • 70. http://github.com/bscofield/athena (under construction)
  • 71. Thank you! Questions? Ben Scofield Development Director, Viget Labs http://www.viget.com/extend | http://www.culann.com ben.scofield@viget.com | bscofield@gmail.com