Agile Tortoise

Greg Pierce’s blog

Tech refresh for the company site

With time that would probably have been better invested in actually improving the content of the site, I instead re-deployed my Agile Tortoise company website, in a far more buzzword compliant fashion. That’s right, rather than running on Rails 1.1.6, behind FastCGI on Apache 1.3 on a shared host with code in Subversion and deployment courtesy of Capistrano 1.4.1 — It’s now under Git, updated to Rails 2.0.2, deployed with Capistrano 2.3 to a Ubuntu (Hardy Heron) VPS running Apache 2 with mod_rails.

So, ladies and gents, I’m serving up my stale content with style! And, well, I’ve learned quite a bit in the process. Git really rocks, too. I can actually do functional and complex branching and merging it in, which I never mastered in Subversion.

Posted in Ruby on Rails, Work | No Comments »

Strip “.svn” folder from Subversion working copy

It seems like there's probably a much easier way to do this, but I had a Rails project under Subversion, where I lost access to the original repository.  In a perfect world, you'd just do an export from the repo to get a clean copy of the code, but I could do that -- so I just wanted to strip out the ".svn" directories to make what I had on disk a clean version.  So I wrote the below. Seemed to work fine. Project now under Git. That is all.

RUBY:
  1. require 'find'
  2. require 'fileutils'
  3.  
  4. def find_and_delete(path, pattern)
  5.   Find.find(path) do |f|
  6.     if !File.file?(f) and f[pattern]
  7.       FileUtils.rm_rf(f)
  8.     end
  9.   end
  10. end
  11.  
  12. # print all the ruby files
  13. find_and_delete(".", /\.svn$/)

Posted in Misc | No Comments »

LOL License

Ok, Adam's bad DL pic got me inspired to post my own, make of it what you will.

Posted in Family and Friends | 1 Comment »

Servoy: Transactions are awesome! I hate transactions!

It's a fact that transactions are important to data integrity in a relational database application. It's also a fact that I find them burdensome and not particularly friendly to integrate in my development process. Why? Well, in a development system, you really don't care about data integrity. It's not real data. You also want as little crud in your code as possible that obscure failure points -- like try/catch/finally blocks. And try/catch/finally blocks are typically how you go about managing transactions.

So, what to do? Well, I've decided to punt on transactions as much as possible. For the most part, transactions are necessary on more complex operations that alter data in a number of different tables. In my Servoy applications, I always write processing like this in a global method -- typically that takes records or id's in the parameters, and does all the heavy lifting. Then I write very simple methods on forms that attach to the buttons, throw up a confirmation dialog (maybe) and forward to the global.

In development, I do not incorporate transactions into these global methods. I call them directly, I test them, I look for failure points, without the lack of clarity caused by the try blocks and transactions. Then, in production, on my button-click methods (or where ever I'm calling from), instead of calling the global method directly, I call it via this wrapper method:

JavaScript:
  1. // globals.db_transactionWrapper method
  2. var methodName = arguments[0];
  3. var result;
  4. // start the transaction
  5. if( !databaseManager.hasTransaction() )
  6.  databaseManager.startTransaction()
  7. // call the method with remaining arguments (up to 5 args supported, though you could add more cases
  8. try {
  9.  switch(arguments.length)
  10.  {
  11.    case 1 : result = globals[methodName](); break;
  12.    case 2 : result = globals[methodName](arguments[1]); break;
  13.    case 3 : result = globals[methodName](arguments[1], arguments[2]); break;
  14.    case 4 : result = globals[methodName](arguments[1], arguments[2], arguments[3]); break;
  15.    case 5 : result = globals[methodName](arguments[1], arguments[2], arguments[3], arguments[4]); break;
  16.    case 6 : result = globals[methodName](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); break;
  17.    default : throw 'ArgumentError';
  18.  }
  19. }
  20. catch(e)
  21. {
  22. // rollback if a failure occured
  23.  databaseManager.rollbackTransaction()
  24. // re-throw the exception so you can handle it in your solution's on_error method.
  25.  throw(e);
  26. }
  27.  
  28. // everything's good -- commit the transaction and return the result
  29. databaseManager.commitTransaction();
  30. return result;

Usage for this method looks like:

JavaScript:
  1. globals.db_transactionWrapper( [globalMethodName], [argumentsForGlobalMethod], etc.);

The wrapper method takes care of the transaction handling, and forwards the call on to the appropriate global method to do the work, returning the same result.

This has a number of advantages. Of course, as mentioned, it relieves you of managing transactions in all of your methods. It also gives you the flexibility to call the methods without transactions if desired -- or to nest the calls to multiple methods in a single transaction when appropriate.

Posted in Servoy | 2 Comments »

Perfunctory “I’m still alive” post

Wow, I really don't blog anymore. The inane chatter has moved to Twitter. The personal stuff long ago moved to the family blog. I could say I'm busy, which would be true, but it's probably also that I'm lazy. Oh, and I've been sick.

But, I'm also still alive and will probably eventually have something to say again. Maybe. Or not.

Posted in Family and Friends | No Comments »

Chronic “smart” date update

b.logi.cx posted an elegant and more complete solution to incorporating Chronic date fields in your ActiveRecord models. my version was certainly hack-ish.

I started on a simple helper plugin to use for AJAX previews of chronic's parsing. Hopefully I'll have something release on that before too long.

Posted in Ruby on Rails | No Comments »

Fat Frank on TV

My Uncle Robert, aka "Fat Frank" of Fat Frank and the Plank Spankers, is going to appear on this week's installment of the Antique Roadshow on PBS. He'll be the one with the Ukelele. If you can't catch that, you can always just watch him on YouTube.

Posted in Family and Friends, TV | No Comments »

Rails and Chronic, easy ’smart’ date fields

There are quite a few Ruby on Rails plugins to give you nice Calendar drop downs for date selection...but, I'm much more partial to the style of fuzzy date entry you see in a lot of apps now, allowing you to enter common strings and have the app figure out the date -- ie, "next friday", "tomorrow", etc. With a pointer from Mike yesterday to the excellent Chronic gem, I was on my way.

Chronic does all the hard work, just install it...

CODE:
  1. gem install chronic

Then, in your views, use a text_field for your date...

RUBY:
  1. <% form_for :model do |f| %>
  2. <% f.text_field :date_attr_name %>
  3. <% end %>

In your model, you'll want to then use Chronic to parse the pre-cast value of the date attribute using the _before_type_cast methods...

RUBY:
  1. require 'chronic'
  2.  
  3. class MyModel <ActiveRecord::Base
  4.  
  5.   def before_save
  6.     self.date_attr_name = Chronic.parse(self.date_attr_name_before_type_cast) if self.date_attr_name_before_type_cast
  7.   end
  8.  
  9. end

I expect I'm going to find that I need to tweak this a little -- and I'm pretty sure I'll want to write a helper that will give the user a AJAX preview of the parsed date before the submit the form, but, it definitely beats the lousy Rails built-in date_select method.

Posted in Ruby on Rails | 2 Comments »

Using the Google Maps API geocoder in Servoy

I've posted a Servoy module that demonstrates how to make HTTP REST calls to the Google Maps API geocoder to get back a variety of useful information (such as Long/Lat) of a query address. Download here.

Posted in Servoy | No Comments »

RIP, Maxie

I had to put down my dog this week. She was 11 1/2 years old, and was, essentially, our first "baby." I had always thought she'd live to be a really old dog, because she was so energetic and active...but, cancer doesn't much care about those things. Katie and I got her together, the year we were married, though it was pretty clear over time that Maxie considered herself my dog.

She was a mutt. Played frisbee and fetched, chased squirrels, climbed trees (really, she did), barked at anyone who came near the house, loved to have her ears rubbed and generally did all those things that make a person love their dog -- which I did.

She was smart and a really good dog. She was always great around the kids, though I'm sure she resented them -- at least until they got big enough to throw her a ball and pet her. She mostly didn't get into things she shouldn't (except tissues. she loved tissues), and didn't annoy the neighbors.

So far the boys are taking it pretty well, and I'm dealing. Being so busy with Christmas probably helps. I'm sure we'll get another dog someday, but right now we're getting used to the fact that despite the constant chaos of a 3 child household it seems pretty quiet around here.

Posted in Family and Friends | No Comments »

Servoy 4.0 preview

On Wednesday, Servoy offered a preview webinar for the changes coming in version 4 -- due for public beta in January, and aimed for release in late Q2 2008. The most high-profile change in this release is the move to Eclipse platform for an IDE, abandoning the somewhat limited proprietary IDE in current versions of Servoy.

This is an interesting move strategically for Servoy. Personally, I'm thrilled. I use Eclipse, it's a top-notch IDE and will offer Servoy lots and lots of developer features that would otherwise likely not exist due to the resources it would require to develop them internally. I think for many Servoy developers, it's a little intimidating -- since many have come from Filemaker or 4GL environments where a lot of things are managed for you. I expect, however, that Servoy will do a good job of hiding the complexity from those who are not interested in it.

For developers who use SVN, add Java, XML or other to their Servoy solutions, it will be an incredible advantage. Need to use XML in your Servoy solution? Why not use Oxygen XML, right in your Eclipse installation to edit it? Good stuff.

Moving to file-based solutions will be great, too, and make it a lot easy to manage modules, and moving code around between solutions -- which is quite burdensome to manage with the current SQL-based repository.

Overall, I'm excited about the possibilities -- and look forward to getting my hands on the beta!

Posted in Servoy | 3 Comments »

Flotsam or jetsam?

So, is a garbarge truck in a swimming pool flotsam or jetsam? OK, probably neither....but, there was one in a swimming pool a couple of blocks from our house tonight.

We went outside to go to dinner and found an entourage of News helicopters circling overhead at low altitude. We didn't know what was going on, but it certainly smelled of a "developing story" -- so we called Kt's mom and had her check the news for us. We drove by on the way back from dinner and saw the crane working on lifting it.

Interesting and unexpected diversion.

Posted in Family and Friends | 1 Comment »

Servoy: simple HTML progress bar

I have several places in Servoy solutions where it's nice to display a simple progress bar to the user. This is for workflows, where the user needs a visual for how far along they are on the task/job/etc. -- not for actual progress on executing code.

I wrote a simple global method you can call from a dataprovider calculation to get back an HTML table that mimics a progress bar. So, if I've got a field (or calculation) on a table "progress_percent", that returns the percent complete on a item, I can also create a method that calls this global, passing in the percent field as an argument, returning a nice little visual of the progress -- like this,

progress.jpg

And here's the code:

JavaScript:
  1. var progress = arguments[0];
  2. if ( progress == null )
  3.     return null;
  4.  
  5. var html = "<html><head>";
  6.  
  7. html += "<style>";
  8. html += "td{font: 8pt Arial;}\n";
  9. html += "td.green{background-color:#AAFFAA;}\n";
  10. html += "td.red{background-color:#FFAAD4;}\n";
  11. html += "</style>";
  12.  
  13. html += "</head><body>";
  14. html += "<table width='100%' cellspacing='1' cellpadding='0' border='0'>";
  15. html += "<tr>";
  16.  
  17. for( var ix = 0; ix <100; ix=ix+10 )
  18. {
  19.     if( ix <progress )
  20.         html += "<td class='green' nowrap='nowrap'>&nbsp;</td>";
  21.     else
  22.         html += "<td class='red' nowrap='nowrap'>&nbsp;</td>"
  23. }
  24.  
  25. html += "</tr>";
  26. html += "</table>";
  27. html += "</body></html>";
  28. return html;

Posted in Servoy | 1 Comment »

Servoy newsletter

Servoy was nice enough to acknowledge my Servoy-related blogging in their October newsletter. Nice compliment, thanks! Now, I just feel guilty about not blogging more. ;-)

Posted in Servoy | No Comments »

Agile Tortoise Widget

Ok, really just an excuse to play with Dashcode, but, yes, ladies and gentlemen, I now have a custom Dashboard Widget for this blog. Please download if you're of the OS X persuasion.

Posted in Apple, Blogging | No Comments »

« Previous Entries