autoloading LoadError: Expected known_ip.rb to define KnownIp

Hello, i have a problem with autoloading model classes.
I have had similar problems before when a file's name in Rails' opinion
did not match with the name of the class defined inside, but eventually
everything worked, so i didn't look into details.
This time the problem comes from running Unit Tests and does not want to
go away.

I have a model class KnownIP defined in a file named "known_ip.rb"
(rather than "known_i_p.rb").
This file name was generated by the model generator, in i prefer it this
way.
In any case, the application works.

The database table is called "known_ips".

To my test_helper.rb i added

  set_fixture_class :known_ips => KnownIP,

(otherwise it would guess "KnownIp").

Now, when it try to run Unit Tests, i get an error:

LoadError: Expected .../known_ip.rb to define KnownIp.
gems/activesupport-3.1.0.rc6/lib/active_support/dependencies.rb:486:in
`load_missing_constant'

I looked into the source and experimented a bit.
I would be ready to say that autoloading loads everything in the models
directory, and KnownIP class gets defined just fine, but then Rails gets
surprised that it has loaded a file named "known_ip.rb" but has no class
named "KnownIp" (even though such class was never mentioned anywhere).

However, if i rename known_ip.rb to foo.rb, Rails does not complain that
"Expected .../foo.rb to define Foo", and everything works.
But i am picky and do not want a class named "KnownIP" to be defined in
a filed named "foo.rb".

Can anybody please explain this or tell how to just load a file,
without complains from Rails about what has not been defined inside?

Thanks.

Alexey.

I've found a recent similar question on StackOverflow:

http://stackoverflow.com/questions/7081782/inconsistent-loaderror-behavior-with-lib-namespacing-autoloading/7093083

I should probably add that adding explicit "require" or "load" did not
help.

If I'm not mistaking, Rails in any case when found file name(.rb) named (passing .tableize method) as a table name, it accepts that file as a model file and seeking the class according to a convention(!) passing .classify.constantize chunk of methods. In your case you have to play with:
1) rename table name "known_ips" to "known_ip_addresses" you are picky :slight_smile:
2) set_table_name "known_ip_addresses" to a KnownIP class.
3) file name "known_ip" you can leave as is.

Valery Kvon wrote in post #1017132:

If I'm not mistaking, Rails in any case when found file name(.rb) named
(passing .tableize method) as a table name, it accepts that file as a
model file and seeking the class according to a convention(!) passing
.classify.constantize chunk of methods. In your case you have to play
with:
1) rename table name "known_ips" to "known_ip_addresses" you are picky
:slight_smile:
2) set_table_name "known_ip_addresses" to a KnownIP class.
3) file name "known_ip" you can leave as is.

Thanks for the answer.

2) yes, i have set the table name in my class with set_table_name.

1,3) i do not want to rename the table or the class, or the file yet, as
the application works fine.
I just want to find out how to override Rails autoloading in this case
(for Unit Tests).

I have tried putting "autoload" in my test_helper.rb, but it didn't work
because (i cheated in my question) my KnownIP is in Admin module, so it
is Admin::KnownIP, and autoload does not want to accept

  autoload 'Admin::KnownIP', path

with an error: "autoload must be constant name: Admin::KnownIP
(NameError)"

I have not tested yet if autoload in this case would work without
Admin::.

Alexey.

I have advanced a bit: the error does not show up if i comment out

  fixtures :all

in test_helper.rb and do not run known_ip_test.rb.
I need to find out now how to load the known_ips.yml fixture and
known_ip.rb class definition without complains from rails...

I am sorry, i have cheated.
I tried with a new application, and in the described above case there
were no errors, i only had to add

    set_fixture_class :known_ips => KnownIP

AFTER `fixtures :all` in `test_helper.rb`

In my application, however, the class actually is `Admin::KnownIP`, and
adding

    set_fixture_class 'admin/known_ips' => Admin::KnownIP

does not help for some reason...
I'll keep trying.

I couldn't make it work with Admin:: namespace and submitted a bug
report:

https://github.com/rails/rails/issues/2572

Please comment.

Alexey.