<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>Stuff.</description><title>Steven Xu</title><generator>Tumblr (3.0; @stevenxu)</generator><link>http://stevenxu.ca/</link><item><title>Array#uniq in Ruby 1.8.7</title><description>&lt;p&gt;On github: &lt;a href="https://gist.github.com/1905081"&gt;https://gist.github.com/1905081&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Equal
  attr_accessor :name

  def initialize(name)
    @name = name
  end

  def inspect
    @name
  end

  def hash
    puts "#{name}: hash"
    super
  end

  def eql?(co)
    puts "#{name}: eql? against #{co.name}"
    super
  end

  def ==(co)
    puts "#{name}: == against #{co.name}"
    super
  end
end

EqualA = Equal.new('EqualA')
EqualB = Equal.new('EqualB')
EqualC = Equal.new('EqualC')

puts

def run(cmd)
  puts "~~ #{cmd} ~~"
  puts eval(cmd).inspect
  puts
end

run '[EqualA, EqualB].uniq'
run '[EqualA, EqualB, EqualC].uniq'

class EqualHash &amp;lt; Equal
  def hash
    puts "#{name}: hash"
    1000
  end
end

EqualHashA = EqualHash.new('EqualHashA')
EqualHashB = EqualHash.new('EqualHashB')
EqualHashC = EqualHash.new('EqualHashC')

puts

run '[EqualHashA, EqualHashB].uniq'
run '[EqualHashA, EqualHashB, EqualHashC].uniq'

class EqualHashAndEql &amp;lt; EqualHash
  def eql?(co)
    puts "#{name}: eql? against #{co.name}"
    true
  end
end

EqualHashAndEqlA = EqualHashAndEql.new('EqualHashAndEqlA')
EqualHashAndEqlB = EqualHashAndEql.new('EqualHashAndEqlB')
EqualHashAndEqlC = EqualHashAndEql.new('EqualHashAndEqlC')
EqualHashAndEqlD = EqualHashAndEql.new('EqualHashAndEqlD')

puts

run '[EqualHashAndEqlA, EqualHashAndEqlB].uniq'
run '[EqualHashAndEqlA, EqualHashAndEqlB, EqualHashAndEqlC].uniq'
run '[EqualHashAndEqlA, EqualHashAndEqlB, EqualHashAndEqlC, EqualHashAndEqlD].uniq'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;Equal&lt;/code&gt; is little more than a wrapper to &lt;code&gt;Object&lt;/code&gt; to make things prettier. &lt;code&gt;EqualHash&lt;/code&gt; is a subclass of &lt;code&gt;Equal&lt;/code&gt; whose instances always return 1000 for &lt;code&gt;#hash&lt;/code&gt;. &lt;code&gt;EqualHashAndEql&lt;/code&gt; is a subclass of &lt;code&gt;EqualHash&lt;/code&gt; whose instances always return true for &lt;code&gt;#eql?&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s the output with commentary:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;~~ [EqualA, EqualB].uniq ~~
EqualA: hash
EqualB: hash
[EqualA, EqualB]

~~ [EqualA, EqualB, EqualC].uniq ~~
EqualA: hash
EqualB: hash
EqualC: hash
[EqualA, EqualB, EqualC]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;#uniq&lt;/code&gt; internally calls &lt;code&gt;#hash&lt;/code&gt; on each element, realizes they&amp;#8217;re different and allows both in the resulting array.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;~~ [EqualHashA, EqualHashB].uniq ~~
EqualHashA: hash
EqualHashB: hash
EqualHashB: eql? against EqualHashA
[EqualHashA, EqualHashB]

~~ [EqualHashA, EqualHashB, EqualHashC].uniq ~~
EqualHashA: hash
EqualHashB: hash
EqualHashB: eql? against EqualHashA
EqualHashC: hash
EqualHashC: eql? against EqualHashB
EqualHashC: eql? against EqualHashA
[EqualHashA, EqualHashB, EqualHashC]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;#uniq&lt;/code&gt; sees the hash collisions and falls back to calling &lt;code&gt;#eql?&lt;/code&gt; in a n^2 loop.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;~~ [EqualHashAndEqlA, EqualHashAndEqlB].uniq ~~
EqualHashAndEqlA: hash
EqualHashAndEqlB: hash
EqualHashAndEqlB: eql? against EqualHashAndEqlA
EqualHashAndEqlA: hash
EqualHashAndEqlB: hash
[EqualHashAndEqlA]

~~ [EqualHashAndEqlA, EqualHashAndEqlB, EqualHashAndEqlC].uniq ~~
EqualHashAndEqlA: hash
EqualHashAndEqlB: hash
EqualHashAndEqlB: eql? against EqualHashAndEqlA
EqualHashAndEqlC: hash
EqualHashAndEqlC: eql? against EqualHashAndEqlA
EqualHashAndEqlA: hash
EqualHashAndEqlB: hash
EqualHashAndEqlC: hash
[EqualHashAndEqlA]

~~ [EqualHashAndEqlA, EqualHashAndEqlB, EqualHashAndEqlC, EqualHashAndEqlD].uniq ~~
EqualHashAndEqlA: hash
EqualHashAndEqlB: hash
EqualHashAndEqlB: eql? against EqualHashAndEqlA
EqualHashAndEqlC: hash
EqualHashAndEqlC: eql? against EqualHashAndEqlA
EqualHashAndEqlD: hash
EqualHashAndEqlD: eql? against EqualHashAndEqlA
EqualHashAndEqlA: hash
EqualHashAndEqlB: hash
EqualHashAndEqlC: hash
EqualHashAndEqlD: hash
[EqualHashAndEqlA]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Same as above, except that because &lt;code&gt;#eql?&lt;/code&gt; returns true, B, C, and D are not added to the intermediate resulting array. I&amp;#8217;m not entirely sure why &lt;code&gt;#hash&lt;/code&gt; is called again once everything is done though.&lt;/p&gt;</description><link>http://stevenxu.ca/post/18221092917</link><guid>http://stevenxu.ca/post/18221092917</guid><pubDate>Fri, 24 Feb 2012 20:29:33 -0500</pubDate></item><item><title>Autoloading in Rails 3</title><description>&lt;p&gt;Rails 3 by default adds these to the autoload paths:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;app/*
vendor/plugins/*/lib
vendor/plugins/*/app/*
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In addition, gems, when they are defined as Rails engines/railties, get each directory in &lt;code&gt;app&lt;/code&gt; added to the autoload path.&lt;/p&gt;

&lt;p&gt;Notable exceptions: Rails does not automatically add its own &lt;code&gt;lib&lt;/code&gt; directory or the &lt;code&gt;lib&lt;/code&gt; directories of any plugins to the load path.&lt;/p&gt;</description><link>http://stevenxu.ca/post/16869107131</link><guid>http://stevenxu.ca/post/16869107131</guid><pubDate>Wed, 01 Feb 2012 12:14:29 -0500</pubDate></item><item><title>Asset fallback paths in Rails 3.1</title><description>&lt;p&gt;Many things can cause your production asset paths to change. When that happens, your previous assets just stop working at all. Moreover, it seems like it would make sense for the bare asset path (without the md5 postfix) should just point to the most recent version of the asset. This little tidbit should take care of all of that.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Myapp::Application.routes.draw do
  match 'assets/:id.:format' =&amp;gt; 'assets#show'
end

class AssetsController &amp;lt; ApplicationController
  def show
    asset_without_digest = "#{params[:id].gsub /-[0-9a-f]{32}$/, ''}.#{params[:format]}"
    new_path = ActionView::Base.new.image_path(asset_without_digest)
    if url_for(params).include? new_path
      head 404
    else
      redirect_to new_path, :status =&amp;gt; 301
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;</description><link>http://stevenxu.ca/post/10096868050</link><guid>http://stevenxu.ca/post/10096868050</guid><pubDate>Sun, 11 Sep 2011 16:54:00 -0400</pubDate></item><item><title>Photo</title><description>&lt;img src="http://24.media.tumblr.com/tumblr_li5vzr0Q8w1qi5e1go1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;</description><link>http://stevenxu.ca/post/3901480524</link><guid>http://stevenxu.ca/post/3901480524</guid><pubDate>Wed, 16 Mar 2011 13:45:27 -0400</pubDate></item></channel></rss>

