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:
-
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.
-
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.
-
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.
-
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