Tuesday, September 27, 2011

Smalltalk MVC Applied in Rails

I am giving a talk today at the weekly Groupon GeekFest event titled "Smalltalk MVC Applied in Rails."

Abstract:

MVC was an architectural pattern that originated in desktop development with Smalltalk. It helped decouple application domain logic from user interface presentation and control flow. Since it relied heavily on observers and the web paradigm does not support observers cheaply, MVC got twisted quite a bit in order to provide some of the same benefits in web development. Unfortunately, the baby got thrown with the bath water on certain fronts... Read More


If you're in the Chicago area, you can attend at lunch time by RSVPing over here:
http://geekfest.gathers.us/events/geekfest-20110927

Sunday, September 18, 2011

Cucumber tests run twice in Rails 3 using an engine (fixed)

Recently, I had a problem with Cucumber tests running twice in a Rails 3 web app after I added a dependency on a Rails engine that I have extracted from another web app. After some investigation, I found out that given that the engine has its own Cucumber.rake, it ends up getting automatically included in the rake tasks of the web app when running "rake", thus queuing Cucumber tests to be run twice.

I solved the problem by adding the following in the Rails engine's Cucumber.rake file:

begin
  EngineModuleName::Application


  ... original Cucumber.rake content


  rescue NameError => e
end

Of course, for that to work, you need to make sure that you have defined an "application.rb" for the engine project with the correct engine module name namespace. That is usually done as part of setting up a new Rails engine project to allow invoking tests in the engine independently of any particular Rails project (by faking a Rails app in the engine).

Then, by adding the code above around Cucumber.rake's original content in the Rails engine project, you are saying that unless you are running within the scope of the engine's application, do not run the original content of Cucumber.rake. That gets rid of the problem of Cucumber tests running twice in any web app consuming the engine.

Happy Cucumber testing with Rails engine reuse!

Saturday, September 17, 2011

More Productive Rails Engine Development via Symlinking

I have been using Rails Engines in Rails 3 quite successfully recently on a client project, enabling the team to reuse functionality that cuts through the MVC layers including front-end Javascript while still being able to customize it for the different web apps we are building.

The price we pay for such reuse though is having to keep updating the git repo reference in Gemfile for the web app on every Rails engine update.

Here is an example of that reference line in Gemfile:

gem 'national_search_map', :git => 'ssh://our_git_account@git.our_project_repo.org/var/git/national_search_map.git', :ref => 'f11671a'

Fortunately, I have found a remedy for that challenge by writing a rake task that creates a symlink for the Rails engine project within the gemset of the web app. That enables developers to make back-and-forth changes in both application and engine with no interruption until completely done working on their feature. Only then do they have to commit the engine code, get a new revision ref number, and then insert it in the web app Gemfile to ensure linkage to a fixed version of the engine code upon deployment.

Here is the code of the rake task I wrote:


namespace "engine" do
 desc "Symlinks an engine gem into a local project for development productivity purposes"
 task :symlink, :gem_name do |t, args|
   gem_name = args[:gem_name]
   gem_file_path = `bundle exec gem which #{gem_name}`
   gem_file_path_match = gem_file_path.match(/(.*)\/lib.*/)
   gem_path = gem_file_path_match[1]
   system "rm -rf #{gem_path}"
   project_gem_path = File.expand_path("#{Rails.root}/../#{gem_name}", __FILE__)
   system "ln -s #{project_gem_path} #{gem_path}"
   puts "Symlinking Complete: #{gem_path} now points to #{project_gem_path}"
 end
end

The rake task can be invoked via: "rake engine:symlink[engine_project_gem_name]". I have it saved under lib/tasks/engine.rake. If you put it in a Rails engine or gem that is reused across all your web apps, then all of them inherit that rake task and you would not have to duplicate it across projects (meta meta!)

Once you are done working in both engine and web app, have all tests passing, and are ready to deploy, make sure to follow these steps to lock a specific version of the gem in the web app for a safe predictable deployment:

  • commit engine code, obtaining a new git ref revision number
  • update Gemfile in web app to point to the new engine git ref revision number
  • bundle install the web app (this automatically gets rid of the rake task symlink) and then run rake again to ensure all tests are passing after linking to the engine via the git repository
  • commit web app code and deploy
That's all folks. You are welcome to share questions and experiences via comments.

Wednesday, September 07, 2011

The Rails Engine That Could

I gave a lightning talk at Groupon's weekly tech event "GeekFest" the other day titled "The Rails Engine That Could"

The talk covered a successful utilization of Rails Engines in a Rails 3 project to modularize MVC features as reusable components. These components provide the best of both worlds, improved productivity through reusable MVC code, and better flexibility by allowing different applications to customize behavior as needed without dirty conditionals by relying on the Extension Point pattern (as used in the Eclipse IDE). Of course, given the benefits of Ruby, no XML is involved in the extension points, but how that was accomplished is beyond the scope of the lightning talk and can be covered in a future blog post.

Check out the slides over here:

Follow-up one-hour long presentation has been posted over here: The Rails Engine That Could - In Motion