Wednesday, June 3, 2009

Renaming a Rake task

Rake has a class for creating packaging task which builds a compressed package from the sources. It's called Rake::PackageTask and it's quite easy to use it, see the documentation.

Unfortunately the name of the created task is package and it's hardcoded so it cannot be changed.
Yast uses make and the standard targets are package and package-local.

  • package-local - build a tarball source package
  • package - does some checks (like SVN repository update check, syntax check, runs the testsuite...) to ensure that the built package follows some rules so it will less likely break something.

We wanted to use the same targets in the Web Yast which uses Ruby on Rails and Rake as the make replacement.

The problem is how to change the package task name. In Ruby it's possible to change or extend even the core classes like String or Object, which might be good or bad because you can break all Ruby applications very easily... But this feature allow us to extend Rake as we need.

The following code adds rename method to Rake::Task class:

# add rename_task method to Rake::Application
# it has an internal hash with name -> Rake::Task mapping
module Rake
class Application
def rename_task(task, oldname, newname)
if @tasks.nil?
@tasks = {}
end

@tasks[newname.to_s] = task

if @tasks.has_key? oldname
@tasks.delete oldname
end
end
end
end

# add new rename method to Rake::Task class
# to rename a task
class Rake::Task
def rename(new_name)
if !new_name.nil?
old_name = @name

if old_name == new_name
return
end

@name = new_name.to_s
application.rename_task(self, old_name, new_name)
end
end
end

And an example how to use it:

# rename 'package' task to 'package-local' task
Rake::Task[:package].rename(:"package-local")

It was quite difficult to figure out the rake internals, so I hope it will help somebody else...

Monday, May 18, 2009

Debugging Ruby on Rails Application

How to debug a Ruby on Rails application?

I needed to debug a Ruby on Rails application which I just have started to develop. I put some logging commands to the code but it's not as good as using a full debugger for inspecting internal data at runtime.

What's needed?

For debugging a Rails application ruby-debug gem is needed. It can be installed by command sudo gem install ruby-debug in Linux or as a package from an installation repository.

How to start the debugger?

At first, the place in the application where the debugger should be started must be marked by debugger keyword.

Then the application must be started in the debugger - it's simple, just use
--debugger option of the starting script, e.g. script/server --debugger.

How to use the debugger?

When the application executes
debugger command it stops and a debugger session is opened in the terminal.

It supports these basic commands:
l (line) - print the source script
c (continue) - stop the debug session at continue executing the application
bt (backtrace) - print the execution stack (which functions were called)
n (next) - execute the next command
s (step) - execute the next command, step inside a function
h (help) - will list more available commands with details

Moreover it's possible to use normal ruby commands to print or inspect the current objects, using e.g. object.class, objec.inspect methods. And it's also possible to modify the current variables, just use var = value command.

This makes the debugger really powerful, it's far better than simple puts command!