Loading models in rake task

I'm working on a rake task that loads AR models from a yaml file,
which fails when I try to use a deserialized object, as its class
hasn't been loaded.

I don't know beforehand exactly which classes are in the file(s), so
need a way to load them dynamically, or load all the model classes.

Thanks in advance,
Isak

I'm not sure this is the preferred way, but if you load config/
environment.rb you will have access to (among other things) all of
your models. So, for example, assuming your task was defined in lib/
tasks/somefile.rake you could call require thusly:

require File.expand_path(File.dirname(__FILE__) + '../../../config/
environment')

-John

> I'm working on a rake task that loads AR models from a yaml file,
> which fails when I try to use a deserialized object, as its class
> hasn't been loaded.
>
> I don't know beforehand exactly which classes are in the file(s), so
> need a way to load them dynamically, or load all the model classes.

I'm not sure this is the preferred way, but if you load config/
environment.rb you will have access to (among other things) all of
your models. So, for example, assuming your task was defined in lib/
tasks/somefile.rake you could call require thusly:

require File.expand_path(File.dirname(__FILE__) + '../../../config/
environment')

I've made my task depend on the :environment task, which i believe
takes care of this.

I can use my models, but it looks like they are loaded lazily and
aren't available to YAML unless i explicitly use them beforehand.

E.g.:

# this works
User.class.to_s # load the User class
my_user = YAML.load(user_data)
puts my_user.name

# while this throws: undefined method `name' for #<YAML::Object:0x343ed94>
my_user = YAML.load(user_data)
puts my_user.name

Suggestions appreciated,

Thanks,
Isak

It feels kludgy, but you could explicitly load the models ahead of
time:

task :preload => :environment do
  # relative path assumes this is defined in a file in lib/tasks
  Dir[File.dirname(__FILE__) + '/../../app/models/*.rb'].each do |
file>
    require file
  end
  ...
end

Alternatively - this feels even more kludgy - you could test whether
the class appears to be loaded and, if necessary, load the class and
reload the YAML data:

task :dynamic => :environment do
  my_user = YAML.load(user_data)
  unless my_user.respond_to?(:name)
    Object.const_get(my_user.class)
    my_user = YAML.load(user_data)
  end
  ...
end

-John

Perhaps a bit kludgy yes, but it seems to work fine. Thanks!

Isak