What Is Ruby on Rails
Pages: 1, 2, 3, 4, 5, 6, 7
Callbacks
As Active Record creates and destroys model objects and creates and updates them in the database, you can monitor these events in the object's life cycle using callbacks. You can use callbacks to handle complex business logic, modify data before Rails writes it to the database (or after Rails reads it from the database), or just about anything else you like.
For example, the save method that saves a model object's data to the database has eight callbacks defined:
before_validation
before_validation_on_create
after_validation
after_validation_on_create
before_save
before_create
after_create
after_save
This gives you fine-grained control over your model objects when you need it.
class CreditCard < ActiveRecord::Base
# Strip everything but digits, so the user can specify "555 234 34" or
# "5552-3434" or both will mean "55523434"
def before_validation_on_create
self.number = number.gsub(/[^0-9]/, "") if attribute_present?("number")
end
end
class Subscription < ActiveRecord::Base
before_create :record_signup
private
def record_signup
self.signed_up_on = Date.today
end
end
class Firm < ActiveRecord::Base
# Destroys the associated clients and people when the firm is destroyed
before_destroy { |record| Person.destroy_all "firm_id = #{record.id}" }
before_destroy { |record| Client.destroy_all "client_of = #{record.id}" }
end
The ActiveRecord::Callbacks documentation covers callbacks.
Transactions
A transaction is necessary when you have multiple database operations that all must succeed before the data in the database can change. If any one of them fails, the data in database should not change. Use transaction blocks to ensure this.
transaction do
david.withdrawal(100)
mary.deposit(100)
end
The database-level transaction shown above will prevent the withdrawal from David's account if the deposit into Mary's account should fail. It will not, however, protect the david
and mary
objects from being modified. To do that, you must use object-level transactions.
Account.transaction(david, mary) do
david.withdrawal(100)
mary.deposit(100)
end
Any failure in this code will roll back the value of the objects as well as the database.
The ActiveRecords::Transactions documentation explains more.
Much, much more
There is a lot more to Active Record than I can cover here. To learn more, consult the Active Record API.
Action Pack
Action Pack implements both the view and controller part of Rails.
View templates
View templates specify the HTML to return in response to a browser request. View templates are rhtml files (HTML with embedded Ruby) that are very similar to ASP or JSP files. Text within <% %>
is Ruby code to execute, and text within <%= %>
is also Ruby code to execute and substitute the results back into the HTML.
<html>
<head>
<title>Invoices for <%= @name
%></title>
</head>
<body>
<% render_partial "invoices_by_customer"
%>
</body>
</html>
By default, Rails will try to find a template whose name matches the currently executing action. If, for example, Rails executes an edit
action in your InvoiceController
, then it will attempt to find and render the view template .../app/views/invoices/edit.rhtml.
You can also build up XML (or HTML) output programmatically in your controller action. This is useful, for example, for building RSS feeds or responding to XML-RPC requests. In the following example, xm
is an XmlMarkup object.
xm.em("emphasized") # => <em>emphasized</em>
xm.em { xmm.b("emp & bold") } # => <em><b>emph & bold</b></em>
xm.a("A Link", "href"=>"http://onestepback.org") # => <a href="http://onestepback.org">A
Link</a>
xm.div { br } # => <div><br/></div>
xm.target("name"=>"compile", "option"=>"fast")
# => <target option="fast" name="compile"\>
# NOTE: order of attributes is not specified.
xm.instruct! # <?xml version="1.0" encoding="UTF-8"?>
xm.html { # <html>
xm.head { # <head>
xm.title("History") # <title>History</title>
} # </head>
xm.body { # <body>
xm.comment! "HI" # <!-- HI -->
xm.h1("Header") # <h1>Header</h1>
xm.p("paragraph") # <p>paragraph</p>
} # </body>
} # </html>
