My blog has moved

It now lives at http://aslakhellesoy.com

And I'll start blogging again. Promise.

If you have ever hosted a project on RubyForge, SourceForge or some other clone such as GForge, you have probably experienced the pain of making a release on these systems.

This is because these systems only offer an ugly form based interface for releases. No web services, no scp. Just these bloody forms. -And most people interact with them manually, uploading files, pasting in release notes and so forth. There are probably some odd, unknown, project-specific scripts lying around in random places that can automate this, but I haven't seen anything reusable.

In fact, I hadn't seen anything at all, so 4 months ago I wrote my own script to do this. Except I couldn't get the HTTP multipart posts (attachments) to work properly. So I left it fermenting for a while...

But two days ago I felt the pain again, and I came across DHH's Rake script which does something very similar. -And it had the multipart code I couldn't grok myself.

So I decided to take the best parts of my old attempt and DHH's code from Rails' Rake script and make a proper library, so that others can use it. -Not only on RubyForge, but hopefully also on SourceForge and other sites running SourceForge clones.

So if you're as lazy as me, check out XForge.

XForge is released using XForge (of course!), so it works fine on RubyForge. Please let me know if you get it to work anywhere else, or if you have bugs or improvements.

Object templates in Ruby

| 1 Comment

The concept of templates are very common in many contexts of programming. A boiler-plate representation of something can be turned into a concrete instance by supplying some extra data. The important point is that the supplied data can vary, and that has an impact on the structure of the concrete instance of the template.

In HTML programming, common template techniques are JSP, PHP, ERB and ASP. By passing some extra data to a template engine, a template can be turned into an HTML page that displays the data, using the layout from the template.

In OO programming, the most common concept of a template is a Class. A piece of a program can supply some data to a class' constructor and get a new object.

Sometimes, instantiating a new object by simply calling a constructor with some extra data is not the optimal way to create an object though. Consider the common situation where the desired object is composed of an aggregation of several other objects. -A complex graph of objects.

One way to approach this is to design classes (aka templates) to honour Dependency Injection (DI), and use a DI container supporting a configuration file (in XML or other format). NanoContainer or Spring are two frameworks that use this approach to instantiate complex graphs of objects composed of "variable data" from a configuration file.

Assuming you want the ability to create object graphs that are configured in an external file, and your language is Java, then it doesn't get much simpler than with NanoContainer or Spring.

But in Ruby...

A similar effect that is radically simpler and extremely easy to use can be achieved with a dash of Ruby magic using YAML and eval under the covers. Consider this object template:

codehaus_project_template = Project.new codehaus_project_template.home_page = "http://\#{unix_name}.codehaus.org" jabber_publisher = JabberPublisher.new jabber_publisher.id_resource = "damagecontrol@jabber.codehaus.org/#{unix_name}" codehaus_project_template.publishers << jabber_publisher (The template object can also be deserialised from a YAML file if we don't wish to do this in Ruby code, but this is not important from the perspective of describing how this object template technique works). The point I'm getting at is that I can create new instances from this template object like this: project = codehaus_project_template.dupe("unix_name" => "mooky") assert_equal("http://mooky.codehaus.org", project.home_page); assert_equal("damagecontrol@jabber.codehaus.org/mooky", project.publishers[0].id_resource); The dupe method takes a Hash that should have one key/value pair for each variable in the object template. The dupe method simply creates a new object graph similar to the one in the template, but substitutes all variables with the values from the hash. -All the way out to the leaves of the object graph! The object template's variables are simply backslash-escaped #{blah} s in various String instance variable values (fields). In the example there is only one (#{unix_name}), but we could use as many as we like, at any level in our object graph. In Ruby it's ridiculously easy to make this happen. Just make the classes whose instances you want to use as templates include ObjectTemplate: module ObjectTemplate def dupe(variables) template_yaml = YAML::dump(self) b = binding variables.each { |key, value| eval "#{key} = variables[\"#{key}\"]", b } new_yaml = eval(template_yaml.dump.gsub(/\\#/, "#"), b) YAML::load(new_yaml) end end A similar approach can be achieved in Java with XStream and Velocity (or Jelly, haha) and maybe a little bit of AOP - in 10 times or more as many lines of code - without the same ease of use.

Ajax with JavaScript Templates

| 5 Comments

Rich, responsive webapps using the Ajax approach are chic. I've started to think about what it would be like to develop the view part of a webapp using the Ajax concepts.

In an Ajax web app the server sends back XML, and the XML is transformed to HTML in the browser. There are several ways to do this transformation:

One approach is to use XSLTProcessor as described here.

However, XSLT is problematic for a couple of reasons. First, not all browsers support it, and more importantly, most web ui designers don't speak XSL.

A second approach is to use XPath in JavaScript to pull out bits of pieces of the XML and modify small pieces of the DOM to fill them in.

A third (and new?) approach could be to use the familiar template approach (as in JSP, ASP, ERB, PHP templates) and generate bigger chunks of DHTML. This would make it much easier to develop nice looking views, since they can now be designed in a regular web authoring tool such as DreamWeaver or NVU.

But wait - the template engine now has to sit inside the browser! And this is where I discovered JavaScript Templates.

JST templates could theoretically be rendered (and tested) in a build system, using Rhino. Being able to test view rendering is something I consider very important, especially when systems start to get complex (which they do with Ajax).

I'm eager to try this out.

Annotations in Ruby

| 14 Comments

A couple of days ago I wished there was a way to use annotations in Ruby. I'm writing a Ruby on Rails application that renders a lot of objects in HTML. Many of these objects are "editable" via the web interface, and in order to make it easier for the user, I wanted the web interface to have both an explanatory text and a HTML tooltip for each object's field.

Because I like simple things I also like to keep things in one place (I don't want to maintain this metadata in a separate RHTML template).

Ruby doesn't support annotations out of the box, so I opened up the Class class and added support for annotations. Now I can do:

require 'rscm/annotations' class EmailSender ann :description => "IP address of the mail server", :tip => "Use 'localhost' if you have a good box, sister!" attr_accessor :server end

The class' annotations can then be accessed like this:

EmailSender.server[:description] # => "IP address of the mail server"

It took the Java community forever to do stuff like this. First a couple of years of XDoclet, then JSR175. And tons of code too. In Ruby it's 1 hour's work and 25 lines of code. Go figure.

For more info see http://rscm.rubyforge.org/classes/Class.html

And oh, here's the code: class Class def ann(anns) @@anns ||= {} def self.method_missing(sym, *args) #:nodoc: @@anns[sym] end $attr_anns ||= {} $attr_anns.merge!(anns) end alias old_attr_reader attr_reader #:nodoc: def attr_reader(*syms) #:nodoc: syms.each do |sym| @@anns[sym] = $attr_anns end $attr_anns = nil old_attr_reader(*syms) end def attr_accessor(*syms) #:nodoc: attr_reader(*syms) attr_writer(*syms) end end UPDATE (March 3 2005) An updated version of the Ruby annotations library is available at rafb

Recent Comments

  • Justin Meyer: I've been working on a replacement to JST, EJS (http://embeddedjs.com). read more
  • me: oh boy! Do i HATE Lotus notes or wht!!!! am read more
  • jason: I am a software engineer as well, and I HATE read more
  • Anon: I *am* a programmer, a java swing interface programmer at read more
  • Anon: From what I can tell, Lotus is ONLY loved by read more
  • Greg: I'm Lotus administrator and I don't Hate it. Yes it's read more
  • George: All I have to say is that they call it read more
  • Miguel: Notes is the worst main-stream piece of software in existence. read more
  • Richard: Notes rocks.. its sweet.... now what sucks ....errr how about read more
  • notes rocks!: Teehee - you people need some soap and a toothbrush read more

Find recent content on the main index or look in the archives to find all content.