Keeping Rails on the Tracks Mikel Lindsaar @raasdnil lindsaar.net
Working in Rails & Ruby for 5+ Years http://lindsaar.net/ http://stillalive.com/ http://rubyx.com/
On the Rails? What do I mean by on the rails? Apps that work and are easy to maintain & bug free
Experience helped write, rewrite, support or review 40 production rails last 12 months released a non trivial gem - mail maintained a non trivial gem - tmail made many patches to Rails itself, in the top 20 committers
Working Code? This is the one end of the pragmatic scale Devs that are paid to make it work take the green light, red light approach too far. Is it running? Yes, therefore it is working - leads to messy code
Sexy Code? This is the other end of the pragmatic scale Devs that get upset if something doesn t look right or is not super neat Time wasters on large scale projects Sexy code is nice to have, but often a waste of money
Maintainable Code? This is probably the middle ground Code that works Code that is neat and tidy, but not sacrificing budget for that Code that can be maintained
A Product is Only a Product if it is Exchanged This is pretty critical to all Rails developers.
Budget Matters Beautiful code is ugly if no one buys it
Trade-Offs are Life Decide how much refactoring needed based on code use Touched once a year, or once a month. Refactor the latter
You are not selling code You are selling a solution Running app are what counts Internal or External client doesn t matter
Deployment is a First Class Citizen This has been said by many people - not the first Need to be able to deploy - make it a trivial and repeatable one liner
Server Setup Use Chef / Puppet / whatever Repeatable Configuration Much easier to run a chef recipe that you know will work at 3am than remember how to install postgres
Use Bundler Removes Deployment Pain Be explicit with versions Only lock to git repos you own Not specifying versions in the Gemfile leads to future pain At least limit using the ~> control Lock to your own github fork, and at least specify branch or sha1 Never lock to open versions Edge rails in bundler, seriously!?
Repeatable Deployment Get the staging server up Use common deployment methods capistrano, or ey deploy, or heroku git deploy
Make a db/seeds.rb file Make it easy for other Developers The other developer may be you! In 6 months you will have no idea what you need to get it working
Link in Security Don t store passwords in the app Use some other data store
Using app Gem
Document It Update that README file! Should be able to open the readme and deploy your app Include authorisation needed (ssh keys on server or whatever)
Fast Page == Happy Client
Page Load Times Count Combine Javascript and CSS CSS Sprites Asset Pipelining in Rails 3.1 Before combination: 40 asset requests After combination: 5 asset requests Trivial in Rails 3.1 Rails 3 and lower, Jammit and other tools
Caching Optimisation Know and love Rails view caching: Fragment Cache Action Cache Page Cache Before fragment cache: 2480ms After fragment caching: 120ms
Big Session == Slow Site Session objects are a slippery slope to pain Store values, not objects 10k session record 5,000 new sessions per month 500mb session table in DB
Pick Your Fights Don t make a persisted session cart for every visitor 500,000 rows in sessions table Removed sessions for non customers Appdex went from 10% => 98% row session database store... no fun. File system is just asking for trouble - not scalable If follow previous two advices then overhead is minimal and very scalable
Opinions Matter
Use Pluralization Breaks conventions - hard to code and remember Simple fix using inflectors
Use the idioms
Less code written == less bugs Remove Useless Code
Being Smart can be Stupid
Explicit Methods Don t use before, after and around filters for object instantiation Filters are for state modification Valid uses of filters: timezones, authorization, authentication et al. Reasons: filters inherit, easy to get lost. Use explicit helpers
Keep Tests Simple Computers are good at nesting Humans less so We need to see context, as close to content as possible
Use Helpers Instead before & after should only maintain the test environment Keep tests wet Don t use before and after for app related activities
Hard to read Especially 2 pages down, where you can t see the before block
Easy to Read Easy to read no matter where you are in the test, also less context switching
Simple is better than Complex What you leave out is almost more important than what you put in Meta Programming has its place, that place is probably not in your Rails App Long writing methods better than dynamic if you can get away with it Meta programming has it s place, that place is not
Good Code is Easy to Read Good code might be non trivial to implement But should be trivial to understand. The more bad code you have, the closer you are to a rewrite
Reinvention is Over Rated
Reinventing Controllers Becomes code smell because you need to relearn simple idioms
Reinventing Controllers
Use the right tool for the job
Cucumber is not Unit Testing Making cucumber specs that should be unit tests
You too can refactor 5 level nested ternary INSIDE A STRING - 343 characters, one line Good t-shirt print
You too can refactor
Read Ruby Docs Go and read the standard Ruby documentation online Array, String, Hash, Ennumerator
Databases have feelings too
You don t need database agnostic code Make use of your database features Out of 50 apps, one is migrating DB Use migrations Good for development and testing Bad for production, get into the SQL and make the DB sing
Instantiation is Slow Report run in ruby: 45 minutes Equivalent SQL query: 15 seconds Object instantiation is slow
Use the DB tools you have Migrate legacy data with Active Record: 150 hours PostgreSQL COPY with generated CSV: 74 mins
Don t Share the DB 12 rails apps against one BIG database 12 places for migration files Refactor to API calls and CAS for auth
Code has responsibilities
Beware the Train Wreck Trivial example, but valid, train wrecks also can blow up your database
Control flow is code smell DEMO (control_flow_demo.rb) 85 line 10 if else statement method You can ALWAYS refactor control flow into object messages Cleaner code, easier to read Again, be pragmatic, and pick your fights
How to stay on track? What do I mean by on the rails? Apps that work and are easy to maintain & bug free
Get an Inspection Many consultancies do this Ask for a sample rubyx Inspect Service rubyx.com/services/inspect
Maintainable Code This is probably the middle ground Code that works Code that is neat and tidy, but not sacrificing budget for that Code that can be maintained
Questions? Mikel Lindsaar @raasdnil rubyx.com rubyx.com/services/inspect speakerrate.com/talks/7575