Ruby AST Tools talk at Raleigh.rb

Mar 26, 2009 in Ruby, Talks

Last week I presented at Raleigh.rb (the local Ruby Brigade) on the Ruby AST and the tools that are available to work with it. I went over briefly what the AST is and the 2 mains ways of getting it in Ruby 1.8.x, ParseTree and ruby_parser.

There’s two types of tools that are generally built on top of ParseTree: code analytics and custom DSLs. I covered 3 of them flog, roodi, and ambition. The first two being code analytics libraries and the second being a custom DSL.

My slides can be found up at SlideShare:

And if you attended you can rate my talk on SpeakerRate.com: http://speakerrate.com/talks/594-ruby-ast-tools

And here’s some more resources for those interested in learning more about the Ruby AST:

Tags: , , , , , ,


Use Twimailer and keep your twitter email address.

Mar 09, 2009 in Tips & Tricks

Recently I started using Twimailer to get improved Twitter follow emails. Shortly after @eliah reminded me that people wouldn’t be able to find me via my email address anymore when using this service.
That seemed like a big Fail to me.

I quickly worked up a hack that gets me both:

  1. Keep your Twitter email address as my gmail address.
  2. Then add a filter in Gmail that takes all emails from “twitter-follow-GMAILUSERNAME=gmail.com@postmaster.twitter.com” (replacing GMAILUSERNAME with your username of course) and with “following” in the subject, and archives them, marks them as read, and forwards them to your Twimailer email address.

Gmail filter to for Twimailer

This works perfectly I keep my email address associated with my twitter account and get the enhanced follow emails.

If you don’t use gmail you could easily adapt this to work with whatever email service you use. You just have to get the service to forward the appropriate emails to the correct email address.

Twimailer is a wonderful service and getting to keep your email address findability on twitter with this trick takes out any negatives from the service leaving just the good stuff.

Tags: , , ,


Facebox for Lowpro

Nov 09, 2008 in Javascript, Web Development

I really like both jQuery and Facebox but sometimes I do need to work with Prototype.

I found a couple of conversions of Facebox for Prototype. After finding these it didn’t take too much work to convert it to Lowpro.

The usage is simple:

Event.addBehavior({
  'a#fbox' : Facebox
});

The code can be found on GitHub.


Squish the slug the Rails way

Nov 06, 2008 in Ruby, Web Development

Recently Pat wrote about writing a quick method for making URL slugs. In the spirit of sharing I thought I’d mention a strategy I use in a number of the Rails apps I work on:

Take this code put it in a file named inflectors.rb in your config/initializers directory, and you’re good to go.

Tags: , , , ,


No Color for Git

Oct 21, 2008 in Git

While working with Git recently and git-submodules. I found myself getting an odd error:

error: pathspec '2eed4e6a42d0a50bb6587930659f943f9fae6c44' did not match any file(s) known to git.
Unable to checkout '2eed4e6a42d0a50bb6587930659f943f9fae6c44' in submodule path 'vendor/extensions/file_system'

This normally means you’ve changed a submodule and not properly handled updating it.

In this case though the repository would check out correctly on other users machines just fine. Odd thing was we were all using the same OS (MacOS X 10.5), the save version of git (1.6.0.1) from the same source (MacPorts), and most of the same external libraries installed via MacPorts. There was no real discernible difference we could find between machines.

After beating our heads enough times and enough fiddling around with my .profile, we found the cause. In my .profile I had the following lines:

GREP_OPTIONS="--color=always"
export GREP_OPTIONS
export GREP_COLOR='1;34;43'

These lines give me colored grep output which I personally find more useful than the non-colored variant. Problem is git uses grep for all sorts of functionality, and the colored output was throwing it off. The solution was to remove (or comment out) those lines from my .profile.

My problem here is just that if you simply run grep with the option “--color=never” the colored output would be disabled, resulting in no problems at all. That being said this clearly seems like a bug in git that will hopefully be fixed soon so I can go back to my colored grep output.

Tags: , , ,


`is_blank` Function for PHP

Mar 24, 2008 in PHP, Web Development

One thing I love from Rails is the ability to do a .blank? method on any object. This is infinitely useful when you can’t be sure what type of value a variable is, or if it can potentially be different types. This is something that I always miss in PHP. Indeed since form data always comes back as strings and different ORM’s and database connectors (PDO, Propel, Doctrine, mysqli, PEAR DB, PEAR MDB2, etc) return different types, having a generic “is this value essentially blank, null, false, empty” is important.

A while back I set out to try and duplicate this functionality in a PHP function. Over the course of the past few months I feel it’s slowly matured and become something extremely valuable that I can’t live without.

It returns true when ever it is sure a value is blank, and false otherwise. It considers NULL, and false to be blank, and true to be not blank at the start. It then considers integers of 0 to be blank, and floats of 0.0 to be blank. It considers any string that is only composed of blank space characters, or “0″’s to be blank. I have considered adding a string of “false” or “null” but for now I considered this not to be generalizable enough. I feel that a string just of “0″’s almost always counts as a blank value when I’m processing data, but I could possibly see a string of “false” or “null” representing a non-blank value.

Then we get to the difficult part, arrays. The function of course regards an empty array as blank, but it will also recursively (this is performed by calling its self) go through all elements and if they are all blank declare the whole array blank.
There is also the special case of Objects that developers wish to be considered enumerable/iterator/array-like objects. These are created by implementing the SPL iterator interfaces. So the function checks to see if the necessary interfaces are implemented, and if they are treats the object, exactly like it would an array.

The last rule is it considers all other objects to be not blank.

This function can of course be expanded or refined to meet your particular needs. If, for instance, you have a self-defined Null object that you use you get set that to return true. Or if you don’t want strings with just “0″ in them to return true, you can change that. The function is very simple and it should be obvious where you change things to get the result you want.

Here’s the code:

function is_blank($value){
   $type = gettype($value);
   switch ($type) {
      case 'NULL':
      return true;
      break;
      case 'boolean':
      if ($value === false)
         return true;
      break;
      case 'integer':
      if ($value == 0)
         return true;
      break;
      case 'double':
      if ($value == 0.0)
         return true;
      break;
      case 'string':
      if (preg_match('/^\s*0*\s*$/', $value))
         return true;
      break;
      case 'array':
      if (count($value) == 0)
      {
         return true;
      }
      else {
         $all_blank = true;
         foreach ($value as $item) {
            if (!is_blank($item)){
               $all_blank = false;
            }
         }
         if ($all_blank){
            return true;
         } else {
            return false;
         }
      }
      break;
      case 'object':
      $implements = class_implements($value);
      if (
         in_array('ArrayAccess', $implements) && 
      (
         in_array('IteratorAggregate', $implements)  || 
         in_array('Iterator', $implements)           || 
         in_array('SeekableIterator', $implements)   || 
         in_array('RecursiveIterator', $implements)
         ) && 
         in_array('Countable', $implements)
         )
      {
         if (count($value) == 0)
         {
            return true;
         }
         else {
            $all_blank = true;

            foreach ($value as $item) {
               if (!is_blank($item)){
                  $all_blank = false;
               }
            }

            if ($all_blank){
               return true;
            } else {
               return false;
            }
         }
      }
      break;
      default:
      return false;
      break;
   }
   return false;
}

Pastie: http://pastie.textmate.org/169940
Pastie code download: http://pastie.textmate.org/pastes/169940/download

Tags: , , , ,


:include_blank => options

Mar 10, 2008 in Ruby, Web Development

So one minor thing I found annoying while working on Heelshousing was that, options_for_select, and options_from_collection_for_select didn’t accept an option or argument for :include_blank. So I created a little file called “include_blank_options.rb” that I threw in my “config/initializers” directory. Here’s the code:

module ActionView::Helpers::FormOptionsHelper
         
   def options_for_select_with_include_blank(container, selected = nil, include_blank = false)
      options = options_for_select_without_include_blank(container, selected)
      if include_blank
         options = "<option value=\"\">#{include_blank if include_blank.kind_of?(String)}</option>\n" + options
      end
      options
   end
   alias_method_chain :options_for_select, :include_blank
   
   def options_from_collection_for_select_with_include_blank(collection, value_method, text_method, selected = nil, include_blank = false)
      options = options_from_collection_for_select_without_include_blank(collection, value_method, text_method, selected)
      if include_blank
         options = "<option value=\"\">#{include_blank if include_blank.kind_of?(String)}</option>\n" + options
      end
      options
   end
   alias_method_chain :options_from_collection_for_select, :include_blank
   
end

Tags: , , ,


New Release of UJS Date-Picker Rails Plugin

Mar 08, 2008 in Ruby, Web Development

I’ve now updated my date-picker Rails plugin based on Brian McAllister’s Unobtrusive Date-Picker Widget. It now includes helper methods for making selects that wrap a ActiveRecord model object, or just a date/time value. It also includes many more options, mostly offering pragmatic ways of adding the options available to controlling the date-picker widget through html classes.

I’ve also created a large number of specs (with RSpec) for testing the plugin. Amazingly, testing plugins is actually really hard task, which I’ll probablly cover in a future post.

I’ve created a wiki page for Documentation and updated the RDoc’s.

If your using the plugin, and have any questions or concerns, or bug reports feel free to contact me.

Tags: , , , ,


Converting Video to Flash in Rails

Mar 07, 2008 in Ruby, Web Development

Video is fairly prevalent on the web these days with services like YouTube, and Joost. And indeed one the features that our client (the Daily Tar Heel) wanted for HeelsHousing was to have a video tour of properties.

I wanted to take the YouTube model and allow property owners to upload videos in any format they had them in and for us to show them in Flash video so that as many users as possible would be able to view it. So I set out constructing the process via which this would occur.
It would start out with a user uploading a video. The file would be moved to a temporary location (although a Tempfile object could not be used as these files get deleted automatically, i.e. before the background process would get to it). This path would have to be saved, and status value given. Then a background process would have to be passed this information to convert the movie, make a preview image, and upload both to Amazon S3, then saving the record as finished. Additionally, this background process would need to notify the property owner if either an error processing the video occurred or it had been successfully converted and uploaded.

The video model class I created is very similar in many ways to the functionality offered by the attachment fu plugin. It handles taking the uploaded file and moving it to a temporary location, it deletes the files when the record is deleted, it keeps track of the preview image and video file paths on S3. It also has a status attribute for the different statuses a video can have: queued, processing, ready, and failed.

The most complicated part of the whole process is how to handle the file once it’s been uploaded and temporarily stored. This needs to be handled by a background process, for Rails the obvious choice is the BackgrounDRb plugin. The background worker I created starts by grabbing the related video record, and sets it’s status to “processing”. It then uses the RVideo library, which in turn uses ffmpeg and flvtool2, to scale the movie and convert it to flash video. Finally, it uses RVideo to make a preview jpeg image, and uploads both to S3.
If anywhere along the way an error occurs the video record’s status is set to “failed” and a notification email is sent to both the property owner and the administrator using ActionMailer. On the other hand if the whole process succeeds the worker sends an email to the property owner only, and marks the video record as “ready”.

The last step was to display the video on a given page. To do this I used SWFObject and the JW FLV Media Player. I created a simple helper to create the SWFObject javascript for the video.

All of the external libraries I can say were very easy to work with, and made creating this functionality much easier. But the one I loved the most was RVideo. This library is a little gem for anyone wanting to script out ffmpeg or flvtool2 commands in Ruby. I highly recommend it.

Tags: , , , , , , , , ,


Customizing ActiveScaffold

Mar 04, 2008 in Ruby, Web Development

At first I was a little skeptical about the ability of ActiveScaffold to really do everything I needed to do, and not involve massive amounts of hacking apart the code. It actually turned out to be fairly easy and offered a great solution for some of the administrative side of HeelsHousing.

First off while not very well documented in my opinion is the ability of rails to have and understand sub controllers, such as the URI “/admin/users” which would be the controller in “app/controllers/admin/users_controller.rb”. To do this just requires some code like this:

app/controllers/admin_controller.rb

class AdminController < ApplicationControllerend

module Admin
end

app/controllers/admin/user_controller.rb

class Admin::UsersController < AdminController

   active_scaffold :user do |config|end

end

Of course the main thing we wanted to do was to style it to match other administrative interfaces we were using. In case you don’t know already the ActiveScaffold team really thought ahead on this one and allows customization at pretty much every level. For sweaping changes that effect style most likely you’re looking at Template Overrides. Since we were looking to have all administrative forms look the same we just had to provide new template in the “app/views/active_scaffold_overrides/” directory. The templates that I found were needed for really doing what I we needed to do to change the look of the forms were the “_form.rhtml”, “_form_association.rhtml”, “_form_association_record.rhtml”, and “_form_attribute.rhtml” templates.

Of course you also often want to change the specifics of how a specific form input is generated for a given column is generated. And for this there’s Form Overrides. These are just little helpers in the helper file for the given controller. So say you want to change the type of input used for your password column on the User form, just add a method called “password\_form \_column” in the “user.helper.rb” file.
But let’s say you want to change all columns that are strings to function in a specific way, like say setting the size and maxlength attributes, well here ya go:

Article.columns.each do |column|
   if column.type == :string
      size = (column.limit > 59) ? 60 : column.limit + 1
      src = <<-end_src
         def #{column.name}_form_column(record, input_name)
            text_field(:record, '#{column.name}', :size => #{size}, :maxlength => #{column.limit}, :name => input_name)
         end
      end_src
      class_eval src, __FILE__, __LINE__
   end
end

Well there’s really lots more I could cover about active scaffold but I’ll let you sophisticats check it out for yourself. The documentation is top notch. All in all a great addition to your Rails toolbox.

Tags: , , , ,