puts Blog.new(”nonsense”)

Video: Grails Presentation at QCon San Francisco

Posted by Jason Rudolph on 20th May 2008

InfoQ recently posted the video of my presentation on Grails from QCon San Francisco. If 50 slides in 50 minutes sounds a tad formulaic and tired to you, then you’re in luck. Instead, you’ll see 50 slides in about 5 minutes, followed immediately by 50 minutes of no-nonsense live coding goodness.

QCon Logo

In what could perhaps be described as a series of 12 back-to-back lightning talks, you can see what it takes to go from a blank slate to a deployable Grails app including…

  • defining domain classes,
  • setting up relationships,
  • hooking up a database,
  • establishing constraints and validation error messages,
  • enjoying sexy dynamic finders,
  • applying custom URL mappings,
  • working with tag libraries,
  • encapsulating business logic in services,
  • integrating with existing Java code,
  • sending e-mail,
  • finding and installing plugins, and
  • locking down the app with secure authentication and authorization

There’s some good Q & A in there as well. Unfortunately not all of the questions came through on the audio, but in most cases you can pick up the context from the reply.

You’ll also hear me reference Charles Nutter’s JRuby talk a few times over the course of the presentation, and I recommend checking out that video as well.

Tags: , , , , , | No Comments »

history meme

Posted by Jason Rudolph on 16th April 2008

Rob dared me to fire up my favorite shell and jump into the game. Imagine my disappointment when I was greeted with this bummer of an error message.

20080416 History Meme Commodore 64

Hmm. No dice. OK, on to my second choice.

  1. jason@jmac:~> history | awk ‘{a[$2]++}END{for(i in a){print a[i] " " i}}’ | sort -rn | head
  2. 48 cd
  3. 30 exit
  4. 29 m
  5. 20 ls
  6. 18 git
  7. 13 mman
  8. 12 **
  9. 10 cap1
  10. 9 ssh
  11. 9 rake


The result? A few well-known friends and some that likely deserve a bit of elaboration.

Tags: , , , , , | No Comments »

Interview at Groovy Zone

Posted by Jason Rudolph on 3rd April 2008

Andres Almiray interviewed me this week for the Groovy Zone. We cover a breadth of topics, including:

  • Just how far Grails has come in the past two years
  • Why the GORM DSL likely obviates previous mapping techniques
  • Groovy as a gateway drug to more and better developer testing
  • Why Grails testing infrastructure improvements deserve top billing in Grails 1.1
  • Something called Rails
  • New testing-related developments in the Groovy ecosystem

For all that and more, check out the interview at Groovy Zone, a new(ish) and hoppin’ community for Groovy and Grails news.

20080404 DZone Logo

(Did I mention that we discuss testing?)

Many thanks to Andres and DZone for the interview.

Tags: , , , , , , | 2 Comments »

Noteworthy Nonsense - March 9, 2008

Posted by Jason Rudolph on 9th March 2008

In the spirit of Andy Glover’s Weekly Bag and Bill Dupre’s frequent batches of Whatever, herein lies the first installment in a (sure-to-be-sporadic) series of Noteworthy Nonsense.

  • iPhone web app authors rejoice! (Yes. You read that right. Web-app authors.) Test your web apps using the official iPhone simulator. (And, oh yeah, you can go native now too…but the lack of RubyCocoa support is a bit of a downer.)

  • A plugin that lets you run Struts 1.x code inside a Grails app? Yeah, I cringed too, but this will surely be a welcome migration path for those folks trapped in the land of *.do.

  • Are SVN users suffering from the Blub paradox? Linus pulls no punches in offering up his take on this matter.

  • Dan Benjamin’s back with the Leopard edition of his definitive “how-to” guide for rolling your own installation of Ruby, Rails, and friends.

  • The last time Glen Smith declared a month o’ Grails, he showed the community just how very much is possible with merely an hour a day. Now Glen’s at it again, but this time it’s MockFor(March). If history is any indicator, expect Glen to blaze new trails in the land of Grails unit testing. Glen: It takes GUTs, but I’m rootin’ for you!

  • Speaking of good unit tests, Jay Fields announced a new version of the expectations gem, complete with a healthy dose of example code. One expectation per test? Saying “goodbye” to cumbersome test names? Jay’s onto something here.

Tags: , , , , , , | No Comments »

test/spec/rails => You Bettuh Recognize

Posted by Jason Rudolph on 8th February 2008

Believe it or not, there are still at least a few of us crazy hold-outs that still haven’t imbibed the increasingly ubiquitous RSpec Kool-Aid. And for the folks in this crowd that still want BDD-style testing, it’s test-spec and test/spec/rails all the way. So when I recently needed a means for validating that a nontrivial route landed in the right controller/action, I naturally went looking for the test/spec/rails equivalent of #assert_recognizes. When I saw that it was nowhere to be found, I knew I’d found another task for Open Source Fridays (er, the first half hour of an Open Source Friday). And thanks to Matthew Bass’s uncanny responsiveness in applying the patch that Rob Sanheim and I submitted, test/spec/rails now offers some handy new specs for testing your routes.

assert_generates => should.route_to

Where you’d use #assert_generates in traditional Rails + test/unit, test/spec/rails now supports #route_to as a more spec-flavored alternative. For example, to verify that a given set of URL options routes to the expected path…

  1. assert_generates "/users/1", :controller => "users", :action => "show", :id  => "1"


becomes

  1. {:controller => "users", :action => "show", :id  => "1"}.should.route_to "/users/1"

assert_recognizes => should.route_from

And where our ancestors once used #assert_recognizes, test/spec/rails now offers #you_bettuh_recognize #route_from. “An example would be nice”, you say? Well, to perform essentially the inverse of the above test…

  1. assert_recognizes({:controller => "users", :action => "show", :id => "1"}, {:path => "/users/1", :method => :get})
 
becomes

  1. {:path => "/users/1", :method => :get}.should.route_from :controller => "users", :action => "show", :id =>"1"


- - -

The rdoc offers additional examples, and check out the test/spec/rails README for more mappings from old-school test/unit assertions to test/spec/rails equivalents.

Tags: , , | No Comments »

Making acts_as_solr Act As Deployable

Posted by Jason Rudolph on 26th November 2007

We recently deployed two new Solr-powered apps, and thanks to acts_as_solr, most of the task of integrating Solr with Rails was downright trivial. Deployment, however, came with a few small roadbumps.

Solr

Know when to nohup

When using acts_as_solr locally, you start and stop Solr via the provided rake tasks (i.e., rake solr:start and rake solr:stop). However, when you run the solr:start task, you’ll quickly notice that all of the would-be log output is right there in your face, and definitely not in some well-tucked-away log file. During development, we didn’t think too much of it. Just open a new terminal tab, start Solr, and get back to devving.

But then came time for deployment. Try to run the vanilla solr:start task as part of a Capistrano deployment, and you’ll quickly be looking for another option. As you watch your deploy script run, here comes all that same output you’ve been seeing locally … but when Cap completes, Solr calls it quits. We need a way to tell Solr to keep running in the background, even after Cap finishes doing its thing.

  1. nohup rake solr:start > #{shared_path}/log/solr.log 2> #{shared_path}/log/solr.err.log

 
(Incidentally, you may want to employ this solution for your local Solr instance as well. After all, that’ll be one fewer terminal window cluttering your workspace.)

Dude, where’s my index?

Now that you have a reliable means for starting and stopping Solr, it’s time to decide where you want to store your index files. By default, acts_as_solr defines SOLR_PATH as #{RAILS_ROOT}/vendor/plugins/acts_as_solr/solr, which means that Solr will store your index files in #{RAILS_ROOT}/vendor/plugins/acts_as_solr/solr/#{RAILS_ENV}/solr/data/#{RAILS_ENV}/index. If you keep that setup, what happens when you deploy a new release of your app? You guessed it: your index files get left behind with the old release.

But that’s almost certainly not the behavior you want. The index files represent data, not application code. You don’t move your database every time you deploy a new release, and you shouldn’t move - or even worse, recreate - your Solr indexes with every release either. (Yes. Just as some releases require database changes, so will some releases require reindexing. But, it’s definitely not a need for every release, and it therefore shouldn’t be your normal practice.)

At this point, you have a few choices, but the goal with each choice remains the same: find a home for the Solr indexes to allow them to survive across multiple deployments. First, copy #{RAILS_ROOT}/vendor/plugins/acts_as_solr/solr to a release-independent location in your deployment environment. Then, you just need to tell your application where to find that directory. Ultimately, SOLR_PATH needs to point to that location. If you don’t want to change the default acts_as_solr settings, then you can configure your deployment script to symlink the copied directory into the location where acts_as_solr expects to find it (i.e., #{RAILS_ROOT}/vendor/plugins/acts_as_solr/solr). Otherwise, you can simply change the definition of SOLR_PATH (defined in #{RAILS_ROOT}/vendor/plugins/acts_as_solr/config/environment.rb) to point to your release-independent directory.

Know your role

Now you have a home for our Solr indexes and you have an easy way to start and stop Solr via Capistrano, but where exactly should Solr itself run? We all want highly performant apps, so you may be tempted to consider running Solr on multiple servers. More is always better. Right?

STOP!

Your app communicates with Solr via HTTP, so Solr can live anywhere on your network. It doesn’t need to live on the same box as your app, as your database, etc. And while you technically could run Solr on all your app servers, it’s highly unlikely that you’ll want to do so. Think about the problems associated with managing redundant databases. Do you really want to manage multiple sets of Solr indexes and try to make sure they all have the same data? Unless you’re Google - in which case, this stuff is your bread and butter - of course not.

If you store the indexes in a shared location and have all the Solr servers use the same indexes, does that make things any easier? Well, you no longer have to keep multiple indexes in sync, but you now have a different problem: data corruption. Solr isn’t designed to share indexes among multiple Solr processes, and when two processes try to update the same indexes, you’re in for all kinds of trouble. UPDATE: Solr isn’t designed to have multiple Solr processes updating a shared set of indexes. (As Hoss points out in the comments, Solr is capable of supporting a distributed installation, but all changes are routed to a single master Solr instance, and multiple query slaves receive the updates from the master.)

So let’s steer clear of all that trouble and find an easy way to run Solr on a single server, while having all your app servers talk to that Solr instance. First up, define a distinct role for the server where you want Solr to run.

  1. task :production do
  2.   role :web, ‘app.example.com’
  3.   role :app, ‘app.example.com’
  4.   role :solr, ’solr.example.com’
  5.   role :db, ‘db.example.com’
  6. end

 

Next, simply define the tasks needed to start and stop Solr on that server, and you’re good to go. (Also notice that we include a task to symlink in the Solr indexes from the release-independent directory discussed above.)

  1. before "deploy:update_code", "solr:stop"
  2. after "deploy:symlink", "solr:symlink"
  3. after "solr:symlink", "solr:start"
  4.  
  5. namespace :solr do
  6.   desc "Link in solr directory"
  7.   task :symlink, :roles => :solr do
  8.     run <<-CMD
  9.       cd #{release_path} &&
  10.       ln -nfs #{shared_path}/solr #{release_path}/solr
  11.     CMD
  12.   end
  13.  
  14.   desc "Before update_code you want to stop SOLR in a specific environment"
  15.   task :stop, :roles => :solr do
  16.     run <<-CMD
  17.       cd #{current_path} &&
  18.       rake solr:stop RAILS_ENV=#{env}
  19.     CMD
  20.   end
  21.  
  22.   desc "After update_code you want to restart SOLR in a specific environment"
  23.   task :start, :roles => :solr do
  24.     run <<-CMD
  25.       cd #{current_path} &&
  26.       nohup rake solr:start RAILS_ENV=#{env} > #{shared_path}/log/solr.log 2> #{shared_path}/log/solr.err.log
  27.     CMD
  28.   end
  29. end

 

And with that little bit of setup, you’re ready to rock! (Well, er, as much as one can rock to full-text search.)

If you want full-text search in your Rails app, definitely take acts_as_solr for a spin. You’ll be up and running in no time, and chances are your users will love the new dimension that full-text search brings to your application.

Looking ahead

As for us, now that these apps are live and flexing all their Solr might, we’re on to looking for ways to make them better, faster, stronger. Long term, we definitely don’t want to maintain the default behavior of synchronously waiting for acts_as_solr to make the call to Solr (in order to update the indexes) each time we save a Solr-enabled ActiveRecord model object. In our apps, it’s more important that we quickly save the object and provide a prompt response back to the user. If it then takes a few seconds of background processing before that change is reflected in Solr, that’s perfectly acceptable (and much preferred over causing the user to wait for us to update the Solr indexes). At least one open source project is already dedicated to mitigating this issue, and we hope to explore this and various asynchronous solutions in the near future.

Tags: , | 2 Comments »

Relevance is Hiring!

Posted by Jason Rudolph on 3rd November 2007

Smart developers. Really.

Working together.

In small teams.

Using the best tools available.

Embracing true agility.

Pushing each other.

And giving back.

In the constant pursuit of excellence.

Relevance

Are you in?

Then check us out.

And let’s hear it: jobs@thinkrelevance.com

Tags: , , , , | No Comments »

Evan Phoenix on Testing Private Methods in Ruby

Posted by Jason Rudolph on 2nd November 2007

At RubyConf today, Stuart Halloway’s Refactotum workshop led to a brief but excellent discussion on the various approaches for testing private methods in Ruby. Ideas ranged from the typical solution of using #send (which won’t work once Ruby 1.9 lands) to Ryan Davis’s technique of simply making everything public. Evan Phoenix, on the other hand, suggested a solution that avoids the soon-to-be-brokeness of using #send while still allowing you to benefit from the inherent intent expressed by defining a method as private.

To demonstrate, let’s assume we have the following (admittedly contrived) class:

  1. class Ninja
  2.   private
  3.     def kill(num_victims)
  4.       "#{num_victims} victims are no longer with us."
  5.     end
  6. end

 
So how can we make sure that the private method is doing what we want, and do so while testing it in isolation? Why not temporarily define a new public method that simply passes through to our elusive private method?

  1. require ‘test/unit’
  2.  
  3. class NinjaTest < Test::Unit::TestCase
  4.   def test_should_punish_sloppy_coders
  5.     @ninja = Ninja.new
  6.     def @ninja.flog_publicly(*args)
  7.       kill(*args)
  8.     end
  9.     assert_equal ‘3 victims are no longer with us.’, @ninja.flog_publicly(3)
  10.   end
  11. end

 
Sweet!

  1. src> ruby ninja.rb
  2. Loaded suite ninja
  3. Started
  4. .
  5. Finished in 0.000274 seconds.
  6.  
  7. 1 tests, 1 assertions, 0 failures, 0 errors

 

Tags: , | 3 Comments »

RubyConf.new(”2007″).observe(:order => :random)

Posted by Jason Rudolph on 2nd November 2007

Ruby Logo

  • It turns out that hotels prefer that you not bring your own bottles of scotch to the bar. Who knew?

  • Marcel Molina explains the three pillars of beautiful code as: proportion, integrity, and clarity.

  • Jim Weirich gives kudos to Groovy as the inspiration for Ruby’s Builder library. (Cool! Cross-pollination goes both ways. Not a zero-sum game. Rinse. Lather. Repeat.)

  • If you show up at RubyConf with a Compaq, apparently you spend the morning calculating the distance to the nearest Apple store.

Compaq Love

  • David Black reminds the “veeee-gans” that they’re special.

  • Nathaniel Talbott: Camping matters because it gets your mind off the drug and refocuses you on the addiction. (OK. Perhaps I paraphrased.)

  • Taking a short break to push a new app live to the world - there’s some darn good satisfaction in that!

  • Ryan Davis: Flog your code. Heckle your tests. And while you’re at it, flog your feeds, flog your daily habits, and ask your boss and your coworkers to flog you. You’ll be better because of it.

  • Wisdom of Matz

    • When asked about his second favorite programming language: “I love all programming languages, except for several.”
    • On working with Apple: Some brief comments on his assistance with Leopard, but offers that “Ruby on the next version of OS X will be even better.” (Hmmm. Speculation about a future Apple product. I suspect that Apple’s legal hounds all paused momentarily as they detected a distant disturbance in the force. Regardless, let’s hope he’s right. Some other languages haven’t been so fortunate.)
    • When asked what kind of programming he does day-to-day: “Ruby.” Ha! Go figure.
    • On whether Ruby is suitable as a first programming language to learn: “Some parents don’t give their children sharp knives, but some do.”

Tags: , | No Comments »

Streamlined 0.9 Released - Stop banging rocks together and build something!

Posted by Jason Rudolph on 13th September 2007

Streamlined 0.9 is now available for download. From the rich and handy quick-add interface to the super-flexible and highly-interactive advanced filtering, this release packs a big punch in terms of quickly empowering your end users with a serious data management interface. In addition to introducing the aforementioned heavy hitters, it also makes standard many common idioms to increase the overall usability of your apps (e.g., auto-labeling for required fields) and offers some optional usability enhancers (mmmm, tasty breadcrumbs) as well.

Of course, those are just some of the many improvements available in Streamlined 0.9. Be sure to check out the release notes for full details, including screen shots and links to additional docs.

As we approach 1.0, Streamlined continues to position itself as the solution for developing an instant, production-ready UI for your ActiveRecord models. So, what are you waiting for? Stop banging rocks together and build something!

Tags: , , | 2 Comments »