ruby on rails - ghost libraryrails! ruby is an excellent language for view logic (succinct,...
TRANSCRIPT
Ruby on RailsRuby on RailsPresentation to Agile Atlanta GroupPresentation to Agile Atlanta GroupOriginally presented May 10 ‘05Originally presented May 10 ‘05
Obie FernandezAgile Atlanta Founder /
ThoughtWorks Technologist
IntroductionIntroduction
Why present Ruby on Rails to Agile Atlanta?
1. Ruby is an agile language
2. Ruby on Rails is Ruby’s Killer App
3. Ruby on Rails promotes agile practices
Presentation AgendaPresentation Agenda
Brief overview of Ruby
Rails Demonstration
Description of Rails framework
Questions and Answers
Why Ruby?Why Ruby?
Write more understandable code in less lines
Free (Very open license)
Extensible
Principles of RubyPrinciples of Ruby
Japanese Design Aesthetics Shine Through
Focus on human factors
Principle of Least Surprise
Principle of Succinctness
Relevant because these principles were followed closely by the designer of Rails, David H. Hansson
Scandinavian Design Aesthetic
The Principle of Least SurpriseThe Principle of Least Surprise
This principle is the supreme design goal of Ruby
Makes programmers happy and makes Ruby easy to learn
Examples
What class is an object?o.class
Is it Array#size or Array#length?same method – they’re aliased
What are the differences between arrays?diff = ary1 – ary2union = ary1 + ary2
Principle of SuccinctnessPrinciple of Succinctness
A.K.A. Principle of Least Effort
We don’t like to waste timeEspecially on XML config files, getters, setters, etc…
The quicker we program, the more we accomplishSounds reasonable enough, right?
Less code means less bugs
Ruby is Truly Object-OrientedRuby is Truly Object-Oriented
All classes derived from Object including Class (like Java) but there are no primitives (not like Java at all)
Ruby uses single-inheritance
Mixins give you the power of multiple inheritancewithout the headaches
Modules allow addition of behaviors to a class
Reflection is built in along with lots of other highly dynamic metadata features
Things like ‘=‘ and ‘+’ that you might think are operators are actually methods (like Smalltalk)
Some Coding ConventionsSome Coding Conventions
Method Chainingprint array.uniq.sort.reverse
Method Names include ! and ?ary.sort! (discuss bang if there is time)
Iterators and Blocks vs. Loopsfiles.each { |file| process(file) }
Case usage: Class names begin with a Capital letter
Constants are ALL_CAPS
Everything else - method call or a local variable
Under_score instead of camelCase
Dynamic ProgrammingDynamic Programming
Duck TypingBased on signatures, not class inheritance
Dynamic DispatchA key concept of OOP: methods are actually messages that are sent to an object instance
Dynamic Behavior Reflection
Scope Reopening (Kind of like AOP)
Eval
Breakpoint debugger
Enough About Ruby!Enough About Ruby!
What about Ruby on Rails?
Rails in a Nutshell Rails in a Nutshell
Includes everything needed to create database-driven web applications according to the Model-View-Control pattern of separation.
Mostly written by David H. Hannson
Talented designer
Dream is to change the world
A 37signals.com principal – World class designers
Over 100 additional contributors to the Rails codebase in 9 months!
The Obligatory Architecture SlideThe Obligatory Architecture Slide
DemoDemo
Todo List Tutorial Projectby Vincent Foley http://manuals.rubyonrails.com/read/book/7
Model – View – Controller Model – View – Controller
Model classes are the "smart" domain objects (such as Account, Product, Person, Post) that hold business logic and know how to persist themselves to a database
Views are HTML templates
Controllers handle incoming requests (such as Save New Account, Update Product, Show Post) by manipulating the model and directing data to the view
Model ClassesModel Classes
Based on Martin Fowler’s ActiveRecord pattern
From Patterns of Enterprise Architecture
An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.
ActiveRecordActiveRecord
Convention over Configuration (Applies to all of Rails)
No XML files!
Lots of reflection and run-time extension
Magic is not inherently a bad word
Admit the Database
Lets you drop down to SQL for odd cases and performance
Doesn‘t attempt to duplicate or replace data definitions
ActiveRecord APIActiveRecord API
Object/Relational Mapping Framework
Automatic mapping between columns and class attributes
Declarative configuration via macros
Dynamic finders
Associations, Aggregations, Tree and List Behaviors
Locking
Lifecycle Callbacks
Single-table inheritance supported
Eager fetching supported
Validation rules
More…
ActiveRecord AggregationsActiveRecord Aggregations
Aggregation expresses a composed of relationship
Define value objects by using composed_of method Tells Rails how value objects are created from the attributes of
the entity object when the entity is initialized and…
how it can be turned back into attributes when the entity is saved to the database
Adds a reader and writer method for manipulating a value object
Value objects should be immutable and that requirement is enforced by Active Record by freezing any object assigned as a value object.
Attempting to change value objects result in a TypeError
ActiveRecord ModelsActiveRecord Models are Multi-talented are Multi-talented actorsactors
The ActiveRecord::Acts module has super cool features that enhance your models behavior
acts_as_list
Provides the capabilities for sorting and reordering a number of objects in list
acts_as_tree
Model a tree structure by providing a parent association and a children association
acts_as_nested_set
Similiar to Tree, but with the added feature that you can select the children and all of it’s descendants with a single query!
ActiveRecord AssociationsActiveRecord Associations
Macro-like class methods for tying objects together through foreign keys
Each adds a number of methods to the class
Works much the same way as Ruby’s own attr* methods
ActiveRecord TimestampsActiveRecord Timestamps
Magic timestamps!
ActiveRecord objects will automatically record creation and/or update timestamps of database objects if columns with the names created_at / created_on or updated_at / updated_on are present in your db table
ActiveRecord TransactionsActiveRecord Transactions
Simple declarative transaction support on both object and database level# Just database transaction # Just database transaction Account.transaction doAccount.transaction do david.withdrawal(100)david.withdrawal(100) mary.deposit(100) mary.deposit(100) end end
# Object transaction# Object transactionAccount.transaction(david, mary) do Account.transaction(david, mary) do david.withdrawal(100)david.withdrawal(100) mary.deposit(100) mary.deposit(100) end end
ActiveRecord vs HibernateActiveRecord vs Hibernate
Instead of
ActiveRecord lets you do
Rails LoggingRails Logging
ActionController APIActionController API
Controllers defined as classes that execute and then either render a template or redirects
An action is a public method on the controller
Getting data in and out of controllers
Request parameters available in the @params hash (and can be multidimensional)
Web session exposed as @session hash
Cookies exposed as @cookies hash
Redirect scope provided by @flash hash (unique to Rails)
Filters and Request InterceptionFilters and Request Interception
The simple way to add Pre and Post processing to actions
Access to the request, response, and instance variables set by other filters or the action
Controller inheritance hierarchies share filters downwards, but subclasses can also add new filters
Target specific actions with :only and :except options
Flexible Filter definition
method reference (by symbol)
external class
inline method (proc)
From Controller to ViewFrom Controller to View
Rails gives you many rendering options…
Default template rendering – follow naming conventions and magic happens
Explicitly render to particular action
Redirect to another action
Render a string response (or no response)
View Template ApproachesView Template Approaches
ERB – Embedded Ruby
Similar to JSPs <% and <%= syntax
Easy to learn and teach to designers
Execute in scope of controller
Denoted with .rhtml extension
XmlMarkup – Programmatic View Construction
Great for writing xhtml and xml content
Denoted with .rxml extension
Embeddable in ERB templates
ERB ExampleERB Example
XmlMarkup ExampleXmlMarkup Example
Similar to JSP is a Good Thing?Similar to JSP is a Good Thing?
Aren’t Rails programmers going to be tempted to put a bunch of application logic in the templates?
The short answer is no.
JSPs are a less painful way to add logic to a screen. Due to the lower pain associated with their use, it is very tempting to add inappropriate code to them
That’s simply not the case with Rails!
Ruby is an excellent language for view logic (succinct, readable) and Rails is also made out of all Ruby. So there's no longing for a better suited template language and there's no pain relief in misappropriating business logic into the view.
- David H. Hansson
Layouts and PartialsLayouts and Partials
Templates in app/views/layouts/ with the same name as a controller will be automatically set as that controller’s layout unless explicitly told otherwise
Partials are sub-templates that render a single object
Partial template files follow convention
Easy API support for rendering collections of partials.
Built-in CachingBuilt-in Caching
Enhance performance by keeping the result of calculations, renderings, and database calls around for subsequent requests
Action Controller offers 3 levels of granularity
Page
Action
Fragment
Sweepers are responsible for expiring caches when model objects change
Page CachingPage Caching
Entire action output of is stored as a HTML file that the web server can serve
As much as 100 times faster than going the process of dynamically generating the content
Only available to stateless pages where all visitors are treated the same
Easy to implement…
Action CachingAction Caching
Entire output of the response is cached
Every request still goes to the controller
filters are run before the cache is served
allows for authentication and other restrictions on whether someone are supposed to see the cache
Fragment CachingFragment Caching
Caches parts of templates without caching the entire action
Use when elements of an action change frequently and other parts rarely change or are okay to share among requests
Four options for storage
1. FileStore – Fragments shared on file system by all processes
2. MemoryStore – Caches fragments in memory per process
3. DrbStore – Fragments cached on a separate, shared process
4. MemCachedStore – Uses Danga’s MemCached open source caching server
PaginationPagination
Macro-style automatic fetching of your model for multiple views, or explicit fetching for single actions
Included for all controllers
Configure as much or as little as desired
PaginationHelper module has methods for generating pagination links in your template
Helper ModulesHelper Modules
Help you spend time writing meaningful code… ActiveRecordHelper
AssetTagHelper
DateHelper
DebugHelper
FormHelper(s)
JavascriptHelper
NumberHelper
PaginationHelper
TagHelper
TextHelper
UrlHelper
Helper Methods ExamplesHelper Methods Examples
DateHelper::distance_of_time_in_words
Reports the approximate distance in time between to Time objects. For example, if the distance is 47 minutes, it'll return "about 1 hour“
JavascriptHelper::link_to_remote
AJAX in one line! Creates link to a remote action that’s called in the background using XMLHttpRequest. The result of that request can then be inserted into the browser’s DOM
JavascriptHelper::periodically_call_remote
More AJAX! Links page to a remote action that’s called in the background using XMLHttpRequest. The result of that request can be inserted into the browser’s DOM
NumberHelper::human_size, number_to_currency, number_to_phone, etc…
You get the picture!
The Quest for The Quest for Pretty URLsPretty URLs
The responsibility of URL parsing is handled by Rails itself. Why?
Not all webservers support rewriting
Allows Rails to function “out of the box” on almost all webservers
Facilitates definition of custom URLs
Linked to URL helper methods such as url_for, link_to, and redirect_to
Routing rules defined in config/routes.rb
routes.rbroutes.rbActionController::Routing::Routes.draw do |map|
# Priority based on creation: first created -> highest priority # Keep in mind you can assign values other than :controller and :action
# You can have the root of your site routed by hooking up '' # just remember to delete public/index.html. map.connect '', :controller => "bakery"
map.connect 'query/:guid', :controller => “global", :action=>"query"
# Allow downloading Web Service WSDL as a file with an extension map.connect ':controller/service.wsdl', :action => 'wsdl'
map.connect ':controller/:action/:id’ # Default
end
Rails to the RescueRails to the Rescue
Actions that fail to perform as expected throw exceptions
Exceptions can either be rescued…
for public view (with a nice user-friendly explanation)
for developers view (with tons of debugging information)
By default, requests from localhost get developers view
ActiveSupport APIActiveSupport API
Rails utility methods
Date conversion
Number handling
String conversions and inflection
Time calculations
ActionMailer APIActionMailer API
Rails’ built-in email service
Write email controllers in same way as web controllers
Integrated with templating system
ActionWebService APIActionWebService API
It’s easy to do web services in Rails Rails has built-in support for SOAP and XML-RPC
Struct base class can be used to represent structured types that don’t have ActiveRecord implementations or to avoid exposing an entire model to callers
Examples
Define a web services client in one line
Add a web service to a controller (next slide)
Defining a WebServiceDefining a WebService
FixturesFixtures
Use YAML sample data for testing Each YAML fixture (ie. record) is given a name and is followed by an
indented list of key/value pairs in the "key: value" format.
Records are separated by a blank line
Unit TestingUnit Testing
Rails includes Ruby’s test/unit
Rake pre-configured to run test suite or individual tests
Easy to load fixtures into a test case
RakeRake Ruby’s Build System
Familiar to Ant users
Your build file is a written in Ruby
Basic build script provided with Rails project
Rails Success StoryRails Success Story
Basecamp (info as of late April ’05)
Average lines of code for an action in Basecamp is 5
Written in 9 months
Tens of thousands of users
300k dynamic page renders/day
Hosted on two app servers with 15 fastcgi processes each + one MySQL server
The Rails CommunityThe Rails Community
The developer community around Rails is very helpful and excited
Rails Wiki - http://wiki.rubyonrails.com/
Rails Mailing List – very active
IRC – Get instant answers to most questions. David and other Rails commiters are all regularly present