Wütend

Oh man, ich bin so verdammt wütend, ein Tweet reicht nicht aus.

Es ist so zum kotzen, dass es Programmiersprachen wie PHP den Leuten so leicht machen, hübsche Sachen zu programmieren, die auseinander fallen, wenn man sie mal schief anschaut.

“Hübsche Gui” und “Ich weiß, was ich da gerade in die Datenbank schreibe” sind zwei Paar Schuhe.

Wie kann man eigentlich eine Checksum Routine so implementieren, dass sie auf unterschiedlichen Architekturen unterschiedliche Ergebnisse liefert? Braucht es da mehr als einen mittelmässig begabten Affen, zu erkennen, dass das eine scheiß Idee ist? Und noch spannender ist es natürlich dann, diese Funktion auch zu nutzen.

Boah echt ey.

Leute, lasst die Finger von PHPs crc32() Implementierung oder benutzt sie richtig.

| Comments (0) »

25-Feb-09


Frustration

if you want something done right, do it yourself

If you happen to use the mint tracking tool like me, be careful when migrating from a 32bit to a 64bit server or vice versa. Mint saves ip addresses and a buttload of checksums as signed long values. That bites you right in the ass when the first visitors starts arriving at your site. All from 127.255.255.255, or at last visitors with an ip starting with > 127.

If you read this post before migrating, just add the following to your migration:

ALTER TABLE mint_visit 
  MODIFY COLUMN `ip_long` BIGINT NOT NULL,
  MODIFY COLUMN `referer_checksum` BIGINT NOT NULL,
  MODIFY COLUMN `domain_checksum` BIGINT NOT NULL,
  MODIFY COLUMN `resource_checksum` BIGINT NOT NULL,
  MODIFY COLUMN `session_checksum` BIGINT NOT NULL;
 
ALTER TABLE mint_debugger   
  MODIFY COLUMN `ip_long` BIGINT NOT NULL;
 
ALTER TABLE mint_geo  
  MODIFY COLUMN `ip` BIGINT NOT NULL;
 
ALTER TABLE mint_hostnames  
  MODIFY COLUMN `ip_long` BIGINT NOT NULL;

and you’re done.

If it’s too late, change your tables as well. You then also have to delete your entire mint_visit data, as the records are already corrupted. Great fail.

However, why on earth store an ip address as a long value?!? It’s an ip address and if i want to look at it, the program needs to go the other way round. To me: It’s just stupid fucking with datatypes and problems as that is what you get if you do so. It maybe makes sense for computation of networks, but not for a statistic tool. At least, i don’t see any sense in this.

Actually, the problem is known.

| Comments (1) »

25-Feb-09


Phusion Passenger and memcached / memcache-client

I recently switch from a mod_proxy / thin setup to Phusion Passenger and my application started to do the funniest things and the production.log was full with errors related to memcached.

It seems, that passengers spawn method “smart” isn’t compatible with memcached. Within seconds on a lightly loaded server the cache gets corrupted big time.

I got better results with a newer memcache client (the ruby gem actually), but for that i need to remove the client from the rails vendor lib. Furthermore, under higher load there still where errors.

Only solution is to set the spawn method to conservative like so

RailsSpawnMethod conservative

Problem seems to be known in the Phusion and Rails teams.

| Comments (1) »

23-Feb-09


Comments are evil?

What can cause this snippet to fail:

<% if !@day.user.is_rateable?  # Workaround für Darstellungsfehler mit Tabellen ohne Bodies im Safari  %>
<!-- blah -->
<% end %>

This little snippet fell apart today. I don’t know if it is passenger, a newer ruby version, RubyInline. All i know is that i am so totally pissed of this incredible amount of incompatible versions of just 3 modules that i literally feel like puking. What a hell of a day.

By the way, the thing that broke was the one-line comment right after the if.

| Comments (0) »

23-Feb-09


Localizing dates and time with Rails’ I18n using procs

Ruby on Rails I18n infrastructure did a great job to internationalization in Rails applications. Most things work right out of the box.

Daily Fratze is fully internationalized and i wanted to use ordinal day numbers in the English version. Pity, there is no template for strftime that works that way.

As i already hat monkey patched a “t” method to all date and time related classes, i came up with the following solution:

Parallel to “en.yml” i now have “en.rb” in my locales folder which gets loaded in environment.rb via

config.i18n.load_path += Dir[File.join(RAILS_ROOT, 'app', 'locales', '*.{yml,rb}')]

The en.rb files defines some procs as translation values like so:

{
  :'en' => {
    :date => {
      :formats => {
        :dmy_with_long_month              => lambda { |date| "%B #{date.day.ordinalize}, %Y" },
      }
    },
    :time => {
      :formats => {
        :dmy_with_long_month                       => lambda { |date| "%B #{date.day.ordinalize}, %Y" },        
        :dmy_with_full_day_and_long_month_and_time => lambda { |date| "%A, %B #{date.day.ordinalize}, %Y at %H:%M" }
      }
    }
  }
}

Used with the standard I18n tools you’ll end up with the string representation of the proc object. Useless 😉

So time for monkeypatching like so:

module DateTimeSupport
  def t(format = nil)
    type = self.respond_to?(:sec) ? 'time' : 'date'
    formats = I18n.translate(:"#{type}.formats")
    format = formats[format.to_sym] if formats && formats[format.to_sym]
 
    I18n.localize(self, :format => format.respond_to?(:call) ? format.call(self) : format)
  end
end
 
class Time
  include DateTimeSupport
end
 
class Date
  include DateTimeSupport
end       
 
class DateTime
  include DateTimeSupport
end
 
class ActiveSupport::TimeWithZone
  include DateTimeSupport
end

Code resides in a file in config/initializers and gets loaded automatically. It adds a t method to all date and time related classes. The method tries to look up the translation of format just like I18n/Simple does.

If it is proc, it gets called and then passed to I18n, otherwise it the original parameter is used.

That way the t method can use “dmy_with_long_month”, :dmy_with_long_month and any other arbitrary format like “%B %Y” that is not defined in any language file.

| Comments (0) »

12-Feb-09