-
-
Save eoinkelly/5811944 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rspec' | |
# This class can be initialised with one of | |
# * a hash | |
# * another instance of the object | |
# and it will have the same result | |
class Thing | |
attr_accessor :name | |
attr_accessor :description | |
def initialize(args = {}) | |
@name = args.fetch(:name, '') | |
@description = args.fetch(:description, '') | |
end | |
def fetch(key, default_value) | |
send(key) || default_value | |
end | |
# This is required for == to determine that both objects are equal | |
def ==(o) | |
(name == o.name) && (description == o.description) | |
end | |
end | |
describe Thing do | |
let(:hash) { { name: 'Duck Type', description: 'Quacks like a duck?' } } | |
it "can be initialised with an instance of Hash representing the attributes" do | |
a = Thing.new(hash) | |
expect(a.name).to eq(hash[:name]) | |
expect(a.description).to eq(hash[:description]) | |
end | |
it "can be initialised with another instance of Thing" do | |
a = Thing.new(hash) | |
b = Thing.new(a) | |
expect(b.name).to eq(hash[:name]) | |
expect(b.description).to eq(hash[:description]) | |
end | |
it 'the created instance should be the same whether we initialise with Hash instance or Thing instance' do | |
a = Thing.new(hash) | |
b = Thing.new(a) | |
expect(a.name).to eq(b.name) | |
expect(a.description).to eq(b.description) | |
expect(a).to eq(b) | |
end | |
end | |
class MemoizedThing | |
@@instances = {} | |
attr_accessor :thing | |
def initialize(thing) | |
new = Thing.new(thing) | |
key = [new.name, new.description] | |
old = @@instances[key] | |
if old | |
@thing = old | |
else | |
@thing = new | |
@@instances[key] = new | |
end | |
end | |
end | |
describe MemoizedThing do | |
let(:hash) { { name: 'Duck Type', description: 'Quacks like a duck?' } } | |
it "re-uses old instances of thing if any are available" do | |
a = MemoizedThing.new(hash) | |
b = MemoizedThing.new(hash) | |
expect(a.thing).to equal(b.thing) | |
end | |
it "creates a new instance of thing if an old one cannot be found" do | |
a = MemoizedThing.new(hash) | |
expect(a.thing).to be_instance_of(Thing) | |
end | |
it "connects together instances of Thing in potentially bad/hilarious ways" do | |
peacenik = MemoizedThing.new(hash) | |
warmonger = MemoizedThing.new(hash) | |
peacenik.thing.name = "Make love not war" | |
warmonger.thing.name = "Kill 'em all" | |
expect(peacenik.thing.name).to eq("Kill 'em all") # Hmmm ... | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Want to pass in a hash or instance of object. Was hoping to avoid is_a? or creating a new object but | |
# think that can only be done with is_a? or overriding new. Also, I might be missing the point as | |
# avoiding is_a? should mean I am using Duck Typing but if I'm using Duck Typing then I shouldn't be | |
# checking object equality anyway. See RSpec test for details. | |
class MyClass | |
attr_accessor :name | |
attr_accessor :description | |
def initialize(args = {}) | |
@name = args[:name] | |
@description = args[:description] | |
end | |
end | |
describe MyClass do | |
let(:hash) { { name: 'Duck Type', description: 'Quacks like a duck?' } } | |
before do | |
@my_instance_1 = MyClass.new(hash) | |
@my_instance_2 = MyClass.new(@my_instance_1) | |
end | |
it 'this is preferable' do | |
@my_instance_1.should equal(@my_instance_2) | |
end | |
it 'this is ok' do | |
@my_instance_1.should eq(@my_instance_2) | |
end | |
end | |
# Possilbe solutions involve overriding MyClass.new or buidling a constructor | |
# http://stackoverflow.com/questions/4888786/how-can-i-change-the-return-value-of-a-class-constructor-in-ruby |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Good old Rubber Duck Debugging | |
# Will only pass 1 of 2 tests | |
class MyClass | |
attr_accessor :name | |
attr_accessor :description | |
def initialize(args = {}) | |
@name = args.fetch(:name, '') | |
@description = args.fetch(:description, '') | |
end | |
def fetch(key, default_value) | |
send(key) || default_value | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment