如何在Ruby中取消定义类?

在Ruby中定义一个方法非常简单,我可以使用undef METHOD_NAME

有什么类似的课程? 我在MRI 1.9.2

我必须取消定义ActiveRecord模型,运行两行代码,并将模型恢复到原始forms。

问题是,我有一个模型Contact ,我正在使用一个公司的API,碰巧他们有一些叫做Contact类,改变我的模型名称将是很多工作对我来说。

在这种情况下我能做些什么?

 >> class Foo; end => nil >> Object.constants.include?(:Foo) => true >> Object.send(:remove_const, :Foo) => Foo >> Object.constants.include?(:Foo) => false >> Foo NameError: uninitialized constant Foo 

编辑只要注意到你的编辑,删除常量可能不是实现你要找的东西的最好方法。 为什么不把其中一个Contact人类移动到一个单独的名称空间。

编辑2你也可以像这样临时重命名你的类:

 class Foo def bar 'here' end end TemporaryFoo = Foo Object.send(:remove_const, :Foo) # do some stuff Foo = TemporaryFoo Foo.new.bar #=> "here" 

同样,这样做的麻烦是,你仍然有新的Contact人类,所以你必须再次删除。 我真的会build议名称间隔你的class级。 这也将帮助您避免任何加载问题

在类似的情况下 – 嘲笑另一个class级内部使用的class级,我尝试testing – 我发现这是一个可行的解决scheme:

 describe TilesAuth::Communicator do class FakeTCPSocket def initialize(*_); end def puts(*_); end end context "when the response is SUCCESS" do before do class TilesAuth::Communicator::TCPSocket < FakeTCPSocket def gets; 'SUCCESS'; end end end after { TilesAuth::Communicator.send :remove_const, :TCPSocket } it "returns success" do communicator = TilesAuth::Communicator.new host: nil, port: nil, timeout: 0.2 response = communicator.call({}) expect(response["success"]).to eq(true) expect(response).not_to have_key("error") expect(response).not_to have_key("invalid_response") end end end 

我原以为会有更好的方法来做到这一点 – 也就是说,我看不出有什么方法可以通过期望的返回值来重复使用,但是现在看起来已经足够好了。 我是新来的嘲笑/工厂,我很想听听任何其他方法。

编辑:

好的,毕竟不是那么相似。

使用RSpec模拟,我发现了一个更好的方法,这要感谢RSpec Google Group的一个很好的解释 :

 context "with socket response mocked" do let(:response) do tcp_socket_object = instance_double("TCPSocket", puts: nil, gets: socket_response) class_double("TCPSocket", new: tcp_socket_object).as_stubbed_const communicator = TilesAuth::Communicator.new host: nil, port: nil, timeout: 0.2 communicator.call({}) end context "as invalid JSON" do let(:socket_response) { 'test invalid json' } it "returns an error response including the invalid socket response" do expect(response["success"]).to eq(false) expect(response).to have_key("error") expect(response["invalid_response"]).to eq(socket_response) end end context "as SUCCESS" do let(:socket_response) { 'SUCCESS' } it "returns success" do expect(response["success"]).to eq(true) expect(response).not_to have_key("error") expect(response).not_to have_key("invalid_response") end end end