Making of a Web App: Part 11 – Technical Interlude

For people with an interest in the technical side of the project, here are notes on the configuration of our development, test, and production environments.

For those who couldn’t care less if PlaybookIQ is powered by mongrels or mice – don’t run away yet. Later this week, I will have the beginnings of actual product on the “production” server where anyone interested can follow along in real-time as updates are made throughout each development day. I would love ongoing feedback from the “live” site. Stay tuned because some real stuff is starting to happen.

Environments and Tools

My environments look like this:

Development and Testing Platform

  • MacBook Pro running OS X
  • TextMate editor
  • Ruby v1.8.6 programming language
  • Ruby on Rails v1.2.2 open source web framework
  • mySQL open source database
  • web-brick web server
  • Subversion version control system
  • net-ssh for password-less connectivity to remote server
  • Dreamweaver and Fireworks for working with html and graphics
  • CSSEdit for working with .css
  • Capistrano to automate deployment
  • a few other little goodies

Remote Host

  • VPS slices at Slicehost.com
  • Ubuntu Unix
  • Rails v1.2.2
  • mySQL database
  • Apache2 web server
  • mongrel cluster as an http load balancer
  • svn server for source code control
  • trac for project management and source code management

The local environment setup was actually done some time ago. The great news for Mac fans is that when OS X Leopard is released in October you will be able to write and deploy Rails apps “out of the box” with Rails, Mongrel and Capistrano pre-bundled into OS X 10.5. Awesome.

Deprec

Once the local install of Ruby and Rails was complete, the rest was easily configured and deployed using deprec, deployment recipes for Capistrano. I first read through the info from the deprec site, then followed a combination of instructions from here, here, and here and now can easily deploy updates using these few commands and without manually logging into the server.


svn commit -m 'new update'
cap disable_web
cap deploy_with_migrations
cap enable_web

Anyone running Rails on Slicehost, drop me a line and I can send you the step-by-step details of what worked for me to get the complete stack setup with deprec.

SSL

All PlaybookIQ users will have SSL, so I wanted to get that built out from the start so that all code would handle it properly. While the setup of all other components was straightforward thanks to deprec, configuring Apache, mongrel, and the Rails app to use SSL took way too much time. The key to anyone looking to use SSL with Apache is to understand VirtualHosts. More details on the exact steps I took to deploy SSL on Rails and Apache will be in a future post.

Making of a Web App: Part 9 – Why I Hope No One Reads My Use Cases

Making of a Web App is Synap Software’s step-by-step look at designing and developing a web app. In this article I share why, despite best attempts by the anti-paperwork crowd, I like written use cases.

Use cases:

  • Contribute directly to the final, deployed app.
  • Expose risks to simplicity.
  • Expose the level of development work required.
  • Are the easiest way to iterate, collaborate and communicate.

Use Cases

Briefly put: a use case can be anything that documents how a person will accomplish a task with your application and how the application will respond. In this article I use the term to mean written use cases (as opposed to diagrams or sketches).

Click here for an example.

Some developers do not write use cases because doing so feels too much like writing documentation and documentation is not the purpose of building a system. So, in an effort to work only on things that directly contribute to building the app, people skip over the use case step and jump right to visual design or sketches (or even just start hacking out code). I have to say that back in my developer-only days, I was that way too. I saw anything but code as wasted time. Now, I don’t. Here are four reasons why I don’t skip the use case step.

1. Use cases contribute directly to the final, deployed app.

Use cases become user documentation (aka help files).

If done right, use cases are not thrown away work that gets shelved after the project is complete. There is at least one part of the final delivered app to which use cases contribute directly. There is a part that is often forgotten or saved until the very end and done as time allows. It’s the part of an app that I hope no one ever uses. It’s documentation and help files.

Typically, a development effort completes and then everyone scrambles around trying to figure out how the documentation is going to get written. Just like writing test cases first, writing the use cases first is good practice.

Unlike test cases though, use cases in the form of help files are, honestly, something that I hope people don’t read. If people are referring to the help files, that means the design is not clear. If people stop their work and have to look up what to do next in a help file; then the design does not communicate the intention of each screen and button clearly enough.

So here we are; even though I hope people do not read it, people still expect documentation and documentation ups the level of professionalism in an application. How to solve this dilemma? By writing use cases from the perspective of people using the app. This way I can use them as both a design tool and part of the delivered app.

Here’s an example. Instead of writing:

  1. User selects the playbook dropdown.
  2. User selects a playbook.
  3. User clicks ‘Save’.
  4. Milestones are copied from the playbook template to the opportunity.
  5. Tasks are copied from the playbook template to the opportunity.
  6. A history record is created with date, time, and username of the current User.

I wrote:

When you select a playbook in the Playbook field and save the opportunity, a few things happen:

  1. Milestones and tasks are copied from the playbook into the opportunity.
  2. A history record is created recording the date, time, and current username.
  3. Any milestones and tasks assigned from previous playbooks are not affected and remain unchanged.

For fans of agile development or Getting Real methods, this seems dangerously close to written documentation. Yet, as I said before, people will expect some form of documentation anyway and using this method ensures we are not running around after the fact trying to figure out how documentation is going to get written.

2. Use cases expose risks to simplicity

In moving from conceptual to concrete, the devils in the details come out.

PlaybookIQ is a great example of the ability of use cases to expose complexity from its favorite hiding spots. At the conceptual and task-flow level, the relationship between contacts, opportunities and playbooks seems quite simple.

  • A contact is a person.
  • An opportunity is a chance to provide products or services to one or more contacts.
  • And a playbook is a series of best-practices to follow when pursuing an opportunity.

Simple.

Except it’s not. It was not until trying to write down the relationships between contacts, opportunities, and playbooks that the complexity was revealed. I won’t go through the details here because this series is not about the app, but rather the process and experience. The short version is that writing use-cases exposed a decision that needed to be made. I found I need to decide: is a playbook applied only to opportunities, only to contacts, or to opportunities and contacts. (If you have thoughts on this decision – let me know because I am still working it out.) Drawing the three with arrows between them all makes it look simple. Writing use cases describing the interactions shows there are more questions that need answered.

3. Use cases expose the level of development work required

One screen is not like another.

If I find myself dreading another sentence when writing the short use cases, I know I will have an even worse time being motivated to write the code. (And an unmotivated coder is one of the worst risks to a project ever. Studies have shown that motivation has a larger impact to programmer productivity – both positive and negative – than any other factor.) A screen sketch just does not capture the depth of interaction and decision-making that an application will be asked to perform. By better understanding the scope and level-of-effort a feature will take, I can better plan the project and make smarter decisions on what should be cut.

Why not just write code now then? It is easier and quicker to change words than it is code, and it is easier to communicate to other stakeholders in words than in code. That’s why.

4. At this stage in the project, use cases are the easiest way to iterate, collaborate and communicate.

Everyone can read, understand, and edit a text document.

ConceptShare is a popular online design collaboration tool, and paper and pencil work well for teams working in the same room. The tools are there, yet people are still more familiar with editing text documents than they are with editing others’ drawings. Some people communicate and learn better with visuals, some with words (and some are audible learners – but no one I know is a “scent learner”, go figure). So while there are visual communication tools out there, they are better put to use when the visual crowd gets their chance later on in the project.

Communicate: Use cases communicate much more than just what screens and fields are required and how they will interact. Use cases are also a great place to write down definitions of key terms and overall expectations of the application. For example, this is from the use case for PlaybookIQ opportunities:

An opportunity is a chance to provide products or services to one or more contacts.

Where would someone put that in a screen sketch? Short descriptions like these help ensure the development team and clients are on the same page and, as mentioned earlier, this same document becomes help material. As final bonus, this document can also be marketing material or at least information that goes on a product site.

Back to Reality

Now, back to reality. I cannot write all day without visual representation is being written about. So, in reality, I sketched up some rough task-flow diagrams and then iterate between use cases and task-flow diagrams.

I draw with pencil on 5” x 8” index cards, then spread those out on the desk, floor, or white-board to visualize the relationship between each major component. Each iteration aims to simplify and clarify how tasks will be accomplished. Because it’s not in soft copy, I need to take some pictures to show what that looks like and will discuss them in a later post.

Enough of this evil documentation work already.

I hope you can see that written use cases are not part of the evil tree-killing conspiracy, but are a useful communication tool that also becomes part of the finished product. And to clarify, like all entries in this series, I cannot tell you how to build your web-app. I don’t know your technical, environmental, or political situation. I’m just sharing what I do. That’s why it’s called “Making of a Web App” and not “How To Make a Web App”. Either way, I know most of us will be glad to move onto something a little more visual and closer to what people think of as the application: screen sketches.

Software Design: Grant Peace of Mind

I understand about indecision

But I don’t care if I get behind

People living in competition

All I want is to have my peace of mind

- “Peace of Mind”, Boston

Avoid Indecision, Grant Peace of Mind

If you are a software designer, your goal should be to have every page have one purpose. This way you minimize user indecision, you find that the application is easier to explain, and by going through the excercise of this constraint you gain more confidence that your design achieves the primary purpose of the app.

Yet in constraining user options and tasks available on any given screen, it is easy to get concerned about falling behind the competition. You think someone is going to look at a competitor’s screenshot and say “Wow – look at everything you can do from here. This is power! I want that power!”

Yet the problem with falling into that trap is that users usually find out what they really want is peace of mind. They want to know that they are doing the “right thing” and that the application is doing what they expect. There are a couple great ways to grant the peace of mind to software users. (With apologies to Boston for twisting their words to fit this scenario).

Where am I? – Street Signs and Breadcrumbs

Though Steve Krug points out that his book “Don’t Make Me Think, a Common Sense Approach to Web Usability, ” does not discuss web applications, most of his approach is relevant to web apps.

One important feature to usability is what Krug calls “Street signs and breadcrumbs”. These features give browsers, and web-app users, something to hold onto – something to not feel lost in their virtual visit. There are several ways to implement street signs and breadcrumbs such as ensuring that in a tab-based navigation the “current tab” is highlighted.

What am I Doing Here?

Yet with web applications we take that a step further and make sure users of Synap Software applications know not only where they are but also why they are here. Both a ‘you are here’ and ‘you are doing x’ signs are needed. For example, with the lead management software, LeadsOnRails, most screens reinforce to the user their reason for being on that screen. When they click “New Track”, the new track page appears and the blue-bar heading changes to “Create New Track”.


Some designers might say that this is wasted space – that users know why they went to a screen and it only causes more reading to have to see “Create New Track”. On the contrary, such notices act as reinforcement to the user that they are, in fact, using the application the “right way”. It helps users feel comfortable and confident in the application.

Other applications have used the area of a screen typically used for notifications such as “Record Updated”. Wherever it is, web applications should have a persistent section of the screen that continuosly reinforces the purpose of the screen. Don’t just remind users where they are. Remind them of the single activity they are here to perform.

One Screen, One Purpose

When you explicitly label screens, you find that you need to narrow the focus of some screens. And this is a good thing. Designing an application so that each screen has a reason – and one reason – to exist really helps you focus on the core purpose and activities of your application.

Grant Peace of Mind

So, if you are a software designer, give it a try. Don’t overwhelm users with options in an attempt to show off the application’s powerful features. Don’t make them decide – that only causes indecision. Don’t worry about getting behind. Don’t worry about your competition. Customers that need complex software requiring extensive training and support will stick with your competitors and are not the ones you – as a small software company – want anyway.

The customers you want are those that try your competitors and find that they simply do not enjoy using their software, or that it is is too complex, or that too much time is spent trying to explain to their teams what to do next. These are the customers that will come to you – and stay with you – when they see the continuous affirmations they receive from your app.

Reason Number 121 Why I Love MacBooks

It’s all the little things. For example, while other people are buying extra laptop cord wraps and ties, MacBooks have one built right into the power supply. Simply flip in the outlet prongs, flip out the wrap feet, wrap the cord, and you have it nice and neat and ready to go. Just another little touch that, when all put together add up to a great experience with the product I use all day, every day.

Manage Leads

LeadsOnRails.com automates lead management and lets you implement lead followup best practices to convert more leads and free your up more of your time.

This system was born from discussions with small business owners who often spend a fortune on lead acquisition only lose the lead information or fail to effectively followup on it due to poor communication among team members, poor advanced planning, or failure to create a lead management plan.

In LeadsOnRails each prospect is put on a track, which assigns steps to users and everyone can see leads progress through the pipeline. No one is left assuming someone else has taken action. As one of users put it – LeadsOnRails.com can serve as an organization’s best-practices manual.

LeadsOnRails is the first in a series of products aimed at making the dedicated expertise found in large, successful companies accessible to small and mid-size companies that do not have the need for a dedicated IT or marketing staff and do not have local IT staff to support desktops, databases, and networks.

Next up:

- New features including integrated email management and web site interfaces

- Improved help and get started pages (with video tutorials)

- Industry specific templates for leads and workflow

The Rails Edge Denver – Bruce Williams

I’m here at The Rails Edge Conference in Denver and will summarize some of the talks. Let me take a moment to put in a personal recommendation for this group of speakers and the Pragmatic Studio conferences. They are a professional group who put on a well run conference. Highly recommended.

Building UI Frameworks – Bruce Williams

Bruce talked about the pain that views impose on developers and how to help yourself in the Rails environment avoid some of the pain. Bruce noted that this is not a Rails problem or an MVC problem, it is just a fact that views are hard to deal with. They mix a developer and designer’s frame of mind in a single place which makes for frustrations and challenges.

The case for frameworks

Frustrations and challenges

Yet, because views are the most visible part of MVC apps, they are the user’s experience and they are the most contenious part of the application when trying to gain concensus from a development team.

Rails Solutions

- “Traditional” DRYing of views is accomplished by helpers, “block” helpers, and partials and cover the “V”(iew) part of MVC.

- “REST” DRYing of views is accomplished by simply_* (such as simply_RESTful, simply_HELPful) – cover the M and V.

- “DRY Interaction/Views” – DSL for Controllers and Plugin with Controller.

Recommendations from Bruce

- Use Edge Rails to stay current (don’t use in production though)

- Use simply_helpful

- Use other plugins and make your own

- Use intermediate objects (for complex views)

- Make your own FormBuilders (form_for DSLs for free)

- Other Ruby projects (get to know Ruby!!)

- Learn to Metaprogram!

Caveats

It’s complex, not well documented, stuff so you take on some risks; yet can be well worth the effort.

Scott’s Take

- If you want to become a better and more efficient Rails developer, Follow Bruce’s recommendations. The recommendation to use simply_restful and simply_helpful is something you can implement with little learning curve and see great benefit. Look into these in more detail and you will see you have no reason not to be using them to make your views cleaner and to save you the headaches of managing DOM id naming conventions.

- Also, you and I, as Rails developers should be thinking about ways to solve the problems Bruce talked about and remove some of the PAIN of views. Think about what you can do to help views suck less.

The Rails Edge Denver – Marcel Molina Jr

I’m here at The Rails Edge Conference in Denver and will summarize some of the talks. This topic is of interest only to those interested in Ruby or Rails, so if that is you – read on. If not, please disregard.

Active Record Demystified by Marcel Molina Jr.

Rails Core Team member Marcel Molina Jr. presented a walkthrough of ActiveRecord::Base#Save ActiveRecord::Base.find as part of the “Active Record Demystified” talk.

Highlights:

Marcel walked through:

1. Connection Adapters

2. ActiveRecord::Base#save

3. ActiveRecord::Base.find.

Connection Adapters

Connection adapters are built from:

- connection_specification.rb

- database_statements.rb

- quoting.rb

- schema_definitions.rb

- schema_statements.rb

connection_specification.rb creates and manages connections

Marcel pointed out that connection_specification.rb had been the big selling point of Rails because it uses the database yml file that used to be the only place configuration was required.

database_statements.rb turns the Rails commands into SQL statements.

On the adapter level, all SQL statements are written in terms of EXECUTE against the database connection. The SELECT statement is the base from which other statements such as select_all, select_one are built. INSERT, UPDATE, DELETE statements are also implemented against the database in terms of EXECUTE.

quoting.rb tells how to handle quoting based on different database vendors.

schema_definitions.rb performs column typecasting. It looks at the column definition from the database using the RDBMS’ adaptors’ reflection utilities. Based on the database column type, the value is coerced into a matching Ruby type.

ActiveRecord::Base#Save

Save calls an SQL INSERT statement if the record is new and SQL UPDATE if not.

Validations does occur because save is aliased to validation, validation then performs the validation and if passes performs the save.

ActiveRecord::Base#Find

The first option passed into find is :first, :all, or an integer. Find first validates the find options. If the options validate, find it then takes one of three paths depending on the value of the first argument:

first

when :first then find_initial(options)
Implements first by adding the limit option to the SQL statement.

all

when :all then find_every(options) runs find_with_associations which leverages a JoinDependency class which then goes into the associations code. Associations code is some of the most powerful features of Rails, but also some of the “least attractive” implementation of Rails.

If there are no associations, then just constructs the sql by constructing an SQL statement out of the joins, conditions, limits, etc. Finally, it calls “find_by_sql”.

else

else find_from_ids(args, options) will find records by id or ids. Did you know that you can pass an array of ids to find!!

DynamicFinders

Dynamic finders (the ability to say find_by_first_name_and_last_name) is supported via method_missing.
method_mising first checks the method name against a regular expression. That regex looks to see if method “looks like “a dynamic finder. If the expression is multiple parts it then splits off the finder using “and” as a delimeter to get a list of attribute names.

Then looks to see if all split out attribute names are columns in the table. If not, then it exits out (via ‘super’) to “no method error”.
If the attribute name is an attribute on the object, then it delegates out to the ActiveRecord::Base#Find

whew…

Other notes:

Databases

sqlLite, postgres, mySQL – are the only adapters maintained by Rails core team. The core team continuously tests against the open source RDBMs. Some other adapters are maintained by other contributors outside of the core team. Core team would love to have folks step forward and volunteer to maintain tests (continuous integration) for other RDBMs.

Positional parameters, option hashes, and keyword arguments

Originally, calls to find had positional arguments. After switching to option hashes, they have found code is more maintainable and extensible as well as making for an easier to use API (e.g. do not need to pass nil params to fulfill positional requirements). Marcel prefers using option hashes over positional parameters, but is looking forward to keyword arguments that are to come in Ruby 2.0.

Dynamic

Marcel talked about the word “Dynamic” and how he now really gets what it means. For example, did you know you can do?


def foo(first, second = first, third = second.size)


[first, second, third]


end;

method_missing:

It is important to use method_missing appropriately. Most importantly: you have to chain back to the original behavior which most likely means ending your method_missing implementation with:


else
super
end

The Rails Edge Denver – Dave Thomas

I’m here at The Rails Edge Conference in Denver and will summarize some of the talks throughout the conference. This topic is of interest only to those interested in Ruby or Rails, so if that is you – read on. If not, please disregard.

Dave Thomas – Buried Treasure

Dave gave a great talk on a ton of little things that all add up to make Ruby and Rails a great environment in which to be working. He covered things such as using svn, the console, handing Strings, Arrays, libraries, blocks, TextMate, and irb. Too much good stuff to mention here!

Scott’s Take

If you are a Ruby on Rails developer, get yourself to the next The Rails Edge.

The Rails Edge Denver

Tomorrow I will be attending the Day 1 of The Rails Edge series presented by the good folks at Pragmatic Studio.

Choice of Language and Framework

Our company is solidly behind web applications as the future of software delivery, especially as Internet connectivity becomes ubiquitous. We are also commited to Ruby on Rails as our development environment of choice. Nothing else has met the speed of development and, more importantly, the joy of development than that which I have experienced with Ruby and Rails. We have developed (but not yet deployed) our first application using Rails.

You can read more about Ruby and Rails in my review of David Black’s book Ruby for Rails.

Choice of Business Model

While choice of language is largely a matter of personal preference, choice of business model is a result of studying the industry; especially looking at other software companies’ experiences in the both product markets and services markets.

Products or Services?

Services provide more chances for recurring revenue

In his book, The Business of Software, MIT Professor Michael A. Cusumano states that he used to believe it was better to be a products company. But as of the writing of the book (2004 – which I know is an eon ago in tech years) he says he “no longer think(s) this is true”. Why?

The key is in recurring revenues. Services companies can sell support and consulting services even during times when customers are not buying software.

Services companies excel at showing that they can provide value (by saving costs, by finding hidden money, etc) even during times when their customers are having a hard time. Professor Cusumano posits that when customers feel that their IT partners understand their needs better than any other service provider, customers will be more likely to continue to do business with them – even in times of downturns.

Service providers seem to be in demand even when on the product side customers decide not to purchase an upgrade during tight times, a customer may no longer be growing so needs no additional seats, or a product may simply become commoditized or fully matured, offering customers no real motivation to make additional purchases.

… yet …

Products Provide Dramatically Improved Profit Margins

The kicker though is the “striking” difference between software companies and service companies: gross profit margin. He cites examples of large software companies that report 99% gross profit margins on their software product business, yet only 61% gross profit margins on services business! Wow! Who wouldn’t want 99% gross profit margins!? (It turns out that there are many companies not saved by their high profit margins – but that’s a different article).

This makes sense and is a basic reason that many of us have the big dream of riches from our software creations: for each additional piece of software that is sold, the incremental gross costs are very little. Mr. Cusumano appropriately compares this to the book business and I would add the music business. One hit and an artists or author can be set for quite some time. While for each additional hour of services provided, there is an almost linear increase in labor cost to the company providing the service.

The goal for a strictly product company would be to create a product or products and then do not perform any customizations or consulting services for individual customers. All customers get the same product. When one customer looks and interacts with the company just like every other, Product companies have no incremental costs with each new customer. Directed at individuals more than companies Steve Pavlina
refers to this as ensuring that your income is not tied to your time.

But – before you head all cylinders down the product road remember the issues with a product strategy are that 1: product sales can quickly fall short of expectations in down times and 2: just like with authors and artists, it can be difficult to produce that hit single.

How about a hybrid?

(and not the kind you drive to save the planet – but maybe a strategy to save a company)

Professor Cusumano’s study is, of course, much more detailed and well-spoken in his book than my ramblings here – but hopefully you get the point up to now and can follow along to the finale. I introduce it here in order to lead up to where I think that Software as a Service (SaaS) might fit in.

Professor Cusumano does not let readers of his book off with the easy choice of a hybrid company that offers both products and services – but I would. And I believe Software as a Service is one way to do so. I don’t claim SaaS as anything revolutionary, I’m not asking you to jump on the Web 2.0 bandwagon, and I hope not to sound like a “me too” lemming waddling toward the cliff. It just jumps out as an answer and I will write more about why in the next installment on this topic.

Ruby for Rails Book

Ruby for Rails is a must have for Ruby on Rails developers.

While you could develop Rails applications without understanding Ruby, to do would completely miss out on the reasons Rails was created in Ruby. Ruby is a powerful and enjoyable language.

For those of you that do not know of David Black, here is a part of the bio from his book: “A Ruby community leader, David Black is the director of Ruby Central, the parent organization of the annual International Ruby Conference (RubyConf) and the International Rails Conference. David is a Ruby core contributor and the creator and maintainer of RCRchive.”

The reasons that I think you must know Ruby to become an effective and efficient Rails programming machine:

1. To understand the Rails source code

2. To make your Rails apps do something beyond pushing data in and out of a database.

3. To take advantage of “Ruby everywhere”

4. To use Ruby for non-Rails tasks (automation).

5. To enjoy developing Rails apps!

There are books on Ruby and there are Books on Rails. David Black is one of the only authors out there that can lead you over the bridge that connects Ruby and Rails. David obviously has a deep and broad understanding of Ruby that he puts to great use in this book. He uses this knowledge to lead you through not only how Ruby works, but also how Rails uses the power of the Ruby language to deliver an efficient and enjoyable framework. Here are some topics he covers:

Part 1: The Ruby Rails Landscape
The first two chapters are introductory overviews to getting your “Hello World” Ruby and Rails programs running. For anyone that has written a Rails program, there is not much new in the first part of the book.

Part 2: Ruby Building Blocks
The next section has a very interesting discussion about Rails as a domain specific language and how Rails feels more like configuration vs. programming. For example, David shows how the Rails declaration has_many :editions is a method call that could be written in several different ways. The Rails idiom of has_many :editions is syntax that makes Rails feel more like configuration and less like programming. This same method call could also be written in your controllers as send("has_many", "editions".intern) or has_many(:editions).

Similarly, David’s discussion of Ruby “syntatic sugar” is enlightening. Syntatic sugar of Ruby allows the programmer great power in the setter methods. It does it more easily and cleanly than other languages (in my opinion). For example, in the setter method
def price=(amount)
@price = amount
end

the method name is “def price=”.

To call the method would look like this:
ticket.price=(65.00)

By allowing you to put a space before the equal sign in the method name and allowing for parens to be optional, Ruby allows for a much more pleasant:
ticket.price = 65.00

What makes Rails great is the combination of Ruby’s flexibility as a language and its ability to support “syntactic sugar” combined with the Rails community’s positive support for coding conventions that have created standards. When reading and writing Ruby for Rails code, it is important to understand the differences between what is a Rails community standard and what is a Ruby language expectation. This understanding will give you the powers itemized above.

This combination of technical and philosophical conversation continues throughout the section brining to light important information on managing classes, constants, modules and mixins, control flow statements, and error handling. The books description of how Ruby yielding works is a valuable read and is a good example of how this book helps you understand what is going on in a Ruby program and how to become a good Ruby and Rails developer.

Part 3: Built-In Classes and Modules
This section is pure Ruby and describes things such as scalar objects, containers, collections and regular expressions. In my current project, this book’s 24 page discussion on Ruby regular expressions was worth the price of the book itself, allowing me to replace custom methods I had written with a few lines of regex. (email me at scott [at] synapsoftware [dot] com if you want the technical details on this statement)

Part 4: Rails Through Ruby, Ruby Through Rails
The book concludes with a step by step walkthrough of the sample application. It discusses not only the how but also the why of Ruby on Rails design decisions. That is what I liked best about this book.

The final chapter invites you to learn more by exploring the Rails source code. It steps through three techniques for discovering how Rails leverages Ruby.

This is a Ruby book first – details on many Rails features are not found here, and rightfully so. For example, except for mentioning that it is not mentioned, the book is missing any mention of testing (got that?). David stresses that testing is crucial, but feels it has been covered at length elsewhere.

Read this book to understand Ruby and to become the next Rails star on your team.