views:

46

answers:

1

I'm using RoR and I want to do concurrency safe update queries. For example when I have

var user = User.find(user_id)
user.visits += 1

I get the following SQL code:

SELECT * FROM Users WHERE ID=1 -- find user's visits (1)
UPDATE Users SET Visits=2 WHERE ID=1 -- 1+1=2

But if there are several queries taking place at the same time, there will be locking problems.

According to RoR API I can use :lock => true attribute, but that's not what I want.

I found an awesome function *update_counters*:

User.update_counters(my_user.id, :visits => 1)

This gives the following SQL code

UPDATE Users SET Visits=Visits+1 WHERE ID=@something

Works great!

Now my question is how can I override the += function to do the update_counters thing instead?

Because

user.visits += 1 # better
User.update_counters(my_user.id, :visits => 1) # than this

UPDATE

I just created the following function

class ActiveRecord::Base

  def inc(column, value)

    User.update_counters(self.id, column => value)

  end

end

Are there any other better ideas?

+1  A: 

Don't know about better ideas, but I would define that method to the User class, not the ActiveRecord. And maybe increment_counter (that uses update_counters) would make it a bit more readable?

def inc(column, value)
  self.increment_counter(column, value)
end

Haven't tested that and not saying this is definitely better idea, but that's probably how I'd do it.

Update: And AFAIK you can't override the "+=", because "a += b" just a shortcut for "a = a + b" and you probably don't want to override "=" to use the update_counters :)

pkauko
increment_counter increases it by 1, sometimes I need different values.Thanks anyway.
Alex