Advanced Rails - Building Industrial-Strength Web Apps in Record Time

(Tuis.) #1

286 | Chapter 9: Incorporating and Extending Rails


Standalone data store


Often, a console or desktop application needs to store persistent data, whether it be
preference data or application data itself. A common solution is to use YAML, which
can marshal and unmarshal most Ruby objects (round trip), while also being human-
readable. However, YAML is verbose compared to binary data formats, which may
be an issue when storing larger amounts of data.SOAP::Marshalfrom Ruby’s stan-
dard library is similar; it can serialize objects into an (often quite verbose) XML rep-
resentation. This approach has similar benefits and drawbacks to YAML.


Another option is to use Ruby’sMarshalmodule, which dumps Ruby objects into a
more concise byte stream. This uses less space, but it can be brittle. Though efforts
are made to maintain backward compatibility across major Ruby versions, Ruby 1.9
has a new Marshal format that is not completely interoperable with Ruby 1.8.


For a more structured approach to persistent data storage, SQLite and ActiveRecord
can provide a helpful balance. The data schema must be defined first and acted upon
by a constrained set of operations (those permitted by SQL DML). But these con-
straints pay off; as the data store is completely separated from the application, the
two halves can evolve separately. There is no need to recode data when an applica-
tion is upgraded, save for application-level data changes.


Using ActiveRecord for this purpose is simple; just open a connection to a SQLite file
(which will be created if it does not exist), and define the appropriate ActiveRecord
classes.


require 'rubygems'
require 'active_record'

ActiveRecord::Base.establish_connection(
:adapter => :sqlite3,
:database => "db.sqlite3"
)

class Client < ActiveRecord::Base
has_many :conversations
end

class Conversation < ActiveRecord::Base
belongs_to :client
end

# Sample usage:
def time_log
Client.find_all_by_active(true).each do |client|
# this uses ActiveRecord::Calculations to grab the sum
# in one SQL query
hours = client.conversations.sum('hours')

# format string gives us a nice table:
# First Client 5.00
# Another Client 12.40
Free download pdf