ruby - रुबी में कक्षा को कैसे परिभाषित किया जाए?



ruby-on-rails-3 activerecord (2)

इसी तरह की स्थिति में - किसी अन्य वर्ग द्वारा आंतरिक रूप से उपयोग की जाने वाली कक्षा का मज़ाक उड़ाते हुए मैं परीक्षण करने की कोशिश कर रहा हूं - मुझे यह एक व्यावहारिक समाधान माना गया है:

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

मैंने सोचा होगा कि ऐसा करने का एक बेहतर तरीका होगा - यानी मैं पुन: उपयोग के लिए वांछित वापसी मूल्य में पास करने का कोई तरीका नहीं देख सका - लेकिन यह अब के लिए काफी अच्छा लगता है। मैं मजाक करने / कारखानों के लिए नया हूं, और मुझे किसी भी वैकल्पिक तरीकों के बारे में सुनना अच्छा लगेगा।

संपादित करें:

ठीक है, तो सब के बाद इतना समान नहीं है।

मुझे आरएसपीसी मॉक का उपयोग करके एक बेहतर तरीका मिला, आरएसपीसी Google समूह में उत्कृष्ट स्पष्टीकरण के लिए धन्यवाद:

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

रूबी में एक विधि को परिभाषित करना बहुत आसान है, मैं केवल undef METHOD_NAME उपयोग कर सकता हूं।

क्या कक्षा के लिए कुछ भी समान है? मैं MRI 1.9.2 पर हूं।

मुझे एक ActiveRecord मॉडल को परिभाषित करना है, कोड की दो पंक्तियां चलाएं, और मॉडल को अपने मूल रूप में वापस बहाल करें।

समस्या यह है कि, मेरे पास एक मॉडल Contact और मैं एक कंपनी के एपीआई का उपयोग कर रहा हूं और ऐसा होता है कि उनके पास Contact नामक कुछ कक्षा है, और मेरे मॉडल नाम को बदलना मेरे लिए बहुत काम करेगा।

इस स्थिति में मुझे क्या करना चाहिए?


Answer #1
>> 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 वर्गों में से एक को अलग नामस्थान में ले जाएं।

EDIT2 आप इस तरह अस्थायी रूप से अपनी कक्षा का नाम बदल सकते हैं:

class Foo
  def bar
    'here'
  end
end

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

फिर, इसके साथ समस्या यह है कि आपके पास अभी भी नई Contact कक्षा होगी, इसलिए आपको इसे फिर से हटाना होगा। मैं वास्तव में इसके बजाय अपनी कक्षाओं को नाम-स्थान की अनुशंसा करता हूं। यह आपको किसी लोडिंग समस्याओं से बचने में भी मदद करेगा





activerecord