Today is not today

Hello there, kind and generous readers. It's been a while since my last post, and i'm quite sure i have been sorely missed. I would really like to say something along the lines of 'the past few months have been really really hectic and i have been immensely busy' but that would be somewhat untrue. The fact of the matter is that i've been doing lots and lots of javascript nothing really seemed that blogworthy i'm a lazy slob.

But from today onwards, i have decided to be a lazy slob no more ! Regular, coherent blogging here i come ! Well, mostly regular, can't quite guarantee coherency on my part. But, i digress. Today's topic is the lovely rubygems and the most disturbing fact that in version 1.0.1,

Today is not today

Just so you know what i'm talking about, in case you have rubygems 1.0.1 installed and ruby 1.8, fire up irb and do the following :

require 'rubygems'
Time.today == Time.today
The thing that'll probably show up will most likely be something along the lines of "=> false". There is a slim chance that it'll return true, but more on that later. Actually, scratch that; more on that now. If you turn that lovely today into a float, you'll be greeted by a lovely bunch of numbers. They may be quite similar to the following:
irb(main):003:0> Time.today.to_f         
=> 1201384800.62603
What may have already gotten your senses tingling should be that floating point part. What's that doing in our upstanding, fixed, and morally responsible time for the present day ? Does our day start at a random millisecond ? Nay, i say ! It does not.

Ok, so we know what the problem is, namely that somebody forgot to trim the floating point part, and we know roughly where it is, namely somewhere inside rubygems. After some grepping, you should find this little gem ( very subtle pun ! ) inside specification.rb:

# Time::today has been deprecated in 0.9.5 and will be removed.
if RUBY_VERSION < '1.9' then
  def Time.today
    t = Time.now
    t - ((t.to_i + t.gmt_offset) % 86400)
  end unless defined? Time.today
end
This is your typical good news - bad news scenario. The good news is that this thing's getting removed, the bad news is that it's buggy, it's in your code, and it's making the very fabric of time collapse upon itself. The way to fix it is quite complex, and instead of giving a rather lengthy and enlightening explanation of its inner workings, i'll just paste the fixed code.
# Time::today has been deprecated in 0.9.5 and will be removed.
if RUBY_VERSION < '1.9' then
  def Time.today
    t = Time.now
    t - ((t.to_f + t.gmt_offset) % 86400)
  end unless defined? Time.today
end
Having read all that reworked and finely retuned code, please take a moment to grab a cup of tea, watch a video, or do whatever you find most relaxing. The last thing i would like to do is strain the honorable reader.

So that's basically it. I've submitted the bug here, and in case you'd like to fix your version before the new one comes out, look for specification.rb in a folder resembling "/usr/lib/ruby/site_ruby/1.8/rubygems". It doesn't have to be identical to that, but that "site_ruby" part is pretty much a given.

Even more metaprogramming

Well, it's been a couple of weeks since i've posted anything and i do feel quite guilty about it. Therefore, i shall post more metaprogramming ! In the project i'm currently working on, it has been my great displeasure to encounter blocks similar to the following

def xml_goats
  configuration_node.root.elements["goats"].text.strip
end
  
def xml_apples
  configuration_node.root.elements["apples"].text.strip
end
  
def xml_cherries
  configuration_node.root.elements["cherries"].text.strip
end

I don't know about you, but to me, that just screams "metametametameta !!!". And it's not just because i'll use any excuse to stick some metaprogramming in my classes, but it genuinely looks like a load of nasty copy-paste malarkey. As such, i proceeded with my evil deeds

class Margerine
  %w[goats apples cherries].each{|x| 
    class_eval(%Q{
      def xml_#{x}
        configuration_node.root.elements["#{x}"].text.strip
      end
    })
  }
end

This by all means pretty much works as expected, and defines all those lovely functions for me. However, it still leaves me feeling a bit empty and unsatisfied. What if someday, somehow, we have more of these functions and they require a different set of method calls on the given node ? What will happen to our beautiful code then ? Will it be thrown to the gutter, like an old mistress with a dirty stocking ? Will it be fed to the wolves, like a lovingly furry squirrel who has eaten one too many hazelnuts ? That would most certainly not do. As such, we must make our code better, stronger, and even more delicious.

class Margerine
  def self.attr_xml_reader(items,submethod = "text.strip")
    items.each{|item|
      class_eval( %Q{
        def xml_#{item}
          configuration_node.root.elements["#{item}"].#{submethod}
        end
      }	)
    }
  end

  attr_xml_reader %w[goats apples cherries], "text.strip.downcase"

end

Now we are indeed satisfied with our work, and knowing that all damsels and squirrels the world over are safe and sound, we rest to code another day

Tasting the sweet nectar of metaprogramming

Metaprogramming is something you hear a lot about when you're around ruby, and with good reason. It's insanely powerful and hands down the most fun you can have with a programming language. Given that it's quite a complex topic, i'll start off slow - custom getters and setters. If you've used ruby for more than 20 minutes, you've probably seen attr_reader / attr_writer / attr_accessor. They're snippets of metaprogramming that just generate methods. Take attr_accessor, for instance. It gets you something to the tune of
def #{name}
  @#{name}
end

def #{name}=(value)
  @#{name} = value
end
But let's say you need something slightly more complex than that. Let's say you're writing an application which features sock possession reporting for animals with silly names. At least in my line of work, that's quite a common requirement. Being the magnificent human being you are, you'd like to write as little as possible. Therefore, you define a module
module Sockless
  def no_socks_for( *names )
    names.each { |name|
      class_eval("
        def #{name}_has_no_socks
          @#{name} + ' is a ghastly beast with no socks'
        end

        def #{name}=(value)
          @#{name} = value*2
        end")
    }
  end
end
Now you just have to extend your desired class with the Sockless module and you're home free
class TheSockZoo
  extend Sockless
  no_socks_for :pig, :sheep
end
Subsequently, you can amaze all sentient beings within a 10 mile radius by just adding these three lines of code and viewing the wonders of modern technology in action
r = TheSockZoo.new
r.pig,r.sheep = "gi","dee"
p r.pig_has_no_socks, r.sheep_has_no_socks

Article tags ? In my layout ?

While carefully constructing the friendly about section earlier today, I noticed that, should an article fail to receive any tags, it would be left with an annoying "Tags:" text and, misleadingly enough, no tags. This makes various baby animals the world over quite sad indeed, so it must be fixed.
My first idea was to dive into the layout and try something to the tune of :
{% unless article.tags.empty? %} Tags: {{ article | linked_tag_list }}{% endunless %}
While this did not actually do anything useful, it did bring to light the fact that my understanding of liquid is laughable, at best. Grep safely in hand, i went deeper and came across this lovely piece of code in 'app\drops\article_drop.rb':
def initialize(source, options = {})
    super source
    @options  = options
    @liquid.update \
      'body'            => @source.body_html,
      'excerpt'         => (@source.excerpt_html.blank? ? nil : @source.excerpt_html),
      'accept_comments' => @source.accept_comments?,
      'is_page_home'    => (options[:page] == true)
  end
Being the horrible person that I am, I added
'tagged'          => !@source.tags.empty?,
Luckily enough, the universe didn't collapse and i could now use
{% if article.tagged %} Tags: {{ article | linked_tag_list }}{% endif %}

Please note that if anybody tries making sense and pointing out that there is no sane reason why an article wouldn't be tagged, i will make up at least 20 reasons, one of which will involve string theories and pandas. You have been warned.

Shameful later edit
Thanks to Cristi i now know what the right way to go about the above problem would have been, namely
{% unless article.tags == empty %} Tags: {{ article | linked_tag_list }}{% endunless %}

Mephisto edge + Rails edge = no love

After postponing putting up a blog about my many and diverse ruby adventures, i finally sat down for a couple of minutes and put this up. Going through the regular motions of installing mephisto, it all seemed ok until i tried to log into the admin account. Then - disaster ! Mephisto died mercilessly stating that
NoMethodError (undefined method `extract_options_from_args!' for #)
After some grepping i found the function in activerecord base, in an earlier version of rails :
def extract_options_from_args!(args) #:nodoc:
  args.last.is_a?(Hash) ? args.pop : {}
end
The whole thing originates in the acts_as_paranoid plugin, so basically you can either patch that with the function definition, replace the call to the function, or just be a horrible human being and patch your edge rails with the function. Whichever way you choose to take, it should fix the issue.

Later edit
As BradC points out, the intended replacement for extract_options_from_args! is args.extract_options!. As such, replacing line 75 of paranoid.rb to
options = args.extract_options!
would not make you a horrible person, quite on the contrary, it would make you a lovely one !