<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>chuyeow.wtf</title>
  <subtitle>Go, Ruby, Rails, Firefox, Anime, Mac</subtitle>
  <link rel="self" type="application/atom+xml" href="https://chuyeow.wtf/categories/open-source/feed.xml"/>
  <link rel="alternate" type="text/html" href="https://chuyeow.wtf"/>
  <generator uri="https://www.getzola.org/">Zola</generator>
  <updated>2010-02-01T22:18:13+00:00</updated>
  <id>https://chuyeow.wtf/categories/open-source/feed.xml</id>
  <entry>
    <title>Setting up virtualization on Ubuntu with KVM</title>
    <published>2010-02-01T22:18:13+00:00</published>
    <updated>2010-02-01T22:18:13+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2010/02/01/setting-up-virtualization-on-ubuntu-with-kvm/"/>
    <id>https://chuyeow.wtf/2010/02/01/setting-up-virtualization-on-ubuntu-with-kvm/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2010/02/01/setting-up-virtualization-on-ubuntu-with-kvm/">&lt;p&gt;These instructions have been tested on &lt;strong&gt;Ubuntu 9.10 (Karmic) 64-bit&lt;&#x2F;strong&gt;. &lt;a href=&quot;#kvm_guide_start&quot;&gt;Skip right to the instructions&lt;&#x2F;a&gt; if you&#x27;re short on time.&lt;&#x2F;p&gt;
&lt;p&gt;After being a &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;06&#x2F;26&#x2F;installing-xen-on-ubuntu-feisty-fawn-the-complete-newbies-guide&#x2F;&quot;&gt;happy Xen user&lt;&#x2F;a&gt; for several years now, I&#x27;ve recently had to switch to an alternative virtualization solution. My colleague Arun (&lt;a href=&quot;http:&#x2F;&#x2F;twitter.com&#x2F;iamclovin&quot;&gt;@iamclovin&lt;&#x2F;a&gt;) actually struggled for a week with Xen VMs that locked up on Hardy; we&#x27;ve had much success with Hardy and Xen before, so we attributed it to a hardware problem since these were our first blade servers.&lt;&#x2F;p&gt;
&lt;p&gt;Out of ideas, we tried Karmic (Ubuntu 9.10) only to discover that Xen support via the apt package system is gone. I went down the path of compiling a &lt;a href=&quot;http:&#x2F;&#x2F;wiki.xensource.com&#x2F;xenwiki&#x2F;XenParavirtOps&quot;&gt;paravirt_ops&lt;&#x2F;a&gt; Dom0 kernel (&lt;a href=&quot;http:&#x2F;&#x2F;www.itkovian.net&#x2F;base&#x2F;the-xen-hypervisor-with-ubuntu-karmic-koala&#x2F;&quot;&gt;this article&lt;&#x2F;a&gt; was &lt;em&gt;very&lt;&#x2F;em&gt; useful) but ended up deciding the process took far too long despite being successful.&lt;&#x2F;p&gt;
&lt;p&gt;With &lt;a href=&quot;http:&#x2F;&#x2F;news.cnet.com&#x2F;8301-13580_3-9867657-39.html&quot;&gt;KVM gaining official support from Ubuntu&lt;&#x2F;a&gt; as &lt;strong&gt;the&lt;&#x2F;strong&gt; virtualization solution, I ended up ditching Xen and switching to &lt;a href=&quot;http:&#x2F;&#x2F;www.linux-kvm.org&#x2F;&quot;&gt;KVM&lt;&#x2F;a&gt; for these new servers on Karmic. The rest of the entry is a step-by-step guide on setting up KVM VMs on a Ubuntu server; I&#x27;m putting this down because like all wikis, the &lt;a href=&quot;https:&#x2F;&#x2F;help.ubuntu.com&#x2F;community&#x2F;KVM&quot;&gt;Ubuntu KVM wiki&lt;&#x2F;a&gt; has grown a little too organically to be useful.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;kvm_guide_start&quot;&gt;Preparing a host server for KVM&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;
    Update and upgrade apt packages (use your own discretion on whether this is necessary):&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;aptitude update &amp;&amp; aptitude dist-upgrade&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
    Check whether CPU supports hardware virtualization:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;egrep &#x27;(vmx|svm)&#x27; --color=always &#x2F;proc&#x2F;cpuinfo&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;    You should see lines with either &quot;vmx&quot; or &quot;svm&quot; highlighted.
  &lt;&#x2F;li&gt;
&lt;li&gt;
    Install these packages:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;aptitude install kvm libvirt-bin ubuntu-vm-builder bridge-utils&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;    If you see a &lt;code&gt;FATAL: Error inserting kvm_intel&lt;&#x2F;code&gt; message during installation, it means that virtualization is not enabled in your machine&#x27;s BIOS. You&#x27;ll need to reboot your machine, enter the BIOS setup and enable virtualization (you&#x27;ll have to hunt for the option).&lt;br &#x2F;&gt;
    &lt;a href=&quot;&#x2F;assets&#x2F;BIOS-virtualization-option.png&quot;&gt;&lt;img src=&quot;&#x2F;assets&#x2F;BIOS-virtualization-option.png&quot; alt=&quot;&quot; title=&quot;BIOS virtualization option&quot; width=&quot;399&quot; height=&quot;243&quot; class=&quot;aligncenter size-full wp-image-1283&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
    After enabling virtualization in the BIOS and rebooting, run:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;modprobe kvm-intel&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;    There should be no error shown (in fact, no console response).
  &lt;&#x2F;li&gt;
&lt;li&gt;
    Optionally, install virt-top, a top-like tool for your VMs:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;aptitude install virt-top&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
    Verify that you can connect to the hypervisor:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;virsh -c qemu:&#x2F;&#x2F;&#x2F;system list&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;    You should see something like this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Connecting to uri: qemu:&#x2F;&#x2F;&#x2F;system
 Id Name                 State
 ----------------------------------&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
    Setup a network bridge on the server for VMs. Edit &lt;code&gt;&#x2F;etc&#x2F;network&#x2F;interfaces&lt;&#x2F;code&gt; so it looks like this (use your own IPs):&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;auto lo
iface lo inet loopback
&lt;p&gt;auto eth0
iface eth0 inet manual&lt;&#x2F;p&gt;
&lt;p&gt;auto br0
iface br0 inet static
address 192.168.1.222
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
gateway 192.168.1.167
bridge_ports eth0
bridge_stp off
bridge_fd 9
bridge_hello 2
bridge_maxage 12
bridge_maxwait 0&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
    Make sure that you have a direct console to the server because you&#x27;re going to restart networking:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&#x2F;etc&#x2F;init.d&#x2F;networking restart&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
    Verify that your changes took place with &lt;code&gt;ifconfig&lt;&#x2F;code&gt;. You should see 2 entries like these:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;br0       Link encap:Ethernet  HWaddr 00:11:22:33:44:55
          inet addr:192.168.1.215  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::223:aeff:fefe:1f14&#x2F;64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1099 errors:0 dropped:0 overruns:0 frame:0
          TX packets:50 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:74665 (74.6 KB)  TX bytes:6223 (6.2 KB)
&lt;p&gt;eth0      Link encap:Ethernet  HWaddr 00:66:77:88:99:00
inet6 addr: fe80::223:aeff:fefe:1f14&#x2F;64 Scope:Link
UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
RX packets:4939 errors:0 dropped:0 overruns:0 frame:0
TX packets:39 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:532798 (532.7 KB)  TX bytes:5585 (5.5 KB)
Interrupt:36 Memory:da000000-da012800&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3&gt;Setting up a VM&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;
    Setup a VM with &lt;code&gt;vmbuilder&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;vmbuilder kvm ubuntu \
    -v \
    --suite=karmic \
    --libvirt=qemu:&#x2F;&#x2F;&#x2F;system \
    --arch=amd64 \
    --cpus=2 \
    --mem=2048 \
    --swapsize=4096 \
    --rootsize=20480 \
    --flavour=server \
    --hostname=billiejean \
    --ip=192.168.1.240 \
    --mask=255.255.255.0 \
    --net=192.168.1.0 \
    --bcast=192.168.1.255 \
    --gw=192.168.1.167 \
    --dns=&#x27;202.157.163.157 202.157.131.118&#x27; \
    --bridge=br0 \
    --mirror=http:&#x2F;&#x2F;archive.ubuntu.com&#x2F;ubuntu \
    --components=&#x27;main,universe&#x27; \
    --addpkg=openssh-server \
    --user=administrator \
    --pass=icanhaspasswd \
    --dest=&#x2F;root&#x2F;vm-billiejean \
    --tmpfs=-&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;    The options you need to care about are:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;suite&lt;&#x2F;code&gt;: Version of Ubuntu to install (e.g. karmic, hardy).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;cpus&lt;&#x2F;code&gt;: Number of CPUs to assign to VM.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;mem&lt;&#x2F;code&gt;: Amount of RAM in MB to assign to VM.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;swapsize&lt;&#x2F;code&gt;: Size of swap in MB of VM.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;rootsize&lt;&#x2F;code&gt;: Size of root filesystem in MB of VM.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;flavour&lt;&#x2F;code&gt;: The &quot;flavour&quot; of kernel to use in the VM. Either &quot;virtual&quot; or &quot;server&quot;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;hostname&lt;&#x2F;code&gt;: Hostname of VM.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ip&lt;&#x2F;code&gt;: IP address of VM.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;mask&lt;&#x2F;code&gt;: Netmask of VM.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;net&lt;&#x2F;code&gt;: Network of VM.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;bcast&lt;&#x2F;code&gt;: Broadcast address of VM.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;gw&lt;&#x2F;code&gt;: Gateway of VM.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;dns&lt;&#x2F;code&gt;: DNS server(s) for VM.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;addpkg&lt;&#x2F;code&gt;: APT packages to install in the VM. openssh-server is needed so that we can login to the VM to setup the virsh console.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;user&lt;&#x2F;code&gt; and &lt;code&gt;pass&lt;&#x2F;code&gt;: User account that&#x27;s setup for you to access the VM.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;dest&lt;&#x2F;code&gt;: Destination directory on server where VM disk image will reside.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
    If your VM is created successfully, there&#x27;ll be a config file for the VM in &lt;code&gt;&#x2F;etc&#x2F;libvirt&#x2F;qemu&#x2F;&lt;&#x2F;code&gt; (e.g. &lt;code&gt;&#x2F;etc&#x2F;libvirt&#x2F;qemu&#x2F;billiejean.xml&lt;&#x2F;code&gt;), and a disk image in the directory specified in the &lt;code&gt;--dest&lt;&#x2F;code&gt; option (e.g. &lt;code&gt;&#x2F;root&#x2F;vm-billiejean&#x2F;disk0.qcow2&lt;&#x2F;code&gt;).
  &lt;&#x2F;li&gt;
&lt;li&gt;
    You can verify that it works by starting the VM and SSHing into it (virsh console will not work yet).&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;virsh start billiejean&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3&gt;Converting Disk Images to LVM Logical Volumes&lt;&#x2F;h3&gt;
&lt;p&gt;Now, we have the VM setup but it&#x27;s running off a disk image. For better performance, running the VM off a LVM logical volume will optimize disk IO.&lt;&#x2F;p&gt;
&lt;p&gt;vmbuilder is supposed to support the &lt;code&gt;--raw&lt;&#x2F;code&gt; option to write the VM to a block device (such as a LVM logical volume), but I&#x27;ve had no success with it (as does Mark Imbriaco, sysadmin of 37signals: &lt;a href=&quot;http:&#x2F;&#x2F;twitter.com&#x2F;markimbriaco&#x2F;status&#x2F;7437688341&quot;&gt;http:&#x2F;&#x2F;twitter.com&#x2F;markimbriaco&#x2F;status&#x2F;7437688341&lt;&#x2F;a&gt; and &lt;a href=&quot;http:&#x2F;&#x2F;twitter.com&#x2F;markimbriaco&#x2F;status&#x2F;7437699338&quot;&gt;http:&#x2F;&#x2F;twitter.com&#x2F;markimbriaco&#x2F;status&#x2F;7437699338&lt;&#x2F;a&gt;). We&#x27;re going to convert the disk images using qemu-img and write the bits into a LVM logical volume instead.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Stop the VM if it&#x27;s running:
&lt;pre&gt;&lt;code&gt;virsh shutdown billiejean&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Convert the VM&#x27;s qcow2 (QEMU image format) disk image to a raw disk image:
&lt;pre&gt;&lt;code&gt;qemu-img convert disk0.qcow2 -O raw disk0.raw&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Create a logical volume to house the VM, making sure it&#x27;s big enough for the VM&#x27;s rootsize and swapsize options:
&lt;pre&gt;&lt;code&gt;lvcreate -L24GB -n &amp;lt;logical_volume_name&amp;gt; &amp;lt;volume_group_name&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Copy raw image into the logical volume:
&lt;pre&gt;&lt;code&gt;dd if=disk0.raw of=&#x2F;dev&#x2F;&amp;lt;volume_group_name&amp;gt;&#x2F;&amp;lt;logical_volume_name&amp;gt; bs=1M&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;      This will take awhile (the bigger your image, the longer it takes).&lt;&#x2F;li&gt;
&lt;li&gt;Edit the VM&#x27;s config so that it uses your new logical volume:
&lt;pre&gt;&lt;code&gt;virsh edit billiejean&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;    Change &lt;code&gt;&amp;lt;disk&amp;gt;&lt;&#x2F;code&gt; to point to the logical volume:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;disk type=&#x27;block&#x27; device=&#x27;disk&#x27;&amp;gt;
  &amp;lt;source dev=&#x27;&#x2F;dev&#x2F;&amp;lt;volume_group_name&amp;gt;&#x2F;&amp;lt;logical_volume_name&amp;gt;&#x27;&#x2F;&amp;gt;
  &amp;lt;target dev=&#x27;hda&#x27; bus=&#x27;ide&#x27;&#x2F;&amp;gt;
&amp;lt;&#x2F;disk&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Startup the VM. You might wanna rename the original &lt;code&gt;disk0.qcow2&lt;&#x2F;code&gt; image first just to make sure your VM isn&#x27;t still using it.&lt;&#x2F;li&gt;
&lt;li&gt;Once you&#x27;re sure your VM is running off your LVM logical volume, you can delete or backup the original qcow2 disk image.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3&gt;Getting a console to your VM from the Host Server&lt;&#x2F;h3&gt;
&lt;p&gt;Now, we have to setup the VM so that virsh console works. This is a console to the VM from the host server that works even when the networking in the VM is not.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Edit the VM&#x27;s settings:
&lt;pre&gt;&lt;code&gt;virsh edit billiejean&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;    In the &lt;code&gt;&amp;lt;devices&amp;gt;&lt;&#x2F;code&gt; block, add:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;serial type=&#x27;pty&#x27;&amp;gt;
  &amp;lt;target port=&#x27;0&#x27;&#x2F;&amp;gt;
&amp;lt;&#x2F;serial&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Startup your VM:
&lt;pre&gt;&lt;code&gt;virsh start billiejean&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;SSH into VM and create a file &lt;code&gt;&#x2F;etc&#x2F;init&#x2F;ttyS0.conf&lt;&#x2F;code&gt;:
&lt;pre&gt;&lt;code&gt;start on stopped rc RUNLEVEL=[2345]
stop on runlevel [!2345]
&lt;p&gt;respawn
exec &#x2F;sbin&#x2F;getty -8 38400 ttyS0 vt102&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;      Start the tty with:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;start ttyS0&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Still in the VM, install acpid so that the VM will respond to shutdown commands from the server:
&lt;pre&gt;&lt;code&gt;aptitude install acpid&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Reboot the VM.&lt;&#x2F;li&gt;
&lt;li&gt;Verify the console works by opening a console to the VM from the server:
&lt;pre&gt;&lt;code&gt;virsh console billiejean&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;      You may have to hit &quot;Enter&quot; before you see any console output.
  &lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3&gt;Miscellaneous VM Setup&lt;&#x2F;h3&gt;
&lt;p&gt;That&#x27;s it, your VM is ready! You&#x27;ll probably want to do these:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Set a root password and possibly delete the user you setup using &lt;code&gt;vmbuilder&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Set the timezone with &lt;code&gt;dpkg-reconfigure tzdata&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
  <entry>
    <title>A curl-ier Curb - better cookie support in Curb</title>
    <published>2009-06-18T09:42:10+00:00</published>
    <updated>2009-06-18T09:42:10+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2009/06/18/better-cookie-support-in-curb/"/>
    <id>https://chuyeow.wtf/2009/06/18/better-cookie-support-in-curb/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2009/06/18/better-cookie-support-in-curb/">&lt;p&gt;As of &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;taf2&#x2F;curb&#x2F;tree&#x2F;master&quot;&gt;Curb&lt;&#x2F;a&gt; 0.3.7, Curb comes with slightly better cookie support that makes it more &quot;&lt;a href=&quot;http:&#x2F;&#x2F;curl.haxx.se&#x2F;&quot;&gt;curl&lt;&#x2F;a&gt;-like&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;It probably sounds like shameless self-promotion that I&#x27;m blogging about these changes since I&#x27;d contributed them. Well, yeah that&#x27;s true, but I&#x27;m also doing so because I doubt these changes will ever be made known since Curb doesn&#x27;t publicize any updates or changelogs. &lt;&#x2F;p&gt;
&lt;p&gt;Curb is my current number 1 HTTP client for Ruby so the more love it gets, the better.&lt;&#x2F;p&gt;
&lt;h3&gt;Passing cookies as a string in Curb requests&lt;&#x2F;h3&gt;
&lt;p&gt;Curl veterans will probably know how to do this with the curl binary:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;curl -b &quot;auth=abcdef; ASP.NET_SessionId=lotsatext;&quot; example.com&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This sends a request to example.com with 2 cookies named &quot;auth&quot; and &quot;ASP.NET_SessionId&quot; (I hate those big-ass ASP.NET cookies btw). There wasn&#x27;t a way to set this in Curb, so I looked up the &lt;a href=&quot;http:&#x2F;&#x2F;curl.haxx.se&#x2F;libcurl&#x2F;c&#x2F;&quot;&gt;libcurl C API docs&lt;&#x2F;a&gt; and replicated the same option in Curb (&lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;taf2&#x2F;curb&#x2F;commit&#x2F;3c3e53c64a2417f78aa19f593a5f66e3ddffc969&quot;&gt;commit on Github&lt;&#x2F;a&gt;). An example:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;curl = Curl::Easy.new(&#x27;http:&#x2F;&#x2F;example.com&#x2F;&#x27;)
curl.cookies = &#x27;auth=abcdef; ASP.NET_SessionId=big-wall-of-text;&#x27;
curl.perform&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Of course, the cookies will more often be retrieved&#x2F;constructed rather than a literal like in the example above. In my case, I was proxying cookies while trying to wrap an API around a site that doesn&#x27;t have one.&lt;&#x2F;p&gt;
&lt;h3&gt;Passing cookies as a file via the &quot;cookiefile&quot; option&lt;&#x2F;h3&gt;
&lt;p&gt;The second change is the new &lt;code&gt;cookiefile&lt;&#x2F;code&gt; option. This replicates curl commands like these:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;curl -b cookies-to-send.txt www.example.com&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;with something like this in ruby:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;curl = Curl::Easy.new(&#x27;http:&#x2F;&#x2F;example.com&#x2F;&#x27;)
curl.cookiefile = &#x27;&#x2F;path&#x2F;to&#x2F;cookies-to-send.txt&#x27;
curl.perform&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The cookies file looks like this (you can get a sample with the &lt;code&gt;--cookie-jar&lt;&#x2F;code&gt; option to curl, e.g. &lt;code&gt;curl --cookie-jar cookies.txt www.wego.com&lt;&#x2F;code&gt;):&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;www.wego.com	FALSE	&#x2F;	FALSE	0	lang	
www.wego.com	FALSE	&#x2F;	FALSE	0	user_country_code	SG&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Check out the &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;taf2&#x2F;curb&#x2F;commit&#x2F;a4910c25198441796f8e6d1958e144998833c7ec&quot;&gt;commit on Github&lt;&#x2F;a&gt; if you&#x27;re interested.&lt;&#x2F;p&gt;
&lt;h3&gt;Why would I use these?&lt;&#x2F;h3&gt;
&lt;p&gt;Now you might be wondering how these 2 changes are useful - well, they &lt;em&gt;are&lt;&#x2F;em&gt; totally irrelevant to you if you&#x27;re not expecting any cookie support in Curb. However, if you&#x27;re accessing or scraping a site that uses &lt;strong&gt;cookie-based authentication&lt;&#x2F;strong&gt;, these changes allow you to keep your Curb client authenticated across sessions, even when doing HTTP POSTs (Curb doesn&#x27;t send cookies properly in POST requests even if &lt;code&gt;curl.enable_cookies&lt;&#x2F;code&gt; is set).&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve found these changes to Curb particularly useful since I vastly prefer Curb to most HTTP clients for its speed and lightweight implementation, and heavier scraper-type HTTP clients like &lt;a href=&quot;http:&#x2F;&#x2F;mechanize.rubyforge.org&#x2F;mechanize&#x2F;&quot;&gt;Mechanize&lt;&#x2F;a&gt; are a last resort.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the Edge (of Rails) has a new home at the Official Ruby on Rails weblog</title>
    <published>2008-06-22T17:55:39+00:00</published>
    <updated>2008-06-22T17:55:39+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/06/22/living-on-the-edge-of-rails-has-a-new-home-at-the-official-ruby-on-rails-weblog/"/>
    <id>https://chuyeow.wtf/2008/06/22/living-on-the-edge-of-rails-has-a-new-home-at-the-official-ruby-on-rails-weblog/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/06/22/living-on-the-edge-of-rails-has-a-new-home-at-the-official-ruby-on-rails-weblog/">&lt;p&gt;You may have &lt;a href=&quot;http:&#x2F;&#x2F;weblog.rubyonrails.org&#x2F;2008&#x2F;6&#x2F;10&#x2F;two-new-weekly-columns&quot;&gt;heard of it&lt;&#x2F;a&gt;, but just in case, &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;category&#x2F;edge-rails&#x2F;&quot;&gt;Living on the Edge&lt;&#x2F;a&gt; is now going to be published on the &lt;a href=&quot;http:&#x2F;&#x2F;weblog.rubyonrails.org&#x2F;&quot;&gt;official Ruby on Rails weblog&lt;&#x2F;a&gt;. Big thanks to &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;&quot;&gt;Gregg Pollack&lt;&#x2F;a&gt; for getting me the new &quot;gig&quot;, and more importantly, for reviving and freshening up the content on the official Rails blog.&lt;&#x2F;p&gt;
&lt;p&gt;Catch the new first edition - this one&#x27;s about the &lt;a href=&quot;http:&#x2F;&#x2F;weblog.rubyonrails.org&#x2F;2008&#x2F;6&#x2F;20&#x2F;living-on-the-edge-or-what-s-new-in-edge-rails-1-api-changes-and-performancetests&quot;&gt;API changes since Rails 2.1&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #22 - pre-Railsconf 2008 edition</title>
    <published>2008-05-25T19:06:36+00:00</published>
    <updated>2008-05-25T19:06:36+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/05/25/living-on-the-edge-of-rails-22-pre-railsconf-2008-edition/"/>
    <id>https://chuyeow.wtf/2008/05/25/living-on-the-edge-of-rails-22-pre-railsconf-2008-edition/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/05/25/living-on-the-edge-of-rails-22-pre-railsconf-2008-edition/">&lt;p&gt;No mind-blowing changes in Rails this week prior to RailsConf - as Gregg mentioned last week in the &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;2008&#x2F;5&#x2F;21&#x2F;rails-envy-podcast-episode-032&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt;, it&#x27;s pre-2.1 days (Rails 2.1 will &lt;em&gt;probably&lt;&#x2F;em&gt; be released at RailsConf) so it&#x27;s pretty easy to see why. Oh and all Rails tests now pass in Ruby 1.9 after a long-standing &lt;code&gt;#module_eval&lt;&#x2F;code&gt; bug got fixed in Ruby 1.9&#x27;s trunk (see &lt;a href=&quot;http:&#x2F;&#x2F;groups.google.com&#x2F;group&#x2F;ruby-core-google&#x2F;browse_thread&#x2F;thread&#x2F;6d08e11363bf49b4&quot;&gt;thread&lt;&#x2F;a&gt; for more details).&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ll be at (my first) Railsconf 2008 in Portland, Oregon this Thursday onwards - if anyone sees me and recognizes me from my &lt;a href=&quot;http:&#x2F;&#x2F;www.facebook.com&#x2F;people&#x2F;Chu_Yeow&#x2F;500115784&quot;&gt;Facebook picture&lt;&#x2F;a&gt; please come and say hi (no head butting though).&lt;&#x2F;p&gt;
&lt;p&gt;This week’s report covers changes from 19th May 2008 to 25th May 2008 (the day the corresponding &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;podcast&#x2F;&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;h3&gt;first and last methods now work with associations and named_scope&lt;&#x2F;h3&gt;
&lt;p&gt;Remember how the &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2008&#x2F;04&#x2F;05&#x2F;living-on-the-edge-of-rails-14-the-extreme-edition-extremely-late&#x2F;&quot;&gt;merging of the has_finder gem into Rails&lt;&#x2F;a&gt; allowed you to do things like &lt;code&gt;Post.first&lt;&#x2F;code&gt; and &lt;code&gt;Post.last&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;p&gt;Now you can go one step further and use the same methods on your ActiveRecord associations. For example:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;post = Post.find(1)
first_comment = post.comments.first&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you have a &lt;a href=&quot;http:&#x2F;&#x2F;ryandaigle.com&#x2F;articles&#x2F;2008&#x2F;3&#x2F;24&#x2F;what-s-new-in-edge-rails-has-finder-functionality&quot;&gt;named_scope&lt;&#x2F;a&gt; named &lt;code&gt;recent&lt;&#x2F;code&gt; defined, you can even do this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;post.comments.recent.last&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This neat little enhancement is courtesy of &lt;a href=&quot;http:&#x2F;&#x2F;railscasts.com&#x2F;&quot;&gt;Ryan Bates&lt;&#x2F;a&gt; (yes, that &lt;em&gt;Ryan Bates&lt;&#x2F;em&gt; of &lt;a href=&quot;http:&#x2F;&#x2F;railscasts.com&#x2F;&quot;&gt;Railscasts&lt;&#x2F;a&gt; fame).&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;73c59638549686fccc749ffd3ac53cb533c5fd61&quot;&gt;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;73c59638549686fccc749ffd3ac53cb533c5fd61&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Cache stores now have an exist? method and controllers get fragment_exist?&lt;&#x2F;h3&gt;
&lt;p&gt;The cache stores in Rails (Memcache, file stores, etc.) now have an &lt;code&gt;exist?&lt;&#x2F;code&gt; method that checks whether a cached value exists given a cache key. This allows Rails controllers to expose a &lt;code&gt;fragment_exist?&lt;br &#x2F;&gt;
&lt;&#x2F;code&gt; method that allows you to check for existence of a cache fragment:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;fragment_exist?(&#x27;example.com&#x2F;foo&#x2F;bar&#x27;)&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This little enhancement is courtesy of &lt;a href=&quot;http:&#x2F;&#x2F;josevalim.blogspot.com&#x2F;&quot;&gt;José Valim&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;99860b72aebe0348f41e82d4710343498d89a84b#diff-2&quot;&gt;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;99860b72aebe0348f41e82d4710343498d89a84b#diff-2&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Create association records with block argument&lt;&#x2F;h3&gt;
&lt;p&gt;You can now create records for associations like so:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;post.coments.create!(:title =&gt; &#x27;Techcrunch&#x27;) do |c|
  c.body = &quot;Rails can&#x27;t scale&quot;
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is in keeping with the &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2008&#x2F;05&#x2F;04&#x2F;living-on-the-edge-of-rails-19-change_table-for-migrations-and-more&#x2F;&quot;&gt;ActiveRecord::Base.create change previously mentioned&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Credit for this patch goes (once again) to &lt;a href=&quot;http:&#x2F;&#x2F;railscasts.com&#x2F;&quot;&gt;Ryan Bates&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;6cba97d2a449faf21aec9fe9d4434067e414226f&quot;&gt;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;6cba97d2a449faf21aec9fe9d4434067e414226f&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As always, let me know of any suggestions or how I can improve the Living on the Edge (of Rails) series.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #21</title>
    <published>2008-05-18T19:54:42+00:00</published>
    <updated>2008-05-18T19:54:42+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/05/18/living-on-the-edge-of-rails-21/"/>
    <id>https://chuyeow.wtf/2008/05/18/living-on-the-edge-of-rails-21/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/05/18/living-on-the-edge-of-rails-21/">&lt;p&gt;It&#x27;s another slow week (just 2 changes of note &lt;acronym title=&quot;in my humble opinion&quot;&gt;imho&lt;&#x2F;acronym&gt;) after the &lt;a href=&quot;http:&#x2F;&#x2F;www.rubyinside.com&#x2F;rails-21-released-891.html&quot;&gt;release of the 1st Release Candidate (RC1) of Rails 2.1&lt;&#x2F;a&gt;. Follow that link for installation instructions - though if you&#x27;re reading this blog post you probably don&#x27;t care! (because you&#x27;re, you know, &quot;living on the edge&quot;). Cheesiness aside, be sure to report any bugs you may encounter when upgrading to 2.1 RC1 or edge at the &lt;a href=&quot;http:&#x2F;&#x2F;rails.lighthouseapp.com&#x2F;projects&#x2F;8994-ruby-on-rails&#x2F;overview&quot;&gt;Rails bug tracker&lt;&#x2F;a&gt; - it is an RC so any bug reports would be very welcome and useful!&lt;&#x2F;p&gt;
&lt;p&gt;This week’s report covers changes from 12th May 2008 to 18th May 2008 (the day the corresponding &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;podcast&#x2F;&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;h3&gt;caches_action can has conditionals&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;caches_action&lt;&#x2F;code&gt; now takes an &lt;code&gt;:if&lt;&#x2F;code&gt; option (just like &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2008&#x2F;04&#x2F;20&#x2F;living-on-the-edge-of-rails-17&#x2F;&quot;&gt;caches_page does&lt;&#x2F;a&gt;). For example:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;caches_action :index, :if =&amp;gt; Proc.new { |c| !c.request.format.json? }&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This little enhancement is courtesy of José Valim.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;7708650f73ddb4db300ea2059c60c1d907a4384e&quot;&gt;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;7708650f73ddb4db300ea2059c60c1d907a4384e&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Bugfix: :select option is now scanned in ActiveRecord finders to ensure needed tables are included in generated SQL&lt;&#x2F;h3&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;Post.find(:all, :include =&amp;gt; :author, :select =&amp;gt; &#x27;posts.*, authors.id as &quot;author_id&quot;&#x27;, :limit =&amp;gt; 2)&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Would generate an SQL statement like this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;sql&quot;&gt;SELECT posts.*, authors.id as &quot;author_id&quot; FROM &quot;posts&quot; LIMIT 2&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice how the &lt;code&gt;authors&lt;&#x2F;code&gt; table is not joined. This oversight is now fixed.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks go to John Devine for this bugfix.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;b28b54cab090bed8f099ef375b419a8f92390dd4&quot;&gt;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;b28b54cab090bed8f099ef375b419a8f92390dd4&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As always, let me know of any suggestions or how I can improve the Living on the Edge (of Rails) series. Also, if anyone has any recommendations of (non-ruby-related) things to do in Portland, do let me know!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #19 - change_table for migrations and more</title>
    <published>2008-05-04T20:18:54+00:00</published>
    <updated>2008-05-04T20:18:54+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/05/04/living-on-the-edge-of-rails-19-change_table-for-migrations-and-more/"/>
    <id>https://chuyeow.wtf/2008/05/04/living-on-the-edge-of-rails-19-change_table-for-migrations-and-more/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/05/04/living-on-the-edge-of-rails-19-change_table-for-migrations-and-more/">&lt;p&gt;This week’s report covers changes from 29 April 2008 to 4th May 2008 (the day the corresponding &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;podcast&#x2F;&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;h3&gt;change_table for ActiveRecord migrations&lt;&#x2F;h3&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;http:&#x2F;&#x2F;zilkey.com&#x2F;&quot;&gt;Jeff Dean&lt;&#x2F;a&gt;, who also &lt;a href=&quot;http:&#x2F;&#x2F;zilkey.com&#x2F;2008&#x2F;4&#x2F;29&#x2F;new-rails-core-feature-proposal-super-sexy-migrations&quot;&gt;blogged about the new change_table feature in ActiveRecord migrations&lt;&#x2F;a&gt;, you can now change a table with a block like so:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;change_table :videos do |t|
  t.add_timestamps
  t.add_belongs_to :goat
  t.add_string :name, :email, :limit =&amp;gt; 20
  t.remove_column :name, :email # takes multiple arguments
  t.rename :new_name
  t.string :new_string_column # executes against the renamed table name
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Some key things to note:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;add_XXX&lt;&#x2F;code&gt; would add a new column for you, e.g. &lt;code&gt;add_string&lt;&#x2F;code&gt; would add a new string field.&lt;&#x2F;li&gt;
&lt;li&gt;Of course, add_timestamps would add the magic &lt;code&gt;created_at&lt;&#x2F;code&gt; and &lt;code&gt;updated_at&lt;&#x2F;code&gt; datetime fields.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;remove_column&lt;&#x2F;code&gt; now takes multiple arguments.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;rename&lt;&#x2F;code&gt; would rename the table.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Very nice, DRY enhancement, props to &lt;a href=&quot;http:&#x2F;&#x2F;zilkey.com&#x2F;&quot;&gt;Jeff Dean&lt;&#x2F;a&gt; once again.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;96980bd561d79824b6cb6efbcbecdcbf8785d452&quot;&gt;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;96980bd561d79824b6cb6efbcbecdcbf8785d452&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;ActiveRecord::Base.create takes a block like ActiveRecord::Base.new&lt;&#x2F;h3&gt;
&lt;p&gt;Yup now you can also &lt;code&gt;create&lt;&#x2F;code&gt; ActiveRecord objects with a block argument just like you could for &lt;code&gt;ActiveRecord::Base.new&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;@person = Person.create(params[:person]) do |p|
  p.name = &#x27;Konata Izumi&#x27;
  p.age = 17
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Credit goes to &lt;a href=&quot;http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;person&#x2F;11022-adam-meehan&quot;&gt;Adam Meehan&lt;&#x2F;a&gt; for this patch.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;dd120ede53eaf71dee76894998a81626b7a689fc&quot;&gt;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;dd120ede53eaf71dee76894998a81626b7a689fc&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Bugfix: change_column should be able to use :null =&gt; true on a field that&lt;br &#x2F;&gt;
formerly had false&lt;&#x2F;h3&gt;
&lt;p&gt;You can now use &lt;code&gt;change_column&lt;&#x2F;code&gt; in your migrations to alter a column as nullable if it was previously &lt;code&gt;NOT NULL&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This bugfix is courtesy of Nate Wiger.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;10ef65a3b054270ed3d458ec8eb7c2b9a3e638f7&quot;&gt;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;10ef65a3b054270ed3d458ec8eb7c2b9a3e638f7&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As always, let me know of any suggestions or how I can improve the Living on the Edge (of Rails) series.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #18</title>
    <published>2008-04-27T19:18:36+00:00</published>
    <updated>2008-04-27T19:18:36+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/04/27/living-on-the-edge-of-rails-18/"/>
    <id>https://chuyeow.wtf/2008/04/27/living-on-the-edge-of-rails-18/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/04/27/living-on-the-edge-of-rails-18/">&lt;p&gt;This week’s report covers changes from 21 Apr 2008 to 27 Apr 2008 (the day the corresponding &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;podcast&#x2F;&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;p&gt;Not much interesting to report this week - there were mostly a bunch of bugfixes and Ruby 1.8.7-compatibility &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commits&#x2F;master&quot;&gt;commits&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3&gt;Introduce ActiveResource::Base.timeout and rescuing from Timeout::Error in ActiveResource::Connection&lt;&#x2F;h3&gt;
&lt;p&gt;These are &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;105910429d5873dce677ef32eef5f705e0625d86&quot;&gt;2&lt;&#x2F;a&gt; &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;cf32baf915442ffe153ec0e4d8148f147776c30a&quot;&gt;changes&lt;&#x2F;a&gt; that I&#x27;d &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2008&#x2F;04&#x2F;22&#x2F;new-in-rails-activeresource-timeouts-and-why-it-matters&#x2F;&quot;&gt;talked about&lt;&#x2F;a&gt; earlier this week so I won&#x27;t repeat myself - take a read through &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2008&#x2F;04&#x2F;22&#x2F;new-in-rails-activeresource-timeouts-and-why-it-matters&#x2F;&quot;&gt;ActiveResource timeouts and why it matters&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3&gt;Smart integer datatype for the MySQL adapter in migrations&lt;&#x2F;h3&gt;
&lt;p&gt;The MySQL adapter in Rails now maps the &lt;code&gt;integer&lt;&#x2F;code&gt; column type in your migrations to either smallint, int, or bigint depending on the :limit option.&lt;&#x2F;p&gt;
&lt;p&gt;This means that a migration like this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def self.up
  create_table :searches do |t|
    t.integer :foo, :limit =&gt; 2
  end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;will create your &lt;code&gt;foo&lt;&#x2F;code&gt; column as a &lt;code&gt;smallint(2)&lt;&#x2F;code&gt; MySQL datatype (instead of &lt;code&gt;int(2)&lt;&#x2F;code&gt; before). (More information &lt;a href=&quot;http:&#x2F;&#x2F;dev.mysql.com&#x2F;doc&#x2F;refman&#x2F;5.0&#x2F;en&#x2F;numeric-types.html&quot;&gt;MySQL numeric datatypes&lt;&#x2F;a&gt;.)&lt;&#x2F;p&gt;
&lt;p&gt;Credit goes to DHH for this patch.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;a37546517dad9f6d9a7de6e1dba4d960909d71e8&quot;&gt;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;a37546517dad9f6d9a7de6e1dba4d960909d71e8&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As always, let me know of any suggestions or how I can improve the Living on the Edge (of Rails) series.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #17</title>
    <published>2008-04-20T19:21:22+00:00</published>
    <updated>2008-04-20T19:21:22+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/04/20/living-on-the-edge-of-rails-17/"/>
    <id>https://chuyeow.wtf/2008/04/20/living-on-the-edge-of-rails-17/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/04/20/living-on-the-edge-of-rails-17/">&lt;p&gt;Not much going on this week on edge Rails. It does seem however that we do have a new Rails core member, &lt;a href=&quot;http:&#x2F;&#x2F;joshpeek.com&#x2F;&quot;&gt;Joshua Peek&lt;&#x2F;a&gt;. Also, the new &lt;a href=&quot;http:&#x2F;&#x2F;rails.lighthouseapp.com&#x2F;&quot;&gt;Rails&#x27; bug tracker&lt;&#x2F;a&gt; hosted on Lighthouse is ready for use, so be sure to submit your patches and bug reports there.&lt;&#x2F;p&gt;
&lt;p&gt;This week’s report covers changes from 14 Apr 2008 to 20 Apr 2008 (the day the corresponding &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;podcast&#x2F;&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;h3&gt;Conditional caches_page&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;code&gt;caches_page&lt;&#x2F;code&gt; now takes an &lt;code&gt;:if&lt;&#x2F;code&gt; option for specifying when a page can actually be cached via a Proc. You can now do this, for example:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;caches_page :index, :if =&amp;gt; Proc.new { |c| !c.request.format.json? }&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That will only cache your index page if the requested format is not JSON.&lt;&#x2F;p&gt;
&lt;p&gt;Credit goes to &lt;a href=&quot;http:&#x2F;&#x2F;deaddeadgood.com&#x2F;&quot;&gt;Paul Horsfall&lt;&#x2F;a&gt; for this enhancement.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;14a40804a29a57ad05ca6bffbe1e5334089593a9&quot;&gt;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;14a40804a29a57ad05ca6bffbe1e5334089593a9&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;New ActionView::TestCase for testing view helpers&lt;&#x2F;h3&gt;
&lt;p&gt;Remember how you can now use &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;12&#x2F;27&#x2F;dry-in-your-functional-and-actionmailer-tests-rails-20-a-feature-a-day-7&#x2F;&quot;&gt;specialized TestCase classes for testing controllers and ActionMailer classes&lt;&#x2F;a&gt;? Now you can do the same with your Rails view helpers with the new ActionView::TestCase class.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a quick example:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;module PeopleHelper
  def title(text)
    content_tag(:h1, text)
  end
&lt;p&gt;def homepage_path
people_path
end
end&lt;&#x2F;p&gt;
&lt;p&gt;class PeopleHelperTest &amp;lt; ActionView::TestCase
def setup
ActionController::Routing::Routes.draw do |map|
map.people &#x27;people&#x27;, :controller =&amp;gt; &#x27;people&#x27;, :action =&amp;gt; &#x27;index&#x27;
map.connect &#x27;:controller&#x2F;:action&#x2F;:id&#x27;
end
end&lt;&#x2F;p&gt;
&lt;p&gt;def test_title
assert_equal &quot;&amp;lt;h1&amp;gt;Ruby on Rails&amp;lt;&#x2F;h1&amp;gt;&quot;, title(&quot;Ruby on Rails&quot;)
end&lt;&#x2F;p&gt;
&lt;p&gt;def test_homepage_path
assert_equal &quot;&#x2F;people&quot;, homepage_path
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Credit goes to Josh Peek for this sweet little enhancement.&lt;&#x2F;p&gt;
&lt;h3&gt;ActiveSupport::Cache&#x27;s mem_cache_store accepts options&lt;&#x2F;h3&gt;
&lt;p&gt;Even though Memcache-client was added to ActiveSupport recently, it didn&#x27;t allow you to specify any configuration options beyond just the IP of the memcached server. Now you can pass along more configuration options like so:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;config.action_controller.fragment_cache_store = :mem_cache_store, &#x27;localhost&#x27;, { :compression =&amp;gt; true, :debug =&amp;gt; true, :namespace =&amp;gt; &#x27;foo&#x27; }&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This patch is courtesy of &lt;a href=&quot;http:&#x2F;&#x2F;blog.innerewut.de&#x2F;&quot;&gt;Jonathan Weiss&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;9e1d506a8cfedef2fdd605e4cbf4bf53651ad214&quot;&gt;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;9e1d506a8cfedef2fdd605e4cbf4bf53651ad214&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As always, let me know of any suggestions or how I can improve the Living on the Edge (of Rails) series.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #16 - Github edition</title>
    <published>2008-04-13T16:09:43+00:00</published>
    <updated>2008-04-13T16:09:43+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/04/13/living-on-the-edge-of-rails-16-github-edition/"/>
    <id>https://chuyeow.wtf/2008/04/13/living-on-the-edge-of-rails-16-github-edition/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/04/13/living-on-the-edge-of-rails-16-github-edition/">&lt;p&gt;A slight change this week since &lt;a href=&quot;http:&#x2F;&#x2F;weblog.rubyonrails.org&#x2F;2008&#x2F;4&#x2F;11&#x2F;rails-premieres-on-github&quot;&gt;Rails has moved to Git&lt;&#x2F;a&gt; - all changesets are now referenced to &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;tree&#x2F;master&quot;&gt;Github&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This week’s report covers changes from 7 Apr 2008 to 13 Apr 2008 (the day the corresponding &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;podcast&#x2F;&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;h3&gt;A helpers proxy method for accessing helper methods from outside of views&lt;&#x2F;h3&gt;
&lt;p&gt;A &lt;code&gt;helpers&lt;&#x2F;code&gt; method has been introduced to ActionController - you can now access your helpers like so:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;ApplicationController.helpers.simple_format(text)&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Credit goes to 19 year old &lt;a href=&quot;http:&#x2F;&#x2F;joshpeek.com&#x2F;&quot;&gt;Josh Peek&lt;&#x2F;a&gt;, one of the more prolific Rails contributors (and most likely to join Pratik in Rails Core imo).&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;917423d664038d6791738a73ad1446437dbb71df&quot;&gt;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;917423d664038d6791738a73ad1446437dbb71df&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;json_escape for escaping HTML entities in JSON strings&lt;&#x2F;h3&gt;
&lt;p&gt;A &lt;code&gt;json_escape&lt;&#x2F;code&gt; (aliased as &lt;code&gt;j&lt;&#x2F;code&gt;, similar to how &lt;code&gt;html_escape&lt;&#x2F;code&gt; is aliased as &lt;code&gt;h&lt;&#x2F;code&gt;) has been introduced by Rick Olson for escaping HTML entities in JSON strings. This is useful if you find yourself emitting JSON strings in HTML pages (e.g. for documenting a JSON API):&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;json_escape(&quot;is a &amp;gt; 0 &amp;amp; a &amp;lt; 10?&quot;)
# =&gt; is a \u003E 0 \u0026 a \u003C 10?&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Of course, since &lt;code&gt;json_escape&lt;&#x2F;code&gt; is aliased as &lt;code&gt;j&lt;&#x2F;code&gt;, you can do this in your ERB templates:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;%=j @person.to_json %&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;0ff7a2d89fc95dcb0a32ed92aab7156b0778a7ea&quot;&gt;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;0ff7a2d89fc95dcb0a32ed92aab7156b0778a7ea&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Automatically parse posted JSON content for Mime::JSON requests&lt;&#x2F;h3&gt;
&lt;p&gt;Rails will now accept POSTed JSON content! For example, you can now send a POST to &quot;&#x2F;posts&quot; of your Post resource like this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;POST &#x2F;posts
{&quot;post&quot;: {&quot;title&quot;: &quot;Breaking News&quot;}}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And your &lt;code&gt;create&lt;&#x2F;code&gt; action will automatically parse the POSTed JSON into the request &lt;code&gt;params&lt;&#x2F;code&gt; so that this code below just works:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def create
  @post = Post.create params[:post]
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Credit goes to Rick Olson.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;4d594cffcfc93b37fad4e423ec8593299e50133c&quot;&gt;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;4d594cffcfc93b37fad4e423ec8593299e50133c&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;schema_migrations table replaces the schema_info table, allowing for interleaved migrations&lt;&#x2F;h3&gt;
&lt;p&gt;A new schema_migrations table for storing which migrations have been run has been introduced, and this replaces the existing schema_info table (which simply keeps track of the last applied schema version). This change makes it possible to add migrations (for example, after you&#x27;ve merged from someone&#x27;s branch) - when you migrate your database via rake db:migrate, those never-applied &quot;interleaved&quot; migrations will be run. Similarly, when migrating down schema versions, never-applied &quot;interleaved&quot; will be skipped.&lt;&#x2F;p&gt;
&lt;p&gt;See &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;11493&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;11493&lt;&#x2F;a&gt; for more information.&lt;&#x2F;p&gt;
&lt;p&gt;This useful patch is the brainchild of &lt;a href=&quot;http:&#x2F;&#x2F;bunster.org&#x2F;&quot;&gt;Jordi Bunster&lt;&#x2F;a&gt; (&lt;a href=&quot;http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;person&#x2F;12130-jordi-bunster&quot;&gt;WWR profile&lt;&#x2F;a&gt;). I&#x27;m sure many Rails developers who branch extensively will thank Jordi for this excellent patch!&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;8a5a9dcbf64843f064b6e8a0b9c6eea8f0b8536e&quot;&gt;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;8a5a9dcbf64843f064b6e8a0b9c6eea8f0b8536e&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;gems:unpack:dependencies Rake task&lt;&#x2F;h3&gt;
&lt;p&gt;Remember how you can now run the &lt;code&gt;gems:unpack&lt;&#x2F;code&gt; Rake task to unpack a gem into your &lt;code&gt;vendor&#x2F;gems&#x2F;&lt;&#x2F;code&gt; directory (this was &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2008&#x2F;04&#x2F;05&#x2F;living-on-the-edge-of-rails-14-the-extreme-edition-extremely-late&#x2F;&quot;&gt;mentioned in an earlier Living on the Edge&lt;&#x2F;a&gt;)?&lt;&#x2F;p&gt;
&lt;p&gt;David Dollar (&lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;ddollar&quot;&gt;Github profile&lt;&#x2F;a&gt;) has firmed up that patch quite a bit by adding the &lt;code&gt;gems:unpack:dependencies&lt;&#x2F;code&gt; Rake task that unpacks the dependencies of the gems as well. So running:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;gems:unpack:dependencies GEM=activecouch&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;would unpack the full Rubygem dependency tree of gems that the &lt;a href=&quot;http:&#x2F;&#x2F;code.google.com&#x2F;p&#x2F;activecouch&#x2F;&quot;&gt;activecouch&lt;&#x2F;a&gt; gem depends upon.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;4364c361b599f99bc2345ce4eb2d145b07ed8a0f&quot;&gt;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;commit&#x2F;4364c361b599f99bc2345ce4eb2d145b07ed8a0f&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As always, let me know of any suggestions or how I can improve the Living on the Edge (of Rails) series! Now go out there and start &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;rails&#x2F;rails&#x2F;tree&#x2F;master&quot;&gt;forking Rails&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #15 - the early edition</title>
    <published>2008-04-06T15:57:01+00:00</published>
    <updated>2008-04-06T15:57:01+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/04/06/living-on-the-edge-of-rails-15-the-early-edition/"/>
    <id>https://chuyeow.wtf/2008/04/06/living-on-the-edge-of-rails-15-the-early-edition/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/04/06/living-on-the-edge-of-rails-15-the-early-edition/">&lt;p&gt;I&#x27;m gonna post up the Living on the Edge a little earlier this week because I&#x27;ve found I just can&#x27;t keep up (when things get busy) with 2 separate sets of notes for the &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;podcast&#x2F;&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; and another for my own blog posts.&lt;&#x2F;p&gt;
&lt;p&gt;From this week onwards, I&#x27;ll be following &lt;a href=&quot;http:&#x2F;&#x2F;m.onkey.org&quot;&gt;Pratik&lt;&#x2F;a&gt;&#x27;s suggestion to post about changes as they happen instead of after an entire week so expect a slight change in the format of Living on the edge for next week!&lt;&#x2F;p&gt;
&lt;p&gt;This week’s report covers changes from 31 Mar 2008 to 6 Apr 2008 (the day the corresponding &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;podcast&#x2F;&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;h3&gt;Rails.env, Rails.logger, Rails.cache, Rails.root&lt;&#x2F;h3&gt;
&lt;p&gt;This has been a long time coming: You can now use &lt;code&gt;Rails.env&lt;&#x2F;code&gt; instead of &lt;code&gt;RAILS_ENV&lt;&#x2F;code&gt;, &lt;code&gt;Rails.root&lt;&#x2F;code&gt; instead of &lt;code&gt;RAILS_ROOT&lt;&#x2F;code&gt;, &lt;code&gt;Rails.logger&lt;&#x2F;code&gt; instead of &lt;code&gt;RAILS_DEFAULT_LOGGER&lt;&#x2F;code&gt;, and &lt;code&gt;Rails.cache&lt;&#x2F;code&gt; instead of &lt;code&gt;RAILS_CACHE&lt;&#x2F;code&gt;. Not having to use constants is nice because it always felt a bit dirty to have so many hard-coded constants in the Rails namespace.&lt;&#x2F;p&gt;
&lt;p&gt;Credit goes to &lt;a href=&quot;http:&#x2F;&#x2F;m.onkey.org&#x2F;&quot;&gt;Pratik Naik&lt;&#x2F;a&gt;, the newest Rails core team member for this cleanup.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9180&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9180&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Render :partial now works with a collection of heterogeneous elements&lt;&#x2F;h3&gt;
&lt;p&gt;You can now use &lt;code&gt;render :partial&lt;&#x2F;code&gt; to render a collection of different elements and Rails will figure out which partial template to use. For example:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;render :partial =&gt; [ monkey, donkey, dramatic_chipmunk ]&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;will render the monkey with the &#x27;monkeys&#x2F;_monkey.html.erb&#x27; partial, donkey with the &#x27;donkeys&#x2F;_donkey.html.erb&#x27; partial, and last but definitely not lest, dramatic_gopher with the &#x27;dramatic_chipmunks&#x2F;_dramatic_chipmunk.html.erb&#x27; partial&lt;&#x2F;p&gt;
&lt;p&gt;This is especially useful if when using &lt;acronym title=&quot;Single Table Inheritance&quot;&gt;STI&lt;&#x2F;acronym&gt;, where your ActiveRecord model would return objects of different types. The collection &lt;code&gt;[ monkey, donkey, dramatic_chipmunk ]&lt;&#x2F;code&gt; could very well be something returned from your &lt;code&gt;Animal&lt;&#x2F;code&gt; model that has subclasses of &lt;code&gt;Monkey&lt;&#x2F;code&gt;, &lt;code&gt;Donkey&lt;&#x2F;code&gt; and &lt;code&gt;DramaticChipmunk&lt;&#x2F;code&gt; via STI.&lt;&#x2F;p&gt;
&lt;p&gt;Credit: &lt;a href=&quot;http:&#x2F;&#x2F;www.continuousthinking.com&#x2F;&quot;&gt;Zach Dennis&lt;&#x2F;a&gt; of &lt;a href=&quot;http:&#x2F;&#x2F;www.continuousthinking.com&#x2F;tags&#x2F;arext&quot;&gt;ar-extensions&lt;&#x2F;a&gt; fame.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9177&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9177&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;ActiveModel work revived&lt;&#x2F;h3&gt;
&lt;p&gt;It seems like work on ActiveModel (think unified ActiveRecord and ActiveResource behaviors) has been revived, if the latest commits (&lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9171&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9171&lt;&#x2F;a&gt; and &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9173&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9173&lt;&#x2F;a&gt;) by David (DHH) is anything to go by.&lt;&#x2F;p&gt;
&lt;h3&gt;Bugfix: Assigning an invalid has_one association now causes #save to fail on parent&lt;&#x2F;h3&gt;
&lt;p&gt;You could do this before:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;firm = Firm.find(:first)
firm.account = Account.new # Associate INVALID account
firm.save # This doesn&#x27;t fail&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now that&#x27;s fixed thanks to &lt;a href=&quot;http:&#x2F;&#x2F;m.onkey.org&#x2F;&quot;&gt;Pratik Naik&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9232&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9232&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As usual, any feedback is respectfully appreciated!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #14 - the extreme edition. Extremely late.</title>
    <published>2008-04-05T00:04:06+00:00</published>
    <updated>2008-04-05T00:04:06+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/04/05/living-on-the-edge-of-rails-14-the-extreme-edition-extremely-late/"/>
    <id>https://chuyeow.wtf/2008/04/05/living-on-the-edge-of-rails-14-the-extreme-edition-extremely-late/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/04/05/living-on-the-edge-of-rails-14-the-extreme-edition-extremely-late/">&lt;p&gt;This week’s report covers changes from 24 Mar 2008 to 30 Mar 2008 (the day the corresponding &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;podcast&#x2F;&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;re lots of big exciting changes this week on edge. Smells like 2.1 soon!&lt;&#x2F;p&gt;
&lt;h3&gt;has_finder gem merged into Rails&lt;&#x2F;h3&gt;
&lt;p&gt;Ryan Daigle has &lt;a href=&quot;http:&#x2F;&#x2F;ryandaigle.com&#x2F;articles&#x2F;2008&#x2F;3&#x2F;24&#x2F;what-s-new-in-edge-rails-has-finder-functionality&quot;&gt;the scoop on the new has_finder-like functionality in Rails&lt;&#x2F;a&gt; so head on over (I won&#x27;t repeat it here in the interests of &lt;acronym title=&quot;Don&#x27;t Repeat Yourself&quot;&gt;DRY&lt;&#x2F;acronym&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Credit goes to &lt;a href=&quot;http:&#x2F;&#x2F;pivots.pivotallabs.com&#x2F;users&#x2F;nick&#x2F;blog&#x2F;articles&#x2F;284-hasfinder-it-s-now-easier-than-ever-to-create-complex-re-usable-sql-queries&quot;&gt;Nick Kallen&lt;&#x2F;a&gt; for coming up with the has_finder gem.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9084&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9084&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;ActiveRecord: Unsaved attribute changes are now tracked&lt;&#x2F;h3&gt;
&lt;p&gt;You can now ask an ActiveRecord model whether its attributes have been changed (and is unsaved) using the &lt;code&gt;{attr_name}_changed?&lt;&#x2F;code&gt; (magic) method. The &lt;code&gt;{attr_name}_was&lt;&#x2F;code&gt; method will return the original value of the attribute, and the &lt;code&gt;{attr_name}_change&lt;&#x2F;code&gt; method will return an array with 2 members, the 1st being the original value, the 2nd being the changed (and unsaved) value.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;# Change person&#x27;s name.
person.name = &#x27;Jason Seifer&#x27;
person.changed?       # =&gt; true
person.name_changed?  # =&gt; true
person.name_was       # =&gt; &#x27;jseifer&#x27;
person.name_change    # =&gt; [&#x27;jseifer&#x27;, &#x27;Jason Seifer&#x27;]
person.name = &#x27;Ceiling Cat&#x27;
person.name_change    # =&gt; [&#x27;jseifer&#x27;, &#x27;Ceiling Cat&#x27;]&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Credit goes to Rails core team member Jeremy Kemper (bitsweat) for this patch (which originated from Jeremy&#x27;s very own &lt;a href=&quot;http:&#x2F;&#x2F;code.bitsweat.net&#x2F;svn&#x2F;dirty&quot;&gt;Dirty plugin&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9127&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9127&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;ActiveRecord#Base.all&#x2F;first&#x2F;last&lt;&#x2F;h3&gt;
&lt;p&gt;Now you can do:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;Post.all.each { |post| # something }
Post.first
Post.last&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Kinda like how some other ORMs do (like DataMapper).&lt;&#x2F;p&gt;
&lt;p&gt;Credit: &lt;a href=&quot;http:&#x2F;&#x2F;www.thechrisoshow.com&#x2F;&quot;&gt;thechrisoshow&lt;&#x2F;a&gt; and again, Nick Kallen for has_finder.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9085&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9085&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Timestamped Migrations&lt;&#x2F;h3&gt;
&lt;p&gt;This is more useful than it sounds: migrations are now timestamped instead of using incremental numbers in your db&#x2F;migrate folder. This eliminates the problem of migrations having the same version number when working on a multi-developer Rails app.&lt;&#x2F;p&gt;
&lt;p&gt;Two new Rake tasks, rake &lt;code&gt;db:migrate:up&#x2F;down&lt;&#x2F;code&gt;, have been added to allow running of the &lt;code&gt;up&lt;&#x2F;code&gt; and &lt;code&gt;down&lt;&#x2F;code&gt; methods of individual migrations.&lt;&#x2F;p&gt;
&lt;p&gt;Credit goes to John Barnette, the guy who gave you &lt;a href=&quot;http:&#x2F;&#x2F;ryandaigle.com&#x2F;articles&#x2F;2007&#x2F;10&#x2F;26&#x2F;what-s-new-in-edge-rails-fixtures-just-got-a-whole-lot-easier&quot;&gt;foxy fixtures&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset:&lt;a href=&quot; http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9122&quot;&gt; http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9122&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;New config.gem option for specifying which gems are required by the application + rake tasks for installing and freezing gems&lt;&#x2F;h3&gt;
&lt;p&gt;Specify which gems are required by your Rails app in your Rails &lt;code&gt;environment.rb&lt;&#x2F;code&gt;! &quot;Vendor everything&quot; supported right in Rails :). An example:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;Rails::Initializer.run do |config| 
  config.gems &#x27;chronic&#x27;
  config.gems &quot;hpricot&quot;, :version =&gt; &#x27;0.6&#x27;, :source =&gt; &quot;http:&#x2F;&#x2F;code.whytheluckystiff.net&quot;
  config.gems &quot;aws-s3&quot;, :lib =&gt; &quot;aws&#x2F;s3&quot;
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are also new Rake tasks:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;# List required gems. 
rake gems 
&lt;h1 id=&quot;install-all-required-gems&quot;&gt;Install all required gems:&lt;&#x2F;h1&gt;
&lt;p&gt;rake gems:install&lt;&#x2F;p&gt;
&lt;h1 id=&quot;unpack-specified-gem-to-vendor-gems-gem-name-x-x-x&quot;&gt;Unpack specified gem to vendor&#x2F;gems&#x2F;gem_name-x.x.x&lt;&#x2F;h1&gt;
&lt;p&gt;rake gems:unpack GEM=chronic&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Credit goes to the prolific &lt;a href=&quot;http:&#x2F;&#x2F;techno-weenie.net&#x2F;&quot;&gt;Rick Olson&lt;&#x2F;a&gt; for this gem of a patch.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9140&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9140&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;ActiveResource #clone&lt;&#x2F;h3&gt;
&lt;p&gt;You can now clone an existing resource:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;gregg = Person.find(1)
borg = gregg.clone&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This doesn&#x27;t clone child ActiveResource members though, just the straight up attributes of resource.&lt;&#x2F;p&gt;
&lt;p&gt;Contribors: &lt;a href=&quot;http:&#x2F;&#x2F;ryandaigle.com&#x2F;&quot;&gt;Ryan Daigle&lt;&#x2F;a&gt; and &lt;a href=&quot;http:&#x2F;&#x2F;www.thechrisoshow.com&#x2F;&quot;&gt;thechrisoshow&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9121&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9121&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Big documentation patch&lt;&#x2F;h3&gt;
&lt;p&gt;A big doc patch consisting of all the efforts going on in the &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;lifo&#x2F;doc-rails&#x2F;&quot;&gt;doc-rails repository on Github&lt;&#x2F;a&gt; has been committed. Check out &lt;a href=&quot;http:&#x2F;&#x2F;groups.google.com&#x2F;group&#x2F;rubyonrails-core&#x2F;browse_thread&#x2F;thread&#x2F;92f822141df3c217&#x2F;71e7460d41bdfd89&quot;&gt;Pratik&#x27;s post&lt;&#x2F;a&gt; for more info on what doc-rails is. Though with Rails moving to Git soon, doc-rails may no longer be necessary!&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9093&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9093&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #13 - Git script&#x2F;plugin install, has_one :through</title>
    <published>2008-03-27T23:46:34+00:00</published>
    <updated>2008-03-27T23:46:34+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/03/27/living-on-the-edge-of-rails-13-git-scriptplugin-install-has_one-through/"/>
    <id>https://chuyeow.wtf/2008/03/27/living-on-the-edge-of-rails-13-git-scriptplugin-install-has_one-through/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/03/27/living-on-the-edge-of-rails-13-git-scriptplugin-install-has_one-through/">&lt;p&gt;It&#x27;s time again for some edge Rails love. If you haven&#x27;t listened to it yet, be sure to check out &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;2008&#x2F;3&#x2F;26&#x2F;rails-envy-podcast-episode-024-03-26-2008&quot;&gt;this week&#x27;s Rails Envy podcast&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This week’s report covers changes from 17 Mar 2008 to 23 Mar 2008 (the day the &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;2008&#x2F;3&#x2F;26&#x2F;rails-envy-podcast-episode-024-03-26-2008&quot;&gt;corresponding Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;h3&gt;script&#x2F;plugin install works for Git repositories&lt;&#x2F;h3&gt;
&lt;p&gt;Yup you can now install plugins from &lt;a href=&quot;http:&#x2F;&#x2F;git.or.cz&#x2F;&quot;&gt;Git&lt;&#x2F;a&gt; repositories simply by running:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;script&#x2F;plugin install git:&#x2F;&#x2F;github.com&#x2F;foo&#x2F;kung_fu&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;What this really does is to clone a git repository (sans the entire git history by passing the &lt;code&gt;—depth 1&lt;&#x2F;code&gt; option) into your plugins directory. If you&#x27;re looking for a Piston-like way to manage external Git repositories though, you&#x27;d still be better off with the development version of &lt;a href=&quot;http:&#x2F;&#x2F;piston.rubyforge.org&#x2F;&quot;&gt;Piston&lt;&#x2F;a&gt; (François Beausoleil, is &lt;a href=&quot;http:&#x2F;&#x2F;blog.teksol.info&#x2F;tags&#x2F;piston&quot;&gt;posting frequently on his progress with adding Git support&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Credit goes to &lt;a href=&quot;http:&#x2F;&#x2F;6brand.com&#x2F;git-svn-externals-rails-plugins&quot;&gt;Jack Danger&lt;&#x2F;a&gt;, a long-time Rails contributor for this patch.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9049&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9049&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;has_one :through&lt;&#x2F;h3&gt;
&lt;p&gt;It&#x27;s been a long time coming - now you can do &lt;code&gt;has_one :through&lt;&#x2F;code&gt; (like &lt;code&gt;has_many :through&lt;&#x2F;code&gt;) for your join models. &lt;a href=&quot;http:&#x2F;&#x2F;ryandaigle.com&#x2F;&quot;&gt;Ryan Daigle&lt;&#x2F;a&gt; has &lt;a href=&quot;http:&#x2F;&#x2F;ryandaigle.com&#x2F;articles&#x2F;2008&#x2F;3&#x2F;24&#x2F;what-s-new-in-edge-rails-has-one-through&quot;&gt;example code&lt;&#x2F;a&gt; on how to use it if you&#x27;re curious (though really, it&#x27;s just like has_many).&lt;&#x2F;p&gt;
&lt;p&gt;Credit goes to the &lt;a href=&quot;http:&#x2F;&#x2F;artofmission.com&#x2F;&quot;&gt;Art of Mission&lt;&#x2F;a&gt; guys and &lt;a href=&quot;http:&#x2F;&#x2F;www.thechrisoshow.com&#x2F; http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;person&#x2F;9008-chris-o-sullivan&quot;&gt;Chris O&#x27;Sullivan&lt;&#x2F;a&gt; for pulling it all together.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9067&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9067&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;rake tasks time:zones:all, time:zones:us and time:zones:local&lt;&#x2F;h3&gt;
&lt;p&gt;Some timezone-related rake tasks have been added to list the names of time zones recognized by the &lt;code&gt;TimeZone&lt;&#x2F;code&gt; class for the &lt;code&gt;config.time_zone&lt;&#x2F;code&gt; option you can put in your &lt;code&gt;environment.rb&lt;&#x2F;code&gt;. For example&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;rake time:zones:local&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;* UTC +08:00 *
Beijing
Chongqing
Hong Kong
Irkutsk
Kuala Lumpur
Perth
Singapore
Taipei
Ulaan Bataar
Urumqi&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Credit: Geoff Buesing (core team member)&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9074&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9074&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;#number_to_currency helper now supports a :format option&lt;&#x2F;h3&gt;
&lt;p&gt;Now you can do something like:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;number_to_currency(123.50, :unit =&gt; &quot;&amp;pound;&quot;, :format =&gt; &quot;%n %u&quot;) 
# =&gt; 123.50 &amp;pound;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instead of being stuck with the &lt;code&gt;{currency_code} {amount}&lt;&#x2F;code&gt; format which doesn&#x27;t work in some locales (such as &quot;42 pounds&quot;).&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9052&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9052&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #12</title>
    <published>2008-03-20T20:19:18+00:00</published>
    <updated>2008-03-20T20:19:18+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/03/20/living-on-the-edge-of-rails-12/"/>
    <id>https://chuyeow.wtf/2008/03/20/living-on-the-edge-of-rails-12/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/03/20/living-on-the-edge-of-rails-12/">&lt;p&gt;This week’s report covers changes from 10 Mar 2008 to 16 Mar 2008 (the day the &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;2008&#x2F;3&#x2F;19&#x2F;rails-envy-podcast-episode-023-03-19-2008&quot;&gt;corresponding Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;h3&gt;Custom JavaScript and stylesheet symbols&lt;&#x2F;h3&gt;
&lt;p&gt;Remember how you can do something like:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;javascript_include_tag :defaults&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and Rails would load all the Prototype JavaScript files and your application.js?&lt;&#x2F;p&gt;
&lt;p&gt;You can now register your own custom expansion symbol too:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;# In a Rails initializer.
ActionView::Helpers::AssetTagHelper.register_javascript_expansion :yui =&gt; [&#x27;yahoo&#x27;, &#x27;autocomplete&#x27;, &#x27;calendar&#x27;]
&lt;h1 id=&quot;in-your-view&quot;&gt;In your view.&lt;&#x2F;h1&gt;
&lt;p&gt;javascript_include_tag :yui&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;would result in:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;html&quot;&gt;&amp;lt;script type=&quot;text&#x2F;javascript&quot; src=&quot;&#x2F;javascripts&#x2F;yahoo.js&quot;&amp;gt;&amp;lt;&#x2F;script&amp;gt;
&amp;lt;script type=&quot;text&#x2F;javascript&quot; src=&quot;&#x2F;javascripts&#x2F;autocomplete.js&quot;&amp;gt;&amp;lt;&#x2F;script&amp;gt;
&amp;lt;script type=&quot;text&#x2F;javascript&quot; src=&quot;&#x2F;javascripts&#x2F;calendar.js&quot;&amp;gt;&amp;lt;&#x2F;script&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can do the same with the &lt;cpde&gt;stylesheet_link_tag&lt;&#x2F;cpde&gt; by registering a custom expansion symbol via &lt;code&gt;register_stylesheet_expansion&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This is useful for anyone but in particular plugin developers who have a multiple asset files would appreciate being able to tell users to include JavaScript or stylesheets using a single symbol.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Warning&lt;&#x2F;strong&gt;: This patch currently breaks the default symbols like &lt;code&gt;:all&lt;&#x2F;code&gt; (&lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;10350&quot;&gt;check out the ticket&lt;&#x2F;a&gt; for more info).&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9016&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9016&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Sexy default timestamps in migrations&lt;&#x2F;h3&gt;
&lt;p&gt;Remember how you can say &lt;code&gt;timestamps&lt;&#x2F;code&gt; in a migration and Rails will create the &#x27;created_at&#x27; and &#x27;updated_at&#x27; columns for you? You can now also do &lt;code&gt;add_timestamps :table_name&lt;&#x2F;code&gt; and &lt;code&gt;remove_timestamps :table_name&lt;&#x2F;code&gt; in your migrations if you decide to add these columns later to a table:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def self.up
  add_timestamps :posts
end
&lt;p&gt;def self.down
remove_timestamps :posts
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9014&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9014&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;ActiveRecord::Base#find(:last)&lt;&#x2F;h3&gt;
&lt;p&gt;Just like &lt;code&gt;Comment.find(:first)&lt;&#x2F;code&gt;, you can now do something like &lt;code&gt;Comment.find(:last)&lt;&#x2F;code&gt;. There&#x27;s some controversy over whether this is bloat, but &lt;acronym title=&quot;David Heinemeier Hansson&quot;&gt;DHH&lt;&#x2F;acronym&gt; makes a good case for it with this example:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class Person
  has_many :comments, :order =&amp;gt; &#x27;created_at&#x27;
end
&lt;p&gt;@some_person.comments.find(:last) # =&amp;gt; Returns the most recent comment.&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9012&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9012&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Database rake tasks fixes&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;rake db:create&lt;&#x2F;code&gt; used to ignore the &#x27;charset&#x27; and &#x27;collation&#x27; options in your database.yml configuration file. This has been fixed so that your created databases now respect those options.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;rake db:drop&lt;&#x2F;code&gt; and &lt;code&gt;rake db:migrate:reset&lt;&#x2F;code&gt; also no longer crash with an unhelpful exception if the database has already been dropped, and instead shows a proper error message.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9004&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9004&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Rails&#x27; logger now creates the log directory if it doesn&#x27;t exist&lt;&#x2F;h3&gt;
&lt;p&gt;This is a blessing to those of us who use version control systems that don&#x27;t support empty directories (like Git). Rails&#x27; default logger (the BufferedLogger), now creates a log&#x2F; directory if it doesn&#x27;t already exist. This should save you the step of creating&#x2F;symlinking a log&#x2F; directory (or symlinking) on deploy.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9013&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9013&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;String#squish is faster&lt;&#x2F;h3&gt;
&lt;p&gt;A faster implementation of the &lt;code&gt;String#squish&lt;&#x2F;code&gt; (and &lt;code&gt;String#squish!&lt;&#x2F;code&gt;) core extension has been committed.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9015&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9015&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;The #excerpt TextHelper no longer includes 1 character too many&lt;&#x2F;h3&gt;
&lt;p&gt;Turns out that the &lt;code&gt;#excerpt&lt;&#x2F;code&gt; helper method was consistently including an extra character. This has been fixed.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9030&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;9030&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As usual, let me know of any inaccuracies or any suggestions you may have in the comments!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #11</title>
    <published>2008-03-12T19:39:17+00:00</published>
    <updated>2008-03-12T19:39:17+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/03/12/living-on-the-edge-of-rails-11/"/>
    <id>https://chuyeow.wtf/2008/03/12/living-on-the-edge-of-rails-11/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/03/12/living-on-the-edge-of-rails-11/">&lt;p&gt;This week’s report covers changes from 3 Mar 2008 to 9 Mar 2008 (the day the corresponding &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;podcast&#x2F;&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;h3&gt;Improve performance on :include&#x2F;:conditions&#x2F;:limit queries by selectively joining in the pre-query&lt;&#x2F;h3&gt;
&lt;p&gt;This is another ActiveRecord performance boost related to the pre-loading any eager-loaded &lt;code&gt;:includes&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2008&#x2F;01&#x2F;30&#x2F;living-on-the-edge-of-rails-5-better-eager-loading-and-more&#x2F;&quot;&gt;mentioned previously&lt;&#x2F;a&gt;. Basically what this patch does is to only join referenced tables when needed. It does this by checking the &lt;code&gt;:conditions&lt;&#x2F;code&gt; and &lt;code&gt;:limit&lt;&#x2F;code&gt; options to determine whether a table should be joined or can be left out and pre-loaded instead. You can find out more in tickets &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;9560&quot;&gt;#9560&lt;&#x2F;a&gt; and &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;9497&quot;&gt;#9497&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Credit goes to &lt;a href=&quot;http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;person&#x2F;8164-gabe-da-silveira&quot;&gt; Gabe da Silveira&lt;&#x2F;a&gt; (dasil003 on Trac) for this awesome performance patch.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8977&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8977&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Better error message for type errors when parsing request parameters&lt;&#x2F;h3&gt;
&lt;p&gt;Now when you pass an incorrectly formed request (e.g. GET, POST) parameter to your controller, it will raise an exception that includes a friendlier error message that indicates exactly what you passed to it. This is helpful when trying to debug whether you constructed your form correctly.&lt;&#x2F;p&gt;
&lt;p&gt;Contributors: &lt;a href=&quot;http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;person&#x2F;5519-chad-humphries&quot;&gt;Chad Humphries&lt;&#x2F;a&gt; and matt.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8986&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8986&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Make MimeResponds::Responder#any work without explicit types.&lt;&#x2F;h3&gt;
&lt;p&gt;Here&#x27;s something I didn&#x27;t know: you can actually use &lt;code&gt;any&lt;&#x2F;code&gt; in your &lt;code&gt;respond_to&lt;&#x2F;code&gt; blocks as a catch-all response. E.g.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;respond_to do |format|
  format.html do
    redirect_to :action =&amp;gt; &#x27;login&#x27;
  end
  format.any(:js, :xml) do
    request_http_basic_authentication &#x27;Web Password&#x27;
  end
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Contrary to its name, using &#x27;any&#x27; actually requires you to pass a list of types to respond to. This has been enhanced now so that if you don&#x27;t pass any arguments, it&#x27;ll function as a real catch-all.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;respond_to do |format|
  format.any do
    request_http_basic_authentication &#x27;Web Password&#x27;
  end
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Credit goes to &lt;a href=&quot;http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;person&#x2F;3231-joshua-wehner&quot;&gt;Joshua Wehner&lt;&#x2F;a&gt; for this patch.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8987&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8987&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Add readonly option to has_many :through associations&lt;&#x2F;h3&gt;
&lt;p&gt;Turns out the &lt;code&gt;:readonly&lt;&#x2F;code&gt; option for associations &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2008&#x2F;02&#x2F;19&#x2F;living-on-the-edge-of-rails-8-the-code-optimization-edition&#x2F;&quot;&gt;mentioned earlier&lt;&#x2F;a&gt; was left out for &lt;code&gt;has_many :through&lt;&#x2F;code&gt; associations. This oversight has been fixed.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;person&#x2F;9147-emilio-tagua&quot;&gt;Emilio Tagua&lt;&#x2F;a&gt; for this bugfix.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8989&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8989&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As usual, let me know of any inaccuracies or any suggestions you may have in the comments!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #10</title>
    <published>2008-03-05T20:01:32+00:00</published>
    <updated>2008-03-05T20:01:32+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/03/05/living-on-the-edge-of-rails-10/"/>
    <id>https://chuyeow.wtf/2008/03/05/living-on-the-edge-of-rails-10/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/03/05/living-on-the-edge-of-rails-10/">&lt;p&gt;Another awfully sleepy week on Rails edge. Though by the time I had sent over the notes to Gregg Pollack and Jason Seifer of the awesome &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;podcast&#x2F;&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt;, there has been some nice changes (that I&#x27;ll be mentioning next week, but there&#x27;s absolutely nothing stopping you from &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;timeline?changeset=on&quot;&gt;checking those out yourself&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;In other interesting news, &lt;a href=&quot;http:&#x2F;&#x2F;m.onkey.org&#x2F;&quot;&gt;Pratik Naik&lt;&#x2F;a&gt; (lifofifo), a long-time Rails contributor has been given commit rights to Rails. Congrats Pratik, well-deserved and it has been long overdue in my opinion! Pratik keeps an interesting blog at &lt;a href=&quot;http:&#x2F;&#x2F;m.onkey.org&#x2F;&quot;&gt;http:&#x2F;&#x2F;m.onkey.org&#x2F;&lt;&#x2F;a&gt; (where he&#x27;s not afraid to say &quot;fuck&quot; in his posts &lt;em&gt;and&lt;&#x2F;em&gt; his code) and hangs out an awful lot on &lt;a href=&quot;irc:&#x2F;&#x2F;irc.freenode.net&#x2F;rubyonrails&quot;&gt;#rubyonrails&lt;&#x2F;a&gt; and &lt;a href=&quot;irc:&#x2F;&#x2F;irc.freenode.net&#x2F;rails-contrib&quot;&gt;#rails-contrib&lt;&#x2F;a&gt; on IRC.&lt;&#x2F;p&gt;
&lt;p&gt;As a sidenote, &lt;a href=&quot;http:&#x2F;&#x2F;weblog.jamisbuck.org&#x2F;2008&#x2F;2&#x2F;28&#x2F;capistrano-2-2-0&quot;&gt;Capistrano 2.2.0 was released&lt;&#x2F;a&gt; by &lt;a href=&quot;http:&#x2F;&#x2F;weblog.jamisbuck.org&#x2F;&quot;&gt;Jamis&lt;&#x2F;a&gt; last week.&lt;&#x2F;p&gt;
&lt;p&gt;This week’s report covers changes from 25 Feb 2008 to 2 Mar 2008 (the day the corresponding &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;podcast&#x2F;&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;h3&gt;Time#end_of_XXX methods&lt;&#x2F;h3&gt;
&lt;p&gt;A bunch of Time core extension methods have been added. These are: &lt;code&gt;Time#end_of_day&lt;&#x2F;code&gt;, &lt;code&gt;Time#end_of_week&lt;&#x2F;code&gt;, &lt;code&gt;Time#end_of_year&lt;&#x2F;code&gt;, and &lt;code&gt;Time#end_of_quarter&lt;&#x2F;code&gt;, which all return exactly what you expect them to return:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;Time.now.end_of_week # =&amp;gt; Sun Mar 09 00:00:00 0800 2008&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Credit goes to &lt;a href=&quot;http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;person&#x2F;5065-juanjo-baz-n&quot;&gt;Juanjo Bazán&lt;&#x2F;a&gt; (a former &lt;a href=&quot;http:&#x2F;&#x2F;weblog.workingwithrails.com&#x2F;2007&#x2F;10&#x2F;22&#x2F;hackfest-winner-interview-juanjo-bazn&quot;&gt;Rails Hackfest winner&lt;&#x2F;a&gt;) and &lt;a href=&quot;http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;person&#x2F;7168-tarmo-t-nav&quot;&gt;Tarmo Tänav&lt;&#x2F;a&gt; for contributing this patch.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8934&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8934&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Date helpers now accept HTML options&lt;&#x2F;h3&gt;
&lt;p&gt;ActionView&#x27;s date helpers (such as &lt;code&gt;date_select&lt;&#x2F;code&gt;, &lt;code&gt;time_select&lt;&#x2F;code&gt;, &lt;code&gt;select_datetime&lt;&#x2F;code&gt;) did not support any HTML options, unlike the other helpers (like &lt;code&gt;f.text_field(:name, :class =&gt; &#x27;my_css_class&#x27;, :size =&gt; 20)&lt;&#x2F;code&gt;). This inconsistency has been fixed and you can now finally do:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&amp;lt;%= date_select &#x27;user&#x27;, &#x27;birthday&#x27;, :order =&amp;gt; [:day], :class =&amp;gt; &#x27;my_css_class&#x27; %&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;person&#x2F;5430-murray-steele&quot;&gt;Murray Steele&lt;&#x2F;a&gt; (h-lame on the Rails Trac) and &lt;a hre=&quot;http:&#x2F;&#x2F;mentalized.net&#x2F;&quot;&gt;Jakob Skjerning&lt;&#x2F;a&gt; contributed this patch.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8968&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8968&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;No need for explicit respond_to for RJS templates&lt;&#x2F;h3&gt;
&lt;p&gt;ActionController has been changed so that JS requests will automatically render action.js.rjs files without the need to specify an explicit &lt;code&gt;respond_to&lt;&#x2F;code&gt; block. This means that your .rjs files work the same way as your .html.erb files - just put them in the right place and Rails will use it.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8956&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8956&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Bugfixes&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8937 - Prevent Rails from crashing when trying to deserialize an XML representation of a model named &quot;Type&quot; (using Hash#from_xml). Contributed by &lt;a href=&quot;http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;person&#x2F;5065-juanjo-baz-n&quot;&gt;Juanjo Bazán&lt;&#x2F;a&gt; and &lt;a href=&quot;http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;person&#x2F;7102-isaac-feliu&quot;&gt;Isaac Feliu&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8942 - Fix eager loading so that it doesn&#x27;t pull in duplicate records in some cases. Contributed by Catfish.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As usual, let me know of any inaccuracies or any suggestions you may have in the comments!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #9 - the sleeper edition</title>
    <published>2008-02-27T09:56:49+00:00</published>
    <updated>2008-02-27T09:56:49+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/02/27/living-on-the-edge-of-rails-9-the-sleeper-edition/"/>
    <id>https://chuyeow.wtf/2008/02/27/living-on-the-edge-of-rails-9-the-sleeper-edition/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/02/27/living-on-the-edge-of-rails-9-the-sleeper-edition/">&lt;p&gt;It&#x27;s been a slow week on the Rails trunk this week in terms of exciting changes.&lt;&#x2F;p&gt;
&lt;p&gt;This week’s report covers changes from 18 Feb 2008 to 24 Feb 2008 (the day the corresponding &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;podcast&#x2F;&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;h3&gt;ActiveResource::Base now accepts user and password configuration&lt;&#x2F;h3&gt;
&lt;p&gt;You can now set the user and password for HTTP authentication in your ActiveResource models:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class Person &lt; ActiveResource::Base
  self.site = &#x27;http:&#x2F;&#x2F;example.com&#x2F;&#x27;
  self.user = &#x27;konata&#x27;
  self.password = &#x27;password&#x27;
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a better way to specify authentication credentials than the current way of doing it by putting it all in the site (e.g. &lt;code&gt;self.site = &#x27;http:&#x2F;&#x2F;konata:password@example.com&#x2F;&#x27;&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8891&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8891&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;script&#x2F;plugin install now supports SVN export&lt;&#x2F;h3&gt;
&lt;p&gt;You can now pass the &lt;code&gt;-e&#x2F;--export&lt;&#x2F;code&gt; option to &lt;code&gt;script&#x2F;plugin install&lt;&#x2F;code&gt; to do an Subversion export of the plugin. This allows you to then check in the plugin&#x27;s files into your own repository. Though seriously, if anyone really wants to do this, I&#x27;d suggest they use &lt;a href=&quot;http:&#x2F;&#x2F;piston.rubyforge.org&#x2F;&quot;&gt;Piston&lt;&#x2F;a&gt;. That is, for those of us still using Subversion rather than Git.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8921&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8921&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Bug fixes for associations preloading&lt;&#x2F;h3&gt;
&lt;p&gt;There&#x27;ve been some bug fixes the associations preloading change mentioned in &lt;a href=&quot;&#x2F;2008&#x2F;01&#x2F;30&#x2F;living-on-the-edge-of-rails-5-better-eager-loading-and-more&#x2F;&quot;&gt;Living on the edge #5&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8894&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8894&lt;&#x2F;a&gt; - Fixed a bug where associations that were preloaded (using nested &lt;code&gt;:includes&lt;&#x2F;code&gt;) errors out when the associations return &lt;code&gt;nil&lt;&#x2F;code&gt; (i.e. when there are no associated records).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;11154&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;11154&lt;&#x2F;a&gt; - Fixed a bug where nested includes were assuming that all records are from the same class. This is not true for polymorphic associations, causing problems when they were being used.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Yup, that&#x27;s it for this week. As usual, let me know of anything I might have missed or any suggestions you may have in the comments!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #8 - the code optimization edition</title>
    <published>2008-02-19T23:30:54+00:00</published>
    <updated>2008-02-19T23:30:54+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/02/19/living-on-the-edge-of-rails-8-the-code-optimization-edition/"/>
    <id>https://chuyeow.wtf/2008/02/19/living-on-the-edge-of-rails-8-the-code-optimization-edition/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/02/19/living-on-the-edge-of-rails-8-the-code-optimization-edition/">&lt;p&gt;Here&#x27;s this week&#x27;s update of the important changes that have been happening on edge Rails. There were lots of performance patches this week, credit mostly due to the guys from &lt;a href=&quot;http:&#x2F;&#x2F;www.acunote.com&#x2F;&quot;&gt;Acunote&lt;&#x2F;a&gt; and their latest &lt;a href=&quot;http:&#x2F;&#x2F;blog.pluron.com&#x2F;2008&#x2F;02&#x2F;rails-faster-as.html&quot;&gt;blog post on optimizing Rails&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This week’s report covers changes from 11 Feb 2008 to 17 Feb 2008 (the day the corresponding &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;podcast&#x2F;&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;h3&gt;ActiveRecord::Base#attributes-related optimizations&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;code&gt;ActiveRecord::Base#attributes_before_typecast&lt;&#x2F;code&gt; no longer clones attribute unnecessarily.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8858&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8858&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;ActiveRecord::Base#attributes&lt;&#x2F;code&gt; now no longer supports options. The &lt;code&gt;ActiveRecord::Base#attributes&lt;&#x2F;code&gt; method used to support &lt;code&gt;:only&lt;&#x2F;code&gt; and &lt;code&gt;:except&lt;&#x2F;code&gt; options, which are actually unnecessary since it returns a Hash. You can use &lt;code&gt;Hash#slice&lt;&#x2F;code&gt; or &lt;code&gt;Hash#except&lt;&#x2F;code&gt; (both ActiveSupport core extensions) directly on the hash.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8863&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8863&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;ActiveRecord associations optimized by avoiding named block arguments&lt;&#x2F;h3&gt;
&lt;p&gt;Alexander Dymo is at it again optimizing ActiveRecord performance, this time by avoiding passing named block arguments. Turns out that it is faster and more memory efficient in Ruby to pass blocks like this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def foo
  bar { |*block_args| yield(*block_args) if block_given?
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;instead of passing the block around like so:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def foo(&amp;&amp;amp;block)
  bar(&amp;amp;block)
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Occurrences of the more expensive way of passing blocks have been replaced in the ActiveRecord associations code so associations are lighter to use.&lt;&#x2F;p&gt;
&lt;p&gt;For a more detailed write-up, check out &lt;a href=&quot;http:&#x2F;&#x2F;blog.pluron.com&#x2F;2008&#x2F;02&#x2F;rails-faster-as.html&quot;&gt;Alexander&#x27;s blog entry&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8865&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8865&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;ActiveRecord associations optimized by using symbol callbacks instead of string callbacks&lt;&#x2F;h3&gt;
&lt;p&gt;Again from Alexander Dymo, this patch also improving ActiveRecord association performance. Internally, ActiveRecord associations code uses a lot of string callbacks (e.g. &lt;code&gt;before_save &quot;some_ruby_code_to_eval&quot;&lt;&#x2F;code&gt;). It turns out that that is significantly more expensive compared to simply using &lt;code&gt;Module#define_method&lt;&#x2F;code&gt; because when the callback string is evaluated, the binding needs to be passed along. Passing the binding takes up memory (which is bad, of course).&lt;&#x2F;p&gt;
&lt;p&gt;The internal associations code has been changed to use that &lt;code&gt;define_method&lt;&#x2F;code&gt; now, and if you&#x27;re using a lot of associations, you would save megabytes of memory! (&lt;a href=&quot;http:&#x2F;&#x2F;blog.pluron.com&#x2F;2008&#x2F;02&#x2F;rails-faster-as.html&quot;&gt;Alexander&#x27;s blog post&lt;&#x2F;a&gt; has more detailed benchmarks.)&lt;&#x2F;p&gt;
&lt;p&gt;Remember, when writing your own before and after filters, not to use a string that needs to be &lt;code&gt;eval&lt;&#x2F;code&gt;ed!&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8867&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8867&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Improve ActiveRecord::Base#save performance by avoiding repeated calls to ActiveRecord::Base#connection&lt;&#x2F;h3&gt;
&lt;p&gt;Another Alexander Dymo performance patch. This particular patch improves performance by getting the connection object just once and calling it directly, instead of needlessly calling several times. This should improve &lt;code&gt;ActiveRecord::Base#save&lt;&#x2F;code&gt; performance.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8871&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8871&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;ActiveRecord associations now support the :readonly option&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;ActiveRecord::Base#find&lt;&#x2F;code&gt; supports the &lt;code&gt;:readonly&lt;&#x2F;code&gt; option to retrieve records that were read-only (i.e. you couldn&#x27;t save them). Now you can do the same for associations, like so:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;has_many :comments, :readonly =&gt; true&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This allows you to protect associated records from being saved.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8864&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8864&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;String#squish and String#squish! to remove consecutive chunks of whitespace&lt;&#x2F;h3&gt;
&lt;p&gt;A &lt;code&gt;String#squish&lt;&#x2F;code&gt; extension has been added that trims whitespace from both ends of a string, and compressing consecutive whitespace groups within the string into 1 space each.&lt;&#x2F;p&gt;
&lt;p&gt;For example,&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;@description = %{ String#squish() allows me to write long strings
  inside my Ruby code, without having to worry about indentation,
  the page margin, spaces, tabs or newlines. &quot;double&quot; or &#x27;single&#x27;
  quotes are both fine, and #{interpolation} works. }.squish
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8878&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8878&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As always, let me know of any inaccuracies or any suggestions you may have in the comments, see you guys next week!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #7 - improved ActiveRecord::Base#attributes, time zone support</title>
    <published>2008-02-13T23:49:44+00:00</published>
    <updated>2008-02-13T23:49:44+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/02/13/living-on-the-edge-of-rails-7-improved-activerecordbaseattributes-time-zone-support/"/>
    <id>https://chuyeow.wtf/2008/02/13/living-on-the-edge-of-rails-7-improved-activerecordbaseattributes-time-zone-support/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/02/13/living-on-the-edge-of-rails-7-improved-activerecordbaseattributes-time-zone-support/">&lt;p&gt;It&#x27;s that time of the week again (every Wednesday for the overly observant, coinciding with the release of the &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;2008&#x2F;2&#x2F;13&#x2F;rails-envy-podcast-episode-018-2-13-2008&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt;) for some choice updates of what changes have been happening on edge Rails. This week&#x27;s report covers changes from 4 Feb 2008 to 10 Feb 2008 (the day the &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;2008&#x2F;2&#x2F;13&#x2F;rails-envy-podcast-episode-018-2-13-2008&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;h3&gt;More efficent ActiveRecord::Base#attributes&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;ActiveRecord::Base#attributes&lt;&#x2F;code&gt; returns a hash of all attributes with clones of their objects as values. This unnecessary cloning is expensive, and has now been removed. &lt;code&gt;ActiveRecord::Base#attributes&lt;&#x2F;code&gt; now returns a hash of &lt;em&gt;values&lt;&#x2F;em&gt; of the attributes.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to Juanjo Bazan, there have been 2 further patches (after the podcast was recorded) related &lt;code&gt;ActiveRecord::Base#attributes&lt;&#x2F;code&gt; that further improves ActiveRecord&#x27;s performance: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8858&quot;&gt;removal of cloning from &lt;code&gt;ActiveRecord::Base#attributes_before_typecast&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8863&quot;&gt;removing options (&lt;code&gt;:only&lt;&#x2F;code&gt; and &lt;code&gt;:except&lt;&#x2F;code&gt; options, specifically) from &lt;code&gt;ActiveRecord::Base#attributes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8824&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8824&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;ActiveResouce::Base#exists? now uses HTTP HEAD instead of a GET&lt;&#x2F;h3&gt;
&lt;p&gt;A &lt;a href=&quot;http:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;HTTP#Request_Methods&quot;&gt;HTTP HEAD&lt;&#x2F;a&gt; request is really all that is needed to check for existence (200 == exists, 404 == doesn&#x27;t exist). This has been changed to HEAD from a GET request, which is more efficient since all we retrieve are the HTTP headers and there&#x27;s no unnecessary instantiation of the ActiveResource object.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8827&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8827&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Time zone support for ActiveRecord, and config.time_zone property for specifying a default Time Zone&lt;&#x2F;h3&gt;
&lt;p&gt;ActiveRecord models now have time zone-aware attribute readers and writers. Times returned from ActiveRecord attribute readers now have a &lt;code&gt;time_zone&lt;&#x2F;code&gt; attribute themselves, allowing time zone-aware calculations.&lt;&#x2F;p&gt;
&lt;p&gt;You can now configure the default &lt;code&gt;Time.zone&lt;&#x2F;code&gt; value with &lt;code&gt;config.time_zone&lt;&#x2F;code&gt; in your &lt;code&gt;environment.rb&lt;&#x2F;code&gt;. Setting this will enable time zone-awareness for ActiveRecord models.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8806&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8806&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;A Template class has been introduced to ActionView&lt;&#x2F;h3&gt;
&lt;p&gt;As part of the ActionPack refactoring that&#x27;s still ongoing, a &lt;code&gt;ActionView::Template&lt;&#x2F;code&gt; class has been introduced to encapsulate all the data relevant to the currently rendered template. This is largely an internal refactoring so Rails users shouldn&#x27;t be affected.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8805&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8805&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Concrete sweeper classes&lt;&#x2F;h3&gt;
&lt;p&gt;You can now use an explicit class when declaring a cache_sweeper. E.g.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class ListsController &amp;lt; ApplicationController 
  caches_action :index, :show, :public, :feed 
  cache_sweeper Sweepers::List, :only =&amp;gt; [ :edit, :destroy, :share ] 
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8819&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8819&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As always, let me know of any inaccuracies or any suggestions you may have in the comments - this week&#x27;s report is a little rushed because I&#x27;m a little late in posting it up!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #6 - better performance, Git support, and more</title>
    <published>2008-02-06T21:54:37+00:00</published>
    <updated>2008-02-06T21:54:37+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/02/06/living-on-the-edge-of-rails-6-better-performance-git-support-and-more/"/>
    <id>https://chuyeow.wtf/2008/02/06/living-on-the-edge-of-rails-6-better-performance-git-support-and-more/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/02/06/living-on-the-edge-of-rails-6-better-performance-git-support-and-more/">&lt;p&gt;Here&#x27;s another week of noteworthy updates on the Rails trunk. Thanks once again to the &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;podcast&#x2F;&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; for featuring my updates, and even bigger thanks to the Rails contributors and committers who make things happen. This week&#x27;s Living on the Edge was covered in &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;2008&#x2F;2&#x2F;6&#x2F;ruby-on-rails-podcast&quot;&gt;Rails Envy podcast #17&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The company I work for, &lt;a href=&quot;http:&#x2F;&#x2F;bezurk.com&#x2F;&quot;&gt;Bezurk&lt;&#x2F;a&gt; (yeah we know some of you hate the name &quot;Bezurk&quot; - that&#x27;s going to change), is currently looking for a Ruby developer to join our ranks. This person will be working mainly on Ruby-based web development projects. As we all know, &quot;Rails doesn&#x27;t scale&quot; (delivered in Jason Seifer-style - meaning it&#x27;s just a joke!) so we&#x27;d love anyone who&#x27;s up for a challenge and who&#x27;s also willing to work outside the Rails comfort zone (our current favorite: &lt;a href=&quot;http:&#x2F;&#x2F;ramaze.net&#x2F;&quot;&gt;Ramaze&lt;&#x2F;a&gt;). Our Ruby team currently comprises 3 experienced developers and 1 up and coming Rubyist.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;re active Open Source contributors (Arun released &lt;a href=&quot;http:&#x2F;&#x2F;code.google.com&#x2F;p&#x2F;activecouch&#x2F;&quot;&gt;ActiveCouch&lt;&#x2F;a&gt; recently), while I am a Rails contributor (I&#x27;m &#x27;chuyeow&#x27; on the &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;&quot;&gt;Rails Trac&lt;&#x2F;a&gt;) myself.&lt;&#x2F;p&gt;
&lt;p&gt;If all this sounds interesting enough to you, do check out the &lt;a href=&quot;http:&#x2F;&#x2F;jobs.monster.com.sg&#x2F;details&#x2F;4917397.html&quot;&gt;full job description&lt;&#x2F;a&gt; and drop us an email. Yes, we&#x27;re serious when we said &quot;+1 for DotA&#x2F;Counterstrike skills)&quot;. There&#x27;s a catch though - you have to work on location at our office in Singapore.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, let&#x27;s get back on topic - this weeks’ report covers changes from 28 Jan 2008 to 3 Feb 2008 (the day the Rails Envy podcast was recorded).&lt;&#x2F;p&gt;
&lt;h3&gt;Saving, creating and updating ActiveRecord objects is more efficient&lt;&#x2F;h3&gt;
&lt;p&gt;Thanks to Gleb Arshinov and Alexander Dymo with their &lt;a href=&quot;http:&#x2F;&#x2F;blog.pluron.com&#x2F;2008&#x2F;01&#x2F;ruby-on-rails-i.html&quot;&gt;blog post and patches about improving Rails performance&lt;&#x2F;a&gt; by approaching it via minimizing garbage collection, saving, creating, and updating ActiveRecord objects is now significantly more efficient.&lt;&#x2F;p&gt;
&lt;p&gt;The expensive &lt;code&gt;ActiveRecord::Base#attributes&lt;&#x2F;code&gt; method is no longer called internally, so there&#x27;s no unnecessary cloning of attribute values. Less memory usage means less garbage collection, which means better performance!&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8770&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8770&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;SQL calls and rendering are faster&lt;&#x2F;h3&gt;
&lt;p&gt;This patch is courtesy of &lt;a href=&quot;http:&#x2F;&#x2F;blog.pluron.com&#x2F;2008&#x2F;01&#x2F;ruby-on-rails-i.html&quot;&gt;Gleb Arshinov and Alexander Dymo&lt;&#x2F;a&gt; too.&lt;&#x2F;p&gt;
&lt;p&gt;Rails surrounds every SQL call and &lt;code&gt;ActionView::Base#render&lt;&#x2F;code&gt; with the ruby method &lt;code&gt;Benchmark#realtime&lt;&#x2F;code&gt; so that it can print out some benchmarking numbers. &lt;code&gt;Benchmark#realtime&lt;&#x2F;code&gt; allocates an unnecessary 45k of memory per call (who knew!). This has been monkey patched in Rails to a leaner implementation, reducing memory usage and increasing performance.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8771&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8771&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;MySQL adapter slight optimization&lt;&#x2F;h3&gt;
&lt;p&gt;Table and column names in the MySQL adapter are now cached in instance variables, reducing memory allocations (and thus the need for &lt;acronym title=&quot;garbage collection&quot;&gt;GC&lt;&#x2F;acronym&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8794&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8794&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;script&#x2F;generate does Git!&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;script&#x2F;generate&lt;&#x2F;code&gt; now allows you to pass the &#x27;--git&#x27; (or &#x27;-g&#x27;) option to add the generated files to git (much like how you could do the same with Subversion with &#x27;-c&#x27; or &#x27;--svn&#x27;). This patch is the work of &lt;a href=&quot;http:&#x2F;&#x2F;blog.stevensoroka.ca&#x2F;&quot;&gt;Steven Soroka&lt;&#x2F;a&gt; so nice work Steven!&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8772&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8772&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;map.resources :products, :as =&gt; &#x27;something_else&#x27;&lt;&#x2F;h3&gt;
&lt;p&gt;Here&#x27;s something that will make non-english Rails developers happy: you can now do, for example,&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;map.resources :comments, :as =&gt; &#x27;comentarios&#x27;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;so that you can keep having your model names independent of what URLs you&#x27;d actually like to appear on the site.&lt;&#x2F;p&gt;
&lt;p&gt;The above &lt;code&gt;map.resources&lt;&#x2F;code&gt; means that you can keep your resource and model names in English (Comment), while having URLs like this: &#x2F;comentarios&#x2F;123.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8785&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8785&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;:index option for form_for and fields_for to simplify multi-model forms&lt;&#x2F;h3&gt;
&lt;p&gt;Inspired by a &lt;a href=&quot;http:&#x2F;&#x2F;railscasts.com&#x2F;episodes&#x2F;75&quot;&gt;Railscasts episode&lt;&#x2F;a&gt; where Ryan Bates mentions how ugly it is to have to pass &lt;code&gt;:index =&gt; nil&lt;&#x2F;code&gt; to prevent &lt;code&gt;#text_field&lt;&#x2F;code&gt; (and other form helpers) from inserting the model&#x27;s ID in the input name (e.g. project[task_attributes][123][name] when what you really want is project[task_attributes][][name]).&lt;&#x2F;p&gt;
&lt;p&gt;Meaning instead of&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&amp;lt;% fields_for &quot;project[task_attributes][]&quot;, task do |f| %&amp;gt;
  &amp;lt;%= f.text_field :name, :index =&amp;gt; nil %&amp;gt;
  &amp;lt;%= f.hidden_field :id, :index =&amp;gt; nil %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;you can now do:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&amp;lt;% fields_for &quot;project[task_attributes][]&quot;, task, :index =&amp;gt; nil do |f| %&amp;gt;
  &amp;lt;%= f.text_field :name %&amp;gt;
  &amp;lt;%= f.hidden_field :id %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8786&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8786&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;No more emails in your production logs&lt;&#x2F;h3&gt;
&lt;p&gt;You&#x27;d probably have noticed that ActionMailer logs &lt;em&gt;entire&lt;&#x2F;em&gt; email messages in the log, even in production. Well, it&#x27;s been changed to be less verbose now. At the &lt;code&gt;:info&lt;&#x2F;code&gt; log level, only the recipients are logged. You can still see the entire email at the &lt;code&gt;:debug&lt;&#x2F;code&gt; log level (which is the default for development environment).&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8781&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8781&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As always, let me know of any inaccuracies or any suggestions you may have in the comments. Oh, and if you liked this, do me a favor by &lt;a href=&quot;http:&#x2F;&#x2F;reddit.com&#x2F;r&#x2F;ruby&#x2F;submit&quot;&gt;submitting it to Ruby Reddit&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>ActiveCouch - a CouchDB library in the spirit of ActiveResource and ActiveRecord</title>
    <published>2008-02-02T14:25:48+00:00</published>
    <updated>2008-02-02T14:25:48+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/02/02/activecouch-a-couchdb-library-in-the-spirit-of-activeresource-and-activerecord/"/>
    <id>https://chuyeow.wtf/2008/02/02/activecouch-a-couchdb-library-in-the-spirit-of-activeresource-and-activerecord/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/02/02/activecouch-a-couchdb-library-in-the-spirit-of-activeresource-and-activerecord/">&lt;p&gt;My fellow Rubyist at work, &lt;a href=&quot;http:&#x2F;&#x2F;arunthampi.wordpress.com&#x2F;&quot;&gt;Arun Thampi&lt;&#x2F;a&gt;, has released &lt;a href=&quot;http:&#x2F;&#x2F;code.google.com&#x2F;p&#x2F;activecouch&#x2F;&quot;&gt;ActiveCouch&lt;&#x2F;a&gt;, a Ruby library for &lt;a href=&quot;http:&#x2F;&#x2F;couchdb.org&#x2F;&quot;&gt;CouchDB&lt;&#x2F;a&gt; (if you don&#x27;t know what CouchDB is, &lt;a href=&quot;http:&#x2F;&#x2F;www.couchdbwiki.com&#x2F;index.php?title=CouchDb:About&quot;&gt;read this&lt;&#x2F;a&gt;). Check out the &lt;a href=&quot;http:&#x2F;&#x2F;blog.bezurk.com&#x2F;2008&#x2F;01&#x2F;23&#x2F;activecouch-a-ruby-wrapper-for-couchdb&#x2F;&quot;&gt;official blog announcement of ActiveCouch&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;ActiveCouch tries to be an ActiveResource and ActiveRecord (yes, there is even an &lt;code&gt;ActiveCouch::Migration&lt;&#x2F;code&gt; class for creating CouchDB views) equivalent for representing CouchDB documents in Ruby. I wish I could write some coherent code examples here but I am not that up to date with the latest changes in ActiveCouch (despite my name being tagged as a committer to ActiveCouch, it is largely &lt;a href=&quot;http:&#x2F;&#x2F;arunthampi.wordpress.com&#x2F;&quot;&gt;Arun&#x27;s&lt;&#x2F;a&gt; awesome little baby).&lt;&#x2F;p&gt;
&lt;p&gt;Never fear though, since Arun and I are chowing down our own dog food - we&#x27;re currently porting several gigabytes worth of hotel data from our hacked together XML and Ferret-based library to use the &lt;a href=&quot;http:&#x2F;&#x2F;code.google.com&#x2F;p&#x2F;activecouch&#x2F;&quot;&gt;ActiveCouch&lt;&#x2F;a&gt; library. I&#x27;m sure we&#x27;ll get a more coherent API after this exercise, since we are no longer relying on specs and mocks, but working on a Real Application.&lt;&#x2F;p&gt;
&lt;p&gt;If you decide to try out ActiveCouch, do let us know of any feedback or bug reports at the &lt;a href=&quot;http:&#x2F;&#x2F;code.google.com&#x2F;p&#x2F;activecouch&#x2F;&quot;&gt;ActiveCouch Google Code site&lt;&#x2F;a&gt;. ActiveCouch is Open Source, so if you&#x27;ve patches that&#x27;s even better!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Frequent disconnects with your Linksys router? Try custom firmware</title>
    <published>2008-02-02T13:41:17+00:00</published>
    <updated>2008-02-02T13:41:17+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/02/02/frequent-disconnects-with-your-linksys-router-try-custom-firmware/"/>
    <id>https://chuyeow.wtf/2008/02/02/frequent-disconnects-with-your-linksys-router-try-custom-firmware/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/02/02/frequent-disconnects-with-your-linksys-router-try-custom-firmware/">&lt;p&gt;I have a rather old &lt;a href=&quot;http:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;WRT54G&quot;&gt;Linksys WRT54G&lt;&#x2F;a&gt; (v2.2) wireless router that used to disconnect rather frequently for no apparent reason. It is almost guaranteed to get disconnected when I go crazy with &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;04&#x2F;29&#x2F;axel-lightweight-command-line-download-accelerator&#x2F;&quot;&gt;using Axel to download files&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The worse part of the entire &quot;router disconnected&quot; thing is how it takes down my DSL connection (provided by my ISP, &lt;a href=&quot;http:&#x2F;&#x2F;www.singnet.com.sg&#x2F;&quot;&gt;Singnet Broadband&lt;&#x2F;a&gt;) with it - trying to reconnect the DSL modem takes upwards of 3 minutes (I imagine it takes awhile for the ISP&#x27;s network to realize that my DSL connection is really down).&lt;&#x2F;p&gt;
&lt;p&gt;A few months ago, I finally couldn&#x27;t stand it any longer and decided to install custom firmware on the router to see if it fixes the problem (which is &lt;a href=&quot;http:&#x2F;&#x2F;www.tomshardware.com&#x2F;forum&#x2F;20801-43-linksys-wrt54g-disconnects-clients-regularly&quot;&gt;quite prevalent&lt;&#x2F;a&gt;). I was unwilling to go down this route considering my bad luck tinkering with firmware and drivers (having broken a cable modem and a near-functional Linux install before).&lt;&#x2F;p&gt;
&lt;div class=&quot;img&quot;&gt;&lt;img src=&quot;&#x2F;assets&#x2F;wrt54g.jpg&quot; alt=&quot;Linksys WRT54G&quot; &#x2F;&gt;&lt;&#x2F;div&gt;
&lt;p&gt;&lt;br style=&quot;clear: both;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, long story short: I installed &lt;a href=&quot;http:&#x2F;&#x2F;www.polarcloud.com&#x2F;tomato&quot;&gt;Tomato Firmware&lt;&#x2F;a&gt; and am enjoying rock solid stability! I can run Axel (10 simultaneous connections) with 2 torrents running and still surf comfortably and even download more stuff through the plain old web browser interface.&lt;&#x2F;p&gt;
&lt;p&gt;Long story, er, long: I tried out &lt;a href=&quot;http:&#x2F;&#x2F;www.dd-wrt.com&#x2F;&quot;&gt;DD-WRT&lt;&#x2F;a&gt; first (since we use the same &lt;a href=&quot;http:&#x2F;&#x2F;bezurk.com&#x2F;&quot;&gt;at work&lt;&#x2F;a&gt;), didn&#x27;t like its bloated interface, and especially didn&#x27;t appreciate reading (old) allegations about &lt;a href=&quot;http:&#x2F;&#x2F;www.bitsum.com&#x2F;about-ddwrt.htm&quot;&gt;how DD-WRT&#x27;s author tried to screw the Open Source community over&lt;&#x2F;a&gt;. So I flashed the firmware to &lt;a href=&quot;http:&#x2F;&#x2F;www.polarcloud.com&#x2F;tomato&quot;&gt;Tomato Firmware&lt;&#x2F;a&gt; and ended up loving its minimalist interface and faster restart cycles (most of the time, since Tomato tries to restart as few services as it needs to when you make configuration changes, rather than reboot the entire router like DD-WRT does).&lt;&#x2F;p&gt;
&lt;p&gt;So, if you&#x27;re experiencing the same troubles with your Linksys router and haven&#x27;t had taken the leap of faith with custom firmware, I really recommend you do so. &lt;strong&gt;Big warning&lt;&#x2F;strong&gt;: Read the installation instructions! Not all WRT54G routers are compatible with Tomato Firmware.&lt;&#x2F;p&gt;
&lt;p&gt;More reading: Lifehacker has a &lt;a href=&quot;http:&#x2F;&#x2F;lifehacker.com&#x2F;344765&#x2F;turn-your-60-router-into-a-user+friendly-super+router-with-tomato&quot;&gt;walkthrough of Tomato Firmware&#x27;s features&lt;&#x2F;a&gt; (and also &lt;a href=&quot;http:&#x2F;&#x2F;lifehacker.com&#x2F;software&#x2F;router&#x2F;hack-attack-turn-your-60-router-into-a-600-router-178132.php&quot;&gt;one for DD-WRT&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #5 - better eager loading and more</title>
    <published>2008-01-30T18:26:39+00:00</published>
    <updated>2008-01-30T18:26:39+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/01/30/living-on-the-edge-of-rails-5-better-eager-loading-and-more/"/>
    <id>https://chuyeow.wtf/2008/01/30/living-on-the-edge-of-rails-5-better-eager-loading-and-more/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/01/30/living-on-the-edge-of-rails-5-better-eager-loading-and-more/">&lt;p&gt;Another week of edge Rails changes, featured on the &lt;a href=&quot;http:&#x2F;&#x2F;www.railsenvy.com&#x2F;podcast&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt;. This weeks’ report covers changes from 21 Jan 2008 to 27 Jan 2008 (the day the &lt;a href=&quot;http:&#x2F;&#x2F;www.railsenvy.com&#x2F;podcast&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;h3&gt;Eager loading :includes does pre-loading&lt;&#x2F;h3&gt;
&lt;p&gt;The current gem Rails behavior when loading associations with something like&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;Author.find(:all, :include =&gt; [:posts, :comments])&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;is to make a big query with multiple joins that fetches all the associations in the same query (for you RDBMS geeks, the &quot;cartesian product&quot;).&lt;&#x2F;p&gt;
&lt;p&gt;Frederick Cheung (fcheung on the Rails Trac) has contributed an impressive optimization to this by pre-loading the associations rather than trying to eager loading with one big query. So a find like this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;Author.find(:all, :include =&gt; [:posts, :comments])&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;would first load all the authors, then all the posts, and then all the comments in 3 smaller, faster queries.&lt;&#x2F;p&gt;
&lt;p&gt;The main benefit of this (depending on your data): Running X simple queries (to fetch authors, then posts and comments) rather than one mega-query that joins all the associated tables is faster most of the time. The result set is often smaller as well.&lt;&#x2F;p&gt;
&lt;p&gt;More details can be found at &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;9640&quot;&gt;ticket #9640 on the Rails Trac&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8672&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8672&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;&lt;code&gt;composed_of&lt;&#x2F;code&gt; aggregations can now be used in finder conditions&lt;&#x2F;h3&gt;
&lt;p&gt;You can now use value objects that you&#x27;ve previously specified that your model is &lt;code&gt;composed_of&lt;&#x2F;code&gt; in the finder conditions hash. E.g. if you have a Customer that has a balance aggregation:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class Customer &amp;lt; ActiveRecord::Base
  composed_of :balance, :class_name =&amp;gt; &quot;Money&quot;, :mapping =&amp;gt; %w(balance amount)
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can now pass a Money value object to &lt;code&gt;Customer#find&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;Customer.find(:all, :conditions =&amp;gt; { :balance =&amp;gt; Money.new(20, &quot;USD&quot;) })&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Convenient.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8671&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8671&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;New helper: label_tag&lt;&#x2F;h3&gt;
&lt;p&gt;A &lt;code&gt;label_tag&lt;&#x2F;code&gt; helper has been missing for quite awhile since the label helper was added. No longer:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;label_tag &#x27;name&#x27;
# =&amp;gt; &amp;lt;label for=&quot;name&quot;&amp;gt;Name&amp;lt;&#x2F;label&amp;gt;
&lt;p&gt;label_tag &#x27;name&#x27;, &#x27;Your name&#x27;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;label-for-name-your-name-label&quot;&gt;=&amp;gt; &amp;lt;label for=&quot;name&quot;&amp;gt;Your name&amp;lt;&#x2F;label&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8685&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8685&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;New ActiveSupport class: ActiveSupport::TimeWithZone&lt;&#x2F;h3&gt;
&lt;p&gt;A new &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;browser&#x2F;trunk&#x2F;activesupport&#x2F;lib&#x2F;active_support&#x2F;time_with_zone.rb&quot;&gt;&lt;code&gt;ActiveSupport::TimeWithZone&lt;&#x2F;code&gt; class&lt;&#x2F;a&gt; has been introduced to make timezone support in Rails easier. Ryan Daigle has a &lt;a href=&quot;http:&#x2F;&#x2F;ryandaigle.com&#x2F;articles&#x2F;2008&#x2F;1&#x2F;25&#x2F;what-s-new-in-edge-rails-easier-timezones&quot;&gt;good writeup&lt;&#x2F;a&gt; on this.&lt;&#x2F;p&gt;
&lt;p&gt;A word of warning though: this is still work in progress, as Geoff Buesing, the core team member responsible for these timezone changes, has more to add on how his &lt;a href=&quot;http:&#x2F;&#x2F;ryandaigle.com&#x2F;articles&#x2F;2008&#x2F;1&#x2F;25&#x2F;what-s-new-in-edge-rails-easier-timezones#comment-6450&quot;&gt;plans for the timezone puzzle in the comments&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8696&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8696&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;map.root can be easily aliased&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;map.root&lt;&#x2F;code&gt; now accept a single symbol as an argument to declare an alias. Just a little something to keep your routes a little more DRY, e.g.:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;map.new_session :controller =&amp;gt; &#x27;sessions&#x27;, :action =&amp;gt; &#x27;new&#x27; 
map.root :new_session&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8738&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8738&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As usual, let me know of any inaccuracies or any suggestions you may have in the comments!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the edge (of Rails) #4 - faster routes, easier form partials</title>
    <published>2008-01-23T19:54:46+00:00</published>
    <updated>2008-01-23T19:54:46+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/01/23/living-on-the-edge-of-rails-4-faster-routes-easier-form-partials/"/>
    <id>https://chuyeow.wtf/2008/01/23/living-on-the-edge-of-rails-4-faster-routes-easier-form-partials/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/01/23/living-on-the-edge-of-rails-4-faster-routes-easier-form-partials/">&lt;p&gt;It&#x27;s time again for your weekly dose of what&#x27;s new in edge Rails. This weeks&#x27; report covers changes from 14 Jan 2008 to 20 Jan 2008 (the day the &lt;a href=&quot;http:&#x2F;&#x2F;railsenvy.com&#x2F;podcast&#x2F;&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; was recorded).&lt;&#x2F;p&gt;
&lt;h3&gt;Route recognition is faster&lt;&#x2F;h3&gt;
&lt;p&gt;Rails&#x27; route recognition has been optimized and is significantly faster especially for applications using many resources (i.e. via &lt;code&gt;map.resources&lt;&#x2F;code&gt; in your &lt;code&gt;config&#x2F;routes.rb&lt;&#x2F;code&gt;). Big thumbs up to Oleg Andreev (aka oleganza) who also &lt;a href=&quot;http:&#x2F;&#x2F;www.novemberain.com&#x2F;2008&#x2F;1&#x2F;17&#x2F;routes-recognition&quot;&gt;wrote a detailed post about it&lt;&#x2F;a&gt;. You can also find out more about how this works in the &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;browser&#x2F;trunk&#x2F;actionpack&#x2F;lib&#x2F;action_controller&#x2F;routing&#x2F;recognition_optimisation.rb&quot;&gt;code comments&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Related changesets: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8674&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8674&lt;&#x2F;a&gt; and &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8652&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8652&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3&gt;render :partial and forms&lt;&#x2F;h3&gt;
&lt;p&gt;Instead of doing:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&amp;lt;% form_for(:person) do |f| %&amp;gt;
  &amp;lt;%= render :partial =&amp;gt; &#x27;form&#x27;, :locals =&amp;gt; { :form =&amp;gt; f } %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;you can now do:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&amp;lt;% form_for(:person) do |f| %&amp;gt;
  &amp;lt;%= render :partial =&amp;gt; f %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Convenient. This also works with your &lt;a href=&quot;http:&#x2F;&#x2F;api.rubyonrails.org&#x2F;classes&#x2F;ActionView&#x2F;Helpers&#x2F;FormHelper.html#M000920&quot;&gt;custom form builders&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&amp;lt;% form_for(:person, :builder =&amp;gt; LabellingFormBuilder) do |f| %&amp;gt;
  &amp;lt;%= render :partial =&amp;gt; f %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The partial template rendered is then &lt;code&gt;people&#x2F;_labelling_form&lt;&#x2F;code&gt; and the local variable in the partial is &lt;code&gt;labelling_form&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8646&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8646&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3&gt;Callbacks refactored into ActiveSupport::Callbacks&lt;&#x2F;h3&gt;
&lt;p&gt;All that duplicated callback code in ActiveRecord, ActionController::Dispatcher, and in test case setup and teardown methods have been extracted into the ActiveSupport::Callbacks module.&lt;&#x2F;p&gt;
&lt;p&gt;Less duplication means more robust code so yay!&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8664&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8664&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3&gt;ActiveRecord test suite gets a makeover&lt;&#x2F;h3&gt;
&lt;p&gt;The ActiveRecord test suite has become something of a maze jungle in recent times, with no clear hierarchy of how things are organize. It&#x27;s not that easy to find what you are looking for especially for newcomers trying to contribute to ActiveRecord. Thankfully, someone (John Barnette - the foxy fixtures guy) has stepped up and cleaned things up quite a bit. Fixtures, test cases, fixture models, etc. are now in their own directories and from looking at the directory hierarchy one should be able to know where to put what at a glance.&lt;&#x2F;p&gt;
&lt;p&gt;Related ticket: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;10742&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;10742&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3&gt;Bugfixes&lt;&#x2F;h3&gt;
&lt;p&gt;* &lt;code&gt;redirect_to nil&lt;&#x2F;code&gt; no longer explodes (but raises a friendlier &#x27;cannot redirect to nil&#x27; exception) (related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8633&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8633&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the Edge (of Rails) #3 - X-Sendfile and many other sexy enhancements</title>
    <published>2008-01-16T23:25:48+00:00</published>
    <updated>2008-01-16T23:25:48+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/01/16/living-on-the-edge-of-rails-3-x-sendfile-and-many-other-sexy-enhancements/"/>
    <id>https://chuyeow.wtf/2008/01/16/living-on-the-edge-of-rails-3-x-sendfile-and-many-other-sexy-enhancements/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/01/16/living-on-the-edge-of-rails-3-x-sendfile-and-many-other-sexy-enhancements/">&lt;p&gt;Edge Rails saw a barrage of refinements and enhancements this week and there&#x27;s even talk about Rails 2.1 being just a little around the corner. There&#x27;s also been a flurry of contributions to making Rails more thread-safe and performance optimizations (all still work in progress at the moment) - it&#x27;s really nice to see how the Rails community is looking seriously at performance post-Rails 2.0 (not that they weren&#x27;t serious about performance before Rails 2.0!).&lt;&#x2F;p&gt;
&lt;p&gt;This week’s report covers changes from 7 Jan 2008 to the day the corresponding &lt;a href=&quot;http:&#x2F;&#x2F;www.railsenvy.com&#x2F;2008&#x2F;1&#x2F;16&#x2F;rails-envy-podcast-episode-014-1-16-2008&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt; was recorded (13 Jan 2008).&lt;&#x2F;p&gt;
&lt;h3&gt;X-Sendfile gets easier with send_file :x_sendfile =&gt; true&lt;&#x2F;h3&gt;
&lt;p&gt;If you only have a vague idea of what it is (like, X-Sendfile is that thing that lets you send files, right?), you&#x27;d do well to read this &lt;a href=&quot;http:&#x2F;&#x2F;john.guen.in&#x2F;past&#x2F;2007&#x2F;4&#x2F;17&#x2F;send_files_faster_with_xsendfile&#x2F;&quot;&gt;helpful explanation&lt;&#x2F;a&gt;. (In short, X-Sendfile allows you to send static files directly and more performantly to HTTP clients and bypassing your app server process.) You don&#x27;t have to set those headers yourself or install the plugin mentioned in that article though, since edge Rails has an augmented &lt;a href=&quot;http:&#x2F;&#x2F;api.rubyonrails.org&#x2F;classes&#x2F;ActionController&#x2F;Streaming.html#M000228&quot;&gt;&lt;code&gt;send_file&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; helper that does all the legwork for you.&lt;&#x2F;p&gt;
&lt;p&gt;All you have to do now is to this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;send_file &#x27;&#x2F;path&#x2F;to.png&#x27;, :x_sendfile =&amp;gt; true, :type =&amp;gt; &#x27;image&#x2F;png&#x27;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rails will set the X-Sendfile header for you (i.e. &lt;code&gt;response.headers[&#x27;X-Sendfile&#x27;] = &#x27;&#x2F;path&#x2F;to.png&#x27;&lt;&#x2F;code&gt;) and sends a HEAD response (empty response body) with the file path, allowing your web server (Apache, Lighttpd) to serve the static file and not involve your Rails processes (such as your precious, perpertually resource-starved &lt;a href=&quot;http:&#x2F;&#x2F;mongrel.rubyforge.org&#x2F;&quot;&gt;mongrels&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;This is &lt;em&gt;really&lt;&#x2F;em&gt; nice if you are serving lots of static files (downloadable images and documents come to mind) and are not already using X-Sendfile or doing it the &quot;long&quot; way (by setting the response header and then &lt;code&gt;render :nothing =&gt; true&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8628&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8628&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;ActionController::Base.asset_host proc now takes the request object as an optional 2nd argument&lt;&#x2F;h3&gt;
&lt;p&gt;Rails 2.0.2 allowed you to set &lt;code&gt;ActionController::Base.asset_host&lt;&#x2F;code&gt; to a proc that took a single &lt;code&gt;source&lt;&#x2F;code&gt; argument (as &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;12&#x2F;17&#x2F;rails-202-released-so-whats-new&#x2F;&quot;&gt;detailed in my earlier post&lt;&#x2F;a&gt;). People were still &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;10549&quot;&gt;running into problems&lt;&#x2F;a&gt; with asset hosting though, particularly while trying to serve assets from an SSL-protected page (i.e. HTTPS requests). When serving SSL-protected pages, you&#x27;d need to either have an SSL certificate for each asset host(!) or live with a mixed media warning (which browsers report when you have SSL and non-SSL content on the same page).&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;asset_host&lt;&#x2F;code&gt; proc now takes the entire controller request instance as an optional second argument. This allows you to either use a single asset host or to disable asset hosting for SSL requests. For example, this proc below practically disables asset hosting:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;ActionController::Base.asset_host = Proc.new { |source, request| 
  if request.ssl? 
    &quot;#{request.protocol}#{request.host_with_port}&quot; # Disable asset hosting.
  else 
    &quot;#{request.protocol}assets.example.com&quot; # Use asset host.
  end 
}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8578&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8578&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Nicer way to access request headers&lt;&#x2F;h3&gt;
&lt;p&gt;There&#x27;s now a nicer way to access headers - instead of &lt;code&gt;request.env[&quot;HTTP_CONTENT_TYPE&quot;]&lt;&#x2F;code&gt; you can now do &lt;code&gt;request.headers[&quot;Content-Type&quot;]&lt;&#x2F;code&gt; (or &lt;code&gt;request.headers[&quot;content-type&quot;]&lt;&#x2F;code&gt; (note all lowercase) or even good old &lt;code&gt;request.headers[&quot;HTTP_CONTENT_TYPE&quot;]&lt;&#x2F;code&gt;. How convenient - I often worry about getting the casing right (was it &#x27;Content-Type&#x27; or &#x27;Content-type&#x27;?) and now I can be sure it doesn&#x27;t matter!&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8625&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8625&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;ActiveSupport::TestCase and friends now support declarative setup and teardown callbacks&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;ActiveSupport::TestCase&lt;&#x2F;code&gt; (and the &lt;code&gt;ActionController::TestCase&lt;&#x2F;code&gt; and &lt;code&gt;ActionMailer::TestCase&lt;&#x2F;code&gt; subclasses) now support declarative setup and teardown callbacks that are called before setup&#x2F;after teardown. For example,&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class FooTestCase &amp;lt; ActiveSupport::TestCase
  setup :run_this_first, :then_run_this do
    # Run this last.
  end
  teardown :remove_tmp_files, :undef_constants
&lt;p&gt;def run_this_first
end&lt;&#x2F;p&gt;
&lt;p&gt;def then_run_this
end&lt;&#x2F;p&gt;
&lt;p&gt;def remove_tmp_files
end&lt;&#x2F;p&gt;
&lt;p&gt;def undef_constants
end
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;will run &lt;code&gt;run_this_first&lt;&#x2F;code&gt;, &lt;code&gt;then_run_this&lt;&#x2F;code&gt;, and finally the stuff that&#x27;s in the given block to &#x27;setup&#x27; before running the actual &lt;code&gt;setup&lt;&#x2F;code&gt; method. The teardown callbacks are done in reverse order, meaning &lt;code&gt;undef_constants&lt;&#x2F;code&gt; is called, and then &lt;code&gt;remove_tmp_files&lt;&#x2F;code&gt; (and then the actual &lt;code&gt;teardown&lt;&#x2F;code&gt; method).&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8570&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8570&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;TMail updated to 1.2.1&lt;&#x2F;h3&gt;
&lt;p&gt;The bundled &lt;a href=&quot;http:&#x2F;&#x2F;tmail.rubyforge.org&#x2F;&quot;&gt;TMail&lt;&#x2F;a&gt; library (that ActionMailer uses) has been updated from 1.1.0 to 1.2.1. This new version currently maintained by &lt;a href=&quot;http:&#x2F;&#x2F;lindsaar.net&#x2F;&quot;&gt;Mikel Lindsaar&lt;&#x2F;a&gt; promises bugfixes and greater test coverage. For more details, see &lt;a href=&quot;https:&#x2F;&#x2F;rubyforge.org&#x2F;frs&#x2F;shownotes.php?group_id=4512&amp;release_id=18049&quot;&gt;https:&#x2F;&#x2F;rubyforge.org&#x2F;frs&#x2F;shownotes.php?group_id=4512&amp;release_id=18049&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Mikel has been working with Rails core to get Tmail Ruby 1.9-compatible. Good work Mikel!&lt;&#x2F;p&gt;
&lt;p&gt;Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8620&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8620&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Bug fixes&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;
    &lt;code&gt;ActionController::UrlWriter&lt;&#x2F;code&gt; respects the &lt;code&gt;relative_url_root&lt;&#x2F;code&gt;. For those of you who don&#x27;t know, the &lt;code&gt;ActionController::UrlWriter&lt;&#x2F;code&gt; module is a convenient mixin that allows you to use &lt;code&gt;url_for&lt;&#x2F;code&gt; &lt;em&gt;and&lt;&#x2F;em&gt; your named routes in arbitrary classes (such as in your mailers or in a BackgrounDRb worker).&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class SitemapWorker &amp;lt; BackgrounDRb::MetaWorker
  &lt;strong&gt;include ActionController::UrlWriter&lt;&#x2F;strong&gt;
&lt;h1 id=&quot;access-your-named-routes-and-the-url-for-helper&quot;&gt;Access your named routes and the url_for helper.&lt;&#x2F;h1&gt;
&lt;p&gt;url = page_url(:permalink =&amp;gt; &#x27;foo&#x27;)
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;  And now it respects your &lt;code&gt;relative_url_root&lt;&#x2F;code&gt; instead of blissfully ignoring it.&lt;&#x2F;p&gt;
&lt;p&gt;  Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8616&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8616&lt;&#x2F;a&gt;
  &lt;&#x2F;li&gt;
&lt;li&gt;
    &lt;code&gt;render :text =&gt; nil&lt;&#x2F;code&gt; and &lt;code&gt;render :text =&gt; false&lt;&#x2F;code&gt; work properly now instead of inexplicably trying to render a file. This was a big gotcha when using &lt;code&gt;render :text =&gt; some_variable&lt;&#x2F;code&gt; where &lt;code&gt;some_variable&lt;&#x2F;code&gt; could potentially be false or nil in some cases - Obie Fernandez has a &lt;a href=&quot;http:&#x2F;&#x2F;www.jroller.com&#x2F;obie&#x2F;entry&#x2F;render_text_gotcha&quot;&gt;writeup on this long-standing bug&lt;&#x2F;a&gt;. Related changeset: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8577&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8577&lt;&#x2F;a&gt;
  &lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3&gt;Optimizations&lt;&#x2F;h3&gt;
&lt;p&gt;There&#x27;re significant performance improvements for classic fixtures with HABTM data, due to some slightly clever caching model classes, and instantiating fixtures from the model class, instead of expensive constant lookups from the name of the class.&lt;&#x2F;p&gt;
&lt;p&gt;Related changesets: &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8560&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8560&lt;&#x2F;a&gt; and &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8561&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8561&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the Edge (of Rails) - 1st week of the year edition</title>
    <published>2008-01-09T22:18:20+00:00</published>
    <updated>2008-01-09T22:18:20+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/01/09/living-on-the-edge-of-rails-1st-week-of-the-year-edition/"/>
    <id>https://chuyeow.wtf/2008/01/09/living-on-the-edge-of-rails-1st-week-of-the-year-edition/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/01/09/living-on-the-edge-of-rails-1st-week-of-the-year-edition/">&lt;p&gt;Yup, it&#x27;s time for your weekly dose of the changes on edge Rails, more or less covered in the latest &lt;a href=&quot;http:&#x2F;&#x2F;www.railsenvy.com&#x2F;2008&#x2F;1&#x2F;9&#x2F;rails-envy-podcast-episode-013-1-9-2008&quot;&gt;Rails Envy podcast&lt;&#x2F;a&gt;. Using edge Rails is neither arcane nor terrifying, and hopefully weekly reports like these will allow you to &lt;a href=&quot;http:&#x2F;&#x2F;www.loudthinking.com&#x2F;posts&#x2F;20-dont-overestimate-the-power-of-versions&quot;&gt;take control of your own release schedule&lt;&#x2F;a&gt; with your Rails apps.&lt;&#x2F;p&gt;
&lt;p&gt;This week&#x27;s report covers changes from 31 Dec 2007 to the day the podcast was recorded (6 Jan 2007).&lt;&#x2F;p&gt;
&lt;h3&gt;Caching changes&lt;&#x2F;h3&gt;
&lt;p&gt;Looks like most of the changes from the &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;browser&#x2F;branches&#x2F;2-1-caching&quot;&gt;2.1 caching branch&lt;&#x2F;a&gt; have been&lt;br &#x2F;&gt;
&lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8546&quot;&gt;merged into the trunk&lt;&#x2F;a&gt;. Some key points:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;memcache-client has been &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;browser&#x2F;trunk&#x2F;activesupport&#x2F;lib&#x2F;active_support&#x2F;vendor&#x2F;memcache-client-1.5.0&quot;&gt;vendored&lt;&#x2F;a&gt; (included in Rails directly). MemCacheStore works out of the box in Rails now, no need to install the &lt;a href=&quot;http:&#x2F;&#x2F;dev.robotcoop.com&#x2F;Libraries&#x2F;memcache-client&#x2F;&quot;&gt;memcache-client gem&lt;&#x2F;a&gt;!&lt;&#x2F;li&gt;
&lt;li&gt;The caching code has been refactored and moved into ActiveSupport (&lt;code&gt;ActiveSupport::Cache::*&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Added &lt;code&gt;ActiveRecord::Base.cache_key&lt;&#x2F;code&gt; to make it easier to cache Active Records in combination with the ActiveSupport cache libraries introduced in this changeset.&lt;&#x2F;li&gt;
&lt;li&gt;Fragment cache keys are now by default prefixed with &#x27;views&#x2F;&#x27;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Deprecation&lt;&#x2F;em&gt;: &lt;code&gt;ActionController::Base.fragment_cache_store&lt;&#x2F;code&gt; is now &lt;code&gt;ActionController::Base.cache_store&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3&gt;Fragment caching now works in RJS and Builder templates&lt;&#x2F;h3&gt;
&lt;p&gt;Yup, you couldn&#x27;t do fragment caching in non-erb views before - &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8542&quot;&gt;now you can&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3&gt;Freezing Rails now automatically updates your Rails app&lt;&#x2F;h3&gt;
&lt;p&gt;If you&#x27;re using edge Rails and use the &lt;code&gt;rails:freeze:edge&lt;&#x2F;code&gt; rake task, you probably usually forget to run (or maybe you&#x27;re not even aware of) &lt;code&gt;rake rails:update&lt;&#x2F;code&gt; to update your Rails app with the latest config&#x2F;, scripts&#x2F; and javascript files from the version of Rails you just froze to. On edge Rails, the &lt;code&gt;rake rails:freeze:edge&lt;&#x2F;code&gt; task runs the &lt;code&gt;rails:update&lt;&#x2F;code&gt; task for you. +1 for convenience!&lt;&#x2F;p&gt;
&lt;p&gt;I prefer to use &lt;a href=&quot;http:&#x2F;&#x2F;piston.rubyforge.org&#x2F;&quot;&gt;Piston&lt;&#x2F;a&gt; so I&#x27;m gonna have to keep remembering to run my &lt;code&gt;rake rails:update&lt;&#x2F;code&gt; now and then!&lt;&#x2F;p&gt;
&lt;p&gt;Check out the &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8532&quot;&gt;related changeset&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3&gt;Optimizations&lt;&#x2F;h3&gt;
&lt;p&gt;Only 1 optimization in the past week worth talking about: the &lt;code&gt;ActiveRecord::Base#exists?&lt;&#x2F;code&gt; method is faster. It now uses &lt;code&gt;ActiveRecord::Base#select_all&lt;&#x2F;code&gt; instead of a more expensive &lt;code&gt;ActiveRecord::Base#find&lt;&#x2F;code&gt; that unnecessarily instantiates AR objects. (Check out the &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8531&quot;&gt;related changeset&lt;&#x2F;a&gt;.)&lt;&#x2F;p&gt;
&lt;h3&gt;Bug fixes&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8541&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8541&lt;&#x2F;a&gt; - Fixed a nasty bug when trying to render partials with layout when done from within the site layout. Yes, you can have &lt;a href=&quot;http:&#x2F;&#x2F;ryandaigle.com&#x2F;articles&#x2F;2007&#x2F;8&#x2F;3&#x2F;what-s-new-in-edge-rails-partials-get-layouts&quot;&gt;layouts for your partials in Rails 2&lt;&#x2F;a&gt;, and yes, you can run into a bug when trying to use partial layouts in your main page layout.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8529&quot;&gt;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8529&lt;&#x2F;a&gt; - Fix &lt;code&gt;atom_feed_helper&lt;&#x2F;code&gt; to comply with the &lt;a href=&quot;http:&#x2F;&#x2F;atomenabled.org&#x2F;developers&#x2F;syndication&#x2F;atom-format-spec.php&quot;&gt;Atom specifications&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
  <entry>
    <title>self.plug :with =&gt; &#x27;Rails Hackfest&#x27;</title>
    <published>2008-01-03T23:24:27+00:00</published>
    <updated>2008-01-03T23:24:27+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/01/03/selfplug-with-rails-hackfest/"/>
    <id>https://chuyeow.wtf/2008/01/03/selfplug-with-rails-hackfest/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/01/03/selfplug-with-rails-hackfest/">&lt;p&gt;Yes, it&#x27;s a &lt;a href=&quot;http:&#x2F;&#x2F;weblog.workingwithrails.com&#x2F;2008&#x2F;1&#x2F;3&#x2F;december-hackfest-winners-announced&quot;&gt;plug for myself&lt;&#x2F;a&gt; and it&#x27;s shameless:&lt;&#x2F;p&gt;
&lt;div class=&quot;img&quot;&gt;&lt;img src=&quot;&#x2F;assets&#x2F;rails-hackfest-dec-2007_thumb.jpg&quot; alt=&quot;Dec 2007 Rails Hackfest&quot; &#x2F;&gt;&lt;&#x2F;div&gt;
&lt;p&gt;&lt;br style=&quot;clear: both;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Whatever &lt;a href=&quot;http:&#x2F;&#x2F;www.zedshaw.com&#x2F;rants&#x2F;rails_is_a_ghetto.html&quot;&gt;Zed Shaw may say about Rails its community&lt;&#x2F;a&gt;, Rails has done a huge part in making web development fun again for jaded web developers (first-time web developers probably won&#x27;t be able to tell the difference), and more importantly, raising the profile of Ruby more than any other Ruby project&#x2F;library&#x2F;framework&#x2F;tool ever did (and I&#x27;m sure we&#x27;re all constantly rolling our eyeballs at the new web frameworks that&#x27;re so terribly familiarly Rails-like). Hell, I bet at least 90% of Rubyists now wouldn&#x27;t even be Rubyists if they hadn&#x27;t come across the &lt;a href=&quot;http:&#x2F;&#x2F;rubyonrails.org&#x2F;&quot;&gt;web framework that could&lt;&#x2F;a&gt; 2 or 3 years ago. So yes I&#x27;d still be contributing to Rails so that it can make my life as a web developer easier, thank you.&lt;&#x2F;p&gt;
&lt;p&gt;I think I had about 18 accepted patches in &lt;a href=&quot;http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;hackfest&#x2F;18-monthly-december-2-7&quot;&gt;December 2007 Rails Hackfest&lt;&#x2F;a&gt; (a few of the patches were not attributed properly in the Hackfest due to technical issues with the Rails Hackfest site).&lt;&#x2F;p&gt;
&lt;p&gt;Probably the only significant patches were:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Allowing a proc to be set for &lt;code&gt;ActionController::Base.asset_host&lt;&#x2F;code&gt; (&lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8421&quot;&gt;changeset 8421&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;to_xml&lt;&#x2F;code&gt; should not automatically pass &lt;code&gt;:procs&lt;&#x2F;code&gt; to associations included with &lt;code&gt;:include&lt;&#x2F;code&gt; (&lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8258&quot;&gt;changeset 8258&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Of course Ruby 1.9 compatibility was a big deal in December 2007 since that Ruby 1.9 was targetted to be released on Christmas (changesets &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8369&quot;&gt;8369&lt;&#x2F;a&gt;, &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8399&quot;&gt;8309&lt;&#x2F;a&gt;, &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8398&quot;&gt;8398&lt;&#x2F;a&gt;, &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8397&quot;&gt;8397&lt;&#x2F;a&gt;, &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8412&quot;&gt;8412&lt;&#x2F;a&gt;). Yes, I know, Ruby 1.9 is a development release.&lt;&#x2F;p&gt;
&lt;p&gt;There were also broken tests to be fixed (changeset &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8271&quot;&gt;8271&lt;&#x2F;a&gt;), bugs to be fixed (&lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8340&quot;&gt;fixing &lt;code&gt;Array#to_sentence&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;), and some refactoring (changesets &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8343&quot;&gt;8343&lt;&#x2F;a&gt; and &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8522&quot;&gt;8522&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;And what would patching Rails be without random documentation fixes (changesets &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8457&quot;&gt;8457&lt;&#x2F;a&gt;, &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8471&quot;&gt;8471&lt;&#x2F;a&gt;, &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8472&quot;&gt;8472&lt;&#x2F;a&gt;, &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8280&quot;&gt;8280&lt;&#x2F;a&gt;, &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8279&quot;&gt;8279&lt;&#x2F;a&gt;, &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8278&quot;&gt;8278&lt;&#x2F;a&gt;, &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8521&quot;&gt;8521&lt;&#x2F;a&gt;). The API documentation always needs a hand, so if you see any outdated or incorrect documentation, or think you can improve them with better examples or whatever, just &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;&quot;&gt;submit a patch&lt;&#x2F;a&gt; (it&#x27;s easy and should take you all of 3 minutes).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;workingwithrails.com&#x2F;hackfest&#x2F;21-monthly-january-2-8&quot;&gt;This month&#x27;s hackfest&lt;&#x2F;a&gt; has a terribly attractive &lt;a href=&quot;http:&#x2F;&#x2F;workingwithrails.com&#x2F;hackfest&#x2F;21-monthly-january-2-8&#x2F;prizes&quot;&gt;top prize of a RailsConf ticket&lt;&#x2F;a&gt;. Too bad I won&#x27;t be able to take part in this month&#x27;s hackfest since winners of past month&#x27;s hackfest are automatically excluded from the next&#x27;s. But maybe you can ;).&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Living on the Edge (of Rails) - the pilot</title>
    <published>2008-01-02T19:30:57+00:00</published>
    <updated>2008-01-02T19:30:57+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2008/01/02/whats-new-on-edge-rails-the-pilot/"/>
    <id>https://chuyeow.wtf/2008/01/02/whats-new-on-edge-rails-the-pilot/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2008/01/02/whats-new-on-edge-rails-the-pilot/">&lt;p&gt;Gregg Pollack of &lt;a href=&quot;http:&#x2F;&#x2F;www.railsenvy.com&#x2F;&quot;&gt;Rails Envy&lt;&#x2F;a&gt; (the guys behind your favorite &lt;a href=&quot;http:&#x2F;&#x2F;www.railsenvy.com&#x2F;tags&#x2F;Commercials&quot;&gt;Ruby on Rails vs everything commercials&lt;&#x2F;a&gt;) asked me recently whether I could provide them with weekly updates of changes on edge Rails for the &lt;a href=&quot;http:&#x2F;&#x2F;www.railsenvy.com&#x2F;podcast&quot;&gt;Rails Envy Podcast&lt;&#x2F;a&gt; (which is often hilarious besides being informative), seeing as I am already keeping up with developments on the Rails trunk while doing my small part contributing to Rails. Of course, I responded with a +1.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.railsenvy.com&#x2F;2008&#x2F;1&#x2F;2&#x2F;rails-envy-podcast-episode-012-1-2-2008&quot;&gt;The podcast is now available&lt;&#x2F;a&gt; and contains only abbreviated notes about the changes that I&#x27;d sent over to Gregg, so here&#x27;s the detailed version of changes on edge Rails from the release of Rails 2.0.2 (17 Dec 2007) to the day the podcast was recorded (30 Dec 2007).&lt;&#x2F;p&gt;
&lt;h3&gt;Noteworthy changes on edge Rails: 2007-12-17 to 2007-12-30&lt;&#x2F;h3&gt;
&lt;h4&gt;Native mongrel handler&lt;&#x2F;h4&gt;
&lt;p&gt;A native Mongrel handler has been &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8488&quot;&gt;introduced&lt;&#x2F;a&gt;. This is so that it can be worked on independent of &lt;a href=&quot;http:&#x2F;&#x2F;mongrel.rubyforge.org&#x2F;&quot;&gt;Mongrel&lt;&#x2F;a&gt;&#x27;s release cycle (the Rails handler is currently in the Mongrel codebase). &lt;a href=&quot;bitsweat.net&#x2F;&quot;&gt;Jeremy Kemper&lt;&#x2F;a&gt; (bitsweat) has already made a minor performance improvement by moving the mutex from the handler itself into the dispatcher. This means that as Rails gets more threadsafe, the Rails team can push the mutex further down so that it&#x27;s not a (scary) giant lock (the existing Mongrel Rails handler has a synchronized block around Rails&#x27; dispatcher).&lt;&#x2F;p&gt;
&lt;p&gt;Note: The native mongrel handler is not used by default at this time on edge Rails.&lt;&#x2F;p&gt;
&lt;h4&gt;Caching branch for Rails 2.1&lt;&#x2F;h4&gt;
&lt;p&gt;A &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;log&#x2F;branches&#x2F;2-1-caching&quot;&gt;caching branch&lt;&#x2F;a&gt; has been introduced, targeted for Rails 2.1. Other than being a big refactoring, there&#x27;s also native cache key management (e.g. &lt;code&gt;Product.find(5).cache_key # =&gt; &quot;products&#x2F;5&quot;&lt;&#x2F;code&gt;) and memcache integration is also being looked at.&lt;&#x2F;p&gt;
&lt;h4&gt;Ruby 1.9 compatibility continues...&lt;&#x2F;h4&gt;
&lt;p&gt;Yup, work on Ruby 1.9 compatibility for Rails continues. Rails is fortunate to have committers and contributors who are so keen on being 1.9-compatible - free performance gains are hard to turn down after all. There&#x27;s been lots of patching going on to deal with the changes in Ruby 1.9 (Unicode changes, new syntax, deprecations, etc.).&lt;&#x2F;p&gt;
&lt;p&gt;Yes, the Rails committers and contributors working on 1.9-compatibility are fully aware that Ruby 1.9 is a &lt;strong&gt;development&lt;&#x2F;strong&gt; release, but nothing&#x27;s lost in making sure Rails is compatible with a version of Ruby that will eventually be a production version of Ruby. Besides, I think most of the 1.9-compatibility contributors have a dream that sometime soon, when Ruby 1.9 becomes &quot;stable&quot; enough, we&#x27;d be running our Rails applications on Ruby 1.9 for a free performance boost.&lt;&#x2F;p&gt;
&lt;p&gt;Too bad running Rails on Ruby 1.9 is not really possible at the moment since other projects like Mongrel need to be updated for Ruby 1.9 as well, first.&lt;&#x2F;p&gt;
&lt;h4&gt;Bugfixes&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;12&#x2F;27&#x2F;dry-in-your-functional-and-actionmailer-tests-rails-20-a-feature-a-day-7&#x2F;&quot;&gt;new TestCase subclasses&lt;&#x2F;a&gt; (&lt;code&gt;ActionController::TestCase&lt;&#x2F;code&gt;,&lt;br &#x2F;&gt;
  &lt;code&gt;ActionMailer::TestCase&lt;&#x2F;code&gt;) introduced in Rails 2 have a &lt;a href=&quot;http:&#x2F;&#x2F;quotedprintable.com&#x2F;2007&#x2F;12&#x2F;5&#x2F;potential-gotcha-with-test-setup-in-rails-2-0&quot;&gt;gotcha&lt;&#x2F;a&gt;. This has been &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8497&quot;&gt;fixed&lt;&#x2F;a&gt; quickly by &lt;a href=&quot;http:&#x2F;&#x2F;joshpeek.com&#x2F;&quot;&gt;Josh Peek&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Fixed a bug where trying to :include for a belongs_to association inferred the foreign key incorrectly from the class name, rather than from the association name (&lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8456&quot;&gt;changeset&lt;&#x2F;a&gt; contributed by &lt;a href=&quot;http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;person&#x2F;4985-jonathan-viney&quot;&gt;Jonathan Viney&lt;&#x2F;a&gt;). Code is probably easier to understand:
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class Post &amp;lt; ActiveRecord::Base
  belongs_to :main_category, :class_name =&amp;gt; &#x27;Category&#x27;
end
&lt;p&gt;Post.find(:first, :include =&amp;gt; :main_category)&lt;&#x2F;p&gt;
&lt;h1 id=&quot;activerecord-statementinvalid-mysql-error-unknown-column&quot;&gt;=&amp;gt; ActiveRecord::StatementInvalid: Mysql::Error: Unknown column&lt;&#x2F;h1&gt;
&lt;p&gt;&#x27;posts.category&#x27; in &#x27;on clause&#x27;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4&gt;Optimizations&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8505&quot;&gt;JSON decoding is faster&lt;&#x2F;a&gt;. This helps if you&#x27;re doing a lot of JSON decoding or deserialization (such as via &lt;a href=&quot;http:&#x2F;&#x2F;api.rubyonrails.org&#x2F;classes&#x2F;ActiveRecord&#x2F;Serialization.html#M001136&quot;&gt;&lt;code&gt;ActiveRecord::Base#from_json&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;), or you are using the &lt;a href=&quot;http:&#x2F;&#x2F;api.rubyonrails.org&#x2F;classes&#x2F;ActiveResource&#x2F;Base.html#M000827&quot;&gt;JSON format for ActiveResource&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;has_many&lt;&#x2F;code&gt; associations are &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8504&quot;&gt;no longer loaded unnecessarily&lt;&#x2F;a&gt; in &lt;code&gt;after_update&lt;&#x2F;code&gt; callbacks.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3&gt;I can has feedback nao plz?&lt;&#x2F;h3&gt;
&lt;p&gt;Please leave any suggestions for improvements you may have - about anything really: format, level of detail, what you&#x27;d like to see, whatever. Until next week...&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>DRY in your functional and ActionMailer tests - Rails 2.0 a feature a day #7</title>
    <published>2007-12-27T18:47:06+00:00</published>
    <updated>2007-12-27T18:47:06+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/12/27/dry-in-your-functional-and-actionmailer-tests-rails-20-a-feature-a-day-7/"/>
    <id>https://chuyeow.wtf/2007/12/27/dry-in-your-functional-and-actionmailer-tests-rails-20-a-feature-a-day-7/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/12/27/dry-in-your-functional-and-actionmailer-tests-rails-20-a-feature-a-day-7/">&lt;p&gt;That&#x27;s right, &lt;strong&gt;D&lt;&#x2F;strong&gt;on&#x27;t &lt;strong&gt;R&lt;&#x2F;strong&gt;epeat &lt;strong&gt;Y&lt;&#x2F;strong&gt;ourself in your functional and ActionMailer tests. If you&#x27;re a Test::Unit user, this will probably look familiar to you when writing Rails functional tests (for your controllers):&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class PostsControllerTest &amp;lt; Test::Unit::TestCase
  def setup
    @controller = PostsController.new
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
  end
&lt;p&gt;def test_should_not_explode
# Invariably sexy test code.
end
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You&#x27;d probably have noticed how &lt;code&gt;setup&lt;&#x2F;code&gt; &lt;em&gt;always&lt;&#x2F;em&gt; sets the &lt;code&gt;@controller&lt;&#x2F;code&gt;, &lt;code&gt;@request&lt;&#x2F;code&gt; and &lt;code&gt;@response&lt;&#x2F;code&gt; instance variables in all your controller tests. In Rails 2.0, you can instead subclass &lt;code&gt;ActionController::TestCase&lt;&#x2F;code&gt; (in turn a subclass of &lt;code&gt;Test::Unit::TestCase&lt;&#x2F;code&gt;) in your test cases and avoid repeating the instance variable assignments.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class PostsControllerTest &amp;lt; ActionController::TestCase
  # No need to define setup.
&lt;p&gt;def test_should_not_explode
# Invariably sexy test code.
end
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Isn&#x27;t that much better?&lt;&#x2F;p&gt;
&lt;p&gt;Watch out for a gotcha though, when you actually do need to define a &lt;code&gt;setup&lt;&#x2F;code&gt; method (like when you need to setup several other things before your tests run), as &lt;a href=&quot;http:&#x2F;&#x2F;quotedprintable.com&#x2F;2007&#x2F;12&#x2F;5&#x2F;potential-gotcha-with-test-setup-in-rails-2-0&quot;&gt;Jeffrey Allan Hardy reports&lt;&#x2F;a&gt;. &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8497&quot;&gt;The issue has been resolved&lt;&#x2F;a&gt; on edge Rails. If you&#x27;re not using edge Rails, you should remember to always call &lt;code&gt;super&lt;&#x2F;code&gt; in your &lt;code&gt;setup&lt;&#x2F;code&gt; method should you define one:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class PostsControllerTest &amp;lt; ActionController::TestCase
  def setup
    super
    @user = users(:konata)
  end
&lt;p&gt;def test_should_not_explode
# Invariably sexy test code.
end
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A similar subclass of &lt;code&gt;Test::Unit&lt;&#x2F;code&gt;, &lt;code&gt;ActionMailer::TestCase&lt;&#x2F;code&gt; is available for your ActionMailer unit tests as well. That means you can replace this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class UserMailerTest &amp;lt; Test::Unit::TestCase
  include ActionMailer::Quoting
&lt;p&gt;def setup
ActionMailer::Base.delivery_method = :test
ActionMailer::Base.perform_deliveries = true
ActionMailer::Base.deliveries = []&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;@expected = TMail::Mail.new
@expected.set_content_type &amp;quot;text&amp;quot;, &amp;quot;plain&amp;quot;, { &amp;quot;charset&amp;quot; =&amp;gt; &amp;quot;utf-8&amp;quot; }
@expected.mime_version = &amp;#39;1.0&amp;#39;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;end&lt;&#x2F;p&gt;
&lt;p&gt;def test_signup
# Test code.
end
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;with this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class UserMailerTest &amp;lt; ActionMailer::TestCase
  def test_signup
    # Test code.
  end
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For the geeks among you, check out the related &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8022&quot;&gt;changeset&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3&gt;About the contributor, Michael Koziarski&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.koziarski.net&#x2F;&quot;&gt;Michael Koziarski&lt;&#x2F;a&gt;, better know as nzkoz, is a long-time &lt;a href=&quot;http:&#x2F;&#x2F;rubyonrails.com&#x2F;core&quot;&gt;Rails core&lt;&#x2F;a&gt; committer. Michael has done a signficant amount of work improving the performance of ActiveRecord for Rails 2.0 so we have him to thank for a good portion of the optimization work done on ActiveRecord. He also keeps a fairly new &lt;a href=&quot;http:&#x2F;&#x2F;www.koziarski.net&#x2F;&quot;&gt;personal blog&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Ruby 1.9.0 has been released</title>
    <published>2007-12-26T00:15:49+00:00</published>
    <updated>2007-12-26T00:15:49+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/12/26/ruby-190-has-been-released/"/>
    <id>https://chuyeow.wtf/2007/12/26/ruby-190-has-been-released/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/12/26/ruby-190-has-been-released/">&lt;p&gt;Just in the nick of time for the Christmas target, the Ruby core team has released Ruby 1.9.0 - &lt;a href=&quot;http:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Yukihiro_Matsumoto&quot;&gt;Matz&lt;&#x2F;a&gt; &lt;a href=&quot;http:&#x2F;&#x2F;www.ruby-forum.com&#x2F;topic&#x2F;136553&quot;&gt;announced the release on the ruby-talk mailing list&lt;&#x2F;a&gt; not too long ago.&lt;&#x2F;p&gt;
&lt;p&gt;Rubygem and Ruby library developers, now&#x27;s the time to get down to making your Ruby code compatible with 1.9.0.&lt;&#x2F;p&gt;
&lt;p&gt;Rails is not too far from being compatible with 1.9, thanks to the efforts of &lt;a href=&quot;http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;person&#x2F;5323-jeremy-kemper&quot;&gt;Jeremy Kemper&lt;&#x2F;a&gt; and a few other contributors. Mongrel is not quite there yet though (I use mongrel for my Rails applications, and I think at least 50% of you do too). So while running your Rails apps on Ruby 1.9 is not an easy task right now (unless you enjoy lots of monkey patching), let&#x27;s hope the full 1.9.0 release will inspire more Ruby developers to get their libraries compatible so we can all enjoy the &lt;a href=&quot;http:&#x2F;&#x2F;antoniocangiano.com&#x2F;2007&#x2F;12&#x2F;03&#x2F;the-great-ruby-shootout&#x2F;&quot;&gt;big speed boost in Ruby 1.9&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Very nice (if somewhat geeky) Christmas present from the Ruby core and contributors!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Generating migrations gets easier - Rails 2.0 a feature a day #6</title>
    <published>2007-12-24T16:58:07+00:00</published>
    <updated>2007-12-24T16:58:07+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/12/24/generating-migrations-gets-easier-rails-20-a-feature-a-day-6/"/>
    <id>https://chuyeow.wtf/2007/12/24/generating-migrations-gets-easier-rails-20-a-feature-a-day-6/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/12/24/generating-migrations-gets-easier-rails-20-a-feature-a-day-6/">&lt;p&gt;You may not have noticed this yet, but Rails 2.0 has a new convenient syntax for generating ActiveRecord migrations. Go ahead, run the migration generator with &lt;code&gt;script&#x2F;generate migration&lt;&#x2F;code&gt;. I&#x27;ll wait.&lt;&#x2F;p&gt;
&lt;p&gt;Yup, you can now specify the columns you want to add in your migration by passing attribute&#x2F;type pairs to the migration generator. Ergo,&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;script&#x2F;generate migration AddMoreToAnime episodes:integer licensed:boolean&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;will generate a migration like so:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class AddMoreToAnime &amp;lt; ActiveRecord::Migration
  def self.up
    add_column :animes, :episodes, :integer
    add_column :animes, :licensed, :boolean
  end
&lt;p&gt;def self.down
remove_column :animes, :licensed
remove_column :animes, :episodes
end
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This ties in pretty nicely with the syntax for the model generator (&lt;code&gt;script&#x2F;generate model&lt;&#x2F;code&gt;), which also accepts attribute pairs. Tiny change but &quot;it&#x27;s all about consistency&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;For the geeks among you, check out the &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;7422&quot;&gt;related changeset&lt;&#x2F;a&gt; and &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;9166&quot;&gt;ticket&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3&gt;About the contributor, Pratik Naik&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;m.onkey.org&#x2F;&quot;&gt;Pratik Naik&lt;&#x2F;a&gt; (&lt;a href=&quot;http:&#x2F;&#x2F;workingwithrails.com&#x2F;recommendation&#x2F;new&#x2F;person&#x2F;5424-pratik-naik&quot;&gt;WorkingWithRails profile&lt;&#x2F;a&gt;), probably better known as lifofifo or just lifo, is an active Rails contributor and can be found on &lt;a href=&quot;irc:&#x2F;&#x2F;irc.freenode.net&#x2F;rails-contrib&quot;&gt;#rails-contrib&lt;&#x2F;a&gt; and &lt;a href=&quot;irc:&#x2F;&#x2F;irc.freenode.net&#x2F;rubyonrails&quot;&gt;#rubyonrails&lt;&#x2F;a&gt; nearly 24&#x2F;7. Almost everyone who&#x27;s used Rails has used code that lifo has written. Oh, and lifo also &lt;a href=&quot;http:&#x2F;&#x2F;weblog.workingwithrails.com&#x2F;2007&#x2F;11&#x2F;1&#x2F;hackfest-winner-interview-pratik-naik&quot;&gt;won one of the monthly Rails Hackfests&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;He also keeps a &lt;a href=&quot;http:&#x2F;&#x2F;m.onkey.org&#x2F;&quot;&gt;pretty good blog&lt;&#x2F;a&gt; where he posts mostly on Rails hacking and tips.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Rails 2.0.2 released, so what&#x27;s new?</title>
    <published>2007-12-17T11:09:13+00:00</published>
    <updated>2007-12-17T11:09:13+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/12/17/rails-202-released-so-whats-new/"/>
    <id>https://chuyeow.wtf/2007/12/17/rails-202-released-so-whats-new/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/12/17/rails-202-released-so-whats-new/">&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8430&quot;&gt;Rails 2.0.2 was tagged not too long ago&lt;&#x2F;a&gt; and will hit the gem servers soon I expect. Being a minor point release there aren&#x27;t many changes, but here&#x27;re the ones I feel are worth mentioning:&lt;&#x2F;p&gt;
&lt;h3&gt;ActionPack changes&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Configurable asset hosts&lt;&#x2F;strong&gt;: You can now pass a proc to &lt;code&gt;ActionController::Base.asset_host&lt;&#x2F;code&gt;. This allows you to get by the hard-coded assumption that you have 4 asset hosts numbered 0-3 when using the &#x27;%d&#x27; wildcard (introduced in Rails 2.0.1).&lt;&#x2F;p&gt;
&lt;p&gt;I &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;10521&quot;&gt;contributed this patch&lt;&#x2F;a&gt; so I&#x27;m gonna be lazy and copy and paste most of the documentation I wrote for patch.&lt;&#x2F;p&gt;
&lt;p&gt;The example proc below generates http:&#x2F;&#x2F;assets1.example.com and http:&#x2F;&#x2F;assets2.example.com randomly.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;ActionController::Base.asset_host = Proc.new { |source| &quot;http:&#x2F;&#x2F;assets#{rand(2) + 1}.example.com&quot; }
image_tag(&quot;rails.png&quot;)
  =&amp;gt; &amp;lt;img src=&quot;http:&#x2F;&#x2F;assets2.example.com&#x2F;images&#x2F;rails.png&quot; alt=&quot;Rails&quot; &#x2F;&amp;gt;
stylesheet_include_tag(&quot;application&quot;)
  =&amp;gt; &amp;lt;link href=&quot;http:&#x2F;&#x2F;assets1.example.com&#x2F;stylesheets&#x2F;application.css&quot; media=&quot;screen&quot; rel=&quot;stylesheet&quot; type=&quot;text&#x2F;css&quot; &#x2F;&amp;gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The proc also takes a single &lt;code&gt;source&lt;&#x2F;code&gt; parameter which is the path of the source asset. This can be used to generate a particular asset host depending on the asset path. This is useful if you have, say, images hosted elsewhere, or you want an SEO-friendly URL for your images:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;ActionController::Base.asset_host = Proc.new { |source|
  if source.starts_with?(&#x27;&#x2F;images&#x27;)
    &quot;http:&#x2F;&#x2F;images.example.com&quot;
  else
    &quot;http:&#x2F;&#x2F;assets.example.com&quot;
  end
}
image_tag(&quot;rails.png&quot;)
  =&amp;gt; &amp;lt;img src=&quot;http:&#x2F;&#x2F;images.example.com&#x2F;images&#x2F;rails.png&quot; alt=&quot;Rails&quot; &#x2F;&amp;gt;
stylesheet_include_tag(&quot;application&quot;)
  =&amp;gt; &amp;lt;link href=&quot;http:&#x2F;&#x2F;assets.example.com&#x2F;stylesheets&#x2F;application.css&quot; media=&quot;screen&quot; rel=&quot;stylesheet&quot; type=&quot;text&#x2F;css&quot; &#x2F;&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Asset cache directories are automatically created&lt;&#x2F;strong&gt;: In Rails 2.0.1, if you tried to cache your assets (javascripts and stylesheets) in a subdirectory (example below), you either need to check it into your source control or have your deployment tool (Capistrano, etc.) create it for you. &lt;a href=&quot;http:&#x2F;&#x2F;joshpeek.com&#x2F;&quot;&gt;Josh Peek&lt;&#x2F;a&gt; &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;10337&quot;&gt;contributed a patch&lt;&#x2F;a&gt; that created the subdirectory instead so you can do something like:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;javascript_include_tag(:all, :cache =&gt; &quot;cache&#x2F;money&quot;)&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and not have to bother about creating the &#x27;cache&#x27; subdirectory.&lt;&#x2F;p&gt;
&lt;h3&gt;Railties changes&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Default database is now SQLite3&lt;&#x2F;strong&gt;: The default database is now SQLite3 instead of MySQL. Running &#x27;rails takeover_the_world_app&#x27; will now come with a database.yml that&#x27;s setup for SQLite3. To get the old behavior (where it&#x27;s preconfigured for MySQL), run &lt;code&gt;rails -d mysql takeover_the_world_app&lt;&#x2F;code&gt; instead. This is mostly to make this &quot;just work&quot; on Mac OS X Leopard, where SQLite3 is already installed with the OS.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Template loading is faster&lt;&#x2F;strong&gt;: DHH has turned on &lt;code&gt;ActionView::Base.cache_template_loading&lt;&#x2F;code&gt; by default in the &lt;code&gt;production.rb&lt;&#x2F;code&gt; environment config file that basically means that Rails no longer does file system stat calls when loading templates. The downside is that you have to restart your Rails application to see templates changes in production mode, but it&#x27;s not really that big an issue since no one should be editing templates anyway &#x27;live&#x27; in a production application.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;New rake tasks for migrations&lt;&#x2F;strong&gt;: &lt;code&gt;rake db:migrate:redo&lt;&#x2F;code&gt; to undo your last migration and re-run it - very useful when developing migrations (when you screw up, that is). &lt;code&gt;rake db:migrate:reset&lt;&#x2F;code&gt; drops the database, re-creates it, and then runs all migrations.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;rake task for generating secret keys&lt;&#x2F;strong&gt;: &lt;code&gt;rake secret&lt;&#x2F;code&gt; to generate a secure key that you can use for cookie sessions. This is useful for updating Rails applications from 1.x to 2.x, which uses cookie-based sessions by default and requires a secret key.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;config.action_controller.session = {
  :session_key =&amp;gt; &#x27;_your_app_session&#x27;,
  :secret      =&amp;gt; &#x27;some super long string that you can generate with the rake secret task&#x27;
}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Personally I just use super long quotes from Family Guy.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s it! For the curious, expect Ruby 1.9 compatibility, improved caching, and big ActionPack and rendering refactoring changes in Rails 2.1.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Sensible GROUP BYs in ActiveRecord::Calculations - Rails 2.0 a feature a day #5</title>
    <published>2007-12-16T15:16:12+00:00</published>
    <updated>2007-12-16T15:16:12+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/12/16/sensible-group-bys-in-activerecordcalculations/"/>
    <id>https://chuyeow.wtf/2007/12/16/sensible-group-bys-in-activerecordcalculations/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/12/16/sensible-group-bys-in-activerecordcalculations/">&lt;p&gt;Doing GROUP BYs in ActiveRecord has always been tricky. There&#x27;s a lot of &quot;magic&quot; in ActiveRecord and room for untested edge cases. Thankfully, Rails also has a squadron of eagle-eyed contributors who are on hand to fix unforeseen errors.&lt;&#x2F;p&gt;
&lt;p&gt;For example, if you wanted to do this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class Click &amp;lt; ActiveRecord::Base
  belongs_to :site  # site_id foreign key is a String, e.g. &#x27;www.rubyonrails.org&#x27;
end
&lt;h1 id=&quot;now-try-counting-the-number-of-clicks-grouped-by-site&quot;&gt;Now, try counting the number of clicks, grouped by site.&lt;&#x2F;h1&gt;
&lt;p&gt;Click.count(:all, :group =&amp;gt; :site)&lt;&#x2F;p&gt;
&lt;h1 id=&quot;nil-1-nil-3&quot;&gt;=&amp;gt; [[nil, 1], [nil, 3]]&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is a surprisingly common thing to do especially when you are producing reports or statistics of any kind and unfortunately decided to go with a non-(auto)numeric foreign key. As you may have noticed, the sites were returned as &lt;code&gt;nil&lt;&#x2F;code&gt; which is totally unhelpful. Thankfully, this has been &lt;a href=&quot;&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;6919&gt;fixed in Rails 2.0:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;Click.count(:all, :group =&gt; :site)
# =&gt; [[nil, 1], [&#x27;www.site, 3]]&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3&gt;GROUP BY and :foreign_key don&#x27;t mix&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;This change is NOT in Rails 2.0.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you wanted to do GROUP BYs in your ActiveRecord models (via the &lt;code&gt;:group&lt;&#x2F;code&gt; option), you had to take note of one particular gotcha. For example, with an ActiveRecord model like this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class Anime &amp;lt; ActiveRecord::Base
  belongs_to :japanese_studio, :class_name =&amp;gt; &#x27;Studio&#x27;, :foreign_key =&amp;gt; &#x27;studio_id&#x27;
end&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that we specified the &lt;code&gt;:foreign_key&lt;&#x2F;code&gt; option since it can&#x27;t be inferred from the association name of &#x27;japanese_studio&#x27;. If we wanted to &lt;code&gt;count&lt;&#x2F;code&gt;ing the number of anime grouped by studio though, we&#x27;re in big trouble:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;Anime.count(:all, :group =&gt; :japanese_studio)
# ActiveRecord fails and mumbles about an unknown &quot;japanese_studio_id&quot; key.
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Basically what happened is Rails did not use the specified foreign key column of &#x27;studio_id&#x27;, inferring it instead from the association name of &#x27;japanese_studio&#x27;. This is not yet fixed but there&#x27;s already a &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;8117&quot;&gt;patch&lt;&#x2F;a&gt; ready for it at the &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;&quot;&gt;Rails issue tracker&lt;&#x2F;a&gt;. In fact, I&#x27;m gonna &lt;a href=&quot;http:&#x2F;&#x2F;weblog.rubyonrails.org&#x2F;2007&#x2F;9&#x2F;15&#x2F;how-to-get-a-patch-into-rails&quot;&gt;verify it&lt;&#x2F;a&gt; right after posting this.&lt;&#x2F;p&gt;
&lt;h3&gt;About the contributor, Kamal Fariz&lt;&#x2F;h3&gt;
&lt;p&gt;I thought it was time to cover Rails 2.0 contributions by someone closer to home (&quot;home&quot; being my home, &lt;a href=&quot;http:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Singapore&quot;&gt;Singapore&lt;&#x2F;a&gt;) so I singled out &lt;a href=&quot;http:&#x2F;&#x2F;blog.bitfluent.com&#x2F;&quot;&gt;Kamal Fariz&lt;&#x2F;a&gt; (&lt;a href=&quot;http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;person&#x2F;4207-kamal-fariz&quot;&gt;WorkingWithRails profile&lt;&#x2F;a&gt;), a Rails developer working in Malaysia for a &lt;a href=&quot;http:&#x2F;&#x2F;blog.ror.com.my&#x2F;&quot;&gt;Rails shop&lt;&#x2F;a&gt;. Kamal&#x27;s also a former &lt;a href=&quot;http:&#x2F;&#x2F;www.workingwithrails.com&#x2F;hackfest&quot;&gt;Rails Hackfest&lt;&#x2F;a&gt; winner (read the &lt;a href=&quot;http:&#x2F;&#x2F;weblog.workingwithrails.com&#x2F;2007&#x2F;7&#x2F;25&#x2F;hackfest-winner-interview-kamal-fariz&quot;&gt;post-Rails Hackfest interview&lt;&#x2F;a&gt;). Kamal is also an active member of the &lt;a href=&quot;http:&#x2F;&#x2F;groups.google.com&#x2F;group&#x2F;malaysia-rb?hl=en&quot;&gt;Malaysia Ruby Brigade&lt;&#x2F;a&gt; (I guess it&#x27;s not called a &quot;Ruby User Group&quot; since &quot;RUG&quot; sounds rather unglamorous).&lt;&#x2F;p&gt;
&lt;p&gt;Wow look at the number of parentheses I used in the last paragraph. For no reason whatsoever here&#x27;s a lolcats picture:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br style=&quot;clear: both;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>gchartrb = Ruby + Google Chart API</title>
    <published>2007-12-12T00:22:27+00:00</published>
    <updated>2007-12-12T00:22:27+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/12/12/gchartrb-ruby-google-chart-api/"/>
    <id>https://chuyeow.wtf/2007/12/12/gchartrb-ruby-google-chart-api/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/12/12/gchartrb-ruby-google-chart-api/">&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;code.google.com&#x2F;apis&#x2F;chart&#x2F;&quot;&gt;Google Chart API&lt;&#x2F;a&gt; looks quite useful. I&#x27;ve used &lt;a href=&quot;http:&#x2F;&#x2F;nubyonrails.com&#x2F;pages&#x2F;gruff&quot;&gt;Gruff&lt;&#x2F;a&gt; to generate graphs before but this looks way easier (and much lighter on the server without all that ImageMagick magic!) I&#x27;ll have to play with it someday - if only I didn&#x27;t have to mess with those &lt;a href=&quot;http:&#x2F;&#x2F;code.google.com&#x2F;apis&#x2F;chart&#x2F;#url_format&quot;&gt;URL params&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;Well, &lt;a href=&quot;http:&#x2F;&#x2F;blog.deepak.jois.name&#x2F;&quot;&gt;Deepak Jois&lt;&#x2F;a&gt; from &lt;a href=&quot;http:&#x2F;&#x2F;groups.google.com&#x2F;group&#x2F;singapore-rb&#x2F;&quot;&gt;singapore.rb&lt;&#x2F;a&gt; (the local Ruby user group) recently &lt;a href=&quot;http:&#x2F;&#x2F;groups.google.com&#x2F;group&#x2F;singapore-rb&#x2F;browse_thread&#x2F;thread&#x2F;47e81778350c37bb&quot;&gt;announced&lt;&#x2F;a&gt; a Ruby wrapper around the Google Chart API: &lt;a href=&quot;http:&#x2F;&#x2F;code.google.com&#x2F;p&#x2F;gchartrb&#x2F;&quot;&gt;gchartrb&lt;&#x2F;a&gt; (&lt;a href=&quot;http:&#x2F;&#x2F;gchartrb.rubyforge.org&#x2F;&quot;&gt;rdocs&lt;&#x2F;a&gt;). You can get it as a rubygem, just run:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;sudo gem install gchartrb&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Looking good so far and I dig the familiarity - Deepak says the API is Gruff-inspired and it tells. If you need a charting solution (for reporting or whatever), this is a gem to consider.&lt;&#x2F;p&gt;
&lt;p&gt;Ah yup, there&#x27;ll be no &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;12&#x2F;09&#x2F;rails-20-a-feature-a-day&#x2F;&quot;&gt;Rails 2 feature&lt;&#x2F;a&gt; today - just submitted a couple of Ruby 1.9 compatibility patches for Rails and feeling a little bummed out now (&lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;browser&#x2F;trunk&#x2F;activesupport&#x2F;lib&#x2F;active_support&#x2F;dependencies.rb&quot;&gt;dependency handling&lt;&#x2F;a&gt; is not that pleasant in Rails). &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;1689&quot;&gt;Rails&#x27; Ruby 1.9 compatibility&lt;&#x2F;a&gt; needs you!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Rails 2.0 released</title>
    <published>2007-12-08T00:02:09+00:00</published>
    <updated>2007-12-08T00:02:09+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/12/08/rails-20-released/"/>
    <id>https://chuyeow.wtf/2007/12/08/rails-20-released/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/12/08/rails-20-released/">&lt;p&gt;Just go to the &lt;a href=&quot;http:&#x2F;&#x2F;weblog.rubyonrails.org&#x2F;2007&#x2F;12&#x2F;7&#x2F;rails-2-0-it-s-done&quot;&gt;release announcement and major features blog post by DHH&lt;&#x2F;a&gt; already!&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re having trouble installing the Rails 2.0.1 gem, do a &lt;code&gt;gem install rails -y --source http:&#x2F;&#x2F;gems.rubyonrails.org&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now that the obligatory link to the Rails 2.0 release announcement is done, I&#x27;d like to urge anyone with any interest in improving Rails or seeing new features or fixes in Rails to try and contribute to Rails. I&#x27;m sure everyone of us Rails users have had &quot;what if Rails could do this&quot; or &quot;why is Rails doing this, that&#x27;s just wrong&quot; moments. Well, roll up your sleeves and help by contributing instead of complaining about how &lt;a href=&quot;http:&#x2F;&#x2F;www.koziarski.net&#x2F;archives&#x2F;2007&#x2F;12&#x2F;1&#x2F;they&quot;&gt;&quot;they&quot;&lt;&#x2F;a&gt; won&#x27;t&#x2F;haven&#x27;t&#x2F;are too stupid to fix it..&lt;&#x2F;p&gt;
&lt;p&gt;A good starting point is to read the &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;wiki&#x2F;&quot;&gt;Rails Trac wiki&lt;&#x2F;a&gt;, and after that be sure to check out John Susser&#x27;s excellent &lt;a href=&quot;http:&#x2F;&#x2F;hasmanythrough.com&#x2F;layingtracks&#x2F;&quot;&gt;guide to contributing to Rails&lt;&#x2F;a&gt; (read the &lt;a href=&quot;http:&#x2F;&#x2F;hasmanythrough.com&#x2F;layingtracks&#x2F;LayingTracks.pdf&quot;&gt;presentation slides&lt;&#x2F;a&gt;, it won&#x27;t take long). You should have enough information to start. I recommend just opening the &lt;code&gt;base.rb&lt;&#x2F;code&gt; classes for ActiveRecord, ActionController and peeking around the ActiveSupport classes just to get a feel of things. After that crack open the relevant test for your issue and write your test-driven patch!&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s really easy, since Rails is written purely in Ruby - if I can do it I&#x27;m sure you can too :) Your contribution doesn&#x27;t even have to be a bona fide patch file with tests, documentation and bits of Ruby code - if you notice a bug and &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;newticket&quot;&gt;report it&lt;&#x2F;a&gt; not knowing how to fix it, that&#x27;s good enough! Or even something as trivial as a new style (CSS and layout) for the Rails error pages (there isn&#x27;t such a patch yet but I&#x27;d love to see prettier default exception pages instead of the current rather plain-looking ones).&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, that&#x27;s enough of the sermon from me - enjoy your Rails 2.0! Congrats to the &lt;a href=&quot;http:&#x2F;&#x2F;rubyonrails.org&#x2F;core&quot;&gt;Rails Core team&lt;&#x2F;a&gt; and contributors on another solid release!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Rails 2.0 - it&#x27;s landed</title>
    <published>2007-12-07T14:14:59+00:00</published>
    <updated>2007-12-07T14:14:59+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/12/07/rails-20-its-landed/"/>
    <id>https://chuyeow.wtf/2007/12/07/rails-20-its-landed/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/12/07/rails-20-its-landed/">&lt;p&gt;&lt;ins&gt;Update: Looks like it&#x27;s going to be released as Rails 2.0.1 instead due to a &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8329&quot;&gt;bugfix&lt;&#x2F;a&gt; post-2.0 tagging.&lt;&#x2F;ins&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Just a quick one - seems like Rails 2.0 has been &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8328&quot;&gt;tagged for release&lt;&#x2F;a&gt;. &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;milestone&#x2F;2.0&quot;&gt;Rails 2.0 milestone&lt;&#x2F;a&gt; has just been completed.&lt;&#x2F;p&gt;
&lt;p&gt;Expect a post on &lt;a href=&quot;http:&#x2F;&#x2F;weblog.rubyonrails.com&#x2F;&quot;&gt;weblog.rubyonrails.com&lt;&#x2F;a&gt; soon.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Try the new Mac OS X UI for Firefox 3</title>
    <published>2007-11-20T18:13:36+00:00</published>
    <updated>2007-11-20T18:13:36+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/11/20/try-the-new-mac-os-x-ui-for-firefox-3/"/>
    <id>https://chuyeow.wtf/2007/11/20/try-the-new-mac-os-x-ui-for-firefox-3/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/11/20/try-the-new-mac-os-x-ui-for-firefox-3/">&lt;p&gt;The Firefox 3 developers have been working on a &lt;a href=&quot;http:&#x2F;&#x2F;blog.mozilla.com&#x2F;faaborg&#x2F;2007&#x2F;10&#x2F;10&#x2F;the-firefox-3-visual-refresh-system-integration&#x2F;&quot;&gt;visual refresh&lt;&#x2F;a&gt; that integrates more tightly into the OS, and the Mac OS X version is looking pretty sweet. Well, public opinion varies greatly - from people who feel that it&#x27;s a &lt;a href=&quot;http:&#x2F;&#x2F;digg.com&#x2F;apple&#x2F;Proposed_Firefox_3_Theme_For_Mac_OS_X_Looks_Exactly_Like_Safari&quot;&gt;rip off of Safari&lt;&#x2F;a&gt; to those who really like the Brushed Metal look (myself included).&lt;&#x2F;p&gt;
&lt;div class=&quot;img&quot;&gt;&lt;img src=&quot;&#x2F;assets&#x2F;firefox-3-with-proto-theme_thumb.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;div&gt;
&lt;p&gt;&lt;br style=&quot;clear: both;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Well, if you wanna check out the proposed Mac OS X Firefox 3 UI for yourself, grab yourself a copy of &lt;a href=&quot;http:&#x2F;&#x2F;www.mozilla.com&#x2F;en-US&#x2F;firefox&#x2F;3.0b1&#x2F;releasenotes&#x2F;&quot;&gt;Firefox 3 Beta 1&lt;&#x2F;a&gt; and go get the &lt;a href=&quot;https:&#x2F;&#x2F;addons.mozilla.org&#x2F;en-US&#x2F;firefox&#x2F;addon&#x2F;6050&quot;&gt;Proto theme&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Firefox 3, Beta</title>
    <published>2007-11-20T17:23:57+00:00</published>
    <updated>2007-11-20T17:23:57+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/11/20/firefox-3-beta/"/>
    <id>https://chuyeow.wtf/2007/11/20/firefox-3-beta/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/11/20/firefox-3-beta/">&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.mozilla.com&#x2F;en-US&#x2F;firefox&#x2F;3.0b1&#x2F;releasenotes&#x2F;&quot;&gt;Firefox 3 Beta 1&lt;&#x2F;a&gt; is out! Check out the pretty sweet &lt;a href=&quot;http:&#x2F;&#x2F;www.mozilla.com&#x2F;en-US&#x2F;firefox&#x2F;3.0b1&#x2F;releasenotes&#x2F;#whatsnew&quot;&gt;list of changes&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;img&quot;&gt;&lt;img src=&quot;&#x2F;assets&#x2F;firefox-3.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;div&gt;
&lt;p&gt;&lt;br style=&quot;clear: both;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you want to try it, you&#x27;ll probably want to &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;08&#x2F;20&#x2F;how-to-have-firefox-3-and-firefox-2-running-at-the-same-time&#x2F;&quot;&gt;run Firefox 3 and Firefox 2 at the same time&lt;&#x2F;a&gt;. Only this time you should remember to rename Firefox 3 so that it doesn&#x27;t override your install of Firefox 2.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d blogged about some of the changes previously if you care for some screenshots of &lt;em&gt;some&lt;&#x2F;em&gt; of the new features (Mozilla Links &lt;a href=&quot;http:&#x2F;&#x2F;mozillalinks.org&#x2F;wp&#x2F;category&#x2F;subject&#x2F;firefox3&#x2F;&quot;&gt;covers a good number of new Firefox 3 changes&lt;&#x2F;a&gt; too):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;09&#x2F;18&#x2F;whats-new-in-firefox-3-download-resume&#x2F;&quot;&gt;Resumable downloading: users can now resume downloads after restarting the browser or resetting your network connection.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;05&#x2F;05&#x2F;growl-integration-in-firefox-3&#x2F;&quot;&gt;supports Growl for notifications of completed downloads and available updates.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;09&#x2F;07&#x2F;smarter-and-less-annoying-password-manager-in-firefox-3&#x2F;&quot;&gt;Easier password management: an information bar replaces the old password dialog so you can now save passwords after a successful login.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;09&#x2F;13&#x2F;open-in-tabs-fixed-in-firefox-3-at-last&#x2F;&quot;&gt;Optimized Open in Tabs behavior: opening a folder of bookmarks in tabs now appends the new tabs rather than overwriting.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
  <entry>
    <title>Konata Izumi in Edge Rails</title>
    <published>2007-10-15T16:25:50+00:00</published>
    <updated>2007-10-15T16:25:50+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/10/15/konata-izumi-in-edge-rails/"/>
    <id>https://chuyeow.wtf/2007/10/15/konata-izumi-in-edge-rails/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/10/15/konata-izumi-in-edge-rails/">&lt;p&gt;You wouldn&#x27;t think that &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;05&#x2F;11&#x2F;lucky-star-konata-ism&#x2F;&quot;&gt;Konata Izumi&lt;&#x2F;a&gt; (a character from the anime, &lt;a href=&quot;http:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Lucky_Star_(manga)&quot;&gt;Lucky Star&lt;&#x2F;a&gt;) and Ruby on Rails (a web MVC framework) would somehow be associated, but they are!&lt;&#x2F;p&gt;
&lt;p&gt;I took the opportunity to fill in the missing &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;browser&#x2F;trunk&#x2F;activerecord&#x2F;lib&#x2F;active_record&#x2F;serializers&#x2F;json_serializer.rb?rev=7905&quot;&gt;&lt;code&gt;ActiveRecord::Base#to_json&lt;&#x2F;code&gt; documentation&lt;&#x2F;a&gt; with examples using Konata Izumi and it got committed unchanged in &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;7905&quot;&gt;revision 7905&lt;&#x2F;a&gt;. Cute. I hope no one changes them.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;ins&gt;Update: Managed to get &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;8010&quot;&gt;more Konata Izumi documentation&lt;&#x2F;a&gt; into Rails ;)&lt;&#x2F;ins&gt;&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>So apparently I&#x27;m a Rails Hackfest winner...</title>
    <published>2007-10-03T02:19:29+00:00</published>
    <updated>2007-10-03T02:19:29+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/10/03/so-apparently-im-a-rails-hackfest-winner/"/>
    <id>https://chuyeow.wtf/2007/10/03/so-apparently-im-a-rails-hackfest-winner/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/10/03/so-apparently-im-a-rails-hackfest-winner/">&lt;p&gt;Got an email not too long ago from &lt;a href=&quot;http:&#x2F;&#x2F;workingwithrails.com&#x2F;&quot;&gt;Working With Rails&lt;&#x2F;a&gt; (&lt;a href=&quot;http:&#x2F;&#x2F;workingwithrails.com&#x2F;person&#x2F;5957-cheah-chu-yeow&quot;&gt;my profile&lt;&#x2F;a&gt;) entitled &quot;WWR September Hackfest Winner - Congrats!&quot;, and almost deleted it thinking it was spam. I read it in the end (after all, how often do you see spam with &quot;Rails&quot; in the subject title), and turns out that &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;7663&quot;&gt;my&lt;&#x2F;a&gt; &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;7699&quot;&gt;recent&lt;&#x2F;a&gt; &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;changeset&#x2F;7697&quot;&gt;patches&lt;&#x2F;a&gt; to Rails pushed me up to 6th position in the &lt;a href=&quot;http:&#x2F;&#x2F;workingwithrails.com&#x2F;hackfest&#x2F;15-monthly-september-2-7&quot;&gt;September Rails contributors rankings&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;img&quot;&gt;&lt;img src=&quot;&#x2F;assets&#x2F;hackfest_sept_2007_thumb.png&quot; alt=&quot;Rails Hackfest September 2007 winners&quot; &#x2F;&gt;&lt;&#x2F;div&gt;
&lt;p&gt;&lt;br style=&quot;clear: both;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I vaguely remember seeing &lt;a href=&quot;http:&#x2F;&#x2F;workingwithrails.com&#x2F;hackfest&quot;&gt;Rails Hackfest&lt;&#x2F;a&gt; mentioned somewhere but only just realized it&#x27;s a &quot;contest&quot; run monthly. The winners are the top 10 contributors to Rails (contribution being determined by the number of accepted patches, docfixes, and even comments). That&#x27;s really nice of the sponsors and &lt;a href=&quot;http:&#x2F;&#x2F;workingwithrails.com&#x2F;&quot;&gt;Working With Rails&lt;&#x2F;a&gt;, since that wasn&#x27;t really what I&#x27;d expected in return for contributing to an Open Source project (that would be &lt;em&gt;a sense of satisfaction&lt;&#x2F;em&gt;, personally-speaking).&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m just really glad that the JSON patches went into Rails before Rails 2.0 and it is satisfying to see my code get into Rails (I&#x27;ll blog about the patches in a separate post). There&#x27;s still &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;9751&quot;&gt;some more work&lt;&#x2F;a&gt; needed though - please help to verify and give suggestions or +1s ;).&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>What&#x27;s new in Firefox 3: Download Resume</title>
    <published>2007-09-18T18:08:21+00:00</published>
    <updated>2007-09-18T18:08:21+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/09/18/whats-new-in-firefox-3-download-resume/"/>
    <id>https://chuyeow.wtf/2007/09/18/whats-new-in-firefox-3-download-resume/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/09/18/whats-new-in-firefox-3-download-resume/">&lt;p&gt;This is not exactly a new change to Firefox 3&#x27;s &lt;a href=&quot;http:&#x2F;&#x2F;ftp.mozilla.org&#x2F;pub&#x2F;mozilla.org&#x2F;firefox&#x2F;nightly&#x2F;latest-trunk&#x2F;&quot;&gt;nightly builds&lt;&#x2F;a&gt; since the bugs have been setting in my browser tab bar for about a week but I figured I&#x27;d write about them anyway since it&#x27;s quite a nice improvement.&lt;&#x2F;p&gt;
&lt;p&gt;What&#x27;s new? &lt;a href=&quot;https:&#x2F;&#x2F;bugzilla.mozilla.org&#x2F;show_bug.cgi?id=377243&quot;&gt;Download Resume&lt;&#x2F;a&gt; - now you can pause and resume your downloads in the Firefox Download Manager. Implemented by a &lt;a href=&quot;http:&#x2F;&#x2F;code.google.com&#x2F;soc&#x2F;2007&#x2F;&quot;&gt;Summer of Code&lt;&#x2F;a&gt; student, this brings Firefox&#x27;s Download Manager up to speed with Safari (which has a really nice download resume feature that leaves &lt;code&gt;.download&lt;&#x2F;code&gt; files that you can just double-click to resume the download).&lt;&#x2F;p&gt;
&lt;div class=&quot;img&quot;&gt;&lt;img src=&quot;&#x2F;assets&#x2F;firefox-3-download-manager-resume.png&quot; alt=&quot;Firefox 3 download resume&quot; &#x2F;&gt;&lt;&#x2F;div&gt;
&lt;p&gt;&lt;br style=&quot;clear: both;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You&#x27;ll notice the insane speeds (986GB&#x2F;s) I&#x27;m getting too in that last screenshot. Nope it&#x27;s not a feature, it&#x27;s a &lt;a href=&quot;https:&#x2F;&#x2F;bugzilla.mozilla.org&#x2F;show_bug.cgi?id=395134&quot;&gt;bug&lt;&#x2F;a&gt;. And a &lt;a href=&quot;https:&#x2F;&#x2F;bugzilla.mozilla.org&#x2F;show_bug.cgi?id=395134&quot;&gt;known one&lt;&#x2F;a&gt; that&#x27;s probably fixed if you have a recent nightly.&lt;&#x2F;p&gt;
&lt;p&gt;For Firefox 1.5 or 2 users, don&#x27;t despair, extensions like &lt;a href=&quot;http:&#x2F;&#x2F;www.downthemall.net&#x2F;&quot;&gt;DownThemAll!&lt;&#x2F;a&gt; allow you to resume downloads. If you use an external download manager, you&#x27;d probably be more interested in &lt;a href=&quot;http:&#x2F;&#x2F;flashgot.net&#x2F;&quot;&gt;FlashGot&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>How to have Firefox 3 and Firefox 2 running at the same time</title>
    <published>2007-08-20T20:06:50+00:00</published>
    <updated>2007-08-20T20:06:50+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/08/20/how-to-have-firefox-3-and-firefox-2-running-at-the-same-time/"/>
    <id>https://chuyeow.wtf/2007/08/20/how-to-have-firefox-3-and-firefox-2-running-at-the-same-time/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/08/20/how-to-have-firefox-3-and-firefox-2-running-at-the-same-time/">&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;wiki.mozilla.org&#x2F;Firefox3&quot;&gt;Firefox 3&lt;&#x2F;a&gt;, or Gran Paradiso, is really shaping up with some pretty &lt;a href=&quot;http:&#x2F;&#x2F;mozillalinks.org&#x2F;wp&#x2F;2007&#x2F;08&#x2F;advanced-bookmarking-tagging-enters-firefox-3&#x2F;&quot;&gt;cool&lt;&#x2F;a&gt; &lt;a href=&quot;http:&#x2F;&#x2F;weblogs.mozillazine.org&#x2F;asa&#x2F;archives&#x2F;2007&#x2F;08&#x2F;nifty_tab_anima.html&quot;&gt;new&lt;&#x2F;a&gt; &lt;a href=&quot;http:&#x2F;&#x2F;mozillalinks.org&#x2F;wp&#x2F;2007&#x2F;08&#x2F;easy-plugin-management-for-firefox-3&#x2F;&quot;&gt;features&lt;&#x2F;a&gt; being implemented in the recent months. That&#x27;s not including the cool &lt;a href=&quot;http:&#x2F;&#x2F;wiki.mozilla.org&#x2F;FUEL&quot;&gt;FUEL&lt;&#x2F;a&gt; (Firefox User Extension Library) JavaScript library that promises to make extension development a bajillion times more productive, &lt;a href=&quot;http:&#x2F;&#x2F;wiki.mozilla.org&#x2F;Places&quot;&gt;Places&lt;&#x2F;a&gt; for data storage, and the use of &lt;a href=&quot;http:&#x2F;&#x2F;cairographics.org&#x2F;&quot;&gt;Cairo&lt;&#x2F;a&gt; for graphics.&lt;&#x2F;p&gt;
&lt;p&gt;The problem with playing around with Firefox 3 is (by default) you can&#x27;t run both Firefox 2 and 3 at the same time since they both insist on using the same profile and insist on running only 1 copy of Firefox at any one time.&lt;&#x2F;p&gt;
&lt;p&gt;Want to get in on checking out the new features but still want good old Firefox 2? Here&#x27;s how:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;First, you should &lt;a href=&quot;http:&#x2F;&#x2F;www.mozilla.org&#x2F;support&#x2F;firefox&#x2F;profile&quot;&gt;create a new profile&lt;&#x2F;a&gt; just for testing Firefox 3. You should do this to keep your precious Firefox profile safe from any problems in Firefox 3. Otherwise, Firefox 3 will use your current Firefox 2 profile by default. You can create a new profile easily with the Profile Manager, which you can access by running:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&#x2F;path&#x2F;to&#x2F;firefox -profilemanager -no-remote&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;    (Thanks to &lt;a href=&quot;http:&#x2F;&#x2F;rubbedcode.com&#x2F;blog&#x2F;&quot;&gt;Jeff&lt;&#x2F;a&gt; for &lt;a href=&quot;#comment-258587&quot;&gt;pointing out&lt;&#x2F;a&gt; that there is no need to close Firefox first before creating a new profile.)&lt;&#x2F;p&gt;
&lt;div class=&quot;img&quot;&gt;&lt;img src=&quot;&#x2F;assets&#x2F;firefox-profile-manager.png&quot; alt=&quot;Firefox profile manager&quot; &#x2F;&gt;&lt;&#x2F;div&gt;
&lt;p&gt;&lt;br style=&quot;clear: both;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Create a new profile (I gave it an obvious name, &#x27;minefield&#x27;, which is the codename of the current Firefox trunk). If you get confused, the official Firefox website has &lt;a href=&quot;http:&#x2F;&#x2F;www.mozilla.org&#x2F;support&#x2F;firefox&#x2F;profile&quot;&gt;more detailed instructions on how to create a new profile&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Now, you should already have one of the Firefox nightly builds. If not, you can download the latest nightly build from the &lt;a href=&quot;http:&#x2F;&#x2F;ftp.mozilla.org&#x2F;pub&#x2F;mozilla.org&#x2F;firefox&#x2F;nightly&#x2F;latest-trunk&#x2F;&quot;&gt;Firefox nightly build directory&lt;&#x2F;a&gt;. You can start up Firefox &lt;strong&gt;2&lt;&#x2F;strong&gt; normally (just so you can see Firefox 2 and 3 running side by side). For Firefox 3, we&#x27;re going to start it differently.&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;We&#x27;re gonna run Firefox 3 using our newly created profile. I&#x27;d written earlier on how you can &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;03&#x2F;01&#x2F;running-two-firefox-profiles-simultaneously&#x2F;&quot;&gt;run two Firefox profiles at the same time&lt;&#x2F;a&gt;, and you can still do the same with Firefox 3:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&#x2F;path&#x2F;to&#x2F;firefox3 -P minefield -no-remote &amp;amp;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &#x27;minefield&#x27; in the command is the name of the profile we created earlier. Windows users should leave out the &#x27;&amp;amp;&#x27; (on UNIX-based systems, this just runs Minefield in the background so that you can exit your terminal).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Firefox 3 should start up with your new clean profile!&lt;&#x2F;p&gt;
&lt;div class=&quot;img&quot;&gt;&lt;img src=&quot;&#x2F;assets&#x2F;firefox-minefield-in-dock.png&quot; alt=&quot;Firefox and Minefield icons in my Mac OS X dock&quot; &#x2F;&gt;&lt;&#x2F;div&gt;
&lt;p&gt;&lt;br style=&quot;clear: both;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s the Firefox 3 (Minefield) icon living right next to my Firefox 2 icon in my dock (yeah, I use a Mac).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.deepcalm.com&#x2F;&quot;&gt;Andy Croll&lt;&#x2F;a&gt; (who works at &lt;a href=&quot;http:&#x2F;&#x2F;bezurk.com&#x2F;&quot;&gt;Bezurk&lt;&#x2F;a&gt; too) has &lt;a href=&quot;http:&#x2F;&#x2F;www.deepcalm.com&#x2F;writing&#x2F;running-firefox-3-at-the-same-time-as-firefox-2-applescript-edition&quot;&gt;written a convenient little AppleScript&lt;&#x2F;a&gt; so you don&#x27;t have to repeat these steps.&lt;&#x2F;p&gt;
&lt;p&gt;Just so I can put up another screenshot (as if I needed to prove that this really works), here&#x27;s Firefox 2 and one of the recent Firefox 3 nightly builds running side by side:&lt;&#x2F;p&gt;
&lt;div class=&quot;img&quot;&lt;img src=&quot;&#x2F;assets&#x2F;firefox-and-minefield-side-by-side.jpg&quot; alt=&quot;Firefox and Minefield running side by side&quot; &#x2F;&gt;&lt;br style=&quot;clear: both;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Have fun! I think I&#x27;ll get back to watching the development of the trunk (now that it&#x27;s getting more exciting) like I &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2006&#x2F;01&#x2F;24&#x2F;tabbed-browsing-enhancements-for-firefox-in-latest-build&#x2F;&quot;&gt;used&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2004&#x2F;07&#x2F;13&#x2F;rss-feed-integration-in-firefox&#x2F;&quot;&gt;to&lt;&#x2F;a&gt; in the &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2004&#x2F;07&#x2F;18&#x2F;show-saved-passwords-option-in-firefox&#x2F;&quot;&gt;build&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2004&#x2F;07&#x2F;09&#x2F;new-find-toolbar-for-mozilla-firefox&#x2F;&quot;&gt;up&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2004&#x2F;10&#x2F;02&#x2F;tabbed-browsing-gets-even-better-in-firefox&#x2F;&quot;&gt;to&lt;&#x2F;a&gt; Firefox 1 and 2. I may even make some posts!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Better JSON output from Rails with the Jsonifier plugin</title>
    <published>2007-07-11T12:46:38+00:00</published>
    <updated>2007-07-11T12:46:38+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/07/11/better-json-output-from-rails-with-the-jsonifier-plugin/"/>
    <id>https://chuyeow.wtf/2007/07/11/better-json-output-from-rails-with-the-jsonifier-plugin/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/07/11/better-json-output-from-rails-with-the-jsonifier-plugin/">&lt;p&gt;&lt;ins&gt;Update: Edge Rails now does whatever Jsonifier does (and more). Check out my blog &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;10&#x2F;10&#x2F;new-on-edge-rails-json-serialization-of-activerecord-objects-reaches-maturity&#x2F;&quot;&gt;post on JSON serialization maturity in edge Rails&lt;&#x2F;a&gt;. This means that this plugin is virtually obsolete if you&#x27;re using edge Rails.&lt;&#x2F;ins&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;ve tried to output JSON from your Rails applications before, you&#x27;d probably have noticed how inadequate it all seems. Let&#x27;s look at the kind of output (pretty-printed for easier reading) you get from calling &lt;code&gt;to_json&lt;&#x2F;code&gt; on your typical User model:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;{
  attributes: {
    id: 1,
    name: &quot;Konata&quot;,
    awesome: true,
    created_at: &quot;07&#x2F;01&#x2F;2007&quot;
  }
}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Some of the common problems developers who write applications that speak JSON have with this are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;attributes&lt;&#x2F;code&gt; part is often unnecessary cruft when consuming ActiveRecord objects as JSON.&lt;&#x2F;li&gt;
&lt;li&gt;There&#x27;s no obvious way to control which attributes are shown in the JSON (e.g. you may want to hide private or lengthy attributes). The way to workaround this is either to write your own &lt;code&gt;to_json&lt;&#x2F;code&gt; instance method for your ActiveRecord model, or to use a Rails plugin (like &lt;a href=&quot;http:&#x2F;&#x2F;geekblog.vodpod.com&#x2F;?p=9&quot;&gt;acts_as_json&lt;&#x2F;a&gt;) or a &lt;a href=&quot;http:&#x2F;&#x2F;json.rubyforge.org&#x2F;&quot;&gt;gem&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Including 2nd (or higher order) associations is tricky (as above, you can achieve this by defining your own &lt;code&gt;to_json&lt;&#x2F;code&gt; instance methods).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3&gt;Under the hood of the current ActiveRecord#to_json&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;code&gt;to_json&lt;&#x2F;code&gt; method for ActiveRecord objects falls back on using that defined in &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;browser&#x2F;trunk&#x2F;activesupport&#x2F;lib&#x2F;active_support&#x2F;json&quot;&gt;ActiveSupport&#x27;s JSON classes&lt;&#x2F;a&gt;. The way it&#x27;s currently done, there are a bunch of JSON encoder classes defined for various types - when you call &lt;code&gt;to_json&lt;&#x2F;code&gt; on an ActiveRecord object it simply uses &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;browser&#x2F;trunk&#x2F;activesupport&#x2F;lib&#x2F;active_support&#x2F;json&#x2F;encoders&#x2F;object.rb&quot;&gt;&lt;code&gt;Object#to_json&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;By the way, see that &lt;code&gt;created_at: &quot;07&#x2F;01&#x2F;2007&quot;&lt;&#x2F;code&gt; bit in the example above which is the JSON output for a Date attribute? That&#x27;s in MM&#x2F;DD&#x2F;YYYY format. Yup, 1st July 2007 not 7th January 2007 you &quot;rest of the world you&quot;. Ouch, but at least you can use JavaScript&#x27;s &lt;code&gt;Date.parse()&lt;&#x2F;code&gt; on it directly as detailed in &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;8399&quot;&gt;this patch&lt;&#x2F;a&gt;. And before you ask, yes, &lt;code&gt;Date.parse()&lt;&#x2F;code&gt; doesn&#x27;t understand the YYYY-MM-DD format.&lt;&#x2F;p&gt;
&lt;h3&gt;Can has Rails patch?&lt;&#x2F;h3&gt;
&lt;p&gt;So about 2 days ago, I wrote a &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;8920&quot;&gt;Rails patch to boost ActiveRecord#to_json with an options hash&lt;&#x2F;a&gt;. Yep much like what you can do with &lt;a href=&quot;http:&#x2F;&#x2F;api.rubyonrails.org&#x2F;classes&#x2F;ActiveRecord&#x2F;XmlSerialization.html#M000910&quot;&gt;&lt;code&gt;ActiveRecord#to_xml&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I hope it gets committed into the core some day. I mean, gosh, isn&#x27;t Rails all about Web 2.0 mashups. It even has that fancy &lt;code&gt;render :json&lt;&#x2F;code&gt; thing. I do believe JSON output needs to be treated more seriously in Rails rather than the half-hearted attempt at JSON encoding. No? Well, if the patch doesn&#x27;t get accepted I&#x27;ll still have &lt;a href=&quot;http:&#x2F;&#x2F;trac.codefront.net&#x2F;jsonifier&#x2F;&quot;&gt;my plugin&lt;&#x2F;a&gt; (&lt;a href=&quot;#jsonifier-plugin&quot;&gt;see below&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, let&#x27;s see some examples:&lt;&#x2F;p&gt;
&lt;h3&gt;Some examples, see?&lt;&#x2F;h3&gt;
&lt;p&gt;Assuming User and Post models where User has_many Posts:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;david = User.find(1)
david.to_json  # {id: 1, name: &quot;David&quot;, awesome: true, created_at: &quot;07&#x2F;01&#x2F;2007&quot;}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;No more &lt;code&gt;attributes&lt;&#x2F;code&gt; cruft!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;:only&lt;&#x2F;code&gt; and &lt;code&gt;:except&lt;&#x2F;code&gt; work the same way that as for &lt;code&gt;ActiveRecord#to_xml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;david.to_json(:only =&gt; :name)                 # {name: &quot;David&quot;}
david.to_json(:only =&gt; [:id, :name])          # {id: 1, name: &quot;David&quot;}
david.to_json(:except =&gt; :created_at)         # {id: 1, name: &quot;David&quot;, awesome: true}
david.to_json(:except =&gt; [:id, :created_at])  # {name: &quot;David&quot;, awesome: true}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can use the &lt;code&gt;:methods&lt;&#x2F;code&gt; options as well to include any methods on the object.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;david.to_json(:methods =&gt; :permalink)
  # {id: 1, name: &quot;David&quot;, awesome: true, created_at: &quot;07&#x2F;01&#x2F;2007&quot;, permalink =&gt; &quot;1-David&quot;}
david.to_json(:methods =&gt; [:permalink, :interestingness])
  # {id: 1, name: &quot;David&quot;, awesome: true, created_at: &quot;07&#x2F;01&#x2F;2007&quot;, \
  #   permalink =&gt; &quot;1-David&quot;, :interestingness =&gt; 666}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;:include&lt;&#x2F;code&gt; option lets you include associations.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;david.to_json(:include =&gt; :posts)
  # {id: 1, name: &quot;David&quot;, awesome: true, created_at: &quot;07&#x2F;01&#x2F;2007&quot;, \
  #    posts: [{id: 1, author_id: 1, title: &quot;Welcome to the weblog&quot;}, \
  #            {id: 2, author_id: 1, title: &quot;So I was thinking&quot;}]}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;:only&lt;&#x2F;code&gt;, &lt;code&gt;:except&lt;&#x2F;code&gt;, and &lt;code&gt;:methods&lt;&#x2F;code&gt; works on the included associations as well:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;david.to_json(:include =&gt; { :posts =&gt; { :only =&gt; :title } })
  # {id: 1, name: &quot;David&quot;, awesome: true, created_at: &quot;07&#x2F;01&#x2F;2007&quot;, \
  #    posts: [{title: &quot;Welcome to the weblog&quot;}, \
  #            {title: &quot;So I was thinking&quot;}]}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Of course, 2nd level (and higher order) associations work too:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;david.to_json(:include =&gt; { :posts =&gt; { \
                              :include =&gt; { :comments =&gt; { \
                                              :only =&gt; :body } }, \
                              :only =&gt; :title } })
  # {id: 1, name: &quot;David&quot;, awesome: true, created_at: &quot;07&#x2F;01&#x2F;2007&quot;, \
  #    posts: [{comments: [{body: &quot;1st post!&quot;}, {body: &quot;OMGWTFBBQ!&quot;}], \
  #             title: &quot;Welcome to the weblog&quot;}, \
  #            {comments: [{body: &quot;Don&#x27;t think too hard&quot;}], \
  #             title: &quot;So I was thinking&quot;}]}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Please do give any feedback at the &lt;a href=&quot;http:&#x2F;&#x2F;dev.rubyonrails.org&#x2F;ticket&#x2F;8920&quot;&gt;Rails patch for ActiveRecord#to_json&lt;&#x2F;a&gt; or here. I wanna know what you feel about adding this functionality into the Rails core!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;jsonifier-plugin&quot;&gt;Jsonifier plugin&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;ve rolled the patch into a plugin: Jsonifier. The &lt;a href=&quot;http:&#x2F;&#x2F;trac.codefront.net&#x2F;jsonifier&#x2F;&quot;&gt;Jsonifier Trac&lt;&#x2F;a&gt; is at &lt;a href=&quot;http:&#x2F;&#x2F;trac.codefront.net&#x2F;jsonifier&#x2F;&quot;&gt;http:&#x2F;&#x2F;trac.codefront.net&#x2F;jsonifier&#x2F;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Git repository:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;git:&#x2F;&#x2F;github.com&#x2F;chuyeow&#x2F;jsonifier.git&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Github project page:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;http:&#x2F;&#x2F;github.com&#x2F;chuyeow&#x2F;jsonifier&#x2F;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To install the plugin:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;ruby script&#x2F;plugin install git:&#x2F;&#x2F;github.com&#x2F;chuyeow&#x2F;jsonifier.git&lt;&#x2F;code&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt; or &lt;code&gt;git clone&lt;&#x2F;code&gt; the repository manually into the &lt;code&gt;vendor&#x2F;plugins&lt;&#x2F;code&gt; directory.&lt;&#x2F;p&gt;
&lt;h3&gt;A note on valid JSON&lt;&#x2F;h3&gt;
&lt;p&gt;The JSON Rails spits out by default is not strictly valid JSON since the &lt;a href=&quot;http:&#x2F;&#x2F;www.ietf.org&#x2F;rfc&#x2F;rfc4627.txt?number=4627&quot;&gt;JSON specifications&lt;&#x2F;a&gt; require keys to be double quoted. To get strictly valid JSON, add&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;ActiveSupport::JSON.unquote_hash_key_identifiers = false&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;in your environment.rb (or in the Rails initializers directory if you&#x27;re on edge). See &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;06&#x2F;20&#x2F;how-to-get-strictly-valid-json-from-rails&#x2F;&quot;&gt;my blog post on how to get strictly valid JSON from Rails&lt;&#x2F;a&gt; for more info.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>WTF is this? (Or how NIS and portmapper on Ubuntu Dapper Drake drove me nuts)</title>
    <published>2007-07-02T19:42:00+00:00</published>
    <updated>2007-07-02T19:42:00+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/07/02/wtf-is-this-or-how-nis-and-portmapper-on-ubuntu-dapper-drake-drove-me-nuts/"/>
    <id>https://chuyeow.wtf/2007/07/02/wtf-is-this-or-how-nis-and-portmapper-on-ubuntu-dapper-drake-drove-me-nuts/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/07/02/wtf-is-this-or-how-nis-and-portmapper-on-ubuntu-dapper-drake-drove-me-nuts/">&lt;p&gt;Not too long ago a couple of the Ubuntu Dapper Drake (6.06 LTS) &lt;acronym title=&quot;Virtual Private Servers&quot;&gt;VPS&lt;&#x2F;acronym&gt;s &lt;a href=&quot;http:&#x2F;&#x2F;www.bezurk.com&#x2F;&quot;&gt;we&lt;&#x2F;a&gt; use abruptly became inaccessible. These VPSs were &lt;a href=&quot;http:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Network_Information_Service&quot;&gt;NIS&lt;&#x2F;a&gt; clients that suddenly could no longer connect to the NIS master. Great. And as far as I could tell I didn&#x27;t do anything to those servers. I even managed to replicate the problem on another similar VPS (that was still accessble) simply by restarting the NIS daemon.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;http:&#x2F;&#x2F;rimuhosting.com&#x2F;&quot;&gt;Rimuhosting&lt;&#x2F;a&gt;&#x27;s fantabulous support, I managed to regain access to the VPSs. Oh yeah, &lt;strong&gt;big lesson learnt&lt;&#x2F;strong&gt; here: when configuring NIS clients, be sure to leave at least one user account with sudo privileges or set the root account&#x27;s password (Ubuntu doesn&#x27;t come with a root account enabled by default - run &lt;code&gt;sudo passwd&lt;&#x2F;code&gt; to set it and enable the root account as a side effect). Big big lesson learnt. Don&#x27;t let this bite you in the ass if you&#x27;re a sysadmin-ish person.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, &lt;code&gt;&#x2F;var&#x2F;log&#x2F;syslog&lt;&#x2F;code&gt; was complaining this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;ypbind[1026]: Unable to register (YPBINDPROG, YPBINDVERS, udp)&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which turned out to be a portmap problem. So yeah portmap wasn&#x27;t running! For a moment there I thought we had an easy solution. Sadly, &lt;code&gt;&#x2F;etc&#x2F;init.d&#x2F;portmap start&lt;&#x2F;code&gt; was throwing this inexplicable error (i.e. Google wasn&#x27;t of much help):&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;root@zoidberg:&#x2F;sbin# &#x2F;etc&#x2F;init.d&#x2F;portmap  restart
 * Stopping portmap daemon...
   ...done.
 * Starting portmap daemon...
dhclient.4.x 2.*.5, December 30th, 2000
Compiled on Dec 12 2003 09:55:54
Features: DBG, SEE, ALS, SEF
init: Couldn&#x27;t open the file .&#x2F;libuuid.so -&amp;gt;
   ...fail!&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It sure isn&#x27;t &lt;a href=&quot;http:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Lolcat&quot;&gt;caturday&lt;&#x2F;a&gt;. After hours spent scrambling to find out why portmap can&#x27;t find libuuid.so, reinstalling the NIS .deb, comparing configuration files between working NIS clients and these busted ones, it finally dawned on me that I have yet to re-install portmap (not that it was logically sound that I&#x27;d have to reinstall it, but at this point I was willing to try anything). Annoyingly enough, it worked!&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;apt-get remove portmap nis
apt-get install nis&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I still don&#x27;t know &lt;acronym title=&quot;What The Fuck&quot;&gt;WTF&lt;&#x2F;acronym&gt; happened there. If anyone has any clue please please point me to it.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Installing Xen on Ubuntu Feisty Fawn - the complete newbie&#x27;s guide</title>
    <published>2007-06-26T21:46:44+00:00</published>
    <updated>2007-06-26T21:46:44+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/06/26/installing-xen-on-ubuntu-feisty-fawn-the-complete-newbies-guide/"/>
    <id>https://chuyeow.wtf/2007/06/26/installing-xen-on-ubuntu-feisty-fawn-the-complete-newbies-guide/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/06/26/installing-xen-on-ubuntu-feisty-fawn-the-complete-newbies-guide/">&lt;p&gt;I had to spend some time setting up &lt;a href=&quot;http:&#x2F;&#x2F;www.xensource.com&#x2F;xen&quot;&gt;Xen&lt;&#x2F;a&gt; on one of the new Dell servers we bought and while there &lt;a href=&quot;https:&#x2F;&#x2F;help.ubuntu.com&#x2F;community&#x2F;XenVirtualMachine&#x2F;XenOnUbuntuFeisty&quot;&gt;was&lt;&#x2F;a&gt; &lt;a href=&quot;http:&#x2F;&#x2F;www.howtoforge.com&#x2F;xen_3.0_ubuntu_dapper_drake&quot;&gt;some&lt;&#x2F;a&gt; &lt;a href=&quot;http:&#x2F;&#x2F;www.howtoforge.com&#x2F;perfect_xen_setup_debian_ubuntu&quot;&gt;documentation&lt;&#x2F;a&gt; &lt;a href=&quot;http:&#x2F;&#x2F;tx.downloads.xensource.com&#x2F;downloads&#x2F;docs&#x2F;user&#x2F;&quot;&gt;around&lt;&#x2F;a&gt;, I had to constantly refer to the different sources since there wasn&#x27;t a complete page which had everything I needed for my particular situation - I have a host machine with Ubuntu Feisty Fawn installed and wanted to install a couple of Xen guest domains on it. One other thing I found lacking in the documentation is the explanation of commands or answers to the question &lt;em&gt;&quot;so why the hell am I doing this?&quot;&lt;&#x2F;em&gt;. I&#x27;m not considering &lt;a href=&quot;http:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Logical_Volume_Manager_(Linux)&quot;&gt;LVM&lt;&#x2F;a&gt; at the moment and am happy with loopback disk file images too.&lt;&#x2F;p&gt;
&lt;p&gt;So I think it&#x27;s a good idea to &lt;em&gt;write this down somewhere&lt;&#x2F;em&gt; for the next time I have to do the same bloody thing over again on any new servers.&lt;&#x2F;p&gt;
&lt;p&gt;Some caveats before we start:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Like I said, I&#x27;m not gonna talk about LVM for disk images since I know next to nothing about configuring it at the moment. The host machine I have isn&#x27;t setup with LVM and I haven&#x27;t got the time to look into LVM either.&lt;&#x2F;li&gt;
&lt;li&gt;I&#x27;m quite the networking newbie, so my setup uses the default Xen bridge installed via apt-get. Check out &lt;a href=&quot;http:&#x2F;&#x2F;wiki.xensource.com&#x2F;xenwiki&#x2F;XenNetworking&quot;&gt;Xen networking on the Xen wiki&lt;&#x2F;a&gt; for more complex network setups.&lt;&#x2F;li&gt;
&lt;li&gt;I&#x27;m not gonna talk about putting a Linux distro other than that of the host machine into the Xen virtual machines. In other words, I have Feisty Fawn for both dom0 and all my domUs.&lt;&#x2F;li&gt;
&lt;li&gt;I probably did some completely stupid things. Stuff like &lt;a href=&quot;http:&#x2F;&#x2F;www.xen-tools.org&#x2F;software&#x2F;xen-tools&#x2F;&quot;&gt;xen-tools&lt;&#x2F;a&gt; exist to simplify Xen administration, but I haven&#x27;t had a chance to use them. Let me know if you spot an error or have a better way of doing something please!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Some terms that deserve explaining (most guides out there just use &quot;DomU&quot; and &quot;Dom0&quot; without any ceremony, and assume you know what they mean):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Domain-0&lt;&#x2F;strong&gt; or &lt;strong&gt;Dom0&lt;&#x2F;strong&gt;: This refers to the host machine OS. You know, the OS of the actual physical server that you have.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;DomU&lt;&#x2F;strong&gt;: This refers to a Xen guest domain. A DomU is a single Xen virtual machine. The &quot;U&quot; stands for &quot;unprivileged&quot; I believe.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;OK let&#x27;s go!&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h3&gt;Installing the Xen Server&lt;&#x2F;h3&gt;
&lt;p&gt;First off, we need to install the Xen server on the host machine (or Dom0). Thankfully, there is a Xen server package in Feisty Fawn&#x27;s apt-get repository.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Make sure &#x27;universe&#x27; is enabled in &lt;code&gt;&#x2F;etc&#x2F;apt&#x2F;sources.list&lt;&#x2F;code&gt; and run: &lt;code&gt;apt-get install ubuntu-xen-server&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Reboot the machine. After boot, running &lt;code&gt;sudo xm list&lt;&#x2F;code&gt; should show you Domain-0 (which is the host machine that&#x27;s running Xen).&lt;&#x2F;li&gt;
&lt;li&gt;Edit &#x2F;etc&#x2F;xen&#x2F;xend-config.sxp and uncomment this line:
&lt;pre&gt;&lt;code&gt;(network-script network-bridge)&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Comment out this line:
&lt;pre&gt;&lt;code&gt;(network-script network-dummy)&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Restart xend:
&lt;pre&gt;&lt;code&gt;sudo xend restart&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;When you run &#x27;ifconfig&#x27;, you should see the &#x27;xenbr0&#x27; interface. This is the Xen network bridge.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3&gt;Creating a base image&lt;&#x2F;h3&gt;
&lt;p&gt;Now let&#x27;s create a base Xen image. We&#x27;ll use this as a template for any future images (domUs).&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Use &#x27;dd&#x27; to create the images (I place them in &#x2F;xen-images&#x2F;):
&lt;pre&gt;&lt;code&gt;dd if=&#x2F;dev&#x2F;zero of=&#x2F;xen-images&#x2F;feisty_base.img bs=1024k count=4000
dd if=&#x2F;dev&#x2F;zero of=&#x2F;xen-images&#x2F;feisty_base_swap.img bs=1024k count=1000&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;  These commands create image files of 4GB and 1GB for your virtual OS and its swap respectively. &#x27;count&#x27; is the number of blocks (block size = 1024k).&lt;&#x2F;li&gt;
&lt;li&gt;Create the filesystem (we&#x27;re using ext3 in this case) within the virtual OS image file.
&lt;pre&gt;&lt;code&gt;mkfs.ext3 &#x2F;xen-images&#x2F;feisty_base.img&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;   Answer &#x27;yes&#x27; to proceed anyway when it complains about the file not being a block device.&lt;&#x2F;li&gt;
&lt;li&gt;Do the same for the swap file:
&lt;pre&gt;&lt;code&gt;mkswap &#x2F;xen-images&#x2F;feisty_base_swap.img&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Now, restrict the permissions on the images so no one else but root can screw around with them.
&lt;pre&gt;&lt;code&gt;chmod 640 &#x2F;xen-images&#x2F;feisty_base*&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Create a mount point for the image. We need this to mount the image to install and configure Ubuntu Feisty Fawn the way we like it. We can then replicate this base image for any future virtual machines.
&lt;pre&gt;&lt;code&gt;mkdir &#x2F;xen-images&#x2F;mnt&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Mount the base image via the loop device:
&lt;pre&gt;&lt;code&gt;mount -o loop &#x2F;xen-images&#x2F;feisty_base.img &#x2F;xen-images&#x2F;mnt&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;  Now we have full access to the base image&#x27;s filesystem. What we need to do now is to put a base install of Feisty Fawn on it.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3&gt;Installing and configuring the base image&lt;&#x2F;h3&gt;
&lt;p&gt;Next, we have to put Ubuntu onto the image and configure it to our liking.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Install debootstrap, a handy tool that bootstraps a basic Debian (Ubuntu in this case) system.
&lt;pre&gt;&lt;code&gt;apt-get install debootstrap&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Bootstrap the base image with &#x27;feisty&#x27;:
&lt;pre&gt;&lt;code&gt;debootstrap feisty &#x2F;xen-images&#x2F;mnt&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;  After this is done you should see the basic Ubuntu file hierarchy:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;ls &#x2F;xen-images&#x2F;mnt&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Copy your sources.list into the base image:
&lt;pre&gt;&lt;code&gt;cp &#x2F;etc&#x2F;apt&#x2F;sources.list &#x2F;xen-images&#x2F;mnt&#x2F;etc&#x2F;apt&#x2F;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Copy your kernel modules as well (replace 2.6.19-4-server with whatever kernel version you have):
&lt;pre&gt;&lt;code&gt;cp -a &#x2F;lib&#x2F;modules&#x2F;2.6.19-4-server&#x2F; &#x2F;xen-images&#x2F;mnt&#x2F;lib&#x2F;modules&#x2F;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Install the &lt;code&gt;libc6-xen&lt;&#x2F;code&gt; package, which is a Xen-compatible glibc that allows applications to use Thread-Local Storage (TLS).
&lt;pre&gt;&lt;code&gt;apt-get install libc6-xen&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;  Taken from the &lt;a href=&quot;http:&#x2F;&#x2F;wiki.xensource.com&#x2F;xenwiki&#x2F;XenFaq&quot;&gt;Xen FAQ&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;&lt;p&gt;Some modern distributions ship with a &#x27;TLS&#x27; version of glibc that is not fully compatible with Xen. To use Xen reliably and with maximum performance you must disable the incompatible glibc.&lt;&#x2F;p&gt;&lt;&#x2F;blockquote&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Configure networking by editing &lt;code&gt;&#x2F;xen-images&#x2F;mnt&#x2F;etc&#x2F;network&#x2F;interfaces&lt;&#x2F;code&gt;:
&lt;pre&gt;&lt;code&gt;auto lo
iface lo inet loopback
&lt;h1 id=&quot;uncomment-this-and-fill-up-with-your-networks-settings&quot;&gt;Uncomment this and fill up with your networks settings.&lt;&#x2F;h1&gt;
&lt;p&gt;#auto eth0
#iface eth0 inet static&lt;&#x2F;p&gt;
&lt;h1 id=&quot;address-192-168-0-201&quot;&gt;address 192.168.0.201&lt;&#x2F;h1&gt;
&lt;h1 id=&quot;netmask-255-255-255-0&quot;&gt;netmask 255.255.255.0&lt;&#x2F;h1&gt;
&lt;h1 id=&quot;broadcast-192-168-255-255&quot;&gt;broadcast 192.168.255.255&lt;&#x2F;h1&gt;
&lt;h1 id=&quot;gateway-192-168-0-1&quot;&gt;gateway 192.168.0.1&lt;&#x2F;h1&gt;
&lt;h1 id=&quot;dns-nameservers-192-168-0-1&quot;&gt;dns-nameservers 192.168.0.1&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;  Notice how the network settings are commented out - this is because we are leaving the base image as a template from which other images would be made from.&lt;&#x2F;li&gt;
&lt;li&gt;Edit the hosts file (&lt;code&gt;&#x2F;xen-images&#x2F;mnt&#x2F;etc&#x2F;hosts&lt;&#x2F;code&gt;):
&lt;pre&gt;&lt;code&gt;127.0.0.1       localhost localhost.localdomain
127.0.0.1       guest
&lt;h1 id=&quot;the-following-lines-are-desirable-for-ipv6-capable-hosts&quot;&gt;The following lines are desirable for IPv6 capable hosts&lt;&#x2F;h1&gt;
&lt;p&gt;::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Give the base image a generic hostname by editing &lt;code&gt;&#x2F;xen-images&#x2F;mnt&#x2F;etc&#x2F;hostname&lt;&#x2F;code&gt;. In this case I&#x27;m just naming it &#x27;guest&#x27; - actual virtual machines would have sensible hostnames.&lt;&#x2F;li&gt;
&lt;li&gt;Edit the filesystem table (&lt;code&gt;&#x2F;xen-images&#x2F;mnt&#x2F;etc&#x2F;fstab&lt;&#x2F;code&gt;).
&lt;pre&gt;&lt;code&gt;proc            &#x2F;proc           proc    defaults        0       0
&#x2F;dev&#x2F;hda1       &#x2F;               ext3    defaults,errors=remount-ro 0       1
&#x2F;dev&#x2F;hda2       none            swap    sw              0       0&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;  Don&#x27;t worry, the &#x2F;dev&#x2F;hda* would be configured to point to the images you created, not to your actual physical harddisks.&lt;&#x2F;li&gt;
&lt;li&gt;You&#x27;re done with the initial configuration and have enough to bootup the image. Let&#x27;s unmount the image:
&lt;pre&gt;&lt;code&gt;umount &#x2F;xen-images&#x2F;mnt&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Now, we need to create a Xen config for the base image so we can boot into it. Create a file named &lt;code&gt;&#x2F;etc&#x2F;xen&#x2F;vm_feisty_base.config.example.sxp&lt;&#x2F;code&gt; (you can name it whatever you like of course):
&lt;pre&gt;&lt;code&gt;name = &quot;feisty_base&quot;
kernel = &quot;&#x2F;boot&#x2F;vmlinuz-2.6.19-4-server&quot;
ramdisk = &quot;&#x2F;boot&#x2F;initrd.img-2.6.19-4-server&quot;
root = &quot;&#x2F;dev&#x2F;hda1 ro&quot;
memory = 512
disk = [&#x27;file:&#x2F;xen-images&#x2F;feisty_base.img,hda1,w&#x27;,&#x27;file:&#x2F;xen-images&#x2F;feisty_base_swap.img,hda2,w&#x27;]
&lt;h1 id=&quot;network&quot;&gt;Network.&lt;&#x2F;h1&gt;
&lt;p&gt;hostname = &quot;feisty_base&quot;
vif = [&#x27;bridge=xenbr0&#x27;]
dhcp = &quot;off&quot;
ip = &quot;192.168.0.201&quot;
netmask = &quot;255.255.255.0&quot;
gateway = &quot;192.168.0.1&quot;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;An explanation of the configuration options:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;name&lt;&#x2F;strong&gt; - a descriptive name of your image.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;kernel&lt;&#x2F;strong&gt; - path to the kernel.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;ramdisk&lt;&#x2F;strong&gt; - path to the &lt;a href=&quot;http:&#x2F;&#x2F;www.cyberciti.biz&#x2F;tips&#x2F;understanding-linux-initrd-initial-ram-disk.html&quot;&gt;initrd&lt;&#x2F;a&gt; (initial RAM disk) image.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;root&lt;&#x2F;strong&gt; - point this to your host machine&#x27;s harddisk where your image files are.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;memory&lt;&#x2F;strong&gt; - the amount of memory assigned to the virtual machine in megabytes&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;disk&lt;&#x2F;strong&gt; - specify a list of block devices that will be export to the virtual machine. In this example, we&#x27;re mapping the &#x2F;xen-images&#x2F;feisty_base.img image file to &#x2F;dev&#x2F;hda1 in the virtual image (same for the swap image). This should match whatever config you did in &#x2F;xen-images&#x2F;mnt&#x2F;etc&#x2F;fstab.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;hostname&lt;&#x2F;strong&gt; - hostname of your virtual machine.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;vif&lt;&#x2F;strong&gt; - virtual network interface that your virtual machine will use. In this case, we&#x27;re using the default &#x27;xenbr0&#x27; bridge that Xen installs. For alternative configurations, check out the &lt;a href=&quot;http:&#x2F;&#x2F;wiki.xensource.com&#x2F;xenwiki&#x2F;XenNetworking&quot;&gt;networking page on the Xen wiki&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;ip&lt;&#x2F;strong&gt; - specify your virtual machine&#x27;s IP here.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;netmask&lt;&#x2F;strong&gt; and &lt;strong&gt;gateway&lt;&#x2F;strong&gt; - netmask and gateway that your virtual machine should use.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ul&gt;
&lt;li&gt;Now, start the base virtual machine:
&lt;pre&gt;&lt;code&gt;xm create &#x2F;etc&#x2F;xen&#x2F;vm_feisty_base.config.example.sxp -c&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;  You should see a console (the &#x27;-c&#x27; option connects you to the console immediately after booting up the virtual machine. Login as root (empty password) - you&#x27;ll want to change the password (with &#x27;passwd&#x27;).&lt;&#x2F;li&gt;
&lt;li&gt;Enable shadowed passwords.
&lt;pre&gt;&lt;code&gt;shadowconfig on&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Create a backup of &lt;code&gt;&#x2F;etc&#x2F;network&#x2F;interfaces&lt;&#x2F;code&gt; and edit &lt;code&gt;&#x2F;etc&#x2F;network&#x2F;interfaces&lt;&#x2F;code&gt; to put in correct values so you can access the Internet from the virtual machine:
&lt;pre&gt;&lt;code&gt;cp &#x2F;etc&#x2F;network&#x2F;interfaces &#x2F;etc&#x2F;network&#x2F;interfaces.bak
vim &#x2F;etc&#x2F;network&#x2F;interfaces&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Start networking:
&lt;pre&gt;&lt;code&gt;ifup -a&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Install the Ubuntu standard system after running an update:
&lt;pre&gt;&lt;code&gt;apt-get update
apt-get install ubuntu-standard&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;I also like to upgrade any packages that have been updated, if any:
&lt;pre&gt;&lt;code&gt;apt-get upgrade&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Install the OpenSSH server so that you can access the virtual machine via ssh:
&lt;pre&gt;&lt;code&gt;apt-get install ssh&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;At this point, do any configuration or installation of packages that you want this base image to have. Remember that we&#x27;re going to replicate this base image for future Xen virtual machines so &lt;strong&gt;don&#x27;t go overboard&lt;&#x2F;strong&gt; and install stuff you&#x27;re not gonna use.&lt;&#x2F;li&gt;
&lt;li&gt;Stop networking and put back the original &#x2F;etc&#x2F;network&#x2F;interfaces:
&lt;pre&gt;&lt;code&gt;ifdown -a
mv &#x2F;etc&#x2F;network&#x2F;interfaces.bak &#x2F;etc&#x2F;network&#x2F;interfaces&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Exit the guest console with &lt;code&gt;Ctrl-]&lt;&#x2F;code&gt;. This will bring you back to dom0&#x27;s shell.&lt;&#x2F;li&gt;
&lt;li&gt;Shutdown the base Xen domU (&lt;code&gt;-w&lt;&#x2F;code&gt; means &quot;wait for the domU to shutdown completely&quot;):
&lt;pre&gt;&lt;code&gt;xm shutdown feisty_base -w&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You&#x27;re done setting up the base image! Now you have a nicely configured base image.&lt;&#x2F;p&gt;
&lt;h3&gt;Creating your first virtual server&lt;&#x2F;h3&gt;
&lt;p&gt;The fruits of thy labor are almost at hand - with the base image, we can now make a copy of it for our first Xen virtual machine.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Make copies of the base image and the swap image (let&#x27;s call our virtual server &quot;yuki&quot;):
&lt;pre&gt;&lt;code&gt;cp &#x2F;xen-images&#x2F;feisty_base.img &#x2F;xen-images&#x2F;yuki.img
cp &#x2F;xen-images&#x2F;feisty_base_swap.img &#x2F;xen-images&#x2F;yuki_swap.img&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;  You may want to &lt;a href=&quot;#resizing&quot;&gt;resize the base image&lt;&#x2F;a&gt; depending on your disk space needs. (And, of course, you can create your own swap image like we did earlier instead of copying the base image&#x27;s swap file.)&lt;&#x2F;li&gt;
&lt;li&gt;Make a copy of the base Xen configuration file that we created for our base image earlier (you can use whatever name you like):
&lt;pre&gt;&lt;code&gt;cp &#x2F;etc&#x2F;xen&#x2F;vm_feisty_base.config.example.sxp &#x2F;etc&#x2F;xen&#x2F;vm_yuki.config.sxp&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Edit the &lt;code&gt;&#x2F;etc&#x2F;xen&#x2F;vm_yuki.config.sxp file&lt;&#x2F;code&gt;, changing the values to suit your virtual server (you probably want to change at least the &#x27;name&#x27;, &#x27;disk&#x27;, &#x27;ip, and &#x27;hostname&#x27; values).
&lt;pre&gt;&lt;code&gt;name = &quot;yuki&quot;
disk = [&#x27;file:&#x2F;xen-images&#x2F;yuki.img,hda1,w&#x27;,&#x27;file:&#x2F;xen-images&#x2F;yuki_swap.img,hda2,w&#x27;]
hostname = &quot;yuki&quot;
ip = &quot;192.168.0.202&quot;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Now start up your cloned virtual server and log into it like we did earlier with the base image (if you haven&#x27;t changed the password, you can login as root with an empty password).
&lt;pre&gt;&lt;code&gt;xm create -c &#x2F;etc&#x2F;xen&#x2F;vm_yuki.config.sxp&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;The first thing you should do is to secure your root password (if you haven&#x27;t done so in the base image earlier).
&lt;pre&gt;&lt;code&gt;passwd&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Now, you&#x27;ll want to change these files:
&lt;ul&gt;
&lt;li&gt;&#x2F;etc&#x2F;network&#x2F;interfaces&lt;&#x2F;li&gt;
&lt;li&gt;&#x2F;etc&#x2F;hostname&lt;&#x2F;li&gt;
&lt;li&gt;&#x2F;etc&#x2F;hosts&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;With the proper network settings, you should be able to bring up networking to connect to the internet (assuming that your dom0 is connected to the internet).
&lt;pre&gt;&lt;code&gt;ifup -a
ping google.com&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;At this point, you are free to customize your virtual machine as you see fit - install nginx for use as a static file server, Rails, MySQL server, whatever.&lt;&#x2F;li&gt;
&lt;li&gt;But first, let&#x27;s make sure this Xen virtual server starts up automatically on boot. Exit the virtual machine console with &lt;code&gt;Ctrl-]&lt;&#x2F;code&gt;
&lt;pre&gt;&lt;code&gt;ln -s &#x2F;etc&#x2F;xen&#x2F;vm_yuki.config.sxp &#x2F;etc&#x2F;xen&#x2F;auto&#x2F;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;  Any Xen domain configuration placed in &lt;code&gt;&#x2F;etc&#x2F;xen&#x2F;auto&#x2F;&lt;&#x2F;code&gt; will be started up automatically on boot (and shutdown when the host machine is shutdown too).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;That&#x27;s it!&lt;&#x2F;strong&gt; You have a functional Xen guest domain that starts up on boot and that can connect to the Internet. Oh before I forget, some useful commands when dealing with the Xen images:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;xm create &#x2F;path&#x2F;to&#x2F;config_file&lt;&#x2F;code&gt; - Starts up the guest domain with the given Xen domU configuration file. (&lt;code&gt;xm create -c&lt;&#x2F;code&gt; to login to the console immediately after booting the image.)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;xm console yuki&lt;&#x2F;code&gt; - Open the console for the &#x27;yuki&#x27; Xen domain.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;xm shutdown yuki&lt;&#x2F;code&gt; - Shutdown the &#x27;yuki&#x27; domU.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;xm list&lt;&#x2F;code&gt; - Lists all the Xen domains you have running.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;resizing&quot;&gt;Resizing your virtual machine disk&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s say you wanna add 1GB of disk space to your virtual machine (named &#x27;yuki&#x27;).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Note that LVM is usually recommended for Xen setups, so you may wanna take a look at that instead.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Create a temporary 1GB file:
&lt;pre&gt;&lt;code&gt;dd if=&#x2F;dev&#x2F;zero of=&#x2F;tmp&#x2F;temp_expand bs=1024k count=1000&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Bring down the virtual machine (I&#x27;ve found that a shutdown is needed so that the virtual machine recognizes the increased disk space):
&lt;pre&gt;&lt;code&gt;xm shutdown yuki&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Append&lt;&#x2F;strong&gt; the file to the disk image of the virtual machine (&#x2F;xen-images&#x2F;yuki.img in this example). &lt;strong&gt;Be sure to use &#x27;&amp;gt;&amp;gt;&#x27;&lt;&#x2F;strong&gt; (which means append) - using a single &#x27;&amp;gt;&#x27; would overwrite the disk image with your temporary file, which you most definitely don&#x27;t want!
&lt;pre&gt;&lt;code&gt;cat &#x2F;tmp&#x2F;temp_expand &gt;&gt; &#x2F;xen-images&#x2F;yuki.img&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Resize the file system:
&lt;pre&gt;&lt;code&gt;resize2fs -f &#x2F;xen-images&#x2F;yuki.img&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Startup the virtual machine again:
&lt;pre&gt;&lt;code&gt;xm create -c &#x2F;etc&#x2F;xen&#x2F;vm_yuki.config.sxp&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Remember to login to your virtual machine to verify that the disk space has increased (&lt;code&gt;df -h&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
  <entry>
    <title>Nginx, PHP and a PHP FastCGI daemon init script</title>
    <published>2007-06-11T21:18:32+00:00</published>
    <updated>2007-06-11T21:18:32+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/06/11/nginx-php-and-a-php-fastcgi-daemon-init-script/"/>
    <id>https://chuyeow.wtf/2007/06/11/nginx-php-and-a-php-fastcgi-daemon-init-script/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/06/11/nginx-php-and-a-php-fastcgi-daemon-init-script/">&lt;p&gt;One of the things us ex-Apache httpd or ex-Lighttpd users have to get used to when installing &lt;a href=&quot;http:&#x2F;&#x2F;nginx.net&#x2F;&quot;&gt;nginx&lt;&#x2F;a&gt; is how there isn&#x27;t built-in FastCGI support for process spawning. While these means nginx is more lightweight and faster, it does mean that you have to manage your FastCGI processes yourself.&lt;&#x2F;p&gt;
&lt;p&gt;Having just upgraded to Ubuntu Feisty Fawn, I set to installing nginx and tried to get WordPress (which needs PHP, of course) running on it. Thanks to the new nginx package in the Feisty universe repository, getting nginx up and PHP (CGI version) and running is really straightforward. There&#x27;re &lt;a href=&quot;http:&#x2F;&#x2F;blog.dominiek.com&#x2F;articles&#x2F;2007&#x2F;5&#x2F;18&#x2F;bye-redskin-zdravstvujte-redstar-nginx-tips&#x2F;&quot;&gt;lots&lt;&#x2F;a&gt; of &lt;a href=&quot;http:&#x2F;&#x2F;www.urbanpuddle.com&#x2F;articles&#x2F;2007&#x2F;05&#x2F;09&#x2F;install-ruby-on-rails-on-ubuntu-feisty-fawn&quot;&gt;tutorials&lt;&#x2F;a&gt; to help you out as well.&lt;&#x2F;p&gt;
&lt;p&gt;So that&#x27;s that. The part that bugged me though, was how the tutorials always provided a script to start your PHP FastCGI processes, but never provided a way to ensure your FastCGI processes started up on a reboot (i.e. an init script). Once again, Google doesn&#x27;t disappoint, turning up this &lt;a href=&quot;http:&#x2F;&#x2F;www.mail-archive.com&#x2F;debian-bugs-dist@lists.debian.org&#x2F;msg352883.html&quot;&gt;php-cgi init script&lt;&#x2F;a&gt;. Tweak the init script a little, put it in &#x2F;etc&#x2F;init.d&#x2F;php-fastcgi, &lt;code&gt;sudo chmod +x &#x2F;etc&#x2F;init.d&#x2F;php-fastcgi&lt;&#x2F;code&gt;, run &lt;code&gt;sudo update-rc.d php-fastcgi defaults&lt;&#x2F;code&gt; and place the configuration for the script in &#x2F;etc&#x2F;default&#x2F;php-fastcgi, and you&#x27;re done. You now have a PHP FastCGI init script that spawns and kills your PHP FastCGI processes.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; Lighttpd does come with a &lt;code&gt;spawn-fcgi&lt;&#x2F;code&gt; binary that does the same, but I&#x27;m having trouble finding a suitable init script for spawn-fcgi (only the Gentoo emerge seems to have the init script). Still, this script works and I didn&#x27;t really want to install lightty on my starving &lt;acronym title=&quot;Virtual Private Server&quot;&gt;VPS&lt;&#x2F;acronym&gt;.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;p&gt;&lt;strong&gt;The init script: &#x2F;etc&#x2F;init.d&#x2F;php-fastcgi&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;#! &#x2F;bin&#x2F;sh
### BEGIN INIT INFO
# Provides:          php-fastcgi
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start and stop php-cgi in external FASTCGI mode
# Description:       Start and stop php-cgi in external FASTCGI mode
### END INIT INFO
&lt;h1 id=&quot;author-kurt-zankl-email-protected&quot;&gt;Author: Kurt Zankl &amp;lt;[EMAIL PROTECTED]&amp;gt;&lt;&#x2F;h1&gt;
&lt;h1 id=&quot;do-not-set-e&quot;&gt;Do NOT &quot;set -e&quot;&lt;&#x2F;h1&gt;
&lt;p&gt;PATH=&#x2F;sbin:&#x2F;usr&#x2F;sbin:&#x2F;bin:&#x2F;usr&#x2F;bin
DESC=&quot;php-cgi in external FASTCGI mode&quot;
NAME=php-fastcgi
DAEMON=&#x2F;usr&#x2F;bin&#x2F;php-cgi
PIDFILE=&#x2F;var&#x2F;run&#x2F;$NAME.pid
SCRIPTNAME=&#x2F;etc&#x2F;init.d&#x2F;$NAME
PHP_CONFIG_FILE=&#x2F;etc&#x2F;php5&#x2F;cgi&#x2F;php.ini&lt;&#x2F;p&gt;
&lt;h1 id=&quot;exit-if-the-package-is-not-installed&quot;&gt;Exit if the package is not installed&lt;&#x2F;h1&gt;
&lt;p&gt;[ -x &quot;$DAEMON&quot; ] || exit 0&lt;&#x2F;p&gt;
&lt;h1 id=&quot;read-configuration-variable-file-if-it-is-present&quot;&gt;Read configuration variable file if it is present&lt;&#x2F;h1&gt;
&lt;p&gt;[ -r &#x2F;etc&#x2F;default&#x2F;$NAME ] &amp;amp;&amp;amp; . &#x2F;etc&#x2F;default&#x2F;$NAME&lt;&#x2F;p&gt;
&lt;h1 id=&quot;load-the-verbose-setting-and-other-rcs-variables&quot;&gt;Load the VERBOSE setting and other rcS variables&lt;&#x2F;h1&gt;
&lt;p&gt;. &#x2F;lib&#x2F;init&#x2F;vars.sh&lt;&#x2F;p&gt;
&lt;h1 id=&quot;define-lsb-log-functions&quot;&gt;Define LSB log_* functions.&lt;&#x2F;h1&gt;
&lt;h1 id=&quot;depend-on-lsb-base-3-0-6-to-ensure-that-this-file-is-present&quot;&gt;Depend on lsb-base (&amp;gt;= 3.0-6) to ensure that this file is present.&lt;&#x2F;h1&gt;
&lt;p&gt;. &#x2F;lib&#x2F;lsb&#x2F;init-functions&lt;&#x2F;p&gt;
&lt;h1 id=&quot;if-the-daemon-is-not-enabled-give-the-user-a-warning-and-then-exit&quot;&gt;If the daemon is not enabled, give the user a warning and then exit,&lt;&#x2F;h1&gt;
&lt;h1 id=&quot;unless-we-are-stopping-the-daemon&quot;&gt;unless we are stopping the daemon&lt;&#x2F;h1&gt;
&lt;p&gt;if [ &quot;$START&quot; != &quot;yes&quot; -a &quot;$1&quot; != &quot;stop&quot; ]; then
log_warning_msg &quot;To enable $NAME, edit &#x2F;etc&#x2F;default&#x2F;$NAME and set START=yes&quot;
exit 0
fi&lt;&#x2F;p&gt;
&lt;h1 id=&quot;process-configuration&quot;&gt;Process configuration&lt;&#x2F;h1&gt;
&lt;p&gt;export PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS
DAEMON_ARGS=&quot;-q -b $FCGI_HOST:$FCGI_PORT -c $PHP_CONFIG_FILE&quot;&lt;&#x2F;p&gt;
&lt;p&gt;do_start()
{
# Return
#   0 if daemon has been started
#   1 if daemon was already running
#   2 if daemon could not be started
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test &amp;gt; &#x2F;dev&#x2F;null &lt;br &#x2F;&gt;
|| return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON &lt;br &#x2F;&gt;
--background --make-pidfile --chuid $EXEC_AS_USER --startas $DAEMON -- &lt;br &#x2F;&gt;
$DAEMON_ARGS &lt;br &#x2F;&gt;
|| return 2
}&lt;&#x2F;p&gt;
&lt;p&gt;do_stop()
{
# Return
#   0 if daemon has been stopped
#   1 if daemon was already stopped
#   2 if daemon could not be stopped
#   other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM&#x2F;30&#x2F;KILL&#x2F;5 --pidfile $PIDFILE &amp;gt; &#x2F;dev&#x2F;null # --name $DAEMON
RETVAL=&quot;$?&quot;
[ &quot;$RETVAL&quot; = 2 ] &amp;amp;&amp;amp; return 2
# Wait for children to finish too if this is a daemon that forks
# and if the daemon is only ever run from this initscript.
# If the above conditions are not satisfied then add some other code
# that waits for the process to drop all resources that could be
# needed by services started subsequently.  A last resort is to
# sleep for some time.
start-stop-daemon --stop --quiet --oknodo --retry=0&#x2F;30&#x2F;KILL&#x2F;5 --exec $DAEMON
[ &quot;$?&quot; = 2 ] &amp;amp;&amp;amp; return 2
# Many daemons don&#x27;t delete their pidfiles when they exit.
rm -f $PIDFILE
return &quot;$RETVAL&quot;
}
case &quot;$1&quot; in
start)
[ &quot;$VERBOSE&quot; != no ] &amp;amp;&amp;amp; log_daemon_msg &quot;Starting $DESC&quot; &quot;$NAME&quot;
do_start
case &quot;$?&quot; in
0|1) [ &quot;$VERBOSE&quot; != no ] &amp;amp;&amp;amp; log_end_msg 0 ;;
2) [ &quot;$VERBOSE&quot; != no ] &amp;amp;&amp;amp; log_end_msg 1 ;;
esac
;;
stop)
[ &quot;$VERBOSE&quot; != no ] &amp;amp;&amp;amp; log_daemon_msg &quot;Stopping $DESC&quot; &quot;$NAME&quot;
do_stop
case &quot;$?&quot; in
0|1) [ &quot;$VERBOSE&quot; != no ] &amp;amp;&amp;amp; log_end_msg 0 ;;
2) [ &quot;$VERBOSE&quot; != no ] &amp;amp;&amp;amp; log_end_msg 1 ;;
esac
;;
restart|force-reload)
log_daemon_msg &quot;Restarting $DESC&quot; &quot;$NAME&quot;
do_stop
case &quot;$?&quot; in
0|1)
do_start
case &quot;$?&quot; in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
echo &quot;Usage: $SCRIPTNAME {start|stop|restart|force-reload}&quot; &amp;gt;&amp;amp;2
exit 3
;;
esac&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Config file for init script (the init script looks for this): &#x2F;etc&#x2F;default&#x2F;php-fastcgi&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;START=yes
&lt;h1 id=&quot;which-user-runs-php-default-www-data&quot;&gt;Which user runs PHP? (default: www-data)&lt;&#x2F;h1&gt;
&lt;p&gt;EXEC_AS_USER=www-data&lt;&#x2F;p&gt;
&lt;h1 id=&quot;host-and-tcp-port-for-fastcgi-listener-default-localhost-9000&quot;&gt;Host and TCP port for FASTCGI-Listener (default: localhost:9000)&lt;&#x2F;h1&gt;
&lt;p&gt;FCGI_HOST=localhost
FCGI_PORT=9000&lt;&#x2F;p&gt;
&lt;h1 id=&quot;environment-variables-which-are-processed-by-php&quot;&gt;Environment variables, which are processed by PHP&lt;&#x2F;h1&gt;
&lt;p&gt;PHP_FCGI_CHILDREN=4
PHP_FCGI_MAX_REQUESTS=1000&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;nginx config file: &#x2F;etc&#x2F;nginx&#x2F;nginx.conf&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;location ~ \.php$ {
  fastcgi_pass   127.0.0.1:9000;
  fastcgi_index  index.php;
  fastcgi_param  SCRIPT_FILENAME  &#x2F;var&#x2F;www&#x2F;chuyeow.wtf$fastcgi_script_name;
  include        &#x2F;etc&#x2F;nginx&#x2F;fastcgi.conf;
}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;My fastcgi.conf file (I&#x27;m not sure I need everything here...)&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;
&lt;p&gt;fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;&lt;&#x2F;p&gt;
&lt;p&gt;fastcgi_param  GATEWAY_INTERFACE  CGI&#x2F;1.1;
fastcgi_param  SERVER_SOFTWARE    nginx;&lt;&#x2F;p&gt;
&lt;p&gt;fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;php-only-required-if-php-was-built-with-enable-force-cgi-redirect&quot;&gt;PHP only, required if PHP was built with --enable-force-cgi-redirect&lt;&#x2F;h1&gt;
&lt;p&gt;fastcgi_param  REDIRECT_STATUS    200;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Toilets and Linux evangelism</title>
    <published>2007-06-05T14:44:54+00:00</published>
    <updated>2007-06-05T14:44:54+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/06/05/toilets-and-linux-evangelism/"/>
    <id>https://chuyeow.wtf/2007/06/05/toilets-and-linux-evangelism/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/06/05/toilets-and-linux-evangelism/">&lt;p&gt;Pardon the self-promoting cross-linking: &lt;a href=&quot;http:&#x2F;&#x2F;blog.bezurk.com&#x2F;2007&#x2F;06&#x2F;05&#x2F;toilets-and-linux-evangelism-or-what-we-use-to-build-bezurk&#x2F;&quot;&gt;Toilets and Linux evangelism (or what we use to build Bezurk)&lt;&#x2F;a&gt; is an entry I just posted on the brand new &lt;a href=&quot;http:&#x2F;&#x2F;blog.bezurk.com&#x2F;&quot;&gt;Bezurk Blog&lt;&#x2F;a&gt; about how the toilet is a good place to spread the word. &lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;ve found other neat ways to use the free Ubuntu stickers (or even the Apple stickers that comes with iPods), do post it!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>ImageMagick port &quot;broken&quot; temporarily</title>
    <published>2007-05-29T19:15:50+00:00</published>
    <updated>2007-05-29T19:15:50+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/05/29/imagemagick-port-broken-temporarily/"/>
    <id>https://chuyeow.wtf/2007/05/29/imagemagick-port-broken-temporarily/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/05/29/imagemagick-port-broken-temporarily/">&lt;p&gt;Just in case anyone runs into this problem (which, I might add, would probably go away when either the portfile is updated or the source mirror fixes the problem) while installing &lt;a href=&quot;http:&#x2F;&#x2F;www.imagemagick.org&#x2F;&quot;&gt;ImageMagick&lt;&#x2F;a&gt; via &lt;a href=&quot;http:&#x2F;&#x2F;www.macports.org&#x2F;&quot;&gt;MacPorts&lt;&#x2F;a&gt;...&lt;&#x2F;p&gt;
&lt;p&gt;While trying to install &lt;a href=&quot;http:&#x2F;&#x2F;rmagick.rubyforge.org&#x2F;&quot;&gt;Rmagick&lt;&#x2F;a&gt; on my spanking, new, glossy, kakkoii &lt;a href=&quot;http:&#x2F;&#x2F;www.apple.com&#x2F;macbook&#x2F;macbook.html&quot;&gt;MacBook&lt;&#x2F;a&gt;, MacPorts reported a checksum error with the ImageMagick source tarball:&lt;&#x2F;p&gt;
&lt;blockquote&gt;&lt;p&gt;Target com.apple.checksum returned: Unable to verify file checksums&lt;&#x2F;p&gt;&lt;&#x2F;blockquote&gt;
&lt;p&gt;At first, I thought it was an outdated portfile but even after a &lt;code&gt;sudo port selfupdate&lt;&#x2F;code&gt; and &lt;code&gt;sudo port -d sync&lt;&#x2F;code&gt;, the checksum error was still occurring (checksum of the file: 4bcb4264c2170fe562b10a732f43e7af, expected checksum in the portfile: 9469ce1b1b645f8c728158cc434b0ff8).&lt;&#x2F;p&gt;
&lt;p&gt;Turns out, the first listed master site (where MacPorts gets its source files from), http:&#x2F;&#x2F;imagemagick.linux-mirror.org&#x2F;download&#x2F; is hosting a source tarball with a bad checksum. Digging around the man page for &lt;code&gt;port&lt;&#x2F;code&gt; a bit, and switching the order of the master source sites solved it, so it was just a case of a bad file on one of the mirror sites.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;sudo port edit imagemagick&lt;&#x2F;code&gt; to edit the portfile and change the source mirror to a legit one. You should see something like this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;master_sites \
  http:&#x2F;&#x2F;imagemagick.linux-mirror.org&#x2F;download&#x2F; \
  http:&#x2F;&#x2F;ftp.surfnet.nl&#x2F;pub&#x2F;ImageMagick&#x2F; \
  sourceforge:imagemagick \
  ftp:&#x2F;&#x2F;ftp.imagemagick.net&#x2F;pub&#x2F;${name}&#x2F; \
  ftp:&#x2F;&#x2F;ftp.fifi.org&#x2F;pub&#x2F;ImageMagick&#x2F; \
  ftp:&#x2F;&#x2F;ftp.nluug.nl&#x2F;pub&#x2F;${name}&#x2F;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Just move an alternative master_site to the top of the list (I used the SourceForge one). There probably is a way to specify the master_site on the command line with &lt;code&gt;port install&lt;&#x2F;code&gt; but I&#x27;ve had just about enough of reading man pages and the now nearly unfindable MacPorts documentation (whatever happened to the &lt;a href=&quot;http:&#x2F;&#x2F;darwinports.com&#x2F;&quot;&gt;old Darwin Ports site&lt;&#x2F;a&gt; that had great documentation?)&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, I&#x27;ve written to the webmaster of the mirror site linux-mirror.org, so this would probably be fixed for all two of you who are gonna be installing ImageMagick via MacPorts within these few days or so. Still, it was a good exercise in debugging bad port installations.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Axel - lightweight command line download accelerator</title>
    <published>2007-04-29T16:50:09+00:00</published>
    <updated>2007-04-29T16:50:09+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/04/29/axel-lightweight-command-line-download-accelerator/"/>
    <id>https://chuyeow.wtf/2007/04/29/axel-lightweight-command-line-download-accelerator/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/04/29/axel-lightweight-command-line-download-accelerator/">&lt;p&gt;I never really fancied download accelerators but &lt;a href=&quot;http:&#x2F;&#x2F;wilmer.gaast.net&#x2F;main.php&#x2F;axel.html&quot;&gt;Axel&lt;&#x2F;a&gt; is different - it&#x27;s a command line application and is naturally significantly more lightweight then those graphical download managers I&#x27;ve stopped using since 1996 (&lt;em&gt;teh intraweb&lt;&#x2F;em&gt; was slower then, and I was sucking bits of it through a state of the art 33.6kbps dial-up modem).&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve been using &lt;code&gt;wget&lt;&#x2F;code&gt; for its auto-resume support, but have switched to using Axel since one of my colleagues at &lt;a href=&quot;http:&#x2F;&#x2F;bezurk.com&#x2F;&quot;&gt;Bezurk&lt;&#x2F;a&gt; introduced me to it. If you&#x27;re a &lt;code&gt;wget&lt;&#x2F;code&gt; or &lt;code&gt;curl&lt;&#x2F;code&gt; fan, Axel is almost a drop-in replacement (although it doesn&#x27;t handle multiple redirects or broken connections too well).&lt;&#x2F;p&gt;
&lt;p&gt;Install it:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
# On a Mac, with Darwin Ports.
sudo port install axel
&lt;h1 id=&quot;on-ubuntu&quot;&gt;On Ubuntu.&lt;&#x2F;h1&gt;
&lt;p&gt;sudo apt-get install axel
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Windows users would require &lt;a href=&quot;http:&#x2F;&#x2F;sources.redhat.com&#x2F;cygwin&#x2F;&quot;&gt;cygwin&lt;&#x2F;a&gt; to get Axel to work for them (what, a Windows user and you don&#x27;t have cygwin installed already?).&lt;&#x2F;p&gt;
&lt;p&gt;Now go download some files. If you need a good place just to test the speeds, go to &lt;a href=&quot;http:&#x2F;&#x2F;developer.yahoo.com&#x2F;yui&#x2F;theater&#x2F;&quot;&gt;YUI Theater&lt;&#x2F;a&gt; and download some videos (watch them too, most of them are pretty good, like Douglas Crockford&#x27;s and the Firebug videos). Run it on the command line by typing:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;axel -n 10 http:&#x2F;&#x2F;example.com&#x2F;some_file.mov&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;-n 10&lt;&#x2F;code&gt; option tells Axel to use a maximum of 10 simultaneous connections when downloading the file. Another useful option is &lt;code&gt;-a&lt;&#x2F;code&gt;, which outputs a &lt;code&gt;wget&lt;&#x2F;code&gt;-like report of download progress in a few lines rather than filling up your screen with download progress messages.&lt;&#x2F;p&gt;
&lt;p&gt;Check out the speeds I managed to get:&lt;&#x2F;p&gt;
&lt;div class=&quot;img&quot;&gt;&lt;img src=&quot;&#x2F;assets&#x2F;axel-super-download-speed.jpg&quot; alt=&quot;Check out the 1MB+&#x2F;s download speed with Axel&quot; &#x2F;&gt;&lt;&#x2F;div&gt;
&lt;p&gt;&lt;br style=&quot;clear: both;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;250MB in 3 minutes, with an average download speed of 1339KB&#x2F;s. That&#x27;s pretty damn fast. Comparatively, I could only get speeds of around 40KB&#x2F;s using Firefox. It&#x27;s hard not to love this raw speed and I think you might too.&lt;&#x2F;p&gt;
&lt;p&gt;Oh, and to go off-topic here, it&#x27;s nice to know we are steadily chipping away at the Windows user base in &lt;a href=&quot;http:&#x2F;&#x2F;bezurk.com&#x2F;&quot;&gt;Bezurk&lt;&#x2F;a&gt;. The colleague who introduced me to Axel recently switched to Ubuntu (he&#x27;s been waiting for Ubuntu 7.04). It was painful to set it up correctly (the KDE part of Kubuntu, not Ubuntu itself), but I think he&#x27;s much happier working on Linux for some inexplicable reason.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Setting up svnsync-ed (mirrored) SVN repositories on Ubuntu (part 2 of 2)</title>
    <published>2007-03-31T23:12:31+00:00</published>
    <updated>2007-03-31T23:12:31+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/03/31/setting-up-svnsync-ed-mirrored-svn-repositories-on-ubuntu-part-2-of-2/"/>
    <id>https://chuyeow.wtf/2007/03/31/setting-up-svnsync-ed-mirrored-svn-repositories-on-ubuntu-part-2-of-2/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/03/31/setting-up-svnsync-ed-mirrored-svn-repositories-on-ubuntu-part-2-of-2/">&lt;p&gt;&lt;ins&gt;Note: if you haven&#x27;t already, you may want to read &lt;a href=&quot;&#x2F;2007&#x2F;03&#x2F;29&#x2F;setting-up-svnsync-ed-mirrored-svn-repositories-on-ubuntu-part-1-of-2&#x2F;&quot;&gt;part 1 of this article&lt;&#x2F;a&gt; first.&lt;&#x2F;ins&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Phew, and that was all the work you needed to do to migrate your Subversion repository to another server. We&#x27;ve barely touched that other server that we wanted to use for mirroring the repository!&lt;&#x2F;p&gt;
&lt;h3&gt;&quot;Bootstrapping&quot; your mirror SVN server for svnsync&lt;&#x2F;h3&gt;
&lt;p&gt;This mirror SVN server also needs Subversion 1.4.x installed, so go ahead and do the (almost) same things we&#x27;ve done in &lt;a href=&quot;&#x2F;2007&#x2F;03&#x2F;29&#x2F;setting-up-svnsync-ed-mirrored-svn-repositories-on-ubuntu-part-1-of-2&#x2F;&quot;&gt;part 1&lt;&#x2F;a&gt; to get Subversion installed. You should be able to use the &lt;code&gt;.deb&lt;&#x2F;code&gt; package generated by &lt;code&gt;checkinstall&lt;&#x2F;code&gt; on your main Subversion server to install Subversion 1.4.x on the mirror SVN server. Just scp it to the mirror SVN server and install it (&lt;code&gt;dpkg -i subversion-1.4.3.deb&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;With Subversion installed, create a new Subversion repository (using &lt;code&gt;svnadmin create&lt;&#x2F;code&gt;, remember?), but &lt;em&gt;don&#x27;t&lt;&#x2F;em&gt; load the repository dump like we did on the main SVN server in &lt;a href=&quot;&#x2F;2007&#x2F;03&#x2F;29&#x2F;setting-up-svnsync-ed-mirrored-svn-repositories-on-ubuntu-part-1-of-2&#x2F;&quot;&gt;part 1&lt;&#x2F;a&gt; (of course, since we are going to be mirroring the repository!).&lt;&#x2F;p&gt;
&lt;h3&gt;Setting up svnsync to mirror your repository&lt;&#x2F;h3&gt;
&lt;p&gt;First, create a SVN user for svnsync to use - let&#x27;s call this the &#x27;svnsync user&#x27;. The easiest (and best) way to do this is edit the svnserve.conf and passwd files:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;conf&#x2F;svnserve.conf&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
# Uncomment this line.
password-db = passwd
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;conf&#x2F;passwd&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
svnsync = secret
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This gives read and write access to the &#x27;svnsync user&#x27;. The &lt;code&gt;svnsync&lt;&#x2F;code&gt; program will authenticate with our repositories as this user via the &lt;code&gt;svn:&#x2F;&#x2F;&lt;&#x2F;code&gt; protocol (i.e. via svnserve).&lt;&#x2F;p&gt;
&lt;p&gt;Next, we need to create a &lt;code&gt;pre-revprop-change&lt;&#x2F;code&gt; hook for the destination repository. The &lt;a href=&quot;http:&#x2F;&#x2F;svn.collab.net&#x2F;repos&#x2F;svn&#x2F;trunk&#x2F;notes&#x2F;svnsync.txt&quot;&gt;svnsync documentation&lt;&#x2F;a&gt; has a detailed explanation. Create a &lt;code&gt;hooks&#x2F;pre-revprop-change&lt;&#x2F;code&gt; file under your destination repository&#x27;s directory.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
#!&#x2F;bin&#x2F;sh
USER=&quot;$3&quot;
&lt;p&gt;if [ &quot;$USER&quot; = &quot;svnsync&quot; ]; then exit 0; fi&lt;&#x2F;p&gt;
&lt;p&gt;echo &quot;Only the svnsync user can change revprops&quot; &amp;gt;&amp;amp;2
exit 1&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Make it executable, and then initialize the sync:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
chmod +x hooks&#x2F;pre-revprop-change
svnsync init file:&#x2F;&#x2F;&#x2F;var&#x2F;svn&#x2F;repositories&#x2F;destination_repos svn:&#x2F;&#x2F;source.host&#x2F;source_repos&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Don&#x27;t worry, this only sets up the sync - there&#x27;s no actual data copying yet. Syncing your repository data may take a long time if you have a big source repository, so I suggest using &lt;code&gt;nohup&lt;&#x2F;code&gt; to run the code overnight (or something), or at least saving the output in a log. Either way, the command to start the sync is:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;svnsync sync --username svnsync file:&#x2F;&#x2F;&#x2F;var&#x2F;svn&#x2F;repositories&#x2F;testsync&#x2F;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You should start seeing svnsync committing in changes from your source repository. Instant gratification (well, almost)! Should your svnsync process get aborted or killed, you can remove the hanging lock by running:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;svn propdel svn:sync-lock --revprop -r 0&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3&gt;Setting up &#x27;on-the-fly&#x27; syncing&lt;&#x2F;h3&gt;
&lt;p&gt;So now you have your source and destination repositories synced, but what happens when you start committing changes to your source repository? Nothing! That&#x27;s because svnsync is merely a passive syncing tool (meaning you have to run it to sync, instead of it knowing when to sync automatically).&lt;&#x2F;p&gt;
&lt;p&gt;There are two ways you can setup &#x27;real-time&#x27; syncing:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
    Use &lt;code&gt;cron&lt;&#x2F;code&gt; (or a similar scheduler) on the destination repository server. Add something like this to your &lt;code&gt;crontab&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;* * * * * &#x2F;usr&#x2F;local&#x2F;bin&#x2F;svnsync --non-interactive sync svn:&#x2F;&#x2F;source.host&#x2F;source_repos&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;    This basically runs svnsync on your destination repository server every minute to pull down any changes to your source repository.
  &lt;&#x2F;li&gt;
&lt;li&gt;Add a post-commit hook to the source repository. I found this &lt;a href=&quot;http:&#x2F;&#x2F;journal.paul.querna.org&#x2F;articles&#x2F;2006&#x2F;09&#x2F;14&#x2F;using-svnsync&quot;&gt;svnsync entry by Paul Querna&lt;&#x2F;a&gt; that has a sample post-commit hook. If I recall correctly I tried it but it didn&#x27;t work for me, so I settled on using cron to sync up my repositories.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3&gt;Things that I skipped&lt;&#x2F;h3&gt;
&lt;p&gt;There&#x27;re some things that I skipped over while writing this, mainly to do with SVN authentication.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
    If you&#x27;re accessing your repository via the &lt;code&gt;svn+ssh:&#x2F;&#x2F;&lt;&#x2F;code&gt; protocol, you&#x27;ve to manage the (group) permissions of the repository files in the filesystem appropriately (basically the repository should be group writable by your users). &lt;code&gt;chmod&lt;&#x2F;code&gt; and &lt;code&gt;chown&lt;&#x2F;code&gt; are your friends, as is &lt;acronym title=&quot;Network Information Service&quot;&gt;NIS&lt;&#x2F;acronym&gt; (or something similar) to manage your users. I use these steps to create a new SVN repository that gets access via the &lt;code&gt;svn+ssh:&#x2F;&#x2F;&lt;&#x2F;code&gt; protocol:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
sudo mkdir &#x2F;var&#x2F;svn&#x2F;repositories&#x2F;funky_project
mkdir &#x2F;tmp&#x2F;funky_project
mkdir &#x2F;tmp&#x2F;funky_project&#x2F;trunk
mkdir &#x2F;tmp&#x2F;funky_project&#x2F;branches
mkdir &#x2F;tmp&#x2F;funky_project&#x2F;tags
sudo svnadmin create &#x2F;var&#x2F;svn&#x2F;repositories&#x2F;funky_project
sudo svn import &#x2F;tmp&#x2F;YourProjectNameHere file:&#x2F;&#x2F;&#x2F;&#x2F;var&#x2F;svn&#x2F;repositories&#x2F;funky_project -m &quot;Initial import.&quot;
rm -rf &#x2F;tmp&#x2F;funky_project
sudo chown -R www-data:www-data &#x2F;var&#x2F;svn&#x2F;repositories&#x2F;funky_project
sudo chmod -R g+w &#x2F;var&#x2F;svn&#x2F;repositories&#x2F;funky_project
    &lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;    As you can see, my SVN users are part of the www-data group, and the repository directory is made group-writable.
  &lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;svn:&#x2F;&#x2F;&lt;&#x2F;code&gt; protocol has authentication configuration files in the &lt;code&gt;conf&#x2F;&lt;&#x2F;code&gt; directory of your repository. The SVN book has a &lt;a href=&quot;http:&#x2F;&#x2F;svnbook.red-bean.com&#x2F;nightly&#x2F;en&#x2F;svn.serverconfig.svnserve.html#svn.serverconfig.svnserve.auth&quot;&gt;section explaining how to configure authentication&lt;&#x2F;a&gt; for &lt;code&gt;svnserve&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Apache httpd can be used to expose your SVN repositories via the WebDAV protocol. This allows for the very commonly seen &lt;code&gt;http:&#x2F;&#x2F;&lt;&#x2F;code&gt; repository URLs (especially for Open Source projects). Configuration is a little more involved and you would probably have to install Apache from source as well. The SVN book has &lt;a href=&quot;http:&#x2F;&#x2F;svnbook.red-bean.com&#x2F;nightly&#x2F;en&#x2F;svn.serverconfig.httpd.html&quot;&gt;the details&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3&gt;Wrapping up&lt;&#x2F;h3&gt;
&lt;p&gt;I hope someone found this entry useful - I know I could have used one when I was setting up Subversion and svnsync.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Setting up svnsync-ed (mirrored) SVN repositories on Ubuntu (part 1 of 2)</title>
    <published>2007-03-29T01:34:36+00:00</published>
    <updated>2007-03-29T01:34:36+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2007/03/29/setting-up-svnsync-ed-mirrored-svn-repositories-on-ubuntu-part-1-of-2/"/>
    <id>https://chuyeow.wtf/2007/03/29/setting-up-svnsync-ed-mirrored-svn-repositories-on-ubuntu-part-1-of-2/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2007/03/29/setting-up-svnsync-ed-mirrored-svn-repositories-on-ubuntu-part-1-of-2/">&lt;p&gt;This is a 2-part journal on setting up migrating and upgrading a Subversion repository, and then using svnsync to mirror the newly created repository. (&lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;03&#x2F;31&#x2F;setting-up-svnsync-ed-mirrored-svn-repositories-on-ubuntu-part-2-of-2&#x2F;&quot;&gt;Part 2&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;h3&gt;Initial setup&lt;&#x2F;h3&gt;
&lt;p&gt;Ever since &lt;a href=&quot;http:&#x2F;&#x2F;subversion.tigris.org&#x2F;&quot;&gt;Subversion&lt;&#x2F;a&gt; 1.4 was &lt;a href=&quot;http:&#x2F;&#x2F;subversion.tigris.org&#x2F;svn_1.4_releasenotes.html&quot;&gt;released&lt;&#x2F;a&gt;, I&#x27;d been eying the new &lt;a href=&quot;http:&#x2F;&#x2F;svn.collab.net&#x2F;repos&#x2F;svn&#x2F;trunk&#x2F;notes&#x2F;svnsync.txt&quot;&gt;svnsync&lt;&#x2F;a&gt; tool because we had a single repository that was not, erm, &lt;em&gt;really&lt;&#x2F;em&gt; backed up (we had daily server backups and occasional manual repository dumps but that was it). svnsync promised to make repository mirroring simple, and after doing some repository migration and upgrading, I can assure you it really does make things easier than any other (more manual) repository backup solutions I had seen before. This is a walkthrough of how you can upgrade your pre-1.4 &lt;acronym title=&quot;Subversion&quot;&gt;SVN&lt;&#x2F;acronym&gt; repositories to 1.4.x, and setup svnsync to mirror your repositories. It&#x27;s going to be very biased to Ubuntu but I&#x27;m sure you can translate any Ubuntu specific steps to your favorite distros.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s our initial setup:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A pre-1.4 (it was version 1.2.3) SVN repository that needed to be upgraded &lt;em&gt;and&lt;&#x2F;em&gt; migrated to another server.&lt;&#x2F;li&gt;
&lt;li&gt;2 cleanly installed Ubuntu 6.06 &lt;acronym title=&quot;Long Term Support&quot;&gt;LTS&lt;&#x2F;acronym&gt; &lt;acronym title=&quot;Virtual Private Servers&quot;&gt;VPSs&lt;&#x2F;acronym&gt;, one of which is the intended target for the repository migration. The other would mirror the new 1.4.x repository (using svnsync).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3&gt;An un-installable Subversion 1.4.x?&lt;&#x2F;h3&gt;
&lt;p&gt;I wish I could have simply ran &lt;code&gt;sudo apt-get install subversion&lt;&#x2F;code&gt; and have Ubuntu pull down the latest 1.4.x .debs. Unfortunately, the version of Subversion in the Ubuntu apt-get repository is still 1.3.1 (which doesn&#x27;t have svnsync). If anyone knows a reliable way to install Subversion 1.4.x via apt-get, let me know! I looked around for a good edge sources.list but came back empty-handed.&lt;&#x2F;p&gt;
&lt;p&gt;I balk at installing stuff from source because I never did figure out how to easily clean out the stuff that gets installed. All thanks to this reluctance, I went digging around and found &lt;a href=&quot;http:&#x2F;&#x2F;asic-linux.com.mx&#x2F;~izto&#x2F;checkinstall&#x2F;&quot;&gt;checkinstall&lt;&#x2F;a&gt;. This thing is &lt;strong&gt;awesome&lt;&#x2F;strong&gt; - I wonder why I didn&#x27;t manage to find it earlier.&lt;&#x2F;p&gt;
&lt;p&gt;What &lt;code&gt;checkinstall&lt;&#x2F;code&gt; basically allows you to do is, instead of running the usual &lt;code&gt;make install&lt;&#x2F;code&gt; after the usual &lt;code&gt;configure&lt;&#x2F;code&gt; and &lt;code&gt;make&lt;&#x2F;code&gt; steps, it creates a Debian package (it also does RPMs and Slackware packages) for you that is easily un-installable with &lt;code&gt;dpkg&lt;&#x2F;code&gt;, and then proceeds to install the files just as it would have for any other deb.&lt;&#x2F;p&gt;
&lt;p&gt;On Ubuntu it&#x27;s really easy to install &lt;a href=&quot;http:&#x2F;&#x2F;asic-linux.com.mx&#x2F;~izto&#x2F;checkinstall&#x2F;&quot;&gt;checkinstall&lt;&#x2F;a&gt;, just:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install checkinstall&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, you no longer should type &#x27;make install&#x27; - always use the &#x27;checkinstall&#x27; command instead:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
.&#x2F;configure
make
sudo checkinstall # instead of &quot;make install&quot;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;checkinstall&lt;&#x2F;code&gt; will ask you a bunch of stuff but you can just go with the defaults for most of them - I did name my packages &#x27;XXX &lt;strong&gt;from source&lt;&#x2F;strong&gt;&#x27;, like &#x27;Subversion 1.4.3 from source&#x27; so it&#x27;s easier to check which packages are &lt;code&gt;checkinstall&lt;&#x2F;code&gt;-generated with a simple grep to &lt;code&gt;dpkg -l&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;checkinstall&lt;&#x2F;code&gt; generates a .deb (Debian) package before it actually installs your software (Subversion, in this case). It should tell you right at the end of its installation process about where to find this .deb and how to uninstall your newly installed (from source!) package (something like &lt;code&gt;dpkg -r subversion-1.4.3&lt;&#x2F;code&gt;). Don&#x27;t delete this .deb yet as we will be using it to install Subversion 1.4.x on our mirror SVN server.&lt;&#x2F;p&gt;
&lt;h3&gt;Installing an un-installable Subversion 1.4.x on Ubuntu&lt;&#x2F;h3&gt;
&lt;p&gt;Now, blessed with our new checkinstall-granted powers, we can install Subversion from source without any qualms. Before we start, be sure to purge any existing Subversion packages you may have installed (do note that if you&#x27;re using any packages that depend on the official Ubuntu Subversion packages, you may run into library version problems).&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
dpkg -l | grep svn
dpkg -l | grep subversion
&lt;p&gt;sudo dpkg --purge subversion
sudo dpkg --purge libsvn0&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now, it&#x27;s time to get the source. Get it from the &lt;a href=&quot;http:&#x2F;&#x2F;subversion.tigris.org&#x2F;&quot;&gt;official Subversion website&lt;&#x2F;a&gt;. Look for the source code download - the file should be something like this: &lt;a href=&quot;http:&#x2F;&#x2F;subversion.tigris.org&#x2F;downloads&#x2F;subversion-1.4.3.tar.gz&quot;&gt;http:&#x2F;&#x2F;subversion.tigris.org&#x2F;downloads&#x2F;subversion-1.4.3.tar.gz&lt;&#x2F;a&gt;. Remember to get SVN dependencies (something like this: &lt;a href=&quot;http:&#x2F;&#x2F;subversion.tigris.org&#x2F;downloads&#x2F;subversion-deps-1.4.3.tar.gz&quot;&gt;http:&#x2F;&#x2F;subversion.tigris.org&#x2F;downloads&#x2F;subversion-deps-1.4.3.tar.gz&lt;&#x2F;a&gt;) as well as these are needed for access to &#x27;http:&#x2F;&#x2F;&#x27; scheme SVN repositories. If you want to use Subversion to connect to a server via a http:&#x2F;&#x2F; or https:&#x2F;&#x2F; URL, you will require these dependencies (more specifically, the Neon library).&lt;&#x2F;p&gt;
&lt;p&gt;Use something efficient like wget, curl or &lt;a href=&quot;http:&#x2F;&#x2F;wilmer.gaast.net&#x2F;main.php&#x2F;axel.html&quot;&gt;Axel&lt;&#x2F;a&gt; (&lt;em&gt;love&lt;&#x2F;em&gt; Axel) to get the sources on the server where you want to install Subversion. Unpack them to the same directory. configure. make. &lt;strong&gt;checkinstall&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
tar zxf subversion-1.4.3.tar.gz
tar zxf subversion-deps-1.4.3.tar.gz 
cd subversion-1.4.3
.&#x2F;configure  # Be sure to read the INSTALL file for any options you may want to set (such as SSL)
make
sudo checkinstall&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you get a warning &quot;configure: WARNING: we have configured without BDB filesystem support&quot; during your &lt;code&gt;configure&lt;&#x2F;code&gt; step, you&#x27;ll get by just fine. Unless you specifically want your Subversion repositories in Berkeley DB format, we can ignore the warning (Subversion will use FSFS filesystem for your repositories) - see &lt;a href=&quot;http:&#x2F;&#x2F;svn.collab.net&#x2F;repos&#x2F;svn&#x2F;trunk&#x2F;notes&#x2F;fsfs&quot;&gt;FSFS notes&lt;&#x2F;a&gt; and &lt;a href=&quot;http:&#x2F;&#x2F;svnbook.red-bean.com&#x2F;nightly&#x2F;en&#x2F;svn.reposadmin.planning.html#svn.reposadmin.basics.backends&quot;&gt;Choosing a Data Store&lt;&#x2F;a&gt; if you want to make an educated decision.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, now with a brand new Subversion 1.4.x installed, we are finally ready for the real work - migrating your Subversion repository!&lt;&#x2F;p&gt;
&lt;h3&gt;Dumping and importing a repository&lt;&#x2F;h3&gt;
&lt;p&gt;Dumping a Subversion repository is dead easy:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
svnadmin dump &#x2F;path&#x2F;to&#x2F;repository &gt; repository_name.dump&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Depending on how big your repository is, you could end up with a pretty large dump file. gzip it, then scp it over to your new server, then gunzip it. Use svnadmin to load the repository dump.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
cd &#x2F;var&#x2F;svn  # I like to keep my svn repositories under &#x2F;var&#x2F;svn
mkdir repository_name
svnadmin create repository_name
svnadmin load repository_name &amp;lt; &#x2F;path&#x2F;to&#x2F;repository_name.dump&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you have a good pipe between the source and destination servers, you can do this in a one-liner:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;svnadmin dump &#x2F;path&#x2F;to&#x2F;repository | ssh -C [IP&#x2F;domain of destination server] svnadmin load &#x2F;path&#x2F;to&#x2F;new_repository&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Of course, all this dumping would require a temporary suspension of any repository write actions otherwise you&#x27;re just going to have an inconsistent dump - just send out an email to your fellow developers and disable svn access.&lt;&#x2F;p&gt;
&lt;h3&gt;Setting up access to your new repository&lt;&#x2F;h3&gt;
&lt;p&gt;Now, you have a Subversion repository that is only accessible via the local filesystem (file:&#x2F;&#x2F; &#x27;protocol&#x27;), which isn&#x27;t very useful. We&#x27;ll need to setup remote access. Your Subversion repository can be accessed in a variety of ways, including:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;svnbook.red-bean.com&#x2F;nightly&#x2F;en&#x2F;svn.serverconfig.svnserve.html&quot;&gt;svnserve&lt;&#x2F;a&gt; standalone daemon (svn:&#x2F;&#x2F;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;svnbook.red-bean.com&#x2F;nightly&#x2F;en&#x2F;svn.serverconfig.svnserve.html&quot;&gt;svnserve&lt;&#x2F;a&gt; with &lt;code&gt;inetd&lt;&#x2F;code&gt; (svn:&#x2F;&#x2F;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;svnbook.red-bean.com&#x2F;nightly&#x2F;en&#x2F;svn.serverconfig.svnserve.html&quot;&gt;svnserve&lt;&#x2F;a&gt; over a SSH tunnel (svn+ssh:&#x2F;&#x2F;)&lt;&#x2F;li&gt;
&lt;li&gt;over the HTTP protocol (http:&#x2F;&#x2F; and https:&#x2F;&#x2F;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The &lt;a href=&quot;http:&#x2F;&#x2F;svnbook.red-bean.com&#x2F;nightly&#x2F;en&#x2F;svn.serverconfig.svnserve.html&quot;&gt;svnserve documentation&lt;&#x2F;a&gt; details how to deal with the first 3, and setting up http:&#x2F;&#x2F; and https:&#x2F;&#x2F; access to your protocol is really a subject that deserves its own tutorial. Try the &lt;a href=&quot;http:&#x2F;&#x2F;svnbook.red-bean.com&#x2F;nightly&#x2F;en&#x2F;svn.serverconfig.httpd.html&quot;&gt;SVN book&lt;&#x2F;a&gt; or Google.&lt;&#x2F;p&gt;
&lt;p&gt;Personally I prefer svn+ssh:&#x2F;&#x2F; access for internal projects since it allows me to unify authentication for my Subversion repositories with UNIX user accounts. Be wary of an angry cadre Windows developers though, since they need to take quite a good number of steps to setup public key authentication and integrate it with their svn clients on Windows machines. Integration with TortoiseSVN is quite a pain, though my Windows-using colleague at work found these useful: &lt;a href=&quot;http:&#x2F;&#x2F;www.mono-project.com&#x2F;Putty_and_TortoiseSvn&quot;&gt;Putty and TortoiseSVN&lt;&#x2F;a&gt;, &lt;a href=&quot;http:&#x2F;&#x2F;brondsema.net&#x2F;blog&#x2F;index.php&#x2F;2005&#x2F;05&#x2F;03&#x2F;using_cygwin_keychain_svn_ssh_and_tortoi&quot;&gt;Using Cygwin, Keychain, SVN+SSH and TortoiseSVN in Windows&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4&gt;svn:&#x2F;&#x2F; access&lt;&#x2F;h4&gt;
&lt;p&gt;I also expose my repositories via svn:&#x2F;&#x2F; (as we&#x27;ll see later, this is useful for allowing access to a svnsync user without messing around with any UNIX user accounts) and use the &lt;code&gt;xinetd&lt;&#x2F;code&gt; daemon (&lt;code&gt;apt-get install xinetd&lt;&#x2F;code&gt; on Ubuntu to install) to launch svnserve process. If you&#x27;re taking this path, create a file (I name it &#x27;svn&#x27;) in &lt;code&gt;&#x2F;etc&#x2F;xinet.d&lt;&#x2F;code&gt; to tell xinetd about svnserve.&lt;&#x2F;p&gt;
&lt;p&gt;In &#x2F;etc&#x2F;xinet.d&#x2F;svn:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
service svn
{
        port                    = 3690
        socket_type             = stream
        protocol                = tcp
        wait                    = no
        user                    = www-data
        server                  = &#x2F;usr&#x2F;local&#x2F;bin&#x2F;svnserve
        server_args             = -i -r &#x2F;var&#x2F;svn
}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice that I needed to use the full path to svnserve (do a &lt;code&gt;which svnserve&lt;&#x2F;code&gt; to get the full path, making sure this is the 1.4.x version that you just installed). The &lt;code&gt;server_args&lt;&#x2F;code&gt; parameter also bears some explanation. The &lt;code&gt;-i&lt;&#x2F;code&gt; option tells svnserve to use inetd (xinetd is a variant of inetd, sorta). The &lt;code&gt;-r &#x2F;var&#x2F;svn&lt;&#x2F;code&gt; option tells svnserve to only expose repositories below that path. This basically translates your repository at &lt;code&gt;&#x2F;var&#x2F;svn&#x2F;my_cool_project&lt;&#x2F;code&gt; to be accessible via &lt;code&gt;svn:&#x2F;&#x2F;your.hostname&#x2F;my_cool_project&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h4&gt;svn+ssh:&#x2F;&#x2F; access&lt;&#x2F;h4&gt;
&lt;p&gt;Accessing your repository this way basically logs in to the host server of your repository over SSH, invokes the svnserve process, and accesses your repository in a very file:&#x2F;&#x2F;-like manner. What this means is that your repository path is taken from the root of your filesystem. An example: a repository located in &lt;code&gt;&#x2F;var&#x2F;svn&#x2F;my_cool_project&lt;&#x2F;code&gt; would be available at &lt;code&gt;svn+ssh:&#x2F;&#x2F;your.hostname&#x2F;var&#x2F;svn&#x2F;my_cool_project&lt;&#x2F;code&gt;. For this reason I often symlink &lt;code&gt;&#x2F;svn&lt;&#x2F;code&gt; to &lt;code&gt;&#x2F;var&#x2F;svn&lt;&#x2F;code&gt; (to get repository URLs like &lt;code&gt;svn+ssh:&#x2F;&#x2F;your.hostname&#x2F;svn&#x2F;my_cool_project&lt;&#x2F;code&gt; instead).&lt;&#x2F;p&gt;
&lt;h3&gt;Relocating working copies&lt;&#x2F;h3&gt;
&lt;p&gt;Now, all your working copies are still pointing to the old Subversion server - no need to fret, a simple &lt;code&gt;svn switch&lt;&#x2F;code&gt; fixes things:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;svn switch --relocate [from] [to]&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Replace &#x27;[from]&#x27; and &#x27;[to]&#x27; with the source and destination Subversion repository URLs.&lt;&#x2F;p&gt;
&lt;p&gt;Remember to stop access to your old server so no one is making commits to the wrong place.&lt;&#x2F;p&gt;
&lt;h3&gt;Setting up svnsync&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;d intended to write this entire piece in one blog post, but I&#x27;m running out of steam at this point. In &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;2007&#x2F;03&#x2F;31&#x2F;setting-up-svnsync-ed-mirrored-svn-repositories-on-ubuntu-part-2-of-2&#x2F;&quot;&gt;Part 2&lt;&#x2F;a&gt;, we&#x27;ll actually setup svnsync for some repository mirroring goodness!&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>VLC 0.8.6 - full screen controller panel</title>
    <published>2006-12-26T16:46:10+00:00</published>
    <updated>2006-12-26T16:46:10+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2006/12/26/vlc-086-full-screen-controller-panel/"/>
    <id>https://chuyeow.wtf/2006/12/26/vlc-086-full-screen-controller-panel/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2006/12/26/vlc-086-full-screen-controller-panel/">&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;developers.videolan.org&#x2F;vlc&#x2F;NEWS&quot;&gt;VLC media player&lt;&#x2F;a&gt; 0.8.6 (&lt;a href=&quot;http:&#x2F;&#x2F;developers.videolan.org&#x2F;vlc&#x2F;NEWS&quot;&gt;changelog&lt;&#x2F;a&gt;) was released a few weeks ago so this may be old news, but I am clearing my backlog of drafts.&lt;&#x2F;p&gt;
&lt;p&gt;Mac OS X users, if you watch videos in full screen mode (like I do most of the time), you&#x27;d be delighted to know that they added a full screen controller &lt;em&gt;Ã  la&lt;&#x2F;em&gt; the video player in iTunes:&lt;&#x2F;p&gt;
&lt;div class=&quot;img&quot;&gt;&lt;img src=&quot;&#x2F;assets&#x2F;vlc-controller-panel-black-lagoon-levy.png&quot; alt=&quot;VLC full screen controller panel&quot; &#x2F;&gt;&lt;&#x2F;div&gt;
&lt;p&gt;&lt;br style=&quot;clear: both&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;That was one of my pet peeves with VLC when I was still using Windows as my main desktop OS, and I&#x27;d stayed true to &lt;a href=&quot;http:&#x2F;&#x2F;sourceforge.net&#x2F;projects&#x2F;guliverkli&#x2F;&quot;&gt;Media Player Classic&lt;&#x2F;a&gt; right to the point where I switched to OS X. Media Player Classic is Windows-only, so I had to switch to VLC as well (QuickTime player never impressed me and I wasn&#x27;t willing to pay for the Pro version). The lack of a full controller in full screen mode and the inability to move to specific spots in the video timeline with sufficient granularity seems to have been fixed with this new full screen controller panel.&lt;&#x2F;p&gt;
&lt;p&gt;And while they still haven&#x27;t made it possible to pause a video by clicking on the video output (which was the case in Media Player Classic), I&#x27;ve mostly compensated for it by hitting the space bar. Now that they&#x27;ve added a right-click context menu to the video output screen, the same can be done but in 2 clicks with just the mouse - not optimal but it does feel better to see a context menu pop up when right-clicking. I guess that&#x27;s the Windows user in me talking - I still feel that almost everything I see should have a context menu or it just feels wrong.&lt;&#x2F;p&gt;
&lt;p&gt;Oh and they added support for the Apple Remote Control. Works great, I just have to remember to take out my remote control and use it next time I&#x27;m sitting back watching a movie or anime.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Essential plugins for Trac</title>
    <published>2006-08-24T20:32:09+00:00</published>
    <updated>2006-08-24T20:32:09+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2006/08/24/essential-plugins-for-trac/"/>
    <id>https://chuyeow.wtf/2006/08/24/essential-plugins-for-trac/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2006/08/24/essential-plugins-for-trac/">&lt;p&gt;I&#x27;ve been setting up several &lt;a href=&quot;http:&#x2F;&#x2F;trac.edgewall.org&#x2F;&quot;&gt;Trac&lt;&#x2F;a&gt; installations recently, and while Trac by itself is already pretty awesome (I love it&#x27;s simplicity and functionality that doesn&#x27;t get in the way), I was pretty dismayed to discover that administration isn&#x27;t that great.  Configuring Trac is a matter of (more) hacking at the command line with the &lt;a href=&quot;http:&#x2F;&#x2F;trac.edgewall.org&#x2F;wiki&#x2F;TracAdmin&quot;&gt;trac-admin&lt;&#x2F;a&gt; script, and user administration is managed with htpasswd or whatever authentication scheme that you choose (point being, you can&#x27;t manage users via Trac itself).&lt;&#x2F;p&gt;
&lt;p&gt;Thankfully, there are some plugins that you can install to alleviate the situation. Trac itself publishes the &lt;a href=&quot;http:&#x2F;&#x2F;trac.edgewall.org&#x2F;wiki&#x2F;WebAdmin&quot;&gt;WebAdmin plugin&lt;&#x2F;a&gt;, which is slated for inclusion in Trac in &lt;a href=&quot;http:&#x2F;&#x2F;trac.edgewall.org&#x2F;milestone&#x2F;0.11&quot;&gt;Trac 0.11&lt;&#x2F;a&gt;. This adds a web interface to trac-admin and it&#x27;s pretty darned useful when used with two other plugins: &lt;a href=&quot;http:&#x2F;&#x2F;trac-hacks.org&#x2F;wiki&#x2F;AccountManagerPlugin&quot;&gt;Account Manager plugin&lt;&#x2F;a&gt; and &lt;a href=&quot;http:&#x2F;&#x2F;trac-hacks.org&#x2F;wiki&#x2F;WebAdminUsersPlugin&quot;&gt;WebAdmin Users plugin&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;trac-hacks.org&#x2F;wiki&#x2F;AccountManagerPlugin&quot;&gt;Account Manager plugin&lt;&#x2F;a&gt; adds HTML form-based login instead of the default HTTP authentication with plain olde Trac (plus user registration and changing of passwords). I&#x27;ll let you in on a secret - I never managed to configure my Trac installs properly to use HTTP auth, but with this plugin it just worked.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;http:&#x2F;&#x2F;trac-hacks.org&#x2F;wiki&#x2F;WebAdminUsersPlugin&quot;&gt;WebAdmin Users plugin&lt;&#x2F;a&gt; let&#x27;s you add&#x2F;remove users via WebAdmin plugin.&lt;&#x2F;p&gt;
&lt;div class=&quot;img&quot;&gt;&lt;img src=&quot;&#x2F;assets&#x2F;trac-web-admin-users-plugin-manage-user.png&quot; alt=&quot;Managing user account with Trac WebAdmin Users&quot; &#x2F;&gt;&lt;&#x2F;div&gt;
&lt;p&gt;&lt;br style=&quot;clear:both&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;By the way, if anyone has got a Linux binary for mod_dav_svn.so for Apache 2.2, let me know - I&#x27;m too lazy to go through the whole trouble of compiling it.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>SitePoint&#x27;s New Book - Run Your Own Web Server Using Linux &amp; Apache</title>
    <published>2005-12-21T15:12:40+00:00</published>
    <updated>2005-12-21T15:12:40+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2005/12/21/sitepoints-new-book-run-your-own-web-server-using-linux-apache/"/>
    <id>https://chuyeow.wtf/2005/12/21/sitepoints-new-book-run-your-own-web-server-using-linux-apache/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2005/12/21/sitepoints-new-book-run-your-own-web-server-using-linux-apache/">&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;sitepoint.com&#x2F;&quot;&gt;SitePoint&lt;&#x2F;a&gt; has just released another book, &lt;a href=&quot;http:&#x2F;&#x2F;www.sitepoint.com&#x2F;books&#x2F;linux1&#x2F;&quot;&gt;Run Your Own Web Server Using Linux &amp; Apache&lt;&#x2F;a&gt;, which is looking to be quite a winner for those of you who want a complete guide to setting up your development environment for &lt;acronym title=&quot;Linux, Apache, MySQL, PHP&quot;&gt;LAMP&lt;&#x2F;acronym&gt; development. As an Advisor over at &lt;a href=&quot;http:&#x2F;&#x2F;sitepoint.com&#x2F;forums&#x2F;&quot;&gt;SitePoint Forums&lt;&#x2F;a&gt;, I am getting this book for free (yay SitePoint!), though to be honest I have been neglecting my duties over there.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, just a little publicity for SitePoint&#x27;s new book (disclaimer: I have no obligation to SitePoint to promote the book) - I really think it looks promising for those of you looking to run your own &lt;acronym title=&quot;Linux, Apache, MySQL, PHP&quot;&gt;LAMP&lt;&#x2F;acronym&gt; setup or even budding system administrators, as it seems to cover a whole lot and SitePoint&#x27;s books have been known for being immediately of practical use. It costs USD39.95 and comes with a Fedora Core 4 DVD, &lt;a href=&quot;http:&#x2F;&#x2F;www.sitepoint.com&#x2F;books&#x2F;linux1&#x2F;poster.php&quot;&gt;Linux Quick Reference Poster&lt;&#x2F;a&gt; and a collectible SitePoint-branded bookmark(!).&lt;&#x2F;p&gt;
&lt;p&gt;Enough said though, because the book hasn&#x27;t arrived yet. If I do have time to read it (though it isn&#x27;t very relevant to me now), I may give it a once-over review (no promises).&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>A new Linux distro - for a fee</title>
    <published>2004-11-09T00:43:17+00:00</published>
    <updated>2004-11-09T00:43:17+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2004/11/09/a-new-linux-distro-for-a-fee/"/>
    <id>https://chuyeow.wtf/2004/11/09/a-new-linux-distro-for-a-fee/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2004/11/09/a-new-linux-distro-for-a-fee/">&lt;p&gt;Seen at &lt;a href=&quot;http:&#x2F;&#x2F;www.rentacoder.com&#x2F;&quot;&gt;Rent A Coder&lt;&#x2F;a&gt;: &lt;a href=&quot;http:&#x2F;&#x2F;www.rentacoder.com&#x2F;RentACoder&#x2F;misc&#x2F;BidRequests&#x2F;ShowBidRequest.asp?lngBidRequestId=208761&quot;&gt;a bid request for a Linux distribution with branding&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;&lt;p&gt;I need a new linux distribution based on kernel 2.6.8 or later (2.7) with branded&#x2F;customized KDE 3.3...&lt;&#x2F;p&gt;&lt;&#x2F;blockquote&gt;
&lt;p&gt;Makes you wonder what the guy wants to do with this. And this is definitely the most &quot;different&quot; bid request I&#x27;ve seen in awhile.&lt;&#x2F;p&gt;
&lt;p&gt;Oh, by the way, if you&#x27;re looking for a freelance PHP or Python developer, or a Linux administrator for your web server, I may just be your man. &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;contact&#x2F;&quot;&gt;Drop me a message&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Version Control System Comparison</title>
    <published>2004-11-06T12:17:32+00:00</published>
    <updated>2004-11-06T12:17:32+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2004/11/06/version-control-system-comparison/"/>
    <id>https://chuyeow.wtf/2004/11/06/version-control-system-comparison/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2004/11/06/version-control-system-comparison/">&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;better-scm.berlios.de&#x2F;comparison&#x2F;comparison.html&quot;&gt;Version Control System Comparison&lt;&#x2F;a&gt;. Why moving to CVS in your organization&#x2F;project may not be the best idea: Atomic commits - CVS doesn&#x27;t have this. Renaming support - CVS doesn&#x27;t have this (there are ways to hack around this, but you will lose revision history). There are better choices out there.&lt;&#x2F;p&gt;
&lt;p&gt;Sidenote: I&#x27;ve been posting quite a few &quot;Asides&quot; recently. On my todo list is to offer an RSS feed without these &quot;Asides&quot; posts.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>MySQL 4.1 production-ready</title>
    <published>2004-10-28T11:27:39+00:00</published>
    <updated>2004-10-28T11:27:39+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2004/10/28/mysql-41-production-ready/"/>
    <id>https://chuyeow.wtf/2004/10/28/mysql-41-production-ready/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2004/10/28/mysql-41-production-ready/">&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.mysql.com&#x2F;news-and-events&#x2F;press-release&#x2F;release_2004_32.html&quot;&gt;MySQL Version 4.1 Certified as Production-Ready&lt;&#x2F;a&gt;. Still waiting for the &lt;a href=&quot;http:&#x2F;&#x2F;dev.mysql.com&#x2F;downloads&#x2F;mysql&#x2F;4.1.html&quot;&gt;MySQL 4.1.7&lt;&#x2F;a&gt; ebuild (relevant bugs - &lt;a href=&quot;http:&#x2F;&#x2F;bugs.gentoo.org&#x2F;show_bug.cgi?id=62582&quot;&gt;MySQL 4.1.6 ebuild&lt;&#x2F;a&gt;, &lt;a href=&quot;http:&#x2F;&#x2F;bugs.gentoo.org&#x2F;show_bug.cgi?id=67871&quot;&gt;request to include mysql 4.1.6 in portage and add ~amd64&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>WordPress hosting up for grabs</title>
    <published>2004-10-17T20:28:03+00:00</published>
    <updated>2004-10-17T20:28:03+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2004/10/17/wordpress-hosting-up-for-grabs/"/>
    <id>https://chuyeow.wtf/2004/10/17/wordpress-hosting-up-for-grabs/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2004/10/17/wordpress-hosting-up-for-grabs/">&lt;p&gt;&lt;ins&gt;Update: All gone! Thanks everyone!&lt;&#x2F;ins&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;ins&gt;Update: seeing how pathetic the (non-)response has been, I&#x27;ve lowered the donation amount to USD2. C&#x27;mon people. Even as a gift for your non-tech-savvy uncle&#x2F;auntie&#x2F;grandma who wants to blog, it&#x27;s a good deal!&lt;&#x2F;ins&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;ins&gt;Update: There &lt;del datetime=&quot;2004-10-5T14:3:37--8:00&quot;&gt;are 3 of the accounts&lt;&#x2F;del&gt; is 1 account left. Thanks Jannah and Phu for making the donations to WordPress!&lt;&#x2F;ins&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Jeff Holman of &lt;a href=&quot;http:&#x2F;&#x2F;www.revisemedia.com&#x2F;&quot;&gt;Revise Media&lt;&#x2F;a&gt; wrote me awhile back to put up ads for his new &lt;a href=&quot;http:&#x2F;&#x2F;www.revisemedia.com&#x2F;services&#x2F;wordpress&#x2F;&quot;&gt;WordPress weblog hosting&lt;&#x2F;a&gt; service, and I gladly agreed because I was kind of a WordPress fan (caution: heavy understatement in use). His ad is on the left where you&#x27;ve probably been seeing it for awhile (if you&#x27;re not reading via a feed reader). (On the subject of ads, well, they fund the webhosting for this blog and then a little more.)&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, Jeff offered to give me 5 &lt;a href=&quot;http:&#x2F;&#x2F;www.revisemedia.com&#x2F;services&#x2F;wordpress&#x2F;compare.html&quot;&gt;Plus plans&lt;&#x2F;a&gt; &lt;ins&gt;(1 year subscription)&lt;&#x2F;ins&gt; for free to give away to you, my dearest readers. There was supposed to be some contest, but I gave up trying to think of a good idea for one. So I spoke with Jeff on this other idea I had and he has agreed to let them go for a &lt;a href=&quot;http:&#x2F;&#x2F;wordpress.org&#x2F;donate&#x2F;&quot;&gt;donation to WordPress&lt;&#x2F;a&gt; (rather than for &quot;free&quot;).&lt;&#x2F;p&gt;
&lt;p&gt;Well, the Plus plans are going at $9.95&#x2F;year each, and I ask of you to &lt;a href=&quot;http:&#x2F;&#x2F;wordpress.org&#x2F;donate&#x2F;&quot;&gt;make a donation to WordPress&lt;&#x2F;a&gt; of at least &lt;del&gt;$5&lt;&#x2F;del&gt; &lt;ins&gt;$2&lt;&#x2F;ins&gt; (this amount was of my choosing). &lt;a href=&quot;https:&#x2F;&#x2F;chuyeow.wtf&#x2F;contact&#x2F;&quot;&gt;Write me&lt;&#x2F;a&gt; first (or leave a comment) if you&#x27;re thinking of donating and claiming a free Plus plan - Jeff has 5 of them for me to give away.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>Infringement of GPL - court grants preliminary injunction</title>
    <published>2004-04-22T00:36:24+00:00</published>
    <updated>2004-04-22T00:36:24+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2004/04/22/infringement-of-gpl-court-grants-preliminary-injunction/"/>
    <id>https://chuyeow.wtf/2004/04/22/infringement-of-gpl-court-grants-preliminary-injunction/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2004/04/22/infringement-of-gpl-court-grants-preliminary-injunction/">&lt;p&gt;The &lt;a href=&quot;http:&#x2F;&#x2F;www.netfilter.org&#x2F;&quot; title=&quot;Go to the netfilter&#x2F;iptables project homepage&quot;&gt;netfilter&#x2F;iptables project&lt;&#x2F;a&gt; has been granted a preliminary injunction against &lt;a href=&quot;http:&#x2F;&#x2F;www.sitecom.com&#x2F;&quot;&gt;Sitecom Germany GmbH&lt;&#x2F;a&gt; for not fulfilling the obligations imposed by the GNU &lt;a href=&quot;http:&#x2F;&#x2F;www.gnu.org&#x2F;copyleft&#x2F;gpl.html&quot;&gt;General Public License&lt;&#x2F;a&gt; (which covers the netfilter&#x2F;iptables code used) - Sitecom did not make the source code available nor did they include the GPL license with their products (GPL is viral). Read the &lt;a href=&quot;http:&#x2F;&#x2F;www.netfilter.org&#x2F;news&#x2F;2004-04-15-sitecom-gpl.html&quot;&gt;press release&lt;&#x2F;a&gt; from the netfilter project for more details.&lt;&#x2F;p&gt;
&lt;p&gt;Reading the comments &lt;a href=&quot;http:&#x2F;&#x2F;www.oreillynet.com&#x2F;pub&#x2F;wlg&#x2F;4708&quot;&gt;here&lt;&#x2F;a&gt; and &lt;a href=&quot;http:&#x2F;&#x2F;www.groklaw.net&#x2F;article.php?story=20040415115414858&quot;&gt;here&lt;&#x2F;a&gt; had me wondering why people were so surprised by the decision made by the (German) judge. I&#x27;d think that the judge would have looked over the GPL and applied the law in accordance with it and copyright law. An anonymous commentor at Groklaw probably &lt;a href=&quot;http:&#x2F;&#x2F;www.groklaw.net&#x2F;comment.php?mode=display&amp;sid=20040415115414858&amp;title=Why%20do%20people%20seem%20so%20suprised%3F&amp;type=article&amp;order=&amp;hideanonymous=0&amp;pid=0#c117597&quot;&gt;said this best&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
  </entry>
  <entry>
    <title>State of IT journalism in Singapore</title>
    <published>2003-07-09T06:25:14+00:00</published>
    <updated>2003-07-09T06:25:14+00:00</updated>
    <author><name>Chu Yeow</name></author>
    <link rel="alternate" type="text/html" href="https://chuyeow.wtf/2003/07/09/state-of-it-journalism-in-singapore/"/>
    <id>https://chuyeow.wtf/2003/07/09/state-of-it-journalism-in-singapore/</id>
    <content type="html" xml:base="https://chuyeow.wtf/2003/07/09/state-of-it-journalism-in-singapore/">&lt;p&gt;There&#x27;s this publication called Computer Times which comes with The Straits Times every Wednesday - supposedly an IT read. Today&#x27;s issue has this article on Singaporean Nickson Fong, COO of Digimax, which does CGI (Computer Generated Imagery) for Hollywood movies, among them The Matrix Reloaded. There&#x27;s nothing wrong with Nickson Fong or Digimax (in fact, I&#x27;m glad a local &quot;made it&quot;) - it&#x27;s the reporting that I&#x27;ve reservations about.&lt;&#x2F;p&gt;
&lt;p&gt;I quote from the article:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;div&gt;
The self-acknowledged geek builds his own computers and knows &lt;strong&gt;programming languages such as Unix and Linux&lt;&#x2F;strong&gt;.
&lt;&#x2F;div&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Aforementioned &quot;self-acknowledged geek&quot; being Nickson Fong of course, who would definitely not have said that himself. The reporter (who&#x27;s name would remain undisclosed in this blog entry) doesn&#x27;t seem to have a clue. And this is an IT publication - if the reporter was a full-time employee of Computer Times, he should be transferred to a more suitable department!&lt;&#x2F;p&gt;
&lt;p&gt;It makes me shake my head really, and this isn&#x27;t the first instance I&#x27;ve seen discrepancies of this sort in Computer Times, nor many other local IT publications.&lt;&#x2F;p&gt;
</content>
  </entry>
</feed>
