Posts about gotcha

ActiveRecord Gotcha

I came across this interesting gotcha while debugging through someone else's rails code. When you set a model's one-to-many attribute(an perhaps other association types as well), let's say:
user.friends = new_friend_list
It doesn't always set it. As far as I can figure from my blackbox testing, it does an equal check first between the old value and the new value, and then sets only if they are different.

Now, in Ruby's == is easily overridable, you can easily make it do anything you want. It happens that Array#== returns true iff both arrays have the same number of elements and each element in one array is == to the element of the other array in the same position. It also happens that ActiveRecord's base class' == returns true as long as the objects are of the same class and the primary keys equal.

Which brings us to the gotcha of the day. The code in question built an array, say new_friend_list independently, starting with an id list passed in from a from, finding each friend in the database and adding them to the array, but, in the meantime, modifying a field in each of the friends, say...friend.charma++. It then goes on to set the friends attribute in the manner you'd already seen above, and saves user. Well, the charma field that was modified in each of the friends retrieved did not get saved, because the set did not happen: the new_friend_list pointed to the same list of friends user was already associated to.

Hmm..., yeah. Watch out for this one. Debugging this one was not fun. It definitely didn't fit with the principle of least surprise.
Posted by Toby 10 months ago about gotcha, programming, rails and ruby (0 comments)

Ruby Gotcha of the Day

Okay, so in ruby:
>> nil or 'value'
=> "value"
because nil acts as false when used with boolean operators and any other object acts as true. Now let's assign the result to a temp variable a:
>> a = nil or 'value'
=> "value"
>> a
=> nil
Whoa?? Can you guess? In ruby the assignment operator is not special. It acts just like any other operator and does not have a lower precedence than the or operator. Therefore the expression
a = nil
executes first, which evaluates to nil, and assigns the value nil to a, and then the result nil is used in the expression nil or 'value'. Therefore to do what we intended we need to do:
>> a = (nil or 'value')
=> "value"
Wow! That is messed up.
Posted by Toby about 1 year ago about gotcha, programming and ruby (0 comments)

Python Optional Arguments Gotcha

When you use Python optional arguments you should know that the default value you set is static, it is set at the time the function is defined, and does not change after that. If you a mutable type as the default value, you need to be careful.
Ex:

>>> def enlist(n, lst=[]):
...   lst.append(n)
...   return lst
...
>>> enlist(3)
[3]
>>> enlist(4)
[3, 4]
>>> enlist(5)
[3, 4, 5]
>>> enlist(6)
[3, 4, 5, 6]

Everytime you call the enlist function, the list gets bigger, because lst is never reset to the empty list. It is set to the empty list only once, when enlist was defined. After that it references the same instance everytime you don't supply a lst argument.
Posted by Toby about 1 year ago about gotcha, programming and python (0 comments)

Javascript Gotcha

offsetTop
element.offsetTop does different things in gecko than IE, best bet is to use the function listed here: http://www.quirksmode.org/js/findpos.html, the code:

function findPos(obj) {
  var curleft = curtop = 0;
  if (obj.offsetParent) {
    curleft = obj.offsetLeft
    curtop = obj.offsetTop
    while (obj = obj.offsetParent) {
      curleft += obj.offsetLeft
      curtop += obj.offsetTop
    }
  }
  return [curleft,curtop];
}
Posted by Toby over 2 years ago about gotcha, javascript and programming (0 comments)