An Introduction to Ruby on Rails
This is a presentation. If you'd like to view all the slides like a normal web page, you can.
Ruby on Rails? What's That?
- "highly opinionated" web application framework written in Ruby
- full-featured MVC, complete with development environment
- as much a philosophy for development as a framework
Ruby on Rails' Strengths
- Easy to get started with, easy to get something done enough to launch
- Easy to re-factor and replace weak code with stronger
- Development speed and philosophy lend themselves to agile development methodologies
Weaknesses
- Some confusion about scale and the "right" architecture for Rails apps
- Lots of people using Rails for the "wrong" thing.
- Can be hard to debug memory and performance issues
- Speed of new features/fixes/best practices can make it hard to keep up, especially in a behemoth like AOL.
- Lots of FUD in other communities about Rails' weaknesses, can be hard to separate myth from reality and past from present.
When (and not) to Use Rails
- When:
- You need the power of MVC, but want to Get Things Done™ quickly
- You want unit tests, a sane and flexible environment and help to do the Right Thing™
- You like being a part of a very active and passionate development community
- You can start with a clean slate database-wise
- But Not When:
- You don't need an MVC or framework, especially if you don't need a database
- You need to get lots of data from lots of different sources for each request
- You're constrained by a legacy database and can't change anything
Some Companies Running Rails
The Ruby in Rails
- Everything is an object
- You can do things like:
15.times do
- Or: "Bob Denver".downcase
- Real support for mix-ins, which makes patching and plugging in new features a snap
- It makes for very compact, expressive and human-readable code.
Demo Time!
- If you have OS X Leopard, you already have Rails (surprise!)
- Before doing anything, you'll need to run: sudo gem update
- On Windows, check out InstantRails
- Lots of tutorials for the different flavors of *nix.
Creating a Rails App
rails name_of_your_rails_app
cd name_of_your_rails_app
- Run
script/server and then go to http://localhost:3000
- Ooh and Ahh.
Creating a Model
script/generate model Entry
- Open up db/migrate/001_create_entries.rb
- Add some columns (see mine)
- Run
rake db:migrate
- Hey look, we have a table!
Playing With Your Model
script/console
entry = Entry.new
entry.title = "My First Blog Entry"
entry.body = "Hey, look, it's a blog entry!"
entry.save!
The Faster Way to Create
entry = Entry.create(
:title => "My Second Blog Entry",
:body => "Wow, that's pretty awesome!"
)
Let's Make It Look Like Something!
- Create a new HTML document and save it to app/views/layouts/blog.html.erb
- script/generate controller entries index show
- Open app/controllers/entries_controller.rb
- Create a new line above "def index" and add:
- On a new line under
def index, add:
@entries = Entry.find(:all,:order => "created_at DESC",:limit => 10)
Looking Good!
- Now, open app/views/entries/index.html.erb
- run
script/server
- visit http://localhost:3000/entries
- Ta-da!
Not Interesting Enough? Let's Add Comments!
script/generate model Comment
- open db/migrate/002_create_comments.rb
- Let's add some columns
rake db:migrate
Associations
- Open app/models/entry.rb
- Create a new line under line 1 and add:
- Open app/models/comment.rb and under line 1, add:
Let's Test It Out!
- Run
script/console
entry = Entry.find(1)
entry.comments
- I guess we don't have any... so, let's create one!
entry.comments.create(:email => "someone@somewhere.com",:url => "http://somewhere.com",:body => "Awesome blog post!")
- Now, let's see what entry.comments is...
Let's Display Them
- Open app/controllers/entries_controller.rb
- Inside "def show", add:
@entry = Entry.find(params['id'],:include => 'comments')
@page_title = @entry.title
- Open app/views/entries/show.html.erb
- Oops! We forgot to get commenters' names!
Database Versioning!
script/generate migration add_name_to_comments
- Open db/migrate/003_add_name_to_comments.rb
- Inside self.up, add:
add_column :comments, :name, :string
- Run
rake db:migrate
- Now we can go display things!
Back to views
- Make sure script/server is running
- Go to http://localhost:3000/entries/show/1
- Ta-da!
That's it!
- There are more associations, unit tests, validations and others, but that's enough for one brown bag.
- I left out almost all data validations and we didn't do any tests.
Things I've Learned
- The console is your friend.
- Fat models and skinny controllers are the best.
- Get someone "honest" to write your tests.
- Think about result set size.
- Speed makes up for a myriad of sins
The Scale Myth
...languages don't scale, architectures do
Scale is Inside
- Rails will scale if you do it right, just like anything else
- Time to market is more important than scale to begin with anyway, so just get it out there and scale when you have to.
- Cache everything you can to protect the hard-to-scale bits of your app (database, disk, etc)
- Don't return unbounded associations!
- For example, back in our controller...
Unbounded Associations
- In app/controllers/entries_controller.rb, show method:
- Entry.find(params['id'],:include => "comments")
- What if that entry has 10,000 comments?
- Create model methods with count limits, and page through.
- Let's fix it...
Model Methods
- Open app/models/entry.rb
- After has_many :comments, add a new method:
def limited_comments(count=10,offset=0)
self.comments.find(
:all,
:limit => count,
:offset => offset
)
end
Let's Try It!
- First, we need to create at least 15 comments (this'll take some time)... or not!
- In script/console
entry = Entry.find(1)
15.times {|i| entry.comments.create(:name => "Me!",:body => "I am comment #{i}!")}
Ch-ch-changes
- In app/controllers/entries_controller.rb, show becomes:
def show
@entry = Entry.find(params['id'])
@page_title = @entry.title
offset = params[:offset] || 0
@comments = @entry.limited_comments(10,offset)
end
Changing the Show
- Which means we need to change app/views/entries/show.html.erb
- Anywhere we see @entry.comments, we change it to @comments
Cache It!
- Protect your database by caching everything you can!
- Don't use disk-based caching in large deployments - because you'll have lots of instances and lots of disks.
- Cache items as atomically as possible.
- Separate cache deletion methods between object and partials (just remember this, it will make sense later)
- Check out the cache_fu plugin
- Memcached is the coolest thing ever.
Be Careful Who You Trust
- There are literally hundreds of Rails plugins out there. Be sure to check the code, and ask around before choosing a plugin for "serious" stuff (like database replication).
- Make sure any tutorials you follow are up to date.
Be Flexible
- The fix-rate in Rails-land is fast and furious. I don't recommend living on Edge Rails, but stay open to rewrites.
- If you decide you have to monkey-patch Rails, keep it small and remember that it's there so future versions don't bite you.
- It should never take you so long to write a single feature that you feel bad about discarding it and starting over!
- Rails feels a lot more like art than code - sketch, form, re-form, tweak and mold.
- And that's Ruby... learn and follow The Ruby Way. Don't write Ruby like you'd write PHP - it will suck.
Keep 'em Separated
- If you have a problematic part of your app, keep it separate! You can run it on separate mongrels, which will give you time to troubleshoot and isolate the problem.
- Mongrel behind Apache with mod_proxy_balancer gives you a lot of flexibility. Use it.
Speed Makes Up For Everything
- On AIM Photos, we were able to completely rewrite how we did things in an afternoon, test it, and repeat until we got it right.
- Developer time is expensive. The faster they can get things done, the better.
- Developer morale is more expensive. If they're not having fun and feeling productive, they'll work much slower.
- At its core, Rails is fun to work with.
An 'Incredible' Quote
In my experience, the thing that has the most significant impact on a movie's budget __ but never shows up in a budget __ is morale. If you have low morale, for every $1 you spend, you get about 25 cents of value. If you have high morale, for every $1 you spend, you get about $3 of value. Companies should pay much more attention to morale.
Brad Bird
The Future
- JRuby looks promising
- Life after Mongrel
- Rails' little brothers