Passing current user id to Rails models

Long time since last post, isn’t it? Well, I’m completely busy with my work in Nettigo, selling Arduinos and other nice gears :) I do not do gigs anymore, so there is a lot less reasons to write about Rails.

But I still use this framework, since my backend software is written in Rails, so here is one thing which I think can be useful for You.

Often we want to pass ID of current user to Rails model internals. Most answers are don’t do that, this is controller work to do authorization stuff, MVC is to prevent such thins, etc.

here was not related picture (as usual on this blog). Some readers were complaining it was not only unrelated but even offending. Well, maybe they were right, so, I have removed that picture.

Yeah, right, but what if we want to keep some kind of audit trail what is happening with given model? This is not authorization, just who done what.

Since in my application case audit records are created in observers simple passing user id as some additional parameter is no go for me – I don’t want to change interface just to pass user info, that breaks too much things.

So, I have chosen this approach:

def with_user user, &block
  if user.blank?
    yield
  else
    Thread.current[:user] = user.id
    yield
    Thread.current[:user] = nil
  end
end

And each operation I want to track I invoke:

with_user(current_user) do
 model.do_some_stuff
end

Thread.current acts as a hash accessible in current thread and allow us to pass some info skipping MVC isolation (You wanted that, right? :) )

In observers I can access user ID and store it with record. If it is not present, audit trails is being marked as created by System. That means probably cron job, or console action (well on console I can run code inside with_user block when needed).

This is safe as long each request is being processed in single thread and we make sure that user ID will be cleared after our operation. When ID will stay in Thread.current, next request being processed by this Rails app instance will have access to that value and wrong audit records will be created.

Code has to be updated, since any exception will occur inside block, code after yield will be skipped and user ID won’t be erased from Thread.current. Here it is, final version:

def with_user user, &block
  if user.blank?
    yield
  else
    Thread.current[:user] = user.id

    begin
      yield
    ensure
      Thread.current[:user] = nil
    end
  end
end

Code inside ensure will be executed each time – both when exception was raised and when execution was clean.

Reloading Your plugin in development mode

For one of my customers I was developing API, wrapped around some older service. This API was meant to be used by new application developed (using RoR of course) by customer itself. Since I was only wrapping old code I could finish quite soon, before main application was ready.

The problem was that API was not defined in every detail upfront. Since I did plain wrapping I did keep old business logic and flow with this API, and new application was not thinking the same way. This was seen before so we have agreed that integration will be done by me and we needed simple way to hook into new application with my integration code. One of obvious ways to achieve it is to use Rails plugin to keep code separated.

Things went OK but I want to share one thing I have learned. Using Rails plugin to wrap code is good idea with one issue – code reloading. Plugin code is not reloaded in development mode (like it is done with controllers or models) so changes in plugin will be visible after application restart. Not very comfortable for development…

Tools for developer

(c) batega

Being lazy and didn’t want to restart application with every change I make, I have started search for some workaround:

Continue reading

Web application that has changed my life

Soon it will be two years since I was exposed to web application, which had probably most impact on me since AJAX was born. I have checked old time entries and it was August 2006 when I found SlimTimer. You ask – time tracking application had most impact on my life? Yes, exactly.

(c) Brenda Anderson

I was working in Hewlett-Packard Poland as network engineer at this time. My career was related to network stuff since 2000, more or less when I moved to Warsaw. But at this point I knew I don’t want to stay in this field. Why? Well… there were two paths if I would be interested to stay in networking – first move to presales support area or became more team manager than technical person. Working earlier as presales and seeing corporate world from inside through last few years I didn’t like any of those.

I wanted to try my luck in US – I was (and I am still) curious how it would be to work there. I was trying to get H1B visa, and one of my attempts I have described in my first post on this blog.

Let’s skip H1B visa topic which is quite interesting since I finally got one, valid up to 2009. But I’m still here in Poland – visa came for me two months to late, my personal situation had changed and I had to leave idea moving to US (at least for some time ;) ). The important lesson from those efforts was my inner belief that I want to return to software development as my occupation (I was doing some C/C++ coding in mid 90). I was thinking about refreshing my C/C++ skills, but there was other thing which have changed my thoughts. Around April or March 2006 I was exposed to Rails and by end of July I was thinking about taking jump into web development world.

But I was not convinced I should do it. I was doing well in my job, despite fact that Dilbert-like situations were on daily basis. I had some feelings there is something not right, but I didn’t allow myself to become aware what really is wrong.

Then on some afternoon I have created account on SlimTimer. I decided I will use this tool to know how much time I spend on particular tasks (this is example of dilbertesque – at this time I had fill time sheets in 3 or 4 places, often giving different values :)) to keep accounting trolls happy). I just needed time tracking solution to know what I’m really doing…

I just re-run report from SlimTimer for first two weeks I was using it. When I look at it now, I remember feeling I had then as it was just yesterday. I was shocked, how much time I waste. Oh boy, I was not aware that I was spending so little time on things which really make me happy in my work. And how huge time sucking hole was impulsive web browsing.

Disproportion between things I was considering fun and definitely not-fun was drive for me to make change – in late August 2006 I was determined to make change with my career. And with such drive almost anything is possible :) In autumn there was opportunity to become contractor on project, which required good mix networking and programing skills. Next few months I have used to prepare to make final step – start freelancing full time. And from September 2007 I’m full time freelancer with focus on Ruby on Rails. And I still use SlimTimer as my time tracking tool.

So, for me SlimTimer became life-changing application. Hard to believe? Maybe, but I would like to know if You have some similar experiences with web applications? SlimTimer or rather conclusion from it’s report was turning point in my career. After two years I can see this very clearly – looking back it is very easy to connect dots…

And how about You?