Category: programming

jQuery, jRails and the Accept header

Posted by on June 18, 2009

I included jQuery by installing the jRails plugin, which seems nice because you can continue using rails’ ajax helpers. But when I tried to implement a more special functionality by using the $.ajax function it proved impossible to set the Accept header for my request. Neither using the dataType option nor by setting it directly in a beforeSend function. The Accept header always read:

text/javascript, text/html, application/xml, text/xml, */*

I was about to uninstall and hate jQuery for the rest of my life.
By coincidence I took a look at jrails.js which is a part of the jRails plugin:

(function($)
{
  $().ajaxSend(
    function(a,xhr,s){
      xhr.setRequestHeader("Accept","text/javascript, text/html, application/xml, text/xml, */*")
    }
  )
}
)(jQuery); 
[...]

WTF? Is that documented anywhere?
This hard coded shit stuff breaks rails’ respond_to functionality, doesn’t it?t
To be fair, it works if you use extensions to determine what datatype you expect. (Like /things/1.js)
But I don’t do that when I build a custom ajax request where I can set the Accept header directly.

Update:
Some research on the topic “accept header vs. extension” showed that in terms of cross browser compatibility I should favor the extension approach. And I’m not surprised it’s Microsoft’s fault :-)

ActiveRecord: Overwrite attribute setter

Posted by on June 17, 2009

It’s somehow trivial, but I found out about ‘write_attribute‘ only just: [another case of rtfm]

class Thing < ActiveRecord::Base
  def name=(str)
    str.upcase! unless str.nil?
    write_attribute(:name, str)
  end
end

Update:
Be careful if you use this with Datetime attributes.

Multi-line comments in ruby

Posted by on April 7, 2009

I keep forgetting how to do them, so I post myself a little reminder here.

Just put

=begin
...
=end

around the stuff to be commented out. There must not be whitespaces before these keywords.

Optimistic Locking for Datamapper

Posted by on October 1, 2008

Update(2009-3-3): dm-optlock now on github

Update(2009-1-10): New version

I should be learning for my test on next tuesday, but coding helps keeping me in a good mood.
Here is a little gem I will need in a future project for which I’ve choosen merb + datamapper. Datamapper doesn’t support any row level locking.
My code checks if the record you want to save was changed since you loaded it. If it was changed it raises an exception (DataMapper::StaleObjectError). It works quite like ActiveRecord’s optimistic locking.
You need to define this column in your model you want to be locked:

property :lock_version, Integer, :default => 0

Anywhere in your code where you update your objects you should be prepared to handle the exception:

begin
  if @obj.update_attributes({:dummy => 123})
    #successful
  else
    #validation errors?
  end
rescue DataMapper::StaleObjectError
  #tell the user that he was too slow
  #or even better: show him the conflicts and let him merge the changes
end

The gem can be downloaded here:
dm-optlock-0.1.0.gem
Please let me know what you think of it. I’ll try and put it on RubyForge, too.

(00:27) Little update:
I added a ’set_locking_column’ method.
dm-optlock-0.1.2.gem

Update:
dm-optlock is on Rubyforge.
Now you can get it like this:

gem install dm-optlock

Mergesort in Ruby

Posted by on September 18, 2008

While playing around with stable sorting I implemented Mergesort.

class Array
  def mergesort(&cmp)
    if cmp == nil
      cmp = lambda { |a, b| a <=> b }
    end
    if size <= 1
      self.dup
    else
       halves = split.map{ |half|
        half.mergesort(&cmp)
      }
      merge(*halves, &cmp)
    end
  end
 
 
  protected
  def split
    n = (length / 2).floor - 1
    [self[0..n], self[n+1..-1]]
  end
 
  def merge(first, second, &predicate)
    result = []
    until first.empty? || second.empty?
     if predicate.call(first.first, second.first) <= 0
        result << first.shift
      else
        result << second.shift
      end 
    end
    result.concat(first).concat(second)
  end
end

It is not suitable for productive use as it’s quite slow. It’s about ten times slower than the stable_sort method from my earlier post.
A little benchmark sorting an array of 2,000,000 random integers:

                user     system      total        real
Original Sort 0.630000   0.010000   0.640000 (  0.639860)
Stable Sort 12.780000   0.700000  13.480000 ( 13.477982)
Mergesort 109.170000  13.420000 122.590000 (122.617323)