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

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    7 Favorites

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

    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
    2. DSLs DSL Intimidate and Frighten flickr: cwsteeds
    3. Rails
    4. Rails your custom framework
    5. Starter Projects
    6. Hello World
    7. main() { printf(\"hello, world\\n\"); } -module(hello). -export([hello/0]). hello() -> io:format(\"Hello World!~n\", []). PROGRAM HELLO PRINT*, 'Hello World!' END
    8. main = putStrLn \"Hello World\" Imports System.Console Class HelloWorld Public Shared Sub Main() WriteLine(\"Hello, world!\") End Sub End Class !greeting. +!greeting : true <- .print(\"Hello World\").
    9. Applications
    10. To-do lists
    11. DIY Blog
    12. Frameworks?
    13. PHP Framework (based on Rails)
    14. NOT FOR PRODUCTION!
    15. well, maybe for production
    16. but really: NOT FOR PRODUCTION!
    17. Frameworks
    18. ActionMailer ActionPack ActiveRecord Ruby on Rails ActiveResource ActiveSupport Railties
    19. request => response
    20. Sequel ActiveRecord persistence layer DataMapper Og
    21. ERB Liquid Amrita2 templating layer Erubis Markaby HAML
    22. Ramaze Waves ActionPack the middle layer Merb Core Sinatra Camping
    23. ActionMailer Merb Helpers utilities ActiveSupport Railties
    24. Tools
    25. Rack
    26. Mack CGI Coset SCGI Camping LSWS Halcyon Mongrel Maveric WEBrick Sinatra FastCGI Vintage Fuzed Ramaze Thin Waves Ebb Merb
    27. mod_rack
    28. Rack::Lint Rack::URLMap Rack::Deflater Rack::CommonLogger middlewares Rack::ShowExceptions Rack::Reloader Rack::Static Rack::Cache
    29. Rack::Request utility Rack::Response
    30. Other Layers
    31. Sequel ActiveRecord persistence layer DataMapper Og
    32. ERB Liquid Amrita2 templating layer Erubis Markaby HAML
    33. Start at the End
    34. Vision
    35. REST and Resources
    36. fully-formed web applications built on resources
    37. fully-formed web applications built on resources
    38. Birth of Athena
    39. Dionysus ask me after if you don’t get the joke
    40. Project
    41. Extraction flickr: 95579828@N00
    42. 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} } }
    43. Results
    44. puts \"Starting Athena application\" require 'active_record' require File.expand_path(File.join('./vendor/athena/lib/athena')) puts \"... Framework loaded\" Athena.require_all_libs_relative_to('resources') puts \"... Resources loaded\" use Rack::Static, :urls => ['/images', '/stylesheets'], :root => 'public' run Athena::Application.new puts \"... Application started\\n\\n\" puts \"^C to stop the application\"
    45. 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
    46. 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
    47. 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
    48. 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
    49. 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 \"set_table_name '#{self.name}'.tableize\" eval \"Persistent#{self.name} = pklass\" @@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 # ...
    50. Lessons About the Web
    51. HTTP status codes http://thoughtpad.net/alan-dean/http-headers-status.gif
    52. 207 Multi-Status
    53. 207 sucks Multi-Status
    54. rack::cache http://tomayko.com/src/rack-cache/
    55. Lessons About Ruby
    56. 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
    57. 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 \"set_table_name '#{self.name}'.tableize\" eval \"Persistent#{self.name} = pklass\" @@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
    58. Tangled classes flickr: randomurl
    59. 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
    60. this session has been a LIE
    61. More to learn flickr: glynnis
    62. ... always flickr: mointrigue
    63. http://github.com/bscofield/athena (under construction)
    64. 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

    + Ben ScofieldBen Scofield, 2 years ago

    custom

    2556 views, 7 favs, 1 embeds more stats

    Slides from session at Rubyconf 2008

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 2556
      • 2463 on SlideShare
      • 93 from embeds
    • Comments 0
    • Favorites 7
    • Downloads 73
    Most viewed embeds
    • 93 views on http://www.culann.com

    more

    All embeds
    • 93 views on http://www.culann.com

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories