h1

Running one migration by hand

March 25th, 2008

Sometimes, you want to run a single migration by hand (to test it maybe…)

You can do this from the command line:


ruby script/runner 'require "db/migrate/005_create_blogs"; CreateBlogs.migrate(:down)'
ruby script/runner 'require "db/migrate/005_create_blogs"; CreateBlogs.migrate(:up)'

h1

DRYing up Actions with a page_errorhandler

March 9th, 2008

When I am developing page actions, I quite often find myself approaching a standard get/post action in the same way. This is particularly because I want to validate a number of ActiveRecord models, only progressing if they are ALL valid, and showing all errors at once

Of course, that means that I need to have a standard way of doing this, and a standard way of reporting it. It also implies the use of transactions, so that all saves are rolled back on failure. I have

So to begin with, an (hypothetical) example of my approach is:


def edit_user
@user = User.find(session[:user_id])
@address = @user.address
if request.post?
begin
# note that I do not want to reference the objects in the
# method call - so that the changes are available to render
@user.transaction do
results = []
results << @user.save
results << @address.save
raise “Validation failed” if results.include?(false)
end
redirect_to :action => :show_user and return
rescue Exception
logger.warn{”Transaction terminated : #{e.message}”}
logger.warn{”@user : #{(@user.errors.full_messages.join(’; ‘) rescue nil)}”}
logger.warn{”@address : #{(@address.errors.full_messages.join(’; ‘) rescue nil)}”}
logger.debug{e.backtrace}
end
end
end

The first thing that is useful about this is that because all objects are saved together and the transaction is not terminated unless ONE of them is invalid, we will not redirect and the edit_user template will be rendered. Also, the validation errors are written to the log “just in case”

Also, note that I am using the log4r syntax of using braces instead of brackets. In Log4r, if the logger is not logging at the level that is specified, the code inside the braces will not be run. In the example above, if we are in production mode and we are not logging DEBUG, the e.backtrace method is actually not executed.

From here, lets DRY it up.

First, there’s those validation messages. There’s quite a lot of code here. I’ve approached this from 2 angles. First, in environment.rb, I put this code in


class ActiveRecord::Base
def full_messages
self.errors.full_messages.join('; ') rescue nil
end
end

and in application.rb

def validation_message(*objects)
str = "Validation error :"
objects.each{ |obj| str << "\n#{obj.class.name} => #{obj.full_messages}” }
str
end

This means that the validation message can now be handled by simply doing this in the rescue block:


logger.warn{validation_message(@user, @address)}

Next, because I use this structure regularly, I created a page_errorhandler method to contain the exception block that does this:


def page_errorhandler(*objects, &block)
begin
yield
rescue Exception => e
logger.warn{"Transaction terminated : #{e.message}"}
logger.warn{validation_message(*objects)}
logger.debug{e.backtrace}
end
end

Combining these with our method above:


def edit_user
@user = User.find(session[:user_id])
@address = @user.address
if request.post?
page_errorhandler(@user, @address) do
# note that I do not want to reference the objects in the
# method call - so that the changes are available to render
@user.transaction do
results = []
results << @user.save
results << @address.save
raise "Validation failed" if results.include?(false)
end
redirect_to :action => :show_user and return
end
end
end

Neatens things up nicely!

h1

Master Pages for Rails (or, Heirarchial Layouts)

March 7th, 2008

One of the things that I like about the .net web application setup is the concept of Master Pages. The most common usage of this is if you have a Home Page that has a slightly different layot from the rest of the site, but you want to share the base DIV structure and assets without having to copy them into another layout… Keep it DRY!

Although there is no “out of the box” solution for sharing common layout setups in Rails except for using Partials, there is in fact a way of replicating this functionality. First, you need to be familiar with the ActionView::Helpers::CaptureHelper class and the methods in it.

So, what you do is create a container rhtml layout that contains the common layout elements, such as the base HTML and div structure.

container.rhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<body>
<%= yield :layout -%>
</div>
</body>
</html>

From there, you can create as many other layouts that reference that container, such as one called application.rhtml:
<% @content_for_layout = capture do %>
<div id='a_new_div' />
<%= yield :layout %>
<% end %>
<%= render 'layouts/container', { 'content_for_layout' => @content_for_layout } %>

Note what happens there - the capture method is used to catch the rendering of this layout file. Then, instead of just allowing it to render, this output is injected into the container.rhtml file. In this way, we have chained the inner layout (application.rhtml) into the outer (container.rhtml) layout.

In our example, the “<div id=’a_new_div’ />” will be injected, along with the data from the view, into the container. There is nothing stopping you from doing this to another layer, although I doubt how often you’d need to do that!

From our example above, we could also easily create a home.rhtml file that had slightly different layout from our application.rhtml file and use that from our HomeController without concern - all of the pages would then render in the correct layout while giving us the benefit of a shared outer container!

I have used this in production, and it works a treat both in terms of performance and code maintainability.

h1

Guide to Electronic Music

August 11th, 2007

I found this Guide to Electronic Music - it’s so comprehensive it makes my head spin… but now when someone ask me what I think of weird music variants I’ll be able to give them an answer ;)

h1

ZFS Boot with NextentaOS

August 9th, 2007

Little bit behind the 8-ball on posting this, but I came across this post at AspiringSysadmin.com - ZFS boot without having to manually set it up like you currently have to do with OpenSolaris.

NexentaOS is a GNU operating system that uses apt on top of the OpenSolaris kernel and runtime. It looks to me as though the www.gnusolaris.org site has been abandoned for the GenUnix NextentaOS site, which is a shame because it’s damn hard to find on Google. The GenUnix site actually also hosts the Belenix and Schillix sites as well, with Belenix a LiveCD, and Schillix a rebuilt OpenSolaris distro.

The AspringSysadmin went into how to set NextentaOS in VMWare - my quest now is to combine VMWare, NextentaOS ZFS Boot and 2×750GB drives in RaidZ configuration… I hope it works!

h1

JRuby-OpenSSL and HTTP request timeouts (in ActiveSalesforce)

July 20th, 2007

So, JRuby looks pretty cool, and I’ve got some code written that uses a weird BouncyCastle encryption implementation going in my rails app. Works well, the WAR deployment works (with goldspike) and everything’s going swimmingly.

Until, of course, I tried to integrate with Another Project that uses the ActiveSalesforce. Behind the scenes, ActiveSalesforce makes SSL encrypted connections to Salesforce API endpoints and performs operations. This was working fine until I started the app under JRuby. All of a sudden, the salesforce connections stopped working.

A bit of digging later, and I discovered that the JRuby-OpenSSL implementation is causing reads of the HTTP responses to stall. JRuby HTTP is fine, Ruby HTTPS is fine, but JRuby HTTPS is not. Boo.

It’s a bug, now. I hope it’s fixed soon!

h1

Integrating Log4r and Ruby on Rails

June 16th, 2007

Aaaaaaaages ago, I wrote a message on the mailing list (before it moved to Google Groups!) about how to integrate Rails and Log4r. Since then a little bit has changed and that way may or may not entirely work any more. Since then, aaaaages ago Jason Rimmer asked me to update so that it’s all new and fresh, but I completely forgot in the move to the UK (very sorry Jason!). So here it is.

I’ve got a few outputters. One that acts like the default outputter, that writes “development.log” and so on. Then another that outputs to standard error for console lovin’ (in dev mode). Then another that uses a date file outputter to automatically roll over logs every day (for production mode), and finally an Email outputter that only runs in production and sends an email of the log for ERROR and FATAL log levels.

Log4r Rails configuration files

The first bit is the configuration YAML file, which is used to configure the loggers. Then there is logger.rb, which turns on and off the outputters as required. The final part is to include this logger.rb into the application configuration.

It is VERY IMPORTANT that you include the file before the call to the Rails::Initializer.run do block. This is because in this section of code the RAILS_DEFAULT_LOGGER is initialised, and if we don’t get in before that, we won’t get our logger injected into the Rails framework stack. So, configure it like this:

require File.join(File.dirname(__FILE__), 'boot')

require File.expand_path(File.dirname(__FILE__) + "/logger")

Rails::Initializer.run do |config|
...

Just drop the require line in there and it will load logger.rb, which loads log4r.yaml, and everything is up and going. You’ll see friendly [DEBUG] lines in your console and everthing! Of course, I prefer verbose logging on the console in development; you may not, customise by reading the log4r manual. Of course, if you expect your error mails to be delivered, change the SMTP server settings at the bottom of the yaml file.

Sorry for the delay Jason!

h1

Rails composite primary key support

June 13th, 2007

I am working with a legacy database. Usually, the built in rails stuff for table prefixing and primary key changes is enough. Sometimes, it’s not.

I had a problem with a join table that has Foreign Key names that are tablename_id, but the tables they reference is tablename_id as well. The has_and_belongs_to_many method DID NOT like it at all. Added to this is that there are attributes in the join table (is_primary) that I need to use. I considered (and discussed with the Java devs) the option of making the join table have an ID and making it a model, but there was potential for breakage and I like to tred very carefully around the existing app and making changes.

So, a bit of time on Google later, and I came across Nic Williams’ Composite Primary Key plugin. Oh man, it works a treat. I created the model for the join table, specified the primary keys, and went as normal!

Beautiful.

h1

Wordpress <code> and <pre> formatting

June 7th, 2007

After the last paste-heavy post, I finally got around to doing something about wordpress’s formatting of code blocks. This site was very helpful:

http://tjulo.blogspot.com/2007/03/wordpress-and-source-code-posts.html

So, edit the file wp-includes/js/tinymce/plugins/wordpress/editor_plugin.js.

Comment out the section that replaces pre content:

/* var startPos = -1;
while ((startPos = content.indexOf('
', startPos+1);
var innerPos = content.indexOf('>', startPos+1);
var chunkBefore = content.substring(0, innerPos);
var chunkAfter = content.substring(endPos);

var innards = content.substring(innerPos, endPos);
innards = innards.replace(/\n/g, '
');
content = chunkBefore + innards + chunkAfter;
}*/

Then I had to update my CSS so that pre used the same class as code and then change my posts over to use pre instead of code.

Next step is to fix code too so that I don’t have to think about it.

It does seem to have the side-effect of not automatically handling the escaping of < and > symbols outside those tags though, which for this post where I started with <code> and <pre> instead of code and pre, made things a bit of a mess.

h1

Rails ActionWebService SOAP error “No valid method call - missing method name”

June 6th, 2007

For a Salesforce.com integration project, I need to create a SOAP server to accept messages from Salesforce. Seeing as there is no way directly import a wsdl into ActionWebService, I instead used wsdl2ruby from the soap4r distribution to generate server stubs. Then, I used ActionWebService to emulate the same service. I had problems with using the default layout, so I changed my structure to use a delegated structure:

class NotificationServiceController < ApplicationController
  web_service_dispatching_mode :delegated
  web_service_scaffold :invoke
  web_service :notifications, NotificationService.new
end
class NotificationServiceApi < ActionWebService::API::Base
  inflect_names false
  require_soap_action_header false
  api_method :notifications,
             :expects => [Notifications],
             :returns => [:bool]
end
class NotificationService < ActionWebService::Base
  web_service_api NotificationServiceApi
  def logger
    RAILS_DEFAULT_LOGGER
  end
  def notifications(organization_id, action_id, session_id, enterprise_url, partner_url, notification)
    my_object_id = notification.sObject.id
    ack = false
    begin
      ack = so_something(my_object_id)
    rescue Exception => e
      logger.error(”Error processing payment: #{e.message}”)
    end
    ack
  end
end

But STILL SOMETHING WAS WRONG. I was getting “No valid method call - missing method name” with the Salesforce outbound message queue reporting “org.xml.sax.SAXParseException: Content is not allowed in prolog.” MMmmmmm helpful. The stack trace was showing that rails was trying to process the request as XMLRPC not SOAP, which was all wrong.

The stack trace looked something like this:

RuntimeError (No valid method call - missing method name!):
    /usr/lib/ruby/1.8/xmlrpc/parser.rb:476:in `parseMethodCall'
    /usr/lib/ruby/1.8/xmlrpc/marshal.rb:63:in `load_call'
    /usr/lib/ruby/1.8/xmlrpc/marshal.rb:32:in `load_call'
    /vendor/rails/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb:36:in `decode_request'
    /vendor/rails/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb:32:in `decode_action_pack_request'
    /vendor/rails/actionwebservice/lib/action_web_service/protocol/discovery.rb:20:in `discover_web_service_request'
    /vendor/rails/actionwebservice/lib/action_web_service/protocol/discovery.rb:18:in `discover_web_service_request'
    /vendor/rails/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb:49:in `dispatch_web_service_request'
    (eval):1:in `notifications'
..........

Then, I came across patch 7077 (indirectly via this and then this), so, using my new best friend Piston I checked out Rails 1.2.3 into vendor/rails, and patched with the diff in the change. It was not entirely smooth - the xmlrpc.rb file could not be patched, but I merged the change manually.

All done! Works!

One thing I did discover the hard way though is that you need to have the whole stack of definitions with the same naming scheme for this to work. That is, if you’ve got a NotificationServiceController, you need to ensure that you have a NotificationService and a NotificationServiceApi defined and in use - no other class names will work. No Reuse of API Definitions, which is a bit of a bugger.