lista - manejo de objetos en ruby
¿Cómo definir la clase en Ruby? (2)
En una situación similar - burlarse de una clase utilizada internamente por otra clase que estoy tratando de probar - encontré que esta es una solución viable:
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
Hubiera pensado que habría una mejor manera de hacerlo, es decir, no podría ver una forma de pasar el valor de retorno deseado para su reutilización, pero por ahora parece lo suficientemente bueno. Soy nuevo en burlas / fábricas, y me encantaría saber acerca de cualquier método alternativo.
Editar:
Ok, entonces no tan similar después de todo.
Encontré una mejor manera de utilizar el simulacro de RSpec, gracias a una excelente explicación en el grupo de Google RSpec :
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
Desdefinir un método en Ruby es bastante simple, solo puedo usar undef METHOD_NAME
.
¿Hay algo similar para una clase? Estoy en MRI 1.9.2
.
Tengo que definir un modelo de ActiveRecord, ejecutar dos líneas de código y restaurar el modelo a su forma original.
El problema es que tengo un modelo de Contact
y estoy usando la API de una empresa, y sucede que tienen una clase llamada Contact
, y cambiar el nombre de mi modelo sería mucho trabajo para mí.
¿Que puedo hacer en esta situacion?
>> 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
EDITAR Acaba de notar su edición, eliminar la constante probablemente no sea la mejor manera de lograr lo que está buscando. ¿Por qué no simplemente mover una de las clases de Contact
a un espacio de nombres separado?
EDIT2 También puede cambiar el nombre de su clase temporalmente así:
class Foo
def bar
''here''
end
end
TemporaryFoo = Foo
Object.send(:remove_const, :Foo)
# do some stuff
Foo = TemporaryFoo
Foo.new.bar #=> "here"
Nuevamente, el problema con esto es que todavía tendrá la clase de Contact
más nueva, por lo que tendrá que eliminarla nuevamente. En realidad, recomendaría espaciar los nombres de tus clases. Esto también te ayudará a evitar problemas de carga