Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Web Applications With Rails (not Ruby)

Web Applications With Rails (not Ruby)

Slides from my Arrrrcamp 2013 talk.

0f9c9bbecc4067b9bce445cb11ed5d53?s=128

David Padilla

October 03, 2013
Tweet

Transcript

  1. None
  2. None
  3. Web Applications with Ruby David Padilla @dabit

  4. None
  5. Image from: ezilon.com

  6. Image from: ezilon.com

  7. None
  8. Manzanillo, Mexico

  9. June 4 - 6 2014

  10. Web applications with Ruby (not Rails)

  11. I invented MVC on ASP Classic

  12. Not really

  13. <% set conn=Server.CreateObject("ADODB.Connection") conn.Open "northwind" %> <html> <head> <title>Super App</title>

    <link href="style.css" /> </head> <body> <h1>Page 1</h1> <% ' Some code here that connects to the DB and ' displays stuff %> </body> </html> page1.asp
  14. <% set conn=Server.CreateObject("ADODB.Connection") conn.Open "northwind" %> <html> <head> <title>Super App</title>

    <link href="style.css" /> </head> <body> <h1>Another Page</h1> <% ' Some code here that connects to the DB and ' displays stuff %> </body> </html> AnotherPage.asp
  15. Index.asp <!--#include file="database.asp"--> <html> <head> <title>Super App</title> <link href="style.css" />

    </head> <body> <% page = Request.QueryString("page") Select Case page Case "page1" %> <!--#include file="page1.asp"--><% Case "AnotherPage" %> <!--#include file="AnotherPage.asp"--><% End Select %> </body> </html>
  16. 2000

  17. None
  18. MVC

  19. None
  20. http://therantygirl.files.wordpress.com/2012/07/happy-cat.jpg

  21. Mid Programmer Life Crisis

  22. Programming Web applications with Rails is BORING

  23. Building websites with Rails is not programming

  24. None
  25. None
  26. None
  27. None
  28. Most of us don’t know what’s going on outside of

    Rails
  29. We used to have all these problems

  30. We used to actually write SQL

  31. Bring programming back

  32. I invented rhp

  33. <% $greeting = "Hello World" %> <% require "includes/stylesheets.rb" %>

    <html> <head> <title>RHP Rocks!</title> <%= Stylesheets.render() %> </head> <body> <h1><%= $greeting %></h1> <p>RHP is a widely-used general-purpose scripting language that is especially suited for Web development and can be embedded into HTML. If you are new to RHP and want to get some idea of how it works, try the introductory tutorial. After that, check out the online manual.</p> </body> </html> cgi/index.erb
  34. <% $greeting = "Hello World" %> <% require "includes/stylesheets.rb" %>

    <html> <head> <title>RHP Rocks!</title> <%= Stylesheets.render() %> </head> <body> <h1><%= $greeting %></h1> <p>RHP is a widely-used general-purpose scripting language that is especially suited for Web development and can be embedded into HTML. If you are new to RHP and want to get some idea of how it works, try the introductory tutorial. After that, check out the online manual.</p> </body> </html>
  35. None
  36. I invented rhp (not really)

  37. None
  38. Rack is cool as Bowties

  39. Web applications with Ruby (not Rails)

  40. Rack

  41. Web Server Web Application A hash with request headers that

    we call ENV
  42. Web Server Web Application A hash with request headers that

    we call ENV respond_to(:call)
  43. Web Server Web Application A hash with request headers that

    we call ENV
  44. [http_code, headers, body] Integer Hash Responds to :each

  45. Web Server Web Application [http_code, headers, body]

  46. run -> (env) { puts env [200, {}, []] }

    config.ru
  47. None
  48. None
  49. run -> (env) { puts env [200, {}, []] }

    config.ru
  50. config.ru run -> (env) { [200, headers, [body]] } body

    = "<html><body><h1>Hello World</h1></body><html>" headers = { "Content-Length" => body.length.to_s }
  51. None
  52. None
  53. config.ru run -> (env) { [200, headers, [body]] } body

    = "<html><body><h1>Hello World</h1></body><html>" headers = { "Content-Length" => body.length.to_s }
  54. None
  55. Router

  56. /posts PostController #index

  57. config.ru run -> (env) { [200, headers, [body]] } body

    = "<html><body><h1>Hello World</h1></body><html>" headers = { "Content-Length" => body.length.to_s }
  58. config.ru $: << '.' require 'app' run App.new

  59. app.rb class App def call(env) body = "<html><body><h1>Hello World</h1></body><html>" headers

    = { "Content-Length" => body.length.to_s } [200, headers, [body]] end end
  60. controllers/root_controller.rb class RootController def show body = "<html><body><h1>Hello World</h1></body><html>" headers

    = { "Content-Length" => body.length.to_s } [200, headers, [body]] end end
  61. app.rb class App def call(env) body = "<html><body><h1>Hello World</h1></body><html>" headers

    = { "Content-Length" => body.length.to_s } [200, headers, [body]] end end RootController.new.show end end
  62. None
  63. app.rb class App def call(env) RootController.new.show end end

  64. app.rb class App def call(env) path = env["REQUEST_PATH"] case path

    when %r{^/$} RootController.new.show else [404, { "Content-Length" => "9"}, ["Not found"]] end end end
  65. app.rb class App def call(env) path = env["REQUEST_PATH"] case path

    when %r{^/$} RootController.new.show else [404, { "Content-Length" => "9"}, ["Not found"]] end end end
  66. None
  67. None
  68. None
  69. controllers/root_controller.rb class RootController def show body = "<html><body><h1>Hello World</h1></body><html>" headers

    = { "Content-Length" => body.length.to_s } [200, headers, [body]] end end
  70. None
  71. config.ru $: << '.' require 'app' require 'controllers/root_controller' run App.new

    require 'haml'
  72. views/root/show.html.haml %html %body %h1 Hello World

  73. controllers/root_controller.rb class RootController def show body = "<html><body><h1>Hello World</h1></body><html>" headers

    = { "Content-Length" => body.length.to_s } [200, headers, [body]] end end
  74. controllers/root_controller.rb class RootController # ... end def render(view_path) template =

    File.open(view_path, 'r').read Haml::Engine.new(template).render end
  75. controllers/root_controller.rb class RootController def show headers = { "Content-Length" =>

    body.length.to_s } [200, headers, [body]] end def render # ... end end body = render('views/root/show.html.haml') body = "<html><body><h1>Hello World</h1></body><html>"
  76. None
  77. views/root/show.html.haml %html %body %h1 Hello World

  78. views/layout/application.html.haml %html %body = yield

  79. controllers/root_controller.rb class RootController def render(view_path) template = File.open(view_path, 'r').read Haml::Engine.new(template).render

    end def render_with_layout(view_path) layout = File.open('views/layout/application.html.haml', 'r').re Haml::Engine.new(layout).render do render(view_path) end end end end
  80. def render_with_layout(view_path) layout = File.open #... Haml::Engine.new(layout).render do render(view_path) end

    end
  81. controllers/root_controller.rb class RootController def show headers = { "Content-Length" =>

    body.length.to_s } [200, headers, [body]] end def render # ... end end body = render('views/root/show.html.haml') body = render_with_layout('views/root/show.html.haml')
  82. None
  83. controllers/root_controller.rb class RootController def show body = render_with_layout('views/root/show.html.haml') headers =

    { "Content-Length" => body.length.to_s } [200, headers, [body]] end def render(view_path) template = File.open(view_path, 'r').read Haml::Engine.new(template).render end def render_with_layout(view_path) layout = File.open('views/layout/application.html.haml', 'r').re Haml::Engine.new(layout).render do render(view_path) end end end class RootController < Controller def show body = render_with_layout('views/root/show.html.haml') headers = { "Content-Length" => body.length.to_s } [200, headers, [body]] end end
  84. config.ru $: << '.' require 'app' require 'controllers/root_controller' run App.new

    require 'haml' require 'controller'
  85. controller.rb class Controller def render(view_path) template = load_template_file(view_path) Haml::Engine.new(template).render end

    def render_with_layout(view_path) layout_template = load_template_file(layout) Haml::Engine.new(layout_template).render do render_template(view_path) end end end
  86. views/root/show.html.haml %h1 Hello World %h1 Hello #{@name}

  87. controller.rb class Controller end attr_accessor :env def initialize(env) self.env =

    env end def params Rack::Utils.parse_nested_query(env["QUERY_STRING"]) end
  88. app.rb class App def call(env) path = env["REQUEST_PATH"] case path

    when %r{^/$} RootController.new(env).show else [404, { "Content-Length" => "9"}, ["Not found"]] end end end
  89. @available_on_the_view = true binding = self HAML::Engine.new(template).render(binding)

  90. controller.rb class Controller def render(view_path) template = load_template_file(view_path) Haml::Engine.new(template).render end

    def render_with_layout(view_path) layout_template = load_template_file('... ') Haml::Engine.new(layout_template).render do render(view_path) end end end class Controller def render(view_path, context = self) template = load_template_file(view_path) Haml::Engine.new(template).render(context) end def render_with_layout(view_path, context = self) layout_template = load_template_file('... ') Haml::Engine.new(layout_template).render(context) do render(view_path, context) end end end `
  91. controllers/root_controller.rb class RootController < Controller def show body = render_with_layout('views/root/show.html.haml')

    headers = { "Content-Length" => body.length.to_s } [200, headers, [body]] end end @name = params["name"] || "World"
  92. None
  93. None
  94. None
  95. Models

  96. ActiveRecord::Base

  97. require 'active_record' class User < ActiveRecord::Base #... end model/user.rb

  98. Sequel

  99. model/user.rb require 'sequel' DB = Sequel.sqlite class User def self.all

    DB[:users].to_a end end
  100. pg mysql

  101. model/user.rb require 'pg' DB = PG.connect( dbname: 'test', host: 'localhost')

    class User def self.all result = DB.exec "SELECT * FROM users" fields = result.fields result.collect do |row| hash = {} row.each_with_index do |value, i| hash[fields[i]] = value end end end end
  102. Once last piece of advice

  103. Don’t actually do this

  104. None
  105. None
  106. Logging Caching Database Pooling Cookies Sessions

  107. Read code

  108. Try to understand how things work

  109. You should start writing your own framework!

  110. <3 Rails Core Team

  111. github.com/dabit/wawr

  112. Disclaimer: I do NOT actually think that writing web applications

    with Rails is boring
  113. @dabit david@crowdint.com Thank You!