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

(Tuis.) #1

274 | Chapter 9: Incorporating and Extending Rails


Ambition is not an object-relational mapper (in fact, it requires ActiveRecord), but it
is a simple interface on top of an ORM. It allows us to write SQL queries as pure
Ruby. It does this using lazy evaluation—putting off SQL queries until the last
possible moment.


To try out Ambition, we will check out the latest code and use the test console pro-
vided with Ambition (which requires us to create a development database first):*


$ git clone git://errtheblog.com/git/ambition
$ cd ambition
$ mysql -uroot -e"create database ambition_development"
$ test/console
(...)
Available models: Admin, Company, Developer, Project, Reply, Topic, and User
>>

This is a standardirbconsole, from which we can interact with any of these models
as if from a Rails console. We can start off by finding users with a salary of greater
than $50,000:


>> User.select{|u| u.salary > 50_000}
=> Query object: call

Here we see lazy loading in action. Nothing has been sent to the database; instead, a
Query object has been created. Ambition relies onkicker methodsto actually run the
query and return results; right now, all that we have is an object representing the query.
(This kind of object is often referred to as apromise; it has the ability to perform an
expensive calculation, but will not do so unless asked.) We can call one of the kicker
methods,map (collect), to run the query and extract the results:


>> User.select{|u| u.salary > 50_000}.map(&:name)
# SELECT * FROM users WHERE (users.`salary` > 50000)
=> ["David", "Jamis", "fixture_3", "fixture_4", "fixture_5", "fixture_6",
"fixture_7", "fixture_8", "fixture_9", "fixture_10", "admin", "Goofy"]

Since theQueryobject being passed around contains all information necessary to run
the query, additional methods chained onto it can actually modify the query as
needed. For example, asking theQueryobject for its length changes the query to
select only a count instead of a full list of columns:


>> User.select{|u| u.salary > 50_000}.length
# SELECT count(*) AS count_all FROM users WHERE (users.`salary` > 50000)
=> 12

These methods can be chained, augmenting the query as they progress. For exam-
ple, thesort_by method adds anORDER BY clause:


>> User.select{|u| u.salary > 50_000}.sort_by{|u| u.name}.map(&:name)
# SELECT * FROM users WHERE (users.`salary` > 50000) ORDER BY users.name
=> ["admin", "David", "fixture_10", "fixture_3", "fixture_4", "fixture_5",
"fixture_6", "fixture_7", "fixture_8", "fixture_9", "Goofy", "Jamis"]


  • Currently, the only way to fetch the latest Ambition source is using Git, a decentralized version control sys-
    tem. We cover the decentralized paradigm in Chapter 10, but for now you can fetch Git fromhttp://git.or.cz/.

Free download pdf