Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing models from within the lib directory in a Rails 3 project

I have a file in the lib directory that uses some constants defined in a model, like:

class User < ActiveRecord::Base
   MAX_EMAIL_ADDRESS_LENGTH = 255
end

and then I have in lib/foo.rb

module Foo
  LONG_EMAIL_ADDRESS = "[email protected]".rjust(User::MAX_EMAIL_ADDRESS_LENGTH, "a")
end

It fails due to not finding the class User. How can I load User before that file on lib?

I'm loading that file by having this in my application.rb:

config.autoload_paths += %W(#{config.root}/lib)
like image 350
pupeno Avatar asked Jul 24 '12 13:07

pupeno


4 Answers

The first part was done right:

config.autoload_paths += %W(#{config.root}/lib)

Next, it is important, module

module Foo
  ...
end

must be placed into

lib/foo.rb

file.

And then, it can be included into application code.

class Comment < ActiveRecord::Base
  include Foo
  ...
end

If file foo.rb from lib directory is not intended to be included (however it is probably a wrong way), then to use Rails models and other stuff inside this code you should put this into foo.rb:

require_relative "../config/environment.rb"
like image 137
denis.peplin Avatar answered Nov 11 '22 07:11

denis.peplin


The solution was, that my file in /lib was actually being required by a rake file, and it seems rake files are loaded before the whole auto-load system is setup by Rails, so it couldn't find the model. After I remove the require from the .rake file, everything started working.

like image 33
pupeno Avatar answered Nov 11 '22 07:11

pupeno


I know this is a old question but I've just faced the same problem and after some searches, I found a solution so I think it worth to share it.

I wanted to use a model "Foo" in one required files located in my /lib directory. First, I did this and it didn't work :

# in my rake file
task :foo_task do
  require /some_path/lib/bar.rb
end

# in /lib/bar.rb
puts "Foo = #{Foo.count} "

# => uninitialized constant Foo

After some searches, I found that to access models in my lib's files, I need to specify the environment in my task. So I just added this to my task declaration :

task :foo_task => [:environment] do

Now, when I call my task, it correctly puts the number of Foo :

# => Foo = 6
like image 3
Hito Avatar answered Nov 11 '22 07:11

Hito


It appears that your class User has not be instantiated, which seems unusual, unless you have 'user.rb' in a location other than 'models'. It is often the case that classes aren't loaded in development unless they are specifically in that directory, but one solution I use is this line that you could put just within your code that you expect to be called prior to the offending line you have..

Rails.application.eager_load! if Rails.env == "development"

The conditional part is probably unnecessary, but I include it just to be certain its effect only occurs in development.

like image 1
Carson Cole Avatar answered Nov 11 '22 07:11

Carson Cole