Ruby: importing two modules/classes of the same name
When my system requires two classes or modules of the same name, what can I do to specify which I mean?
I'm using rails (new to it), and one of my models is named "Thread". When I try to refer to the class "Thread" in thread_controller.rb, the system returns some other constant of the same name.
<thread.rb>
class Thread < ActiveRecord::Base
def self.some_class_method
end
end
<thread_controller.rb>
class ThreadController < ApplicationControlle开发者_C百科r
def index
require '../models/thread.rb'
@threads = Thread.find :all
end
end
When I try Thread.find(), I get an error saying that Thread has no method named find. When I access Thread.methods, I don't find my some_class_method method among them.
Any help? (And don't bother posting "just name your model something else." It's not helpful to point out obvious compromises.)
You could put your app into its own namespace.
<my_app/thread.rb>
module MyApp
class Thread
end
end
No really, name your model something else.
Thread
is a reserved constant in Ruby and overriding that constant is only going to make you run into trouble. I compromised for my application and called it Topic
instead.
If you absolutely must overwrite an existing constant, you can do something like this:
# use Object to make sure Thread is overwritten globally
# use `send` because `remove_const` is a private method of Object
# Can use OldThread to access already existing Thread
OldThread = Object.send(:remove_const, :Thread)
# define whatever you want here
class MyNewThread
...
end
# Now Thread is the same as MyNewThread
Object.send(:const_set, :Thread, MyNewThread)
Obviously anything that relied on the pre-existing Thread
would be busted unless you did some kind of monkey-patching.
Just because this kind of thing can be done, doesn't mean it should be. But in certain circumstances it can be handy, for example in tests you can override a remote data source with your own 'dumb' object.
精彩评论