Ruby 1.9, Rails, and UTF-8

(main purpose of this post is to link this “server error” page of rubygems.org)

The relevant issue in Rails Issue Tracker (3789). AFAICT, there are few ways to “fix” (read: workaround) this:

  • Modify the relevant Rack code to handle this crap
  • Create additional middleware to intercept (how?) the request (tried, either didn’t work or horribly inefficient)
  • Extend rack before it is started

Well, they all sucks. Hopefully someone comes up with actual working solution for this.

Oh, there’re another solutions:

  • Use REE 1.8 (really?)
  • Use JRuby in 1.8 mode
  • Use Rubinius (rbx 2.0 where?) in 1.8 mode

Um, yeah.

Update: I figured out how to “fix” it. Check it out in Moebooru (requires this).

Rails: read_multi and dalli

Be careful when using read_multi with dalli: it may return nil-valued key instead of the correct key.

The issue is tracked here and thanks to this I dropped the read_multi usage in moebooru and used the much simpler (and most likely slower) single fetch (per entry) instead. There’s alternative way to use it – do a read_multi and refetch whatever missing/nil-keyed but apparently I’m too lazy to do it.

Optimize all the queries!

While digging more into the code called “Moebooru” which was forked from “Danbooru”, I noticed this:

def self.included(m)
  m.extend(ClassMethods)
  m.after_create :increment_count
  m.after_destroy :decrement_count
end

def increment_count
  connection.execute("update table_data set row_count = row_count + 1 where name = 'users'")
end

def decrement_count
  connection.execute("update table_data set row_count = row_count - 1 where name = 'users'")
end

Counting takes ages, right. Except it is not. I’ve done this, yes, but on a table with 10+ millions of data (this one has ~400k in mainline danbooru), with multiple data inserted (this one got, uh, one every other week?) and queried every second (see below), and with the required count method not a simple select count(1) on some_table (which is what the example above used for).

The best part? It’s only used once, when user registers:

def set_role
  if User.fast_count == 0
    self.level = CONFIG["user_levels"]["Admin"]
  elsif CONFIG["enable_account_email_activation"]
    self.level = CONFIG["user_levels"]["Unactivated"]
  else
    self.level = CONFIG["starting_level"]
  end

  self.last_logged_in_at = Time.now
end

FreeBSD is Rolling Release (the ports)

Don’t get tricked by the “release” system. Apart of the base system, FreeBSD perfectly qualifies as rolling release. I guess it’s also why the binary package management sucked so badly. You won’t find how to upgrade certain packages using binary method in their Ports’ UPDATING page.

Here’s the example:

20120225:
  AFFECTS: users of archivers/libarchive
  AUTHOR: glewis@FreeBSD.org

  libarchive has been updated to version 3.0.3, with a shared library bump.
  This requires dependent ports to be rebuilt.

  # portmaster -r libarchive
  or
  # portupgrade -r archivers/libarchive

You would think the dependent packages got version bump to ensure their proper dependency – but they didn’t. Instead you had to recompile everything depending on it.

And then there’s another case:

20120220:
  AFFECTS: users of graphics/libungif
  AUTHOR: dinoex@FreeBSD.org

  libungif is obsolete, please deinstall it and rebuild all ports using
  it with graphics/giflib.

  # portmaster -o graphics/giflib graphics/libungif
  # portmaster -r giflib
  or
  # portupgrade -o graphics/giflib graphics/libungif
  # portupgrade -rf giflib

Of course, ArchLinux kind of managed to do it but that’s a purely binary rolling release Linux distro. The maintainer worked hard to ensure such kind of thing get handled properly by all their users which mostly use binary packages. FreeBSD on other hand tried to claim capable of both but it really isn’t (unless I missed something).

I’m intending to contact pkgng creator to ask his opinion about this but have yet to do it…

This pile of crap called OpenLDAP

In attempt to learn THE directory service called LDAP, I tried to setup OpenLDAP in Scientific Linux. The install went all right and slapd can be immediately started without much problem. Except that the config is one big mystery and there’s not even a rootpw defined by default. Being a complete newbie in LDAP thingy, I decided to build configuration and all from zero.

…except that it’s not actually trivial. Most examples/tutorials are for OpenLDAP prior to 2.4 which still uses slapd.conf which was obsoleted in favor of configuration in meta-format using LDAP’s ldif. Instead of one nice config, instead we have directories called cn=config etc inside slapd.d. Someone must’ve been into Linux too much (xxx.d – Linux users sure love “modularizing” their configs).

Anyway, the example in manual page of slapd-config doesn’t even work because the include syntax was wrong (should be file:///etc/… instead of /etc/…) and even after fixing that there still an error:

[root@charlotte openldap]# slapadd -F /etc/openldap/slapd.d -n 0 -l initman.ldif
str2entry: invalid value for attributeType olcSuffix #0 (syntax 1.3.6.1.4.1.1466.115.121.1.12)
slapadd: could not parse entry (line=626)
_#################### 100.00% eta   none elapsed            none fast!
Closing DB...
[root@charlotte openldap]# slaptest
slaptest: bad configuration file!

The example from the guide also gives exact same error.

In short, I kind of given up and tried to follow the “Quick Start” from the very same guide. Instead of using slapd.d format, it still uses slapd.conf format despite it being a guide for 2.4. Seems like following a pattern, the config example also spit out error:

[root@charlotte openldap]# vi slapd.conf
[root@charlotte openldap]# slaptest
/etc/openldap/slapd.conf: line 2:  invalid DN 21 (Invalid syntax)
slaptest: bad configuration file!

So much for an example. Few attempts later at both methods, I gave up and wrote this post.

Hitsugi no Chaika chapter 1

Here be fileserve link to Hitsugi no Chaika chapter 1 which seems to be recommended by Kurogane.

Here’s the bash command I used to leech from this batoto.com thingy. Originally one-liner but reformatted for readability:

for i in {1..66}; do
  curl -O "$(curl http://www.batoto.net/read/_/52737/hitsugime-no-chaika_ch1_by_village-idiot/$i 
    | grep 'img src="http://img.batoto.com/comics/' 
    | sed -E 's/.*src="([^"]+)".*/1/')"
done

Yes, I parsed html using sed/regex 😀

Flame away.

PS: Apparently I fail at leeching shit. Should’ve checked file formats before deciding it’s jpg. Just extract the files and rename the files with correct extension if you’re feeling dilligent (or getting broken image with MMCE). Only page 1-4 are jpg.

PS: whatever. Fixed everything. Added ddl from my own site since I want to waste some bandwidth.

[ Fileserve | myconan.net ]