Rails Sojourn: One Man's Journey - Wicked Good Ruby Conference 2013
-
Upload
mike-desjardins -
Category
Technology
-
view
2.237 -
download
0
description
Transcript of Rails Sojourn: One Man's Journey - Wicked Good Ruby Conference 2013
RAILS SOJOURN: ONE MAN’S
JOURNEYMike Desjardins
Monday, October 14, 13
HI, I’M MIKE!
I’M FROM PORTLAND
Monday, October 14, 13
NO, NOT THAT PORTLANDMonday, October 14, 13
THIS PORTLANDMonday, October 14, 13
CONFESSION
Monday, October 14, 13
OK MIKE, WE GET IT. YOU HAVE SELF ESTEEM ISSUES.
So what is this presentation about?
Monday, October 14, 13
So I’ve worked on some decently “big” Rails apps
Monday, October 14, 13
FAT MODELS
Monday, October 14, 13
MASSIVE CONTROLLERSMonday, October 14, 13
VIEWS WITH
(CONFUSING) LOGIC
IN THEM
Monday, October 14, 13
STUFF HAPPENS
Monday, October 14, 13
GOOD NEWS:This presentation isn’t a complain-fest about Rails
Monday, October 14, 13
I work here:
(we’re kinda awesome)Monday, October 14, 13
But I used to work here:
Monday, October 14, 13
(NEED A BULLPEN)
Monday, October 14, 13
INCUBATIONMONTH
Monday, October 14, 13
LIKE CHRISTMAS MORNING!
Monday, October 14, 13
WE SHOULD USE
THIS TIME TO EXPLORE!
Monday, October 14, 13
LET’S BUILD AN APP!It’ll be one of those
new-fangledsingle page whizz-
bang Javascript MVC thingies!
Monday, October 14, 13
WHAT TO DO?
Monday, October 14, 13
WHAT TO DO?
Monday, October 14, 13
WHAT TO DO?
Monday, October 14, 13
BACK END CRITERIA•Had to be Ruby•Building RESTful API•Had to be easily deployed•Want “lightweight”•Had to be actively developed•Couldn’t be Rails. Just ‘cuz.
Monday, October 14, 13
Monday, October 14, 13
FRONT END CRITERIA
•Active Development•Strategic choice for company•Well documented•Stable API
(Not gonna talk a whole lot about these)Monday, October 14, 13
FRONTEND
(Not gonna talk a whole lot about these)Monday, October 14, 13
ARCHITECTURE
User Application
Amazon SQS (Queueing Service)
Static Single-Page Javascript Front End
Happy User
Notifications
Client Gem
Worker Process
Worker Process
Collector
SQLDB
Collector
API ServerAPI Server
Monday, October 14, 13
FOCUS ON
CollectorCollector API ServerAPI Server
THE “RUBY” PARTS
Monday, October 14, 13
HMM...require 'sinatra'
get '/hi' do "Hello World!"end
$ ruby hi.rbMonday, October 14, 13
HMM...
$ lsapp.rb$
Monday, October 14, 13
Monday, October 14, 13
GOOD NEWS:This presentation isn’t a How-To
session on Sinatra
Monday, October 14, 13
SETTLED ON THISGemfileGemfile.lockProcfileREADME.mdRakefileapp.rbconfig/config.rulog/middlewares/routes/services/spec/templates/
Monday, October 14, 13
INIT.RB PATTERN
Monday, October 14, 13
CONFIG AND INITIALIZERS
Monday, October 14, 13
THIS SERVED US PRETTY WELL.
Monday, October 14, 13
ASIDE: MONKLearned about this project
after the fact.
Website down?
http://monkrb.comMonday, October 14, 13
WAIT, WHERE ARE THE MODELS?
Monday, October 14, 13
ORM
Monday, October 14, 13
ORMWe tried three different ones.
Models were in their own gem.
Monday, October 14, 13
DATAMAPPERRan into issues.
1.x kind of a ghost town.
Monday, October 14, 13
Monday, October 14, 13
OPEN SOURCE
Monday, October 14, 13
OPEN SOURCEYou can, you know, actually
read the source when you get stuck.
Monday, October 14, 13
ONE OF THE BIGGEST THINGS
I LEARNED!•I always had been intimidated by
complexity Rails’ source.
•Intimidated by size and talent of community.
•Hadn’t run into trouble with Rails, no need to look at the source.
Monday, October 14, 13
bundle open <gem name>
Monday, October 14, 13
DON’T BE AFRAID.
LESSON #1
Monday, October 14, 13
SEQUELWeird (concurrency?) problem we just couldn’t nail down.
Probably wasn’t Sequel, probably was us.Running out of time so...
Monday, October 14, 13
ACTIVERECORDWe swallowed our pride.
Monday, October 14, 13
PUTTING THE MODELS INTO
THEIR OWN GEM SAVED OUR
BACON.Monday, October 14, 13
ISOLATE YOUR APP FROM YOUR
LIBRARY CHOICES.
LESSON #2
Monday, October 14, 13
WHAT IS RACK?Monday, October 14, 13
“A Rack application is an Ruby object (not a class) that responds to call. It takes exactly one argument, the environment and returns an Array of exactly three values: The status, the headers, and the body.” - Rack API docs
Monday, October 14, 13
“A Rack application is an Ruby object (not a class) that responds to call. It takes exactly one argument, the environment and returns an Array of exactly three values: The status, the headers, and the body.” - Rack API docs
require 'rubygems'require 'rack'
class HelloWorld def call(env) [200, {"Content-‐Type" => "text/html"}, "Hello Rack!"] endend
Rack::Handler::Mongrel.run HelloWorld.new, :port => 9292
Monday, October 14, 13
MIDDLEWAREMonday, October 14, 13
SECURITYMonday, October 14, 13
• Rack::Attack - middleware to do whitelisting, blacklisting, throttling.
• Rack::Protection - middleware that handles a bunch of attack vectors (IP Spoofing, Path Traversal, Session Hijacking, others).
• Omniauth::Identity - User authentication
Monday, October 14, 13
SERIALIZATION
Monday, October 14, 13
SERIALIZATION
• achiu/rack-parser - I was surprised to learn that converting JSON docs to Rack parameters wasn’t automatic.
• HashWithIndifferentAccess - Don’t expect your parameter names to be symbolized for you.
Monday, October 14, 13
SESSION COOKIESRack::Session::Cookie
Monday, October 14, 13
WE EVEN WROTE OUR OWN
MIDDLEWARE!
HTTP status handling for common errors
Monday, October 14, 13
class ErrorMiddleware def initialize(app, options = {}) @app = app end def call(env) dup._call(env) end
def _call(env) @app.call env rescue Exception => e logger.error "-‐-‐-‐ rescued #{e.inspect} at #{Time.now} -‐-‐-‐" e.backtrace.each do |line| logger.error line end
handler = ExceptionHandler.new(e) Rack::Response.new(handler.body, handler.status, {}).finish endend
Monday, October 14, 13
ExceptionHandler.register( "CloudshineData::UniqueConstraintViolation" => { body: {errors: ["Already taken"]}.to_json, status: 422 })
ExceptionHandler.register( "CloudshineData::Unauthorized" => {status: 401, body: "Unauthorized"})
ExceptionHandler.register( "CloudshineData::RecordNotFound" => { body: {errors: ["Resource not found."]}.to_json, status: 404 })
ExceptionHandler.register("CloudshineData::ValidationFailed" => HandlerWithMessage)
ExceptionHandler.register("Cloudshine::MissingParameter" => HandlerWithMessage)
INITIALIZER
Monday, October 14, 13
class ExceptionHandler HANDLERS = {} attr_accessor :exception
def self.register(handler={}) HANDLERS.merge!(handler) end
def initialize(exception) @exception = exception @handler_map = HANDLERS @handler_map.default = {body: {errors: ["Server error"]}.to_json, status: 500} end
def handler return @handler if @handler logger.info "using #{handler_map[@exception.class.to_s]} to handle” logger.info " a #{@exception.class.to_s} exception." handler = handler_map[@exception.class.to_s] @handler = handler.is_a?(Class) ? handler.new(@exception) : OpenStruct.new(handler) end
def status; handler.status; end def body; handler.body; end
private attr_accessor :handler_mapend
Monday, October 14, 13
MIDDLEWARE IS EASY!
LESSON #3
Monday, October 14, 13
TOOLS
Monday, October 14, 13
ARCHITECTURE
User Application
Amazon SQS (Queueing Service)
Static Single-Page Javascript Front End
Happy User
Notifications
Client Gem
Worker Process
Worker Process
Collector
SQLDB
Collector
API ServerAPI Server
Monday, October 14, 13
CODE IS SPREAD OVER EIGHT
REPOSITORIES
Minimum of four separate applications just to run the system.
Monday, October 14, 13
VAGRANT
Monday, October 14, 13
VAGRANTStill doesn’t help w/ the nuisance of having to commit code into multiple places to make one feature change.
Monday, October 14, 13
VAGRANTIf I had to do it over again, I’d
probably keep one repo/app for the server-side components and deploy
it differently by task.Monday, October 14, 13
OTHER HANDY TOOLS
Monday, October 14, 13
RAILS CONSOLEMonday, October 14, 13
RAILS CONSOLEMissed it for a while.
Monday, October 14, 13
RAILS CONSOLEMissed it for a while.
Then I realized I could just make a silly setup script.
Monday, October 14, 13
RAILS CONSOLEMissed it for a while.
Then I realized I could just make a silly setup script.
It worked just as well and was a lot faster.
Monday, October 14, 13
SILLY SETUP SCRIPTrequire 'bundler'require 'active_record'require 'activeuuid'Bundler.require(:default,:development)ActiveRecord::Base.establish_connection( :adapter => 'mysql2', :database => 'cloudshine_dev', :username => 'root', :host => 'localhost')ActiveUUID::Patches.apply!
Monday, October 14, 13
RERUNMonday, October 14, 13
RERUN
Restarts your server for you when files change in your app’s directory.
Wouldn’t work with pokey old Rails but works great with Sinatra.
Monday, October 14, 13
CORS Issues
Cross Origin Resource Sharing
Monday, October 14, 13
User’s Browser Web Server
HTTP OPTIONS http://api.myapp.com/resource
Origin: http://www.myapp.com
PRE-F
LIGHT
Monday, October 14, 13
200 OK
Access-‐Control-‐Allow-‐Origin: http://www.myapp.com
User’s Browser Web Server
Monday, October 14, 13
HTTP GET http://api.myapp.com/resource
Origin: http://www.myapp.com
User’s Browser Web Server
Monday, October 14, 13
CORS SupportFirefox: 3.5+Chrome: 3+Safari: 4+
Opera: 12+IE: 10+
Monday, October 14, 13
CORS IssuesCan’t serve your singlepage app from file:// during development
Can’t go across ports without explicit
permission
Monday, October 14, 13
CORS Issues
Did all of this with (you guessed it) middleware!
github.com/cyu/rack-cors
Monday, October 14, 13
SUMMARY•Don’t be afraid to look at the source code
of your libraries.•Isolate your app from libraries•Middleware is easy!•There are lots of cool tools out there. Learn
about them.•Figure out your strategy for dealing w/
cross origin requests right away.
Monday, October 14, 13
SPENDING TIME AWAY FROM RAILS DE-MYSTIFIED IT FOR ME AND MADE ME
MORE COMFORTABLE WITH RUBY.
Monday, October 14, 13
SPENDING TIME AWAY FROM RAILS DE-MYSTIFIED IT FOR ME AND MADE ME
MORE COMFORTABLE WITH RUBY.
It was totally worth it.
Monday, October 14, 13
HOWEVER...
If I were starting all over again,I probably would just use
Rails API.
Monday, October 14, 13
Monday, October 14, 13
@mdesjardins
github.com/mdesjardins
Monday, October 14, 13
FIN.Monday, October 14, 13
PHOTO CREDITSLobster on Slide 2: Creative Commons © Man Pikin (http://www.flickr.com/photos/musicamang/)
Priest on Slide 3: © Anyka, Licensed from Fotolia.com, All Rights Reserved
Giant NES Controller on Slide 8: Creative Commons © Pop Culture Geek (http://www.flickr.com/photos/popculturegeek/)
Boston Construction Road Sign on Slide 9: Creative Commons © NNECAPA (http://www.flickr.com/photos/nnecapa/)
Bird Poop on Slide 10: Creative Commons © Chris Smith Ronnie Shumate “My Favorite Pet Sitter” (http://www.flickr.com/photos/myfavoritepetsitter/)
Fenway Bullpen on Slide 15: Creative Commons © BuzzFarmers “Red Sox Game at Fenway Park.” (http://www.flickr.com/photos/buzzfarmers/)
Alien Incubator on Slide 16: Creative Commons © Steve Jurvetson “alien incubator” (http://www.flickr.com/photos/jurvetson/)
Christmas Morning on Slide 17: Creative Commons © John Lemieux “Nikon Christmas” (http://www.flickr.com/photos/newdimensionfilms/)
Segway on Slide 42: Creative Commons © Wesley Fryer “Darth Vader on a segway in the Edmond 4th of July Parade” (http://www.flickr.com/photos/wfryer)
Bacon on Slide 49: Creative Commons © Shawn Zamecheck “Bacon” (http://www.flickr.com/photos/shawnzam/)
Rack of Lamb on Slide 51: Creative Commons © Waferboard “rack of lamb presentation II” (http://www.flickr.com/photos/waferboard/)
Rainbow Cake on Slide 54: Creative Commons © Janine and Jim Eden “Rainbow Cake” (http://www.flickr.com/photos/edenpictures/)
Security Cameras on Slide 55: Creative Commons © Jake Setlak “Security” (http://www.flickr.com/photos/pylbug/)
Cookies on Slide 59: Creative Commons © Jeramey Jannene “Cookies” (http://www.flickr.com/photos/compujeramey/)
Tool Chest on Slide 66: Creative Commons © El Cajon Yacht Club “tool chest” (http://www.flickr.com/photos/el_cajon_yacht_club/)
Console on Slide 73: Creative Commons © Cliff “Console, Countdown and Monitor“ (http://www.flickr.com/photos/nostri-imago/)
Apple Cores Slides 80-85: Creative Commons © Roger Karlsson “red apple core two days” (http://www.flickr.com/photos/free-photos/)
Mosaic 3.5” Floppy Slides 81-83: Creative Commons © Bill Rawlinson “plug-n-play-mosaic” (http://www.flickr.com/photos/thefinalcut/)
Mainframe Slides 81-83: Creative Commons © Don DeBold “NEC 2203 Mainframe Computer” (http://www.flickr.com/photos/ddebold/)
Creative Commons images licensed under the CC 2.0 Attribution License.
Monday, October 14, 13