Logging in tests in Rails

posted Sun, 11 Dec 2005 00:38:00 GMT by Jonas Bengtsson

To use the logger in tests in Rails is fairly simple, you can access the logger with RAILS_DEFAULT_LOGGER. However, the test.log file gets a little hard to read since you don’t know which test method generated the messages. This is a problem even if you don’t use the logger manually if you for example want to look at the SQL statements.

The following snippet generates a log message when each test method is called and one message when the test method is done. To use it you need to include the snippet in test_helper.rb and add log_test_methods in the end of your test class (I couldn’t figure out a better way to solve it).

class Test::Unit::TestCase
  def self.log_test_methods
    class_eval do
      test_methods = instance_methods.select {|m| m.match(/^test/)}
      test_methods.each do |method|
        alias_method "orig_#{method}", method
        define_method method do
          begin
            RAILS_DEFAULT_LOGGER.info ">>> #{method}"
            send "orig_#{method}"
            RAILS_DEFAULT_LOGGER.info "<<< #{method}"
          rescue => e
            RAILS_DEFAULT_LOGGER.info "<<< #{method}"
            raise e
          end
        end
      end
    end
  end
end

Comments Zero comments

Tag cloud

posted Mon, 24 Oct 2005 20:54:00 GMT by Jonas Bengtsson

Today I finally made the first feature addition to this blog since its launch. I’ve been having some instabilities with Eclipse / RDT and my Subversion repository, and updated my Typo installation so I haven’t been able to work for a while. The feature is nothing spectacular but just a tag cloud which I’ve been wanting for a while.

Comments Zero comments

rake migrate

posted Sat, 22 Oct 2005 14:19:00 GMT by Jonas Bengtsson

This is the first time I’m updating my Typo installation, and the update contains changes to the database schema as well to make things a little bit more interesting.

I start by backing up my MySQL database:
$ mysqldump -C -u username -p --opt --lock-tables=false --skip-add-locks --skip-extended-insert database > dump.sql

I fetch the dump to my laptop and bring it into my local MySQL server (using SQLyog, but could just as well have used MySQL directly). Updating to latest version of Typo.

svk sync --all
svk update andthennothing-dev
svk smerge //typo/mirror andthennothing-dev
svk commit andthennothing-dev

When I try to run Typo now it doesn’t work since the database schema has changed. This is where Active Record’s Migrations come in. It should be as easy as rake migrate, but it wasn’t for me. Not this time. First I try it out on my laptop and since the Typo user doesn’t have all permissions needed some of the migration steps don’t succeed (that’s at least what I think went wrong). However, after changing the permissions of the user, changing schema_info.version to 18 (the version it was before I tried to migrate) and re-restoring the dumped database it works as expected.

Since I don’t want the same problem on my production server I create a test database and checkout the new Typo version in a temporary directory on the server. But it failed in another way:

$ rake migrate RAILS_ENV=test
rake aborted!
WARNING:  You have a nil object when you probably didn't expect it!  Odds are you want an instance of Array instead.

Look in the callstack to see where you're working with an object that could be nil.
Investigate your methods and make sure the object is what you expect!
./rakefile:218

The reason was that the schema_info table somehow was empty, don’t know how it happened. But adding a record with version = 18, the migration works.

After some testing locally of the new version I’m ready to push the new version to the production server. Merge dev to trunk locally:

svk update andthennothing-trunk
svk smerge //andthennothing/branches/dev andthennothing-trunk
svk commit andthennothing-trunk
On the server (I still have the database dump if anything should go wrong):
$ killall lighttpd # I think I'll manage some downtime
$ svn update
$ rake migrate RAILS_ENV=production
Trying to add whiteboard to: articles... comments... pages... done.
Renaming Articles table
Copying article data
Adding a type column
Extending Content table
Converting comments
Extending Content table
Converting trackbacks
Extending content table
Converting pages
Updating all articles
$ #restart lighttpd

Everything seems to work just fine! The update took something like one or two minutes I think, which is quite an acceptable downtime on a personal web site. I will look into how to update without any downtime some other time since I think it’s possible with Rails.

It was a quite painless experience once I figured out how to get around the problems, and I’m glad I tried it out locally first. Rails Migrations rocks! The only objection I have is why it didn’t perform the migration in a transation so when it failed the first time it wouldn’t have screwed up my database?

Update: The transaction problem is fixed by scott.

Comments Zero comments

Routes - URLs on Rails

posted Fri, 07 Oct 2005 17:18:00 GMT by Jonas Bengtsson

As I was getting ready to get this blog out the door I wanted to change the permalinks for the entries. Normally on a Typo powered blog the entries are places under /articles/YYYY/MM/DD/name/, but I wanted to change from articles to archives. So I started updating config/routes.rb and all the places where links were created (which is quite a few). I actually got a little angry that they didn’t use custom helpers to generate all links, since it would be much easier to make the change in on place (putting them together with the routes would be even better, I thought, to honor DRY).

But somehow I realised that Rails was cleverer than that. Actually, routing works both ways – both for incoming requests and for URL generation. url_for (which is used to create URLs for links etc.) uses the routing to create the correct URLs. So to change from articles to archives all that was needed was to change config/routes.rb and everything worked. I think it’s neat with separation between URL design and controller names!

Rails’ “convention over configuration” hides some of its neatness so you’ll have to do some digging.

Comments Zero comments

Picking up the axe

posted Mon, 29 Aug 2005 00:42:00 GMT by Jonas Bengtsson

It’s been a while since I’ve been coding Ruby. I learned the basics back in 2002 but since I’m much more fluent in Python I very rarely use Ruby when I need something done. But this time I have the motivation of Rails and a newly bought Programming Ruby 2nd edition (a.k.a. PickAxe).

Now to some random incoherent things I’ve learned about Ruby recently.

The most important and interesting aspect of the language, IMHO, is blocks, and I think I grok it now and am able to know when to apply them.

There were two conventions that made Rails-code hard for me to understand before: symbols and e.g. belongs_to. Kevin Clark taught me symbols and this piece of code describes how belongs_to et al. work:

def tinker_with_class
  class_eval do
    def hello
      puts "Hello world!"
    end
  end
end

class Hello
  tinker_with_class
end

h = Hello.new
h.hello

Output: Hello world!

One thing that I wasn’t aware of before was that Range supports custom classes (implementing the succ and <=> methods), which is neat and something that Python lacks.

Mixins seems to be a really good means of reuse, but I don’t know that much about them for a couple of chapters.

Private methods and variables can only be accessed by the own object, i.e. you can’t access private methods and variables of objects of the same class (as you can in Python, C++, Java and most other languages).

Many of the Perlisms seems to be less preferred now than the first edition of the PickAxe, which is a good thing. Who wants to remember the difference between $!, $&, $., $_, $~ etc?

The main gripe I have is that irb doesn’t work that well with Swedish keyboard layout on Windows, which is a shame since interactive Python was instrumental in my learning of Python.

Anyhow, I like most aspects of Ruby and I hope it will become as natural to me as Python.

Comments Zero comments

Now I kind of GET it

posted Tue, 24 May 2005 23:37:00 GMT by Jonas Bengtsson

Just an update to an entry I posted some days ago, where I ranted a bit and touched upon Ruby on Rails getting support for Javascript generated POSTs on links. I didn’t see the problem back then, but today I understand a tad more learning that Flickr had a serious defect with GETs.

Eric Costello provided this enlighting quote on the Flickr API mailing list from the HTTP/1.1 RFC:

In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered “safe”. This allows user agents to represent other methods, such as POST, PUT and DELETE, in a special way, so that the user is made aware of the fact that a possibly unsafe action is being requested.

That makes sense, but it wasn’t something that I was actively aware of (I’m not a web developer, so I’m not too embarrassed). If this advice was followed, the hoopla about Google Web Accelerator “prefetched” naughty pages such as “delete this post” in WordPress would never have happened.

But I’m still not sure why you would like links that works as POSTs. Are FORMs too cumbersome? Perhaps it’s a brilliant idea but I don’t understand enough of the problem yet — still learning.

Note to self: use POST (or PUT/DELETE) when the state is changed on the server!

Comments Zero comments

Javascript and links

posted Fri, 13 May 2005 01:14:00 GMT by Jonas Bengtsson

Looking at today’s Daily WTF is amusing, where VBScript is used in a tad unnecessary way. Using VB/javascript for something as basic as links makes me cringe. A few years back I read a bit about ASP.NET because it was new and for some reason I have been interested in web development frameworks for quite a while. But I didn’t like it, mostly due to its usage of javascript for links (that’s at least how I remember it, although my memory might be failing me and ASP.NET might have changed since).

Nowadays, Ajax is all the rage, and javascript gains popularity. I think that Ajax, à la Gmail, is nice and might have the possibility to transform the web experience to some degree. But still, I don’t like relying on something fragile as javascript for something basic and fundamental as sending and receiving information. The simplicity of HTML and http is, if you ask me, one of the main reasons of the success of the web.

When Gmail first came into beeing, it didn’t work on browsers that didn’t support XMLHttpRequest. Nowadays there is also support for other browsers. Backpack is another Ajaxy web application that doesn’t support browsers such as Opera. That makes me little nervous since Backpack has been the driving force of the Ajax support in Ruby on Rails. I really like RoR so I hope it doesn’t take a wrong turn. Even though I don’t fully understand the problem, javascript generated POSTs on links seems wrong.

I’m all for experimenting with Ajax to enhance the user experience, but if the browser doesn’t support what you are trying to do, you should degrade gracefully. Everything else is soo 1998!

Comments Zero comments