The Enterprise Strikes Back

2,589 views

Published on

Mostly the same talk as my earlier version with the same title for SDEC11, but this one was updated a little bit for Prairie Dev Con in November 2011.

Published in: Technology, Art & Photos
1 Comment
1 Like
Statistics
Notes
No Downloads
Views
Total views
2,589
On SlideShare
0
From Embeds
0
Number of Embeds
186
Actions
Shares
0
Downloads
7
Comments
1
Likes
1
Embeds 0
No embeds

No notes for slide

The Enterprise Strikes Back

  1. 1. The Enterprise Strikes Back Burke Stefan Libbey PennerWednesday, 23 November, 11
  2. 2. Burke Stefan Libbey PennerWednesday, 23 November, 11
  3. 3. Burke Libbey Stefan Penner @burkelibbey @stefanpennerWednesday, 23 November, 11
  4. 4. Burke Libbey Stefan Penner @burkelibbey @stefanpennerWednesday, 23 November, 11
  5. 5. Burke Libbey Stefan Penner @burkelibbey @stefanpennerWednesday, 23 November, 11
  6. 6. Overview • Core concepts • Ruby on the JVM (and the CLR, sort of) • Data • Integration • Deployment • Sysadmin • The CloudWednesday, 23 November, 11
  7. 7. Ruby’s weaknesses • Poor performance • Type system sometimes causes headaches in large codebases • No compiler to catch certain bugs But your tests catch these, right?Wednesday, 23 November, 11
  8. 8. Why ruby is slow • Late method lookup • Lots of context tracking to allow for eval • Stop-the-world Mark & Sweep GC • Runtime modification of codeWednesday, 23 November, 11
  9. 9. Ruby’s strengths • Developing working code quickly • Reducing incidental complexity Especially when best practices are adhered to • Ease of developing powerful libraries and succinct DSLsWednesday, 23 November, 11
  10. 10. Uniform Access Principle All services o ered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation. - Bertrand MeyerWednesday, 23 November, 11
  11. 11. Two Rules • Everything is an object • Objects expose methods and only methodsWednesday, 23 November, 11
  12. 12. Wednesday, 23 November, 11
  13. 13. </background>Wednesday, 23 November, 11
  14. 14. Ruby Java + Productive + Not Scary - Scary - Less productiveWednesday, 23 November, 11
  15. 15. Ruby in Java + Not Scary + ProductiveWednesday, 23 November, 11
  16. 16. http://jruby.orgWednesday, 23 November, 11
  17. 17. • Full ruby implementation on the JVM • Access to both ruby and Java libraries • Can be deployed to existing Java infrastructureWednesday, 23 November, 11
  18. 18. The many flavours of ruby • MRI (and YARV) • JRuby • IronRuby • MacRuby • Rubinius • ...and several more...Wednesday, 23 November, 11
  19. 19. java.lang.System.out.println("Hello World")Wednesday, 23 November, 11
  20. 20. The Magic Sauce require java (contains up to 30% midichlorians)Wednesday, 23 November, 11
  21. 21. Calling Java from ruby f = javax.swing.JFrame.new f.getContentPane.add(javax.swing.JLabel.new("Hello World")) close_operation = javax.swing.JFrame::EXIT_ON_CLOSE f.setDefaultCloseOperation(close_operation) f.pack f.setVisible(true)Wednesday, 23 November, 11
  22. 22. Impedance Mismatch f = javax.swing.JFrame.new f.getContentPane.add(javax.swing.JLabel.new("Hello World")) close_operation = javax.swing.JFrame::EXIT_ON_CLOSE f.setDefaultCloseOperation(close_operation) f.pack f.setVisible(true) Let’s break this down.Wednesday, 23 November, 11
  23. 23. Impedance Mismatch “Getters” and “Setters” are non-idiomatic in ruby. f = javax.swing.JFrame.new f.getContentPane.add(javax.swing.JLabel.new("Hello World")) getContentPane close_operation = javax.swing.JFrame::EXIT_ON_CLOSE f.setDefaultCloseOperation(close_operation) f.pack f.setVisible(true) snake_case is generally preferred to CamelCaseWednesday, 23 November, 11
  24. 24. Impedance Mismatch JavaBean properties can be accessed like this: f = javax.swing.JFrame.new f.content_pane.add(javax.swing.JLabel.new("Hello World")) close_operation = javax.swing.JFrame::EXIT_ON_CLOSE f.setDefaultCloseOperation(close_operation) f.pack f.setVisible(true) (UA P in action!) “get” disappears, CamelCase changes to snake_caseWednesday, 23 November, 11
  25. 25. Impedance Mismatch “set” is replaced by “=” f = javax.swing.JFrame.new f.content_pane.add(javax.swing.JLabel.new("Hello World")) close_operation = javax.swing.JFrame::EXIT_ON_CLOSE f.default_close_operation = close_operation f.pack f.visible = true “setDefaultCloseOperation(x)” becomes “default_close_operation = x”Wednesday, 23 November, 11
  26. 26. Ugliness Abounds f = javax.swing. javax.swing.JFrame.new f.content_pane.add(javax.swing.JLabel.new("Hello World")) javax.swing. close_operation = javax.swing. javax.swing.JFrame::EXIT_ON_CLOSE f.default_close_operation = close_operation f.pack f.visible = true Namespaces everywhere!Wednesday, 23 November, 11
  27. 27. Ugliness Abounds java_import javax.swing.JFrame java_import javax.swing.JLabel f = JFrame.new f.content_pane.add(JLabel.new("Hello World")) JLabel.new close_operation = JFrame::EXIT_ON_CLOSE f.default_close_operation = close_operation f.pack f.visible = true java_import adds classes to a ruby contextWednesday, 23 November, 11
  28. 28. 100% Rubified™ java_import javax.swing.JFrame java_import javax.swing.JLabel JFrame.new.tap do |f| f.content_pane.add JLabel.new("Hello World") f.default_close_operation = JFrame::EXIT_ON_CLOSE f.pack f.visible = true endWednesday, 23 November, 11
  29. 29. Method Rubification™ • In general, CamelCase Java methods can optionally be transliterated to snake case.Wednesday, 23 November, 11
  30. 30. Method Rubification™ Java System.currentTimeMillis() Ruby System.current_time_millisWednesday, 23 November, 11
  31. 31. Seriously though, not actually trademarked. Method Rubification™ Java person.getName() Ruby person.nameWednesday, 23 November, 11
  32. 32. Someone should get on that. Method Rubification™ Java person.setAge(42) Ruby person.age = 42Wednesday, 23 November, 11
  33. 33. Method Rubification™ FALSE! TRUE! Java person.isJedi() Ruby person.jedi?Wednesday, 23 November, 11
  34. 34. Is ruby an acceptable Java? (http://bit.ly/pfNluA) • Most Java code can literally be written as ruby with few high-level changes. • A more relaxed type system and syntax often has productivity benefits.Wednesday, 23 November, 11
  35. 35. Exhibit A // interfaces = HashMap{ label => NetworkInterface } Java Collection c = interfaces.values(); Iterator itr = c.iterator(); while(itr.hasNext()) { NetworkInterface interface = itr.next(); if (interface.isLoopback()) { return interface.getDisplayName(); } } VS. # interfaces = {label => NetworkInterface} Ruby interfaces.values.find(&:loopback?).display_nameWednesday, 23 November, 11
  36. 36. Exhibit A // interfaces = HashMap{ label => NetworkInterface } Java Collection c = interfaces.values(); Iterator itr = c.iterator(); while(itr.hasNext()) { NetworkInterface interface = itr.next(); if (interface.isLoopback()) { return interface.getDisplayName(); } } VS. # interfaces = {label => NetworkInterface} Ruby interfaces.values.find(&:loopback?).display_name 1 2 345 67 Only 7 characters of syntactic support!Wednesday, 23 November, 11
  37. 37. “Are you suggesting I write all my Java in ruby?!” • Not really... • JRuby is much slower than Java (doesn’t matter as often as you’d think) • Ruby’s added expressiveness makes it easier to shoot yourself in the foot. (or, in fact, to lazily clone an infinite number of your feet every planck length between your gun and your target)Wednesday, 23 November, 11
  38. 38. “Are you suggesting I write all my Java in ruby?!” • ...but maybe sometimes. • One possibility: • Encode high-level logic in expressive and concise ruby code • Supporting code in fast, safe Java • Mix and match as appropriateWednesday, 23 November, 11
  39. 39. Ruby as Glue • Ruby is great for: • wiring existing codebases together • other miscellaneous tasksWednesday, 23 November, 11
  40. 40. Perl The original “Swiss Army Knife”Wednesday, 23 November, 11
  41. 41. Perl Pretty much mean the same thing. • “glue” • “duct tape” • “swiss army knife”Wednesday, 23 November, 11
  42. 42. Perl RubyWednesday, 23 November, 11
  43. 43. Subcategories of “Glue” • Wiring stu together • Sysadmin tasksWednesday, 23 November, 11
  44. 44. Wiring stu together • There’s a lot we could cover here, but:Wednesday, 23 November, 11
  45. 45. Nokogiri • An extremely user-friendly XML library • fast! (wraps libxml2)Wednesday, 23 November, 11
  46. 46. Nokogiri require open-uri require nokogiri html = open("http://slashdot.org").read doc = Nokogiri::XML(html) (doc/".story a").each do |link| puts "#{link.text} (#{link.attr(href)})" end # Britains Broadband Censors: a Bunch of Students (//yro.slashdot... # ...Wednesday, 23 November, 11
  47. 47. Don’t do this. (Nokogiri::XML(open("http://slashdot.org").read)/".story a").each{|a|puts "#{a.text} (#{a.attr("href")})"}Wednesday, 23 November, 11
  48. 48. Sysadmin with Ruby • Nice system APIs (quite similar to perl’s) • System provisioning libraries/DSLsWednesday, 23 November, 11
  49. 49. Provisioning systems • Puppet • Chef • VagrantWednesday, 23 November, 11
  50. 50. Puppet • Describe system, and puppet sets it up • Nontrivial, but the general idea is: • I want mysql • I want nginx < 0.8 • I want this cron job: “....” • Go. http://puppetlabs.com/Wednesday, 23 November, 11
  51. 51. Puppet class postgres-server { package { postgresql-server: ensure => latest } group { postgres: gid => 26 } user { postgres: comment => "PostgreSQL Server", uid => 26, gid => 26, home => "/var/lib/pgsql", shell => "/bin/bash" } service { postgresql: running => true, pattern => "/usr/bin/postmaster", require => package["postgresql-server"] } }Wednesday, 23 November, 11
  52. 52. Puppet • Fantastic for defining a reproducible production environmentWednesday, 23 November, 11
  53. 53. Chef • Same idea as puppet • Somewhat less powerful • Slightly more approachable to most ruby developers http://www.opscode.com/chef/Wednesday, 23 November, 11
  54. 54. Chef package "sudo" do action :upgrade end template "/etc/sudoers" do source "sudoers.erb" mode 0440 owner "root" group "root" variables( :sudoers_groups => node[authorization][sudo][groups], :sudoers_users => node[authorization][sudo][users], :passwordless => node[authorization][sudo][passwordless] ) endWednesday, 23 November, 11
  55. 55. Puppet Chef Configuration Language custom ruby Targeted at production production “Powerfulness” Lots Mostly lots Verdict Good Di erent Written in ruby rubyWednesday, 23 November, 11
  56. 56. Vagrant • Uses puppet and/or chef • End product is a virtual machine for development use • Consistent system for all developers, per projectWednesday, 23 November, 11
  57. 57. Vagrant • If you use puppet or chef, vagrant lets you test production locallyWednesday, 23 November, 11
  58. 58. Suggestions • As a non-ruby-dev: • Use puppet • Consider vagrantWednesday, 23 November, 11
  59. 59. Suggestions • As a ruby developer: • Consider chef and puppet, use whichever suits your taste and needs • Consider vagrantWednesday, 23 November, 11
  60. 60. DatabasesWednesday, 23 November, 11
  61. 61. In the Real World,Wednesday, 23 November, 11
  62. 62. In the Real World, We have DataWednesday, 23 November, 11
  63. 63. In the Real World, We have Data Which lives in DatabasesWednesday, 23 November, 11
  64. 64. Databases Are Always simpleWednesday, 23 November, 11
  65. 65. All our data is ALWAYS in the same DBMSWednesday, 23 November, 11
  66. 66. Reality CheckWednesday, 23 November, 11
  67. 67. Luckily We have ODBC + JDBCWednesday, 23 November, 11
  68. 68. Luckily We have ODBC + JDBC + RubyWednesday, 23 November, 11
  69. 69. Ruby Gives you Options • Active Record • Sequel • DataMapper • moreWednesday, 23 November, 11
  70. 70. Active Record Design pattern coined by Martin Fowler in “Patterns of enterprise application architecture”. Also, Ruby on Rails’s default ORM. • Lots of Power • Lots of Opinion • Might fight with you (for non-standard uses) https://github.com/rails/rails/tree/master/activerecordWednesday, 23 November, 11
  71. 71. Active Record Syntax (Raw) require active_record ActiveRecord::Base.establish_connection({ :adapter => mysql, :database => test_database, :username => tester, :password => test22 }) connection = ActiveRecord::Base.connection connection.tables > [users, products, ducks, oranges] users = [] connection.execute(SELECT * FROM users).each_hash do |user| users << user end users > .... array of users, each user as a hash. users.first > { :id => 1, :username => stefan, :password => is_super_secure }Wednesday, 23 November, 11
  72. 72. Active Record Syntax (ORM) require active_record ActiveRecord::Base.establish_connection({ :adapter => mysql, :database => test_database, :username => tester, :password => test22 }) # class <camel_case_singular_table_name> < ActiveRecord::Base class User < ActiveRecord::Base # if the tables name does not fit convention, it can be manually overridden. # table_name :users_table end User.first > #<User id: 2, :name => stefan, :password => is_super_secure > User.find(2) > #<User id: 2, :name => stefan, :password => is_super_secure > User.where(:name => stefan) > #<User id: 2, :name => stefan, :password => is_super_secure >Wednesday, 23 November, 11
  73. 73. Active Record Syntax (AREL) User.first > #<User id: 2, :name => stefan, :password => is_super_secure > User.find(2) > #<User id: 2, :name => stefan, :password => is_super_secure > User.where(:name => stefan) > #<User id: 2, :name => stefan, :password => is_super_secure > User.where(:name => stefan).order(id ASC) > #<User id: 2, :name => stefan, :password => is_super_secure >Wednesday, 23 November, 11
  74. 74. Sequel Elegant Full featured database toolkit for ruby. • Supports a ton of DBMS’s • DSL • ORM http://sequel.rubyforge.org/ Supports - ADO, Amalgalite, DataObjects, DB2, DBI, DO, Firebird, ibmdb, Informix, JDBC, MySQL, Mysql2, ODBC, OpenBase, Oracle, PostgreSQL, SQLite3, Swift, and tinytdsWednesday, 23 November, 11
  75. 75. require "sequel" Sequel Example # connect to an in-memory database DB = Sequel.sqlite # create an items table DB.create_table :items do primary_key :id String :name Float :price end # create a dataset from the items table items = DB[:items] # populate the table items.insert(:name => abc, :price => rand * 100) items.insert(:name => def, :price => rand * 100) items.insert(:name => ghi, :price => rand * 100) # print out the number of records puts "Item count: #{items.count}" # print out the average price puts "The average price is: #{items.avg(:price)}"Wednesday, 23 November, 11
  76. 76. Sequel ORM require "sequel" # connect to an in-memory database DB = Sequel.sqlite # create an items table DB.create_table :items do primary_key :id String :name Float :price end # create a dataset from the items table class Item < Sequel::Model(:items) # associations # validations end # populate the table Item.create(:name => abc, :price => rand * 100) Item.create(:name => def, :price => rand * 100) Item.create(:name => ghi, :price => rand * 100) # print out the number of records puts "Item count: #{Item.count}" # print out the average price puts "The average price is: #{Item.avg(:price)}"Wednesday, 23 November, 11
  77. 77. Sequel ORM + jRuby ready out of the boxWednesday, 23 November, 11
  78. 78. Sequel ORM + IRONRuby apparently works?Wednesday, 23 November, 11
  79. 79. Case Study (Access) • Access (top 2 solutions) • Solution 1 (Cross Platform) • jRuby • JDBC • HXTT’s driver (www.hxtt.com) • Sequel • Solution 2 (Windows Only) • Ruby • ADO via WIN32OLE • SequelWednesday, 23 November, 11
  80. 80. Case Study (Access)Wednesday, 23 November, 11
  81. 81. Case Study (Access) 1. Download jRuby http://jruby.org/Wednesday, 23 November, 11
  82. 82. Case Study (Access) 1. Download jRuby http://jruby.org/ 2. Install Sequel gem install SequelWednesday, 23 November, 11
  83. 83. Case Study (Access) 1. Download jRuby http://jruby.org/ 2. Install Sequel gem install Sequel 3. Download JDBC Access Driver http://www.hxtt.com/access.htmlWednesday, 23 November, 11
  84. 84. Case Study (Access) require rubygems require sequel require sequel/adapters/jdbc require sequel/jdbc_hxtt_adapter require ../Support/Access_JDBC40.jar root = File.expand_path "../../", __FILE__ path_to_db = root + "/Support/AccessThemeDemo.mdb" DB = Sequel.connect("jdbc:access:////#{path_to_db}") puts DB.tables class Notes < Sequel::Model(:Notes) end class ThemeImages < Sequel::Model(:tbl_ThemeImages) end class Users < Sequel::Model(:tbl_Users) endWednesday, 23 November, 11
  85. 85. ba-da-bingWednesday, 23 November, 11
  86. 86. But our new app and our old database have di erent system requirements.Wednesday, 23 November, 11
  87. 87. We Want IsolationWednesday, 23 November, 11
  88. 88. _ -Need We Want IsolationWednesday, 23 November, 11
  89. 89. Power by.. Sinatra Web DSL get /pictures do [picture1,picture2,picture2] end post /pictures {} put /pictures/:id {} delete /pictures/:id {} used at linkedIn http://engineering.linkedin.com/44/linkedin-app-end-end-jruby-frontier-and-voldemortWednesday, 23 November, 11
  90. 90. sooo... big deal?Wednesday, 23 November, 11
  91. 91. RestServer • any jdbc database into a restful json service • https://github.com/stefanpenner/restserverWednesday, 23 November, 11
  92. 92. Portability/Bundling • Warbler http://github.com/nicksieger/warbler • single jar/war file • compiled (if needed)Wednesday, 23 November, 11
  93. 93. it’s an app!Wednesday, 23 November, 11
  94. 94. Putting it all together (p1) ScreenShotr download: https://github.com/stefanpenner/screenshotr/zipball/master git@github.com:stefanpenner/screenshotrWednesday, 23 November, 11
  95. 95. Sorry, contrived example!Wednesday, 23 November, 11
  96. 96. anyways...Wednesday, 23 November, 11
  97. 97. Java Gives Us • Portability Ruby Gives Us • HappinessWednesday, 23 November, 11
  98. 98. ScreenShotr Normally Annoying re: Portability • screen capture • GUI but thx jRubyWednesday, 23 November, 11
  99. 99. Lets Shoot some Screens require java java_import java.awt.Robot java_import java.awt.Toolkit java_import java.awt.Rectangle java_import java.awt.Image java_import java.awt.image.BufferedImage java_import javax.imageio.ImageIO screenRect = Rectangle.new(Toolkit.default_toolkit.getScreenSize()) capture = Robot.new.createScreenCapture(screenRect) ImageIO.write(capture,jpg,java.io.File.new(some_tmp_file.jpg))Wednesday, 23 November, 11
  100. 100. Hold UPWednesday, 23 November, 11
  101. 101. Hold UP java_import ?Wednesday, 23 November, 11
  102. 102. Hold UP java_import ? why not require?Wednesday, 23 November, 11
  103. 103. Hold UP java_import ? why not require? requiring classes just makes them discoverable later.Wednesday, 23 November, 11
  104. 104. Hold UP java_import ? why not require? requiring classes just makes them discoverable later. why not import?Wednesday, 23 November, 11
  105. 105. Hold UP java_import ? why not require? requiring classes just makes them discoverable later. why not import? Rake defines importWednesday, 23 November, 11
  106. 106. Hold UP java_import ? why not require? requiring classes just makes them discoverable later. why not import? Rake defines import weird...Wednesday, 23 November, 11
  107. 107. And fill some clipboards require java java_import java.awt.Toolkit java_import javax.imageio.ImageIO ss = StringSelection.new(public_url) Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, nil)Wednesday, 23 November, 11
  108. 108. upload to server gem install rest-client require rubygems require rest-client RestClient.post(http://../resource, :file => File.new(path/to/file))Wednesday, 23 November, 11
  109. 109. upload to server gem install rest-client require rubygems require rest-client RestClient.post(http://../resource, :file => File.new(path/to/file))Wednesday, 23 November, 11
  110. 110. <Insert Segue Here>Wednesday, 23 November, 11
  111. 111. ...and Vice Versa • We’ve done a lot of calling Java from ruby. • The reverse is possible as well.Wednesday, 23 November, 11
  112. 112. ...and Vice Versa import org.jruby.embed.InvokeFailedException; import org.jruby.embed.ScriptingContainer; // ... ScriptingContainer container = new ScriptingContainer(); container.runScriptlet("puts "Thats no Moon""); http://en.wikipedia.org/wiki/JrubyWednesday, 23 November, 11
  113. 113. Testing Java with Ruby “i find your lack of tests disturbing.”Wednesday, 23 November, 11
  114. 114. Testing Java with Ruby • JtestR is wonderful • Includes most of ruby’s leading testing libraries • supports ant and maven • easy to add to a project • takes advantage of jruby/java bridgeWednesday, 23 November, 11
  115. 115. JtestR Installation • Download jarfile from jtestr.codehaus.org • Add to classpath • Add a task to maven/ant • Create tests in ./test or ./spec • Run taskWednesday, 23 November, 11
  116. 116. Example! import java.util.HashMap describe "An empty", HashMap do before :each do @hash_map = HashMap.new end it "accepts new entries" do @hash_map.put "foo", "bar" @hash_map.get("foo").should == "bar" end it "returns a keyset iterator that throws an exception on next" do proc do @hash_map.key_set.iterator.next end.should raise_error(java.util.NoSuchElementException) end endWednesday, 23 November, 11
  117. 117. BDD Any language • Cucumber • http://cukes.infoWednesday, 23 November, 11
  118. 118. “i saw a city in the clouds”Wednesday, 23 November, 11
  119. 119. MYTH: Ruby can’t scale.Wednesday, 23 November, 11
  120. 120. FACT: Ruby scales like a BOSSWednesday, 23 November, 11
  121. 121. FACT: Ruby scales like a BOSS (because it has to)Wednesday, 23 November, 11
  122. 122. Fog • “The Ruby Cloud Services Library” • Lets you upload to S3, provision instances in EC2, set DNS records in DNSimple... • ...and much more.Wednesday, 23 November, 11
  123. 123. Fog “ • Chewbacca-approved. whargarblbgarblgr-Wednesday, 23 November, 11 ” garblgragh
  124. 124. Fog “ • Chewbacca-approved. (chewbaccaproved?) whargarblbgarblgr-Wednesday, 23 November, 11 garblgragh ”
  125. 125. 2.5 imperial tons of providersWednesday, 23 November, 11
  126. 126. ( )eh. 2.5 imperial tons of H providersWednesday, 23 November, 11
  127. 127. Wednesday, 23 November, 11
  128. 128. Wednesday, 23 November, 11
  129. 129. Wednesday, 23 November, 11
  130. 130. Wednesday, 23 November, 11
  131. 131. Wednesday, 23 November, 11
  132. 132. Wednesday, 23 November, 11
  133. 133. Wednesday, 23 November, 11
  134. 134. Wednesday, 23 November, 11
  135. 135. Wednesday, 23 November, 11
  136. 136. Wednesday, 23 November, 11
  137. 137. Wednesday, 23 November, 11
  138. 138. Wednesday, 23 November, 11
  139. 139. Wednesday, 23 November, 11
  140. 140. Wednesday, 23 November, 11
  141. 141. Wednesday, 23 November, 11
  142. 142. Wednesday, 23 November, 11
  143. 143. Wednesday, 23 November, 11
  144. 144. Wednesday, 23 November, 11
  145. 145. Wednesday, 23 November, 11
  146. 146. Wednesday, 23 November, 11
  147. 147. Wednesday, 23 November, 11
  148. 148. Wednesday, 23 November, 11
  149. 149. Wednesday, 23 November, 11
  150. 150. Wednesday, 23 November, 11
  151. 151. Sinatra Example #config.ru require ./lib/screen_shotr/server run ScreenShotr::Server.newWednesday, 23 November, 11
  152. 152. require sinatra require fog require digest/sha1Wednesday, 23 November, 11
  153. 153. module ScreenShotr class Server < Sinatra::Base def storage #@storage ||= Fog::Storage.new({ # :provider => AWS, # :aws_access_key_id => ACCESS_KEY_ID, # :aws_secret_access_key => SECRET_ACCESS_KEY}) @storage ||= Fog::Storage.new({ :local_root => ~/fog, :provider => Local }) def directory storage.directories.find("data").first or storage.directories.create(:key => data ) end# snip ....Wednesday, 23 November, 11
  154. 154. get / do "hello, world!" endWednesday, 23 November, 11
  155. 155. post /picture/create do file = params[:file] data = file[:tempfile] #super secure filename filename = file[:filename] key = Digest::SHA1.hexdigest("super random seed"+Time.now.to_s) key << .jpg file = directory.files.create( :body => data.read, :key => key ) file.public_url or "http://0.0.0.0:9292/picture/#{key}" endWednesday, 23 November, 11
  156. 156. get /picture/:key do file = directory.files.get(params[:key]) send_file file.send(:path) endWednesday, 23 November, 11
  157. 157. rackupWednesday, 23 November, 11
  158. 158. and...Wednesday, 23 November, 11
  159. 159. Wednesday, 23 November, 11
  160. 160. Fog Storage: Kind of cool.Wednesday, 23 November, 11
  161. 161. Fog Compute: Wicked cool.Wednesday, 23 November, 11
  162. 162. Wednesday, 23 November, 11
  163. 163. Wednesday, 23 November, 11
  164. 164. Wednesday, 23 November, 11
  165. 165. Wednesday, 23 November, 11
  166. 166. Wednesday, 23 November, 11
  167. 167. Wednesday, 23 November, 11
  168. 168. Wednesday, 23 November, 11
  169. 169. Wednesday, 23 November, 11
  170. 170. Wednesday, 23 November, 11
  171. 171. Wednesday, 23 November, 11
  172. 172. Heroku Classic Stack (run rack/rails) Cedar Stack (run “anything”)Wednesday, 23 November, 11
  173. 173. Heroku Classic Stack (run rack/rails) $ heroku create Created sushi.herokuapp.com | git@heroku.com:sushi.git $ git push heroku master -----> Heroku receiving push -----> Rails app detected -----> Compiled slug size is 8.0MB -----> Launching... done, v1 http://sushi.herokuapp.com deployed to HerokuWednesday, 23 November, 11
  174. 174. Heroku Cedar Stack (run “anything”) $ cat Procfile web: bundle exec rails server -p $PORT worker: bundle exec rake resque:work QUEUE=* urgentworker: bundle exec rake resque:work QUEUE=urgent clock: bundle exec clockwork clock.rb $ heroku scale web=4 worker=2 urgentworker=1 clock=1 Scaling processes... done “O cially Everything”: Ruby, Node.js,Clojure, Java, Python, and ScalaWednesday, 23 November, 11
  175. 175. Recap • Core concepts • Ruby on the JVM (and the CLR, sort of) • Data • Integration • Deployment • Sysadmin • The CloudWednesday, 23 November, 11
  176. 176. “help me ruby... you’re my only hope!”Wednesday, 23 November, 11
  177. 177. “good... the force is strong with you. Thanks! a powerful rubyist youWednesday, 23 November, 11 will become.”

×