Book Review - Ruby on Rails: Enterprise Application Development
on May 03, 2008 @ 12:50 PM

I know Slashdot is a busy place, but come on, four months and a book review is still pending, and they don’t respond to any emails? Anyways here is my review of “Ruby on Rails: Enterprise Application Development”.

Ruby on Rails – Enterprise Application Development by Elliot Smith and Rob Nichols targets a new niche in the Rails world of published books. Its goal is to connect all of the dots that make up typical Rails development for developers who have been through the tutorials, but wonder ‘what do I do next?’

The focus of this book is breadth and not depth. The authors do a good job of balancing the explanation of essential Rails concepts while letting the reader know when they are approaching a more advanced topic that won’t be covered in depth.

Throughout the book the authors follow a fictional, yet realistic scenario in which Rory the IT guy implements a simple web-based contacts management application. Each chapter builds on the previous walking the reader through the whole process of development to production deployment.

There is no Rails development until Chapter 4, pg 91. The emphasis of the first 90 pages is understanding what Rails is and why you would use it, as well as introducing the problem scenario that will be used throughout the book. This would be a bigger turn off then it was, but the authors made up for this a little walking the reader through installing everything required for Rails development on multiple operating systems.

Rather then focus on a single platform for development or production the authors use a mixed environment of Ubuntu Linux, OSX and Windows and a cross platform Eclipse IDE. They also take the time to walk the reader through installation and setup of each platform as it pertains to Rails development.

The majority of the development in this book sticks to the functionality included in Rails itself. When it comes to core components of Rails the authors do a great job of covering them: migrations, models, validations, associations, controllers, filters, views and view helpers.

Plugins are not covered except for acts_as_attachment, which is now deprecated in favor of attachment_fu.

The only issue I had with the book was with the sections on testing. The authors cover unit and functional testing with the built-in Rails testing framework. Unfortunately, the example tests are horrible and should not appear in production quality code. The sections on testing should only be used to understand how the built-in testing framework works in Rails and not as an example for writing tests. It is too bad that the authors didn’t cover integration testing either.

A good thing that did come out of the testing sections in this book is the encouragement for developers to write tests which expose bugs before fixing them. It’s the only way to ensure you really fixed it.

Rails 1.2.3 is used throughout the book so any changes, improvements or deprecations in Rails 2.0 aren’t covered. If the reader follows the book with Rails 1.2.3 they should have no issues walking through and developing the code themselves. If the reader follows the book with Rails 2.0 they should be aware of some of the changes, those can be found at http://weblog.rubyonrails.org/2007/12/7/rails-2-0-it-s-done

The things that stuck out to me were:

  • view template file naming conventions
  • the verbosity of not having named routes
  • the lack of the db:rollback rake task

The authors take the time to walk the reader through setting up and using Subversion as an integral part of Rails software development. It also includes setting up and using Apache and Mongrel to serve Rails. As the book moves from development to production deployment the user is shown how to deploy automatically from Subversion to their production server using Capistrano.

There were a few minor typos and one redundant sentence on page 52. This is considerably lower then other technical books that I’ve read.

The only giant red sections marked in my copy are the ones on testing. Take those examples with a grain of salt.

Overall, the majority of the book is filled with good advice for novice Rails developers like, “do not wait until your application is built before you create and test the production environment” and “involve the end users throughout the process”.

If you are a novice Rails developer who understand bits and pieces of Rails this book does a good job of connecting the other dots because the authors take the time to go through the full process of development to production. On the other hand if you have a good grasp on the whole Rails development process you can skip this book.

A good chapter outline of this book can be found at PACKT’s web site

.
0 comments | Filed Under: | read on

Rails Ticket #11491
on April 01, 2008 @ 12:46 AM

If you have a few minutes, please review and comment on Rails ticket #11491.

http://dev.rubyonrails.org/ticket/11491

In short, it adds the ability for “render :partial => some_collection” to render the correct partial based on each element in some_collection. Currently Rails uses the first element to determine what to render for every element in the collection.

Thanks in advance,

0 comments | Filed Under: | read on

What is a factory and why FactoryLoader?
on March 22, 2008 @ 12:58 AM

This statement and question were posted to the http://www.gr-ruby.org mailing list as it pertained to the release of FactoryLoader. This post should answer the question “what is a factory?” and also provide more insight into what FactoryLoader’s role is.

1
2
> I've read over your website, but I still have a lagging question which
> completely blinds my ability to see the usefulness of it: What is a factory?

A factory is “a mechanism for encapsulating complex creation logic” [0].

Here’s an example. Let’s say that you start writing an application that is a project management tool for a business. To start with they need the ability to create Projects. This is no big deal, you have a ProjectsController#create action and it makes your Project by doing something similar to the below:

1
2
3
4
5
6
7
8
9
10
  def create
    project = Project.new params[:project]
    if project.save
      flash[:notice] = "successfully created the project"
      render :action => "create"
    else
      flash[:error] = "failed to create the project"
      render :action => "new"
    end
  end  

Now a few weeks later the customer says that in order to create a project it needs to be assigned a project manager off the bat (the currently logged in user). This is not a very big deal since you have a “current_user” already, you just update your controller to look like:

1
2
3
4
5
6
7
8
9
10
11
  def create
    project = Project.new params[:project]
    project.manager = current_user
    if project.save
      flash[:notice] = "successfully created the project"
      render :action => "create"
    else
      flash[:error] = "failed to create the project"
      render :action => "new"
    end
  end

A few more weeks go by and your customer says that projects are tied to company budgets and when they are created they need to be automatically assigned to the correct budget based on the type of project. So we update to ProjectsController#create looks like the below:

1
2
3
4
5
6
7
8
9
10
11
  def create
    project = Project.new params[:project]
    project.manager = current_user
    project.budget = Budget.find_by_project_type(project.type)
    if project.save
      flash[:notice] = "successfully created the project"
    else
      flash[:error] = "failed to create the project"
      render :action => "new"
    end
  end  

Uh oh. There are important business rules being applied in the controller. The controller’s responsibility is to map an incoming request with an outgoing response and to know high level what the application needs to be doing. It should not know the intimate details of Project creation. Since we’re implementing the business rules on the controller we can’t re-use them for anything, unless we make a POST request to ProjectsController#create. This is quite limiting.

Another option to make them more reusable would be to tuck this away in the Project model itself. Perhaps we add a before_save callback which finds the appropriate budget. Even then we’ve only moved the budget logic out of the controller and there is still requirement for a Project to have a manager. If we go this route we’ll be separating two important pieces of how a Project gets constructed from each other. We would have the ProjectsController#create action setting the manager and then a before_save callback on the Project model finding a budget, both of which are required for a Project to be constructed.

One thought to remedy this would be put everything in the Project model, maybe in a before_save callback or overriding the constructor. But we quickly hit a roadblock because our Project model doesn’t know about the current user, that is application state and only the model knows about that. We could do something stupid and make the current_user global to the application, but that is a bad decision with pretty bad repercussions.

It’d be nice if we had a single object responsible for constructing a Project with these business rules. This is where a ProjectFactory comes into play. The ProjectFactory looks like:

1
2
3
4
5
6
7
8
  class ProjectFactory
    def create(project_attrs, manager)
      project = Project.new project_attrs
      project.budget = Budget.find_by_project_type(project.type)
      project.save!
      project
    end
  end

And the ProjectsController#create action looks like:

1
2
3
4
5
6
7
  def create
    project = ProjectFactory.create params[:project], current_user
    flash[:notice] = "successfully created the project"
  rescue 
    flash[:error] = "failed to create the project"
    render :action => "new"    
  end

This is pretty straightforward. I just moved some of the lines from the action into the factory. More importantly then just moving line of code is that the act of constructing a valid project (given the customer’s requirements) isn’t the responsibility of the Project. The act of constructing a valid project is a process by itself which is important to the customer, so we isolate it in a ProjectFactory.

This is valuable because:

  • the business logic used to construct a project is in one spot. Should the customer change, add or remove requirements you only have to go to one spot to implement them. Granted if the method signature to this changes you have to go update the spots calling the create method, but you the actual logic for constructing the project isn’t spread throughout multiple files or classes.
  • it promotes reusability (the whole DRY thing), since my ProjectFactory is much more reusable then my ProjectsController.
  • it promotes single responsibility
  • it provides clearer meaning to the code base because we aren’t muddying up the controller or the Project model with creation logic
  • it makes for easier testing and easier to understand tests

The technical implementation of this pattern is mentioned in the GoF book [1]. The value of the pattern as it applies to Domain Driven Design is mentioned in the DDD book by Eric Evans.

Hopefully that helps clarify what a factory is, by seeing how it is used and some of the value it provides. This relates to the FactoryLoader because sometimes the progression of creation logic is over time.

For the first few weeks or months of a project you are hardcoding things like “Project.create” in multiple spots. When the customer starts introducing requirements for constructing (or updating) a Project you have to go update all of those spots with the same code (violating DRY) or go find all of those spots and refactor them to use a ProjectFactory, and then make a ProjectFactory. It doesn’t happen all the time, but when it does happen it can be time consuming, frustrating and painful to do.

What FactoryLoader would do in our example is it give us a ProjectFactory upfront w/o having to write any code. If we used FactoryLoader in the above example our ProjectsController#create action would look like:

1
2
3
4
5
6
7
8
9
10
  def create
    project = ProjectFactory.create params[:project]
    if project.save
      flash[:notice] = "successfully created the project"
      render :action => "create"
    else
      flash[:error] = "failed to create the project"
      render :action => "new"
    end
  end  

Where the ProjectFactory is created for you by FactoryLoader (you didn’t create the class, FactoryLoader did dynamically). There’s only one line that differs between the example that uses the FactoryLoader and the one that doesn’t.

Now when the customer starts adding business rules for creating a Project you can create your own ProjectFactory class and implement the customer’s business rules. FactoryLoader will see that you have provided your own ProjectFactory so it won’t dynamically create one. Since all of the spots where you create a Project are already using a ProjectFactory they get the changes for free. Overall you get to touch less code for the changes and you get to spend less time refactoring if any refactoring is needed.

The goal of FactoryLoader is to allow developers the ability to scale to these customer requirements with less pain. The above examples have been quite trivial, hopefully they are clear enough and meaningful enough to express why I wrote FactoryLoader,

— Zach Dennis http://www.continuousthinking.com

  • 0 – Domain Driven Design by Eric Evans
  • 1 – Design Patterns: Elements of Reusable Object-Oriented Software by Gamma, Helm, Johnson and Vlissides
4 comments | Filed Under: factory_loader | read on

Factory Loader
on March 18, 2008 @ 06:10 AM

FactoryLoader is intended to help scale object creation with less pain and less refactoring by creating factory classes for basic object construction.

In the early stages of a project object creation is simple and dependencies are kept to a minimum. As the project grows so does the complexity of object creation and its dependencies. It doesn‘t make sense to create custom factory classes upfront to deal with complex object construction that may not exist yet. But when those custom factories are needed it is usually painful and time consuming to update the code base to use them. It‘s also easy for developers to give-in due to time constraints and start making bad decisions.

This is where FactoryLoader comes into play. It automatically creates a Factory class for your objects and provides a create method which passes any arguments along to your object‘s constructor.

When you need to have custom factory behavior you can implement the factory without having to update other code references (assuming you‘ve used the factory in the rest of your application rather then direct class references).

  project/
    init.rb
    lib/
     |--things/
            |-- foo.rb
            |-- bar.rb
     |--factories/
            |-- bar_factory.rb

Given the above project directory structure you could have the following code in init.rb:

1
2
 factory_loader = FactoryLoader.new("lib/factories")
 factory_loader.load("lib/things")

The first call constructs a factory loader telling it which directory is used to store developer-written custom factories.

The second call will create an in-memory factory class for each *.rb file in the lib/things/ directory. A FooFactory class will be created to correspond with the foo.rb file. The generated factory will provide a create method which will pass along all arguments to the constructor of the object it wraps. So…


 FooFactory.new.create :a => :b

is the same as:


 Foo.new :a => :b

Even though a bar.rb file exists a BarFactory will NOT be created. This is because we told the FactoryLoader that custom factories are storied in lib/factories/ and a bar_factory.rb file exists there, so FactoryLoader assumes you want to use a custom factory. It also assumes that the class inside of bar_factory.rb is BarFactory.

FactoryLoader dynamically creates the factory classes — they are not written to disk. FactoryLoader also uses file naming conventions to determine what to do. For example:

1
2
   foo.rb => FooFactory
   crazy_dolphins.rb => CrazyDolphinsFactory

Factory.new

The dynamically created factories are classes and create is an instance method on them. You have to construct a factory in order to use it. This is so the factories themselves can be easily used in dependency injection frameworks.

Making a custom factory

So you’re using FactoryLoader to do the work of creating factories for you. Let’s say our Foo object now has some creation logic that we do not want in Foo’s constructor. To put it in the FooFactory just create the file in lib/factories/foo_factory.rb. The contents of foo_factory.rb might look like:

1
2
3
4
5
6
7
8
9
class FooFactory  
  def create options={}
    if business_logic_passes?
      Foo.new options
    else
      raise "business logic failed"
    end
  end
end

Install it!

gem install -r factory_loader

More Info

Author

Me, Zach Dennis

Special Thanks

  • Dave Crosby at Atomic Object
  • Ryan Fogle at Atomic Object
0 comments | Filed Under: factory_loader | read on

Trying RSpec's Rubyesque Stories
on March 05, 2008 @ 12:35 AM

Today my pair and I wrote some stories using the rubyesque RSpec story style along with a corresponding step file. It went better then expected. We ended up a story like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# in stories/expenses/a_user_creating_a_misc_expense_story.rb
Story "User creating misc. expense", %|
  As a user 
  I want be able to submit an expense reimbursement request for a misc. expense
  so that I can be reimbursed for business expenditures|,
  :steps_for => :expense,
  :type => RailsStory do
 
  Scenario "creating a misc. expense unsuccessfully" do
    Given "a user at a new expense reimbursement page"
    # ....
  end
  
  Scenario "creating a misc. expense successfully" do
    Given "a user at a new expense reimbursement page"
    # ...
  end
end


# in stories/steps/expense.rb
steps_for :expense do
  Given "a user at a new expense reimbursement page" do
    go_to_root
    click_new_expense_reimbursement_link
  end

  # ...
end

Overall there are four story styles (that I’m aware of) in RSpec: plain text stories, rubyesque stories with separate step files, rubyesque stories with inlined steps and rubyesque stories with inlined blocks.

We did try using plain text stories at first, but one drawback of plain text stories is being able to run them individually from within your editor or easily from the command line. We didn’t have the need for plain text stories so we opted to not use it.

We started using the rubyesque stories with inlined steps secondly until we got a feel for the stories and then we moved those steps into their own file so we could achieve higher reuse and better step organization.

We knew coming in that we were not going to use the inlined block style since we have used that on another project and it gets clunky really fast.

If you’re considering using RSpec stories try the rubyesque stories with step matchers (inlined or in separate files). If you’re going to take the plunge into trying plain text stories look to RSpec itself for examples. The actual stories in the stories/ directory helped us get up and running earlier today.

0 comments | Filed Under: | read on

Mocha's error messages suck
on February 26, 2008 @ 08:04 PM

Mocha’s parameter matching error messages suck.

When writing a failing test similar to the below snippet I am given the error message “undefined method `keys’ for :no_args:Symbol”


@user.should_not_receive(:update_attributes).with(has_key('name'))

I love Mocha’s parameter matching, but what kind of error message is that?

This is not the first time I’ve gawked at Mocha’s error messages, but this time just did it for me. My pair didn’t know if we should ping or if we had broken our app.

1 comment | Filed Under: | read on

Trying out Vlad the Deployer
on January 26, 2008 @ 09:09 PM

This blog wasn’t using any form of automated deployment until late last night. For the longest time rsync and ssh seemed to be adequate enough even though I’m familiar with Capistrano and had been well aware of Vlad the Deployer’s release. Since I know about Capistrano I decided to invest some time getting to know Vlad.

This site is currently running on a 0.7.3 Mephisto installation with a custom theme by yours truly and it’s hosted on Dreamhost servers. Out of the box Vlad works with mongrel+apache+svn. Unfortunately Dreamhost uses apache+fastcgi, but thankfully tweaking Vlad was a piece of cake.

I followed the instructions on the examples page for Vlad, but ultimately found I needed to do a little tweaking for my environment. Based on those basic examples I ended up making the following changes to my Rakefile and deploy.rb recipe file.

Here’s what I appended to my Rakefile:

1
2
3
# appended to my Rakefile
require 'vlad'
Vlad.load(:app => :apache)

Here’s my config/deploy.rb file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
set :domain,      "continuousthinking.com"
set :deploy_to,   "/my/path/to/continuousthinking.com/"
set :repository,  "http://myserver/svn/continuousthinking.com/trunk"
set :web_command, "echo skipping web "

namespace :vlad do
  remote_task :start_app do
    run "pkill -f dispatch.fcgi"
    fork do
      puts "sending a request to the domain so dispatchers restart"
      `wget http://#{domain} -O /dev/null`
    end
  end

  remote_task :update do
    Rake::Task['vlad:after_update'].invoke
  end
  
  remote_task :after_update do
    run "ln -s #{deploy_to}/shared/system/database.yml #{deploy_to}/current/config/database.yml"
    run "rm -f /home/zdennis/continuousthinking.com &&
         ln -s #{deploy_to}/current /home/zdennis/continuousthinking.com"      
  end
  
  remote_task :deploy => [:update, :start_app]
end

I overrode the :web_command setting so Vlad didn’t try to restart apache. The other tasks were added to customize specific needs for the deployment of the blog:

  • :start_app – kill all of dispatchers on Dreamhost and then send a request to have Dreamhost launch new ones
  • :update – adds this task to the :update task call chain. This simulates an after_update.
  • :after_update – create symlinks, etc to be performed after code has been updated.
  • :deploy – update code and restart the app

Overall, it was a pleasant process. I give Vlad a +1.

0 comments | Filed Under: | read on

rak, ack and findit
on December 13, 2007 @ 04:52 AM

In Helpful Command Line Tools from last month I posted on my custom findit script.

Jason Porrit commented on that post and mentioned ack , a perl alternative to grep and find which offers terminal color highlighting to your results. I also found this morning a ruby alternative called rak

All of these utilities do the same thing, they search a directory structure for files whose contents match a given pattern.

Here’s Ack

Here’s Rak

Here’s findit

Overall ack and rak beat out findit, but findit has a much better name. I think I’ll just alias findit to rak. (yes I”m biased to ruby code over perl code).

The only thing ack and rak are missing is a filename only option. If I can find every file matching a pattern from a given start directory that would rid me of findfile as well!

3 comments | Filed Under: | read on

RMagick, Rubygems and Windows
on December 05, 2007 @ 08:40 PM

Rubygems 0.9.5 doesn’t like RMagick on Windows. Here is a useful post from a Google thread which describes how to fix this. Basically re-install 0.9.4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
I woud like to thank Robin Mayfield for indirectly resolving my 
similar issue with RMagick. 

RMagick is now installed and working. 

Here's what I did: 

1. Downloaded 0.9.4 RubyGems zip file. 

2. Ran the setup.rb 

3. From within the unzipped RMagic-win32 directory I ran: gem install 
rmagick-1.14.1-win32.gem --local 

I didn't need to insert require 'RMagick' in the environment.rb file. 

Yeeha!!
 
Apparently, RMagick doesn't work with RubyGems 0.9.5. 

Thanks again. 

Regards 

Walter 

Thanks to Walter Lockhart for reposting this.

0 comments | Filed Under: | read on

magic models, meh
on December 01, 2007 @ 10:59 AM

While catching up on RSS feeds this morning I followed a few interesting links and again came across a link to Dr. Nic’s Magic Models . In the past I felt uneasy about this gem, but now I just don’t think it should be used for real projects, although I’m sure it was a fun exercise for the author to write.

The idea seems to be based on removing declarative statements about your model in your model. You would normally write:

1
2
3
4
5
6
class Person < ActiveRecord::Base
  has_many :memberships
  has_many :groups, :through => :memberships
  belongs_to :family
  validates_presence_of :firstname, :lastname, :email
end

The author finds an issue with this, to him it seems unncessary. So he ponders the question:

Why do I have write my own has_many, belongs_to, and validates_presence_of commands if all the data is in the database schema?

I think this is the wrong question to ask, but I can see where the author came up with the question. As I read through the entire page on magic models I see my code beginning to vanish. Something like:

1
2
3
4
5
6
class Person < ActiveRecord::Base
  has_many :memberships
  has_many :groups, :through => :memberships
  belongs_to :family
  validates_presence_of :firstname, :lastname, :email
end

to…

1
2
class Person < ActiveRecord::Base
end

to…


# no more code , the person.rb model file has been deleted

This progression bothers me because in the end you end up without any self-documenting code, and you’ve moved application logic from your application into your database. It seems that I’d rather have a database constraint (like not allowing null fields) reinforce self-documenting declarations in the model such as:


validates_presence_of :firstname, :lastname, :email

And why would you want to kill declarative relationships in your application?

1
2
3
  has_many :memberships
  has_many :groups, :through => :memberships
  belongs_to :family

to …


 # ... nothing here ...

Self-documenting code is useful especially when you’re describing how one object relates to another object in your application.

It seems much more appealing to see that in a model rather then having to go fish in the database schema. Leave application logic in the application. There are times you need to use database constraints (among other things) to reinforce your application logic, but you shouldn’t remove self-documenting clean code just because you can.

This is just my developer preference, but I think it’s a good preference to have. I don’t want to unnecessarily spread application logic outside of my application code for the sake of being clever.

0 comments | Filed Under: | read on

form_test_helper edge gets support for multiple submit buttons
on November 27, 2007 @ 11:49 AM

form_test_helper edge has been updated to support multiple submit buttons on a form. It also includes a fix to avoid namespace collisions if models are named Select, Option, etc.

If you have a view which looks like:

1
2
3
4
<form id="test">
  <input type="submit" value="yes" />
  <input type="submit" value="no" />
</form>

You can have choose which value to submit when the form is submitted:

1
2
3
4
5
6
7
8
9
10
11
# selecting the form and submitting it in separate steps
form = select_form "test", :submit_value => "yes"
form.submit

# submitting a form with a submit value in one step
submit_form "test", :submit_value => "yes"

# submitting a form with a submit value in one step using a block
submit_form "test", :submit_value => "yes" do |form|
   # .. 
end

You don’t have to supply a :submit_value. If you don’t the first submit value found on the form will be used. If you try to supply a non-existent value then an exception will raised.

For example:

1
2
3
# trying to submit on a non-existent input value
form = select_form "test", :submit_value => "fooey"
form.submit  # => raises a FormTestHelper::Form::MissingSubmitError

Installing

As an external:


  ./script/plugin install -x http://form-test-helper.googlecode.com/svn/form_test_helper

Not as an external:


  ./script/plugin install http://form-test-helper.googlecode.com/svn/form_test_helper

With piston:

1
2
  cd vendor/plugins/
  piston import http://form-test-helper.googlecode.com/svn/form_test_helper

Rdoc

Rdoc pages for form_test_helper edge are hosted on rubyforge. You can find them at http://continuous.rubyforge.org/form_test_helper/rdoc/

If you have any questions feel free to ask. If you find issues, bugs or odd behavior please create an issue over at http://code.google.com/p/form-test-helper/

1 comment | Filed Under: | read on

form_test_helper 1.0.1 and 1.1.1
on November 27, 2007 @ 11:07 AM

form_test_helper 1.0.1 and 1.1.1 have been released.

  • 1.0.1 is for people who are on 1.2.x (specifically 1.2.5 and 1.2.6)
  • 1.1.1 is for people who are on a Rails Edge revision between 6764 and 7420

If you are on Rails Edge newer then 7420 then you’ll want to use form_test_helper edge. A separate announcement will be made for that release.

The 1.0.1 and 1.1.1 releases fix a namespace collision issue if you happen to have a model named Option or Select. Thanks to Tomasz Wegrzanowski for pointing this out and supplying a patch.

For information on how-to install, or for usage examples please check out the rdoc for these releases:

This will probably be the last release for the 1.1.x branch of development since it targets such as a small set of revisions on Rails Edge and it will be out of date shortly if it isn’t already.

0 comments | Filed Under: | read on

OSX Leopard mysql gem for ruby
on November 21, 2007 @ 10:12 AM

If you install mysql from ports then you can install the mysql ruby bindings in the following manner:

1
2
3
4
5
sudo su

ARCHFLAGS='-arch i386' gem install -r mysql -- \
   --with-mysql-include=/opt/local/include/mysql5/mysql/ \
   --with-mysql-lib=/opt/local/lib/mysql5/mysql/

If you don’t use ports then check out http://nullcreations.net/entry/installing-ruby-mysql-gem-in-osx-10-5-leopard

0 comments | Filed Under: | read on

OSX Leopard sqlite-ruby and sqlite2
on November 18, 2007 @ 12:07 PM

OSX Leopard comes with sqlite3 and sqlite3-ruby pre-installed. If you need to install the sqlite-ruby gem for sqlite2 you’ll find that it fails to install by itself.

Here’s what you’ll probably get:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
zdennis@elijah:>sudo gem install sqlite-ruby
Select which gem to install for your platform (universal-darwin9.0)
 1. sqlite-ruby 2.2.3 (ruby)
 2. sqlite-ruby 2.2.3 (mswin32)
 3. sqlite-ruby 2.2.2 (ruby)
 4. sqlite-ruby 2.2.2 (mswin32)
 5. Skip this gem
 6. Cancel installation
> 1
Building native extensions.  This could take a while...
ERROR:  While executing gem ... (Gem::Installer::ExtensionBuildError)
    ERROR: Failed to build gem native extension.

ruby extconf.rb install sqlite-ruby
checking for main() in -lsqlite... no
checking for sqlite.h... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
details.  You may need configuration options.

Provided configuration options:
        --with-opt-dir
        --without-opt-dir
        --with-opt-include
        --without-opt-include=${opt-dir}/include
        --with-opt-lib
        --without-opt-lib=${opt-dir}/lib
        --with-make-prog
        --without-make-prog
        --srcdir=.
        --curdir
        --ruby=/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
        --with-sqlite-dir
        --without-sqlite-dir
        --with-sqlite-include
        --without-sqlite-include=${sqlite-dir}/include
        --with-sqlite-lib
        --without-sqlite-lib=${sqlite-dir}/lib
        --with-sqlitelib
        --without-sqlitelib


Gem files will remain installed in /Library/Ruby/Gems/1.8/gems/sqlite-ruby-2.2.3 for inspection.
Results logged to /Library/Ruby/Gems/1.8/gems/sqlite-ruby-2.2.3/ext/gem_make.out

If you become root and attempt to do the install it will also fail.

Installing with sqlite2 from ports

I have MacPorts installed and you’ll want to make sure sqlite2 is installed:


zdennis@elijah: sudo port install sqlite2

Now to install sqlite-ruby:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# run the command as root
zdennis@elijah: sudo su

sh-3.2# ARCHFLAGS="-arch i386"  gem install sqlite-ruby -- --with-sqlite-include=/opt/local/include/ --with-sqlite-lib=/opt/local/lib/

Select which gem to install for your platform (universal-darwin9.0)
 1. sqlite-ruby 2.2.3 (ruby)
 2. sqlite-ruby 2.2.3 (mswin32)
 3. sqlite-ruby 2.2.2 (ruby)
 4. sqlite-ruby 2.2.2 (mswin32)
 5. Skip this gem
 6. Cancel installation
> 1
Building native extensions.  This could take a while...
Successfully installed sqlite-ruby-2.2.3
Installing ri documentation for sqlite-ruby-2.2.3...
Installing RDoc documentation for sqlite-ruby-2.2.3...

That’s it. Now it works:

1
2
3
4
5
6
zdennis@elijah: irb
irb(main):001:0> require 'rubygems'
=> false
irb(main):002:0> require 'sqlite'
=> true
irb(main):003:0> 
0 comments | Filed Under: | read on

test/unit story runner
on November 14, 2007 @ 01:53 AM

As you may know rspec has integrated RBehave into itself. In the rspec world it’s more recently been called Story Runner.

Some background links:

Story Runner itself hasn’t officially been released and while it has been becoming more polished myself and a colleague (Drew Colthorp) wanted higher level acceptance tests in my ruby projects (including rails).

Story Runner also has two implementations (or at least APIs). The latest is the plain text Story Runner. This requires that for every story you have at least two files. One that is plain text for the customer to write and one that is a “matcher” file developers write. Information on this can be found here

The older version of Story Runner uses the original RBehave style syntax. Lots of blocks and lots of argument passing. There is also a bug in this implementation regarding sharing blocks given to story parts. But enough about rspec, this post is on a lighter weight and simpler Story Runner.

So here’s to a working and testing implementation of a Story Runner in test/unit.

test/unit Story Runner

To start, an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class EventCreationTest < ActionController::IntegrationTest
  fixtures :all

  Story "As a user I should be able to create an event so that others can RSVP and attend."
  
  Scenario "Creating an event unsuccessfully with insufficient input" do
    Given :a_user_at_the_create_an_event_page
    When :they_submit_the_create_an_event_form_with_insufficient_input
    Then :they_will_see_an_error_explanation
    And :they_will_see_the_create_an_event_page
  end 

   #
   # HELPERS
   #
   def a_user_at_the_create_an_event_page
       # ....
   end

   def submit_the_create_an_event_form_with_insufficient_input
       # ...
   end

   def see_an_error_explanation
       # ...
   end

   def see_the_create_an_event_page
      # ...
   end
end

Some important things to note on the structure:

  • the Story takes a description of the story. It does NOT take a block.
  • multiple Story’s can be defined in a file although I prefer organizing them in separate files
  • all Scenario’s which follow a Story will belong to that Story.
  • the Scenario takes a description of the particular scenario or acceptance test for a story. It does take a block.
  • inside of a Scenario you describe the story parts. These are Given, When, Then, and And.

Some important things to note on the story part descriptions:

  • Each story part can take a string or symbol description
  • helper method calls are generated off from the story part description

Helper method calls are generated by taking the full story part description and then removing the leading word until a helper method is found. If there are no helper methods found then an exception is raised.

Some important things to note on the goals of this implementation:

  • in theory customers write acceptance tests
  • in practice developers translate customer desires into acceptance tests
  • ideally the acceptance tests should be high level enough that a customer can read/write them
  • since developers will most likely write these acceptance tests this implementation should allow for developer shortcuts
  • this should just work on a test/unit project, projects updating to this shouldn’t have to convert or make changes up front to existing code

script/plugin install

script/plugin install \
  http://continuous.rubyforge.org/svn/tags/test_unit_story_runner-0.1.0

Final Thoughts

Before I forget you can do argument passing as well on story parts:

1
2
3
4
5
Scenario "a user successfully making a guess in the game" do
  Given :a_user_at_the_game
  When :they_make_a_guess_of, 20_000
  Then :they_will_win_a_car
end

This feature is there, but I would advocate only using it when it helps the readability of your tests.

This is a stable (tested) experiment. It’s a thin wrapper around the test/unit framework and it works with any Test::Unit::TestCase. The price to pay for higher level acceptance tests is now next to nothing so give it a shot.

This is the creation of a trip to Madison, WI where Drew and I had a chance to discuss and vent about the state of acceptance tests in Rails projects specifically. A few days later we had this implementation, and about a month later you’ve got this post…

Suggestions and feedbacks are warmly welcomed.

Happy rubying!

0 comments | Filed Under: | read on