[LRUG] Looping through classes

Ronny Ager-Wick ronny at ager-wick.com
Wed Mar 13 22:09:14 PDT 2013


I got three private replies, which were all useful, so I'll summarize here for 
reference:

On 14/03/13 08:40, Jared Fraser wrote:
> If they're all active record based, you can do ActiveRecord::Base.subclasses 
> assuming they're all loaded (like in production)
>
> Jared
I'm not using ActiveRecord, but that subclasses method sure would be useful! I 
forgot to mention I use Sinatra, not Rails, and no classes seem to respond to 
that method, unfortunately.


On 14/03/13 08:50, George Drummond wrote:
>
> On Thu, Mar 14, 2013 at 12:38 AM, Ronny Ager-Wick <ronny at ager-wick.com 
> <mailto:ronny at ager-wick.com>> wrote:
>
>     I've been trying to find a way to do this, but I may be searching for
>     the wrong terms or something because I get nowhere, even with the help
>     of my friend Google.
>     I want to loop through the defined classes to see which ons of them
>     responds to certain methods.
>     The classes I'm trying to find are Ohm Models that have a certain
>     attribute defined.
>     If I had a collection of classes, I'd probably do something like this:
>
>     classes = #get list of all classes
>     classes.each { |c|
>       # assume it's an Ohm::Model if it responds to :first
>       # maybe there's a better way of filtering out only the Ohm models
>
> # Will work if they are all Ohm::Model objects, wont however work if you 
> have something that inherits from this class like Car < Ohm::Model
> if c.is_a? Ohm::Model
Alas, that's exactly what I have.

>
>       if c.respond_to?(:first) && c.first.respond_to?(:updated_at)
>         # convert the timestamp of all records in this model.
>       end
>     end
>
>     The end objective is to convert the timestamp from the old way they used
>     to store it (Ohm-contrib 0.*) which looks like this "2011-02-25 21:54:06
>     UTC", and the new way, which are UNIX timestamps.
>     I could always just make a list of the models manually and loop through
>     them, but I want to make a reusable script that others can benefit from
>     as well.
>
>
> A better approach may be to fork the gem this is in and rewrite the methods 
> that return a UTC date and have a conditional to return the unix timestamp?
Now that is a really good idea! I'll see what I can do with that. I was 
thinking of running my conversion before upgrading Ohm and Ohm-contrib, 
because after upgrade, I can't even access any of the records:
$ irb -r ./init.rb
irb(main):001:0> Person[1]
NoMethodError: undefined method `2011-02-25 21:52:26 UTC=' for :Person
     from /home/user/app/current/vendor/ohm-1.2.0/lib/ohm.rb:1380:in `block in 
update_attributes'
     from /home/user/app/current/vendor/ohm-1.2.0/lib/ohm.rb:1380:in `each'
     from /home/user/app/current/vendor/ohm-1.2.0/lib/ohm.rb:1380:in 
`update_attributes'
     from /home/user/app/current/vendor/ohm-1.2.0/lib/ohm.rb:1142:in `load!'
     from /home/user/app/current/vendor/ohm-1.2.0/lib/ohm.rb:746:in `[]'
     from /home/user/app/current/vendor/ohm-contrib-1.2/lib/ohm/slug.rb:9:in `[]'
     from (irb):1
     from /usr/bin/irb:12:in `<main>'
irb(main):002:0>
It would be a good idea to patch the new version to actually understand old 
data! Or in worst case, patch the old version to be able to write new data.


On 14/03/13 08:56, Andrew McDonough wrote:
> Assuming all the classes you want to find inherit from Ohm::Model, you could 
> just do:
>
> Ohm::Model.subclasses
>
> Andrew
Yes they do, but I don't have that handy subclasses method. However after 
consulting with my knowledgeable friend Google, I found one ( 
https://groups.google.com/forum/?fromgroups=#!topic/comp.lang.ruby/DoEsfO9EapY 
<https://groups.google.com/forum/?fromgroups=#%21topic/comp.lang.ruby/DoEsfO9EapY>) 
that I improved a little to remove the class (Ohm::Model in my case) itself:
https://gist.github.com/agerwick/5158730

So now I can simply do:

class Class
def subclasses
class_hash = {}
ObjectSpace.each_object do |obj|
if Class == obj.class
# remove first item from ancestors, which is the class itself - it's wrong to 
say a class is a subclass of itself
if obj.ancestors[1..-1].include? self
class_hash[obj] = true
end
end
end
class_hash.keys
end
end


Ohm::Model.subclasses.each do |c|
   if c.new.respond_to?(:created_at)
     # deal with it
   end
c.new.respond_to?(:updated_at)
     # deal with it
   end
end

Thanks for the great response everybody!
Ronny.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lrug.org/pipermail/chat-lrug.org/attachments/20130314/7b8637c1/attachment-0003.html>


More information about the Chat mailing list