Splitting Strings in Ruby with Regular Expressions

Sometimes you need to split into parts and splitting on a sub string just won’t cut it. One such example I ran across the other day involved splitting a string containing file paths. The given string would contain a number of file paths (such as folder/cuke.feature). This string would then be split at each space. However, sometimes the file path could contain spaces. This resulted in an incorrect array of files.

"folder/cuke.feature folder two/cuke.feature".split
# => [ "folder/cuke.feature:2", "folder", "two/cuke.feature:4" ]

This would cause problems when cucumber would look for a feature file that didn’t exist.

In Ruby, split can take a regular expression as a parameter (Note that using a regular expression to split will also add the empty string “” to your result). By adding the following to the split above the correct file paths are obtained. The empty string can be discarded and the results can be trimmed to remove excess white space.

"folder/cuke.feature folder two/cuke.feature".split(/(.*?\.feature.*?) /).collect(&:strip).reject(&:empty?)
# => [ "folder/cuke.feature", "folder two/cuke.feature" ]

The capture group in the regular expression is actually important. Without it, the sub string for the file paths would be discarded and the result would be different, so keep this in mind if your split string is missing things:

"folder/cuke.feature folder two/cuke.feature".split(/.*?\.feature.*? /)
# => ["", "folder two/cuke.feature"]

Customizing Cucumber Formatters

Note: example code can be found at the following github repo:https://github.com/callahat/cucumber_custom_print

Sometimes you come across a client that adamantly thinks they need more of a record from running tests than the output the standard formatters supply. In terms of the HTML formatter the client can see in the report the usual stats about how many scenarios ran, how long they took, and a listing of each scenario, each scenario step, and any error messages for failing scenarios. The “puts” method can allow for adding more of an audit trail by telling the formatter to include the text in the report. You can even pass in HTML tags to puts (and javascript) and it will wind up in your HTML report. And pretty report. And any other formatters you tell cucumber to use that listen to the puts method.

If you don’t want HTML markup getting dumped into your Pretty report you can add your own print methods to cucumber by monkey patching a few classes as well as your formatters. For example, consider the method “put_collapsible_list” that will take an array we want to display in the HTML report. Since this array might have a lot of information that we may or may not immediately care about we can make it hidden initially. To let cucumber know about this method, a few classes and modules need patched:

module Cucumber
  module RbSupport
    module RbWorld
      def put_collapsible_list(list_title, list)
        @__cucumber_runtime.put_collapsible_list(list_title, list)
      end
    end
  end
end

module Cucumber
  class Runtime
    module UserInterface
      def put_collapsible_list(list_title, list)
        @visitor.put_collapsible_list(list_title, list)
      end
    end
  end
end

module Cucumber
  class Runtime
    class ForProgrammingLanguages
      def_delegators :@user_interface,
                     :put_collapsible_list
    end
  end
end

module Cucumber
  module Ast
    # Walks the AST, executing steps and notifying listeners
    class TreeWalker
      def put_collapsible_list(list_title, list)
        broadcast(list_title, list)
      end
    end
  end
end

(I came about this solution by a combination of tracing many debug points, and a bit of trial and error).
Once the method has been added to the world, delegator created for it, added to the tree walker, and runtime, the formatter also needs this method defined. Formatters without this method will do nothing when the “put_collapsible_list” method is invoked in your step. From the example here is one way the method could look:

module Cucumber
  module Formatter
    class Html
      def put_collapsible_list(list_title, list)
        @delayed_messages << <<-HTML.strip
          <a onclick="ol=document.getElementById('#{list_title}'); ol.style.display = (ol.style.display == 'none' ? 'block' : 'none');return false">#{list_title} (click to expand/hide)</a>
          <ol id="#{list_title}" style="display:none;">
          #{list_helper(list)}
          </ol>
        HTML
      end

      def list_helper(list)
        list.to_a.flatten.inject("") do |a, item|
          a + <<-HTML
            <li>#{item}</li>
          HTML
        end
      end
    end
  end
end

For the HTML report, this markup and JS will end up in a blue box, and there will be a link you can click to show/hide the contents of the array in an ordered list.

Setting Volume in an Android Application

A search on how to set the volume in an android app yielded two methods. The first used AudioManager to set the stream volume. The second set the volume on the MediaPlayer object. After experimenting with both those methods, an important distinctions were observed.

mediaPlayer.setVolume(float left, float right)
Both parameters should be between 0.0 and 1.0 inclusive. According to the docs, these are both scalars. Passing in 1.0 for both will set the volume to the media player to be the max of the current volume for that stream.

In order to set the volume of the stream itself, using the AudioManager is necessary. For example, the media stream is turned all the way down but you want your app to make noise using that stream. Once the sound is finished, its polite to return the stream to the original volume set by the user. Resetting the volume can be accomplished by:
1. Save the original volume
2. Add a onCompletionListener to the MediaPayer object
3. In the onCompleteListener, reset the original stream volume.

Code to accomplish this would look something like this:

mp = MediaPlayer.create(context, resourceID);
final AudioManager audioManager = 
    (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
    int maxVol = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
    final int origVol = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
    audioManager.setStreamVolume(
        AudioManager.STREAM_MUSIC,
        maxVol , 0);

    mp.setOnCompletionListener(new OnCompletionListener(){
        @Override
        public void onCompletion(MediaPlayer mp) {
            audioManager.setStreamVolume(
                AudioManager.STREAM_MUSIC,
                origVol, 0);
        }
    });
}
mp.start();

Note: The above will play a sound at the max volume.

Droid and OpenGL

Recently I have been experimenting around with textures and openGL for the android phone. Using example code found online I put together something that drew simple sprites, using a square with a texture on it. This was working fine in the emulator, however, when sent to the phone, instead of the texture, there was just a white box. Someone posted a similar problem on stack overflow here. The phone I was using was indeed a Motorola Droid, and replacing

    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
        R.drawable.icon2);

with

    InputStream is = context.getResources().openRawResource(R.drawable.icon2);
    Bitmap bitmap = null;
    try {
        bitmap = BitmapFactory.decodeStream(is);
    } finally {
        try {
            is.close();
            is = null;
        } catch (IOException e) {
        }
    }

did the trick. The textures appeared again.

Click Listeners

A post at another blog describes three ways to attach click listeners (for elements such as buttons in Android applications). The first, the “Old Java [Object Oriented] Way”, way retrieves the object (ie, Button), and sets the onClickListener by creating an anonymous object which is passed to the button object. As he points out, this can be expensive in terms of memory, and can make for sloppy code.

The second way, The Shared Listener, uses a shared onClickListener object among all the [button] objects. A switch statement is used within the listener to determine which [button] object was hit and act accordingly. This still has the disadvantage of needing to retrieve the Button objects and attach the listener to each.

The third (and preferred way), the Declarative Approach, makes use of a method in the Activity to act as a shared listener and attaching that method in the XML via the “android:onClick” attribute. This relieves the burden of grabbing all your buttons in code and assinging them the listener method.

The added benifit of NOT using the first approach, as mentioned in the linked blog post, is a reduction of package size and a reduction in source bloat. To test how much memory was saved, a skeleton application was created. It consisted of five buttons linking to different activities (the fifth button was actually the quit button). When coded the first way, that is grabbing the button objects and assigning an anonymous object, the package size was about 17.8 Kb. When coded the third way, that is using the shared method and “android:onClick” attribute, the package size was 17.0 Kb.

Thats an overall savings of about 40 lines of code and 0.8 Kb (~4.5%) of package size for the above example.

SVN via WebDAV over HTTPS notes

Many guides exist for setting up a subversion server using WebDAV through HTTPS (on Apache on Ubuntu), such as this one (which also includes other access methods of your subversion repositories):
https://help.ubuntu.com/community/Subversion

After installing the plugins, it was time to copy over a repository from an existing machine (such as an old Windows XP computer) to the new location (such as an Ubuntu box). Using the svnadmin command, dump the existing repo and put the output to a file. It is important to note that if the output gets dumped to the terminal, all sorts of human and non human characters will be written to the terminal. If you have an internal speaker, some of those nonhuman characters will cause it to beep loudly and often for a long time.
The command for the svn dump looks like this:
svnadmin dump _PATH_TO_YOUR_REPO > _DUMP_FILE_
or
svnadmin dump C:\repo\myProject > myProject.dump

As each revision is dumped, it is reported to the screen.

Copy this file to the new machine (or somewhere as accessable) and load it to the empty repository. Don’t forget that to load into a repository, you will need to have created one using the “svnadmin create” command.
“svnadmin load” takes input from stdin, so cat that dump file and pipe it in. This looks like:
cat _DUMP_FILE_ | svnadmin load _PATH_TO_NEW_REPO_
OR
cat /tmp/myProject.dump | svnadmin load /svn/repos/myProject

If all goes well, you’re repository should now be loaded, and accessable on that machine.

Misc pointers:
1. Don’t set the DocumentRoot of the HTTPS virtual server to be the same as your repo. Anyone will be able to then see your repo (even if you have “Require valid-user”)
2. Make sure the “Listen 443″ is really “Listen 443 https” in ports.conf (or where the Listen directives are). If that is not set, you may see an error.

Android Apps, Versioning, and Publishing

Assuming you’re using Eclipse and have already setup the android-sdk and have a working application ready to move from being developed and running in the emulator/your device, the next step is taking care of licensing (if you haven’t done so already) and then signing the application.

Licensing

Licensing is important if you want to make it more difficult for your application to be available on a device without users downloading it via the android market place. If you have an app you intend people to pay for then its a pretty good idea to implement the license verification library (LVL) in your application. More details on how to do this can be found at the the android developer docs on licensing page. It also goes into greater detail about how the licensing works, and how to implement it in your application. If you’ve have a demo app, don’t care about it making you any money via paid downloads then you can probably skip this step (however, if anyone has a reason why this step should always be included feel free to leave a comment).

Versioning

In your android manifest file, make sure you have the following two attributes:
android:versionCode
android:versionName

The market uses “versionCode” to track the versions of your application floating around. If you fix a few bugs, make a few enhancements, or just upload a new version with nothing different, users who have already installed your app won’t be notified that an update is available. With each update to your application published, increment the “versionCode”.

“versionName” is what the user sees for the version of your application. Not as important as the previous attribute.

Here’s an example of these attributes in action:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="net.callahat.myApp"
      android:versionCode="2"
      android:versionName="1.0.3">

For more information on versioning, see the the android developer documents here.

Signing

Finally its time to create a signed package. If you’re using Eclipse, then this is pretty easy (hardest part is remembering those passwords).

  1. Right click on your project in Eclipse
  2. Mouseover “Android Tools”
  3. Click “Export Signed Application Package” (Your package should be selected as the package to export)
  4. Click next
  5. If you haven’t exported a package before, select “Create new keystore”. Chose a location you will remember, as this will store your keys for all your applications. Guard it well, and make sure its backed up. Losing it will complicate things, especially if you have updates to applications you need to make later. Also don’t forget the password you give it.
  6. If you haven’t created a key for this application before, select “Create new key”
  7. Give it a logical alias, such as the name of your application. Each application you sign should have a different key, which will be identifiable to you by the alias. Make sure you don’t forget this password either. When you sign a new version of your application you will use this same key.
  8. Make sure you give the validity a high number of years (at least 25 years or more is recommended)
  9. Fill out the details identifying you as the publisher.
  10. Specify where you want the package put and what you want it called, then upload that package to the marketplace (after testing it on your device to verify its working first.)

If you’ve already created a keystore, make sure you use the same key that you first signed the package with.

For more information on signing, see the androd dev signing documents.

More on Single Table Inheritence

The previous post touched briefly on single table inheritance and gave a simple example of setting up the base model, Fruit, and two inherited models, Apple and Watermelon. Where the two kinds grow, on a vine or tree, has been defined. Say its time to harvest, so we’ll define a function to take care of that. We could define that function in the base class.

 def harvest
    plant.take_fruit
  end

This works if both sub models can be treated the same by the function. Now its time to prepare the fruit. Eat fruit is prepared differently; apple is sliced and the core removed, the wattermelon is cut into wedges. End users of the watermelon are responsible for dealing with the seeds (unless the watermelon is a seedless). The prepare function can be defined in the Apple and Watermelon models:

class Apple < Fruit
  ...
  def prepare
    #slice fruit
    #remove core
  end
  ...
end

class Watermelon < Fruit
  ...
  def prepare
    #Halve fruit
    #cut into wedges
  end
  ...
end

While the above could be done without STI, but might not be the cleanest thing possible. For example, lets give apples their own table and model, and watermelon their own table and model, and do away with the fruits table/model. This gives us two very similar tables in the database [apples, watermelons] where there would be just one [fruits] and a duplicated harvest method. Things continue to get complicated and duplicated if there arises a need to represent different types of fruit, like bananas, strawberries, etc, down the road with duplicate code and additional similar database tables.

Alternatively, keep the single fruits table and model, and use the fruits model to handle the different types of fruit by using the ‘kind’ column to figure out what fruit it is. The prepare function bloats, as it needs at least a case statement to determine how to prepare different fruit, which leads to a cluttered function. As different fruit are added, the case statement grows larger. On the plus side, code isn’t being duplicated, and the database isn’t flooded with similar tables.

With using STI and adding more fruit, its as simple as defining a new model with Fruit as the base class. In this way, where there are multiple models STI can save you code and tables when you have distinct objects with a similar/same table schema. Its also imporant to note that STI is not for everything, and careful analysis should be used before deciding if STI is right for you.

More on inherited functions

A model can also inherit from another model higher than the base class. For example, more specific varieties of fruit:

class Fiji < Apple
  ...
end

We don’t define the prepare method for this model directly. Consider:

f = Fiji.new
f.prepare

Since the ‘prepare’ function is not defined for Fiji, the parent model is checked next for the definition, and is used from there. This is useful, as there are many kinds of apples, but they can all be prepared the same, and we don’t need to add any function definitions. STI will start with the object model, and work its way too the root base model sequentially until it finds the definition for the called function (or errors if that function was never defined).

Single Table Inheritence and Fixtures

Setting up a fixture for an STI table is fairly simple. The inheritence column (the default is ‘type’, but can be overridden) should be set as appropriate for each yml entry. If you are making use of foreign keys via a ‘belongs_to’, set for :foreign_key as the general foreign key from the base class. This way, you can make use of the ‘foreign_table: yml_object’ shortcut instead of excplicitly setting foreign ids. For example, consider the following table, and subclasses representing fruit and the kind of on which it grows:

create_table :fruits do |t|
  t.integer "number"
  t.integer "plant_id"
  t.string  "kind"
end

class Fruit < ActiveRecord::Base
  self.inheritance_column = 'kind'
end

class Apple < Fruit
  belongs_to :tree, :foreign_key => 'plant_id'
end

class Watermelon < Fruit
  belongs_to :vine, :foreign_key => 'plant_id'
end

Assume we also have a Plant and Tree model, with a apple_tree and watermelon_vine defined respectively.
The fruits.yml fixture can be setup as follows:

watermelon:
  number: 10
  vine: watermelon_vine
  kind: "Vine"
apple:
  number: 50
  tree: apple_tree
  kind: "Tree"

Using ‘plant’ will confuse the test runner, but ‘plant_id’ can still be used to explicitly give the id of an object.

Search Engine Friendly Redirects Using Apache

HTTP Status code 301 is a server response for a page that has been moved permanently. If you have a primary domain with one domain extension, such as foo.com, and several secondary domains with different extensions, such as foo.net and foo.org, that you want to wind up at the primary domain use the 301 server response. This will let search engines know about your primary domain. The 302 responses can adversely affect your search engine rankings. Your domain registrar may be able to take care of these redirects for you.

Apache can also take care of redirects. Have the secondary domains resolve to where the apache server is running, and set up a virtual server to handle the redirects. The configuration could look something like this:

<VirtualHost *>
 ServerName foo.net
 ServerAlias foo.net www.foo.net
</VirtualHost>

<VirtualHost *>
 ServerName redir_foo_domains
 ServerAlias foo.com *.foo.com foo.org *.foo.org
 Redirect 301 / http://foo.net
</VirtualHost>

Check the server headers to verify that your secondary domains are redirecting correctly. There are a few sites that can do this for you, such as http://www.seoconsultants.com/tools/headers.asp