How to include classes in extensions?

Hi,

I would like to access this snippet of code from within my extension
tags:

class Numeric
def ordinal
cardinal = self.to_i.abs
if (10…20).include?(cardinal) then
cardinal.to_s << ‘th’
else
cardinal.to_s << %w{th st nd rd th th th th th th}[cardinal % 10]
end
end
end

As the tags get called on the page I have tried adding the above to:

module StartDate::PageExtensions
class Numeric < Page

 def ordinal
   cardinal = self.to_i.abs
   if (10...20).include?(cardinal) then
     cardinal.to_s << 'th'
   else
     cardinal.to_s << %w{th st nd rd th th th th th th}[cardinal %

10]
end
end

end
end

which is called from:

Page.send :include, StartDate::PageExtensions

The tag works fine when I don’t call the new method, but when I do I’m
getting an “undefined method ‘ordinal’ error”, so I must be defining
it wrong, but how do I do it right?

Any advice?

Thanks,

Dominic

[email protected] wrote:

 else
   cardinal.to_s << %w{th st nd rd th th th th th th}[cardinal % 10]
 end

end
end

This by itself in a file should be fine. However, if you want to make
sure you’re using the existing Numeric class and not creating a new one,
change class Numeric … end to Numeric.class_eval do … end.

     cardinal.to_s << %w{th st nd rd th th th th th th}[cardinal %  

10]
end
end

end
end

Here you’ve made a class StartDate::PageExtensions::Numeric which
inherits from Page. I don’t think this is what you want to do. You
want to override the existing Ruby Numeric class.

I would take your first snippet, put it in a file
lib/numeric_extensions.rb, then explicitly require it from your
extension’s activate method.

Hope this helps!

Sean

Hi Dominic,

First off, I think what you’re trying to do is already done by a Rails
core extension to Integer. See:

http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Integer/Inflections.html

If you still want to do something like this, it needs to be more like
(and I haven’t tested this code):

module Ordinalizable
def ordinalize
cardinal = self.to_i.abs
if (10…20).include?(cardinal) then
cardinal.to_s << ‘th’
else
cardinal.to_s << %w{th st nd rd th th th th th th}[cardinal % 10]
end
end
end

Only Integers should be ordinalized

Integer.send :include, Ordinalizable

Stick this in your extension’s lib directory and explicitly require it
from the extension file.

Your first example where you monkey-patch Numeric should have worked
(depending of course on if the file was loaded), however, like I said
above, Floats and most of the other Numerics probably shouldn’t be
ordinalized. I think module mixin is generally cleaner from a design
standpoint (opinions may vary), though.

Your second one has a couple of problems, which I point out not out of
toolishness, but in the hope that it’s helpful: :wink:

  1. Numeric doesn’t need to inherit from Page. This is only necessary
    for new Page types, which will appear in the Page Type select box.

  2. Putting a class inside an extension is often a good way to keep
    your namespace clean, but you probably shouldn’t do it for anything
    that inherits from ActiveRecord::Base.

  3. It looks like what you’ve got is a case of mixed metaphors here:
    you’re trying to mixin a module to put an instance method into a
    class, and you’re trying to monkey-patch the class directly. Both are
    fine on their own (with varying opinions on cleanliness), but neither
    will work this way.

  4. You don’t want to include the module into Page. Since ordinalize
    assumes that self is an Integer, it doesn’t make any sense for it to
    operate on a Page. If, however, you defined a module with a number of
    tags (which it sounds like you’re also trying to do elsewhere), that
    is what you want to do to get the tags into Page.

Hope this helps,
Andrew

Many thanks for both your detailed answers, they were indeed very
helpful. I went ahead with the mixin module as I also wanted the
ordinals styled with 's. After some thought I should imagine a
much cleaner way would be by defining a regexp for the date string and
running that from the tags, but as you can probably tell I’m learning
as I go. I’m not sure well formed the tags are on the other side but
it’s seems to be working as I wanted.

For your pleasure:

   start_date = page.start_date
   sdate = start_date.strftime("%A") + " " +

start_date.strftime("%d").to_i.ordinalize + " " +
start_date.strftime("%B")
sdate

Its probably not the place to ask, but if anyone knows a simple way to
replace those ordinals in the string using regexp I would be very
gratefiul!

Thanks once again for your all help,

Dominic