Getting class in /lib folder to see a model (const_missing)?

Hello,

I wrote a new class that I decided to put in the /app/lib folder. Part way through one of the methods, I call #new on the model, update some of the fields and then call #save (on the model).

When I do this though, I get a 'const_missing' error coming from Active Support. Here's the error:

"......./lib/active_support/dependencies.rb:105:in `const_missing': uninitialized constant ClassA::ModelA (NameError)"

The 'ModelA' is the model I'm trying to access, and 'ClassA' is the class in /app/lib/class_a.rb. I'm not sure why it seems to think that ModelA is a part of ClassA, perhaps that's the problem?

I would have probably just used "require ../models/model_a.rb", but I found the following at StackOverflow:

"One way to solve this would be to explicitly require the model file aircraft.rb. However, you will find this approach quickly leads to insanity as it will break the Rails auto-loader in subtle and astonishing ways. Rails is much easier if you work with the Rails class loader, not against it."

Source: http://stackoverflow.com/questions/326277/rails-calling-a-model-class-in-a-library

I then found an example at http://www.strictlyuntyped.com/2008/06/rails-where-to-put-other-files.html that suggests adding this to the file in the /app/lib folder:

  def self.included(base)      base.extend(ClassMethods)   end

And then creating a file in /config/initializers with the following:

  require 'rails_extensions/user_logger'

  ActionController::Base.class_eval do     include ActionController::UserLogger   end

Being new to Ruby/Rails, I'm really not sure what this supposed to do, but I'm guessing it will work. That post was written in 2008 though, so I'm thinking there may be a better way for this.

Does anyone have a suggestion as to the best way to get a class in the /app/lib folder to see a model?

Thank you very much, Mike

That can indeed happen (the thing that breaks is usually the code reloading in development mode). Does the rest of your app pick up this model automatically. How/where is this class in /lib being used ?

Fred

Frederick Cheung wrote:

I would have probably just used "require ../models/model_a.rb", but I found the following at StackOverflow:

"One way to solve this would be to explicitly require the model file aircraft.rb. However, you will find this approach quickly leads to insanity as it will break the Rails auto-loader in subtle and astonishing ways. Rails is much easier if you work with the Rails class loader, not against it."

That can indeed happen (the thing that breaks is usually the code reloading in development mode). Does the rest of your app pick up this model automatically. How/where is this class in /lib being used ?

Fred

Hi Fred,

Thanks for your response. The other parts of the app (i.e. the controllers) do seem to pick up this model. The class in the /lib folder is being used separately. I'm currently running it manually, but I'm looking into running it automatically using a cron job or something similar later on.

So, it's not included by another file at the moment, as it's meant to run as a standalone script. (I'm guessing that may have fixed the problem if that file already had access to the model.)

Thanks, Mike

Thanks for your response. The other parts of the app (i.e. the controllers) do seem to pick up this model. The class in the /lib folder is being used separately. I'm currently running it manually, but I'm looking into running it automatically using a cron job or something similar later on.

So, it's not included by another file at the moment, as it's meant to run as a standalone script. (I'm guessing that may have fixed the problem if that file already had access to the model.)

What does running it manually mean - is the rails environment loaded ? If it isn't then you have your answer (since one of the things that gets you is rails' magic file loader)

Fred

Shouldn't it be in

{Rails.root}/lib/class_a.rb

rather than

{Rails.root}/app/lib/class_a.rb

???

Frederick Cheung wrote:

Thanks for your response. The other parts of the app (i.e. the controllers) do seem to pick up this model. The class in the /lib folder is being used separately. I'm currently running it manually, but I'm looking into running it automatically using �a cron job or something similar later on.

So, it's not included by another file at the moment, as it's meant to run as a standalone script. (I'm guessing that may have fixed the problem if that file already had access to the model.)

What does running it manually mean - is the rails environment loaded ? If it isn't then you have your answer (since one of the things that gets you is rails' magic file loader)

Fred

Ah! That was the problem, thank you! I've been running it using:

$ ruby app/lib/class_a.rb

(The file has a call to "run()" outside of the class methods, which calls ClassA::run.)

But by running the script using the line below, the Rails environment is loaded properly and the script works fine. :slight_smile:

$ script/runner app/lib/class_a.rb

I'm still kinda new to Rails, so I didn't know that I'd need to do that, but it makes total sense!

Shouldn't it be in

{Rails.root}/lib/class_a.rb

rather than

{Rails.root}/app/lib/class_a.rb

???

-- Rick DeNatale

By '{Rails.root}', do you mean the app's root directory, or the Rails root directory?

Anyway, I put it in {AppRoot}/app/lib because, for some reason, I thought that the {AppRoot}/lib folder was for external libraries (i.e. the ones I didn't write). I like it this way anyway because things are separated better, in my opinion. I know that the stuff in the /app directory are the things that I made, and I don't really need to visit the {AppRoot}/lib folder unless there's something in there that I want to modify.

Or is this against Rails' best practices?

Thanks again, Mike