-
-
Save ootoovak/5811499 to your computer and use it in GitHub Desktop.
# 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. | |
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 |
# 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 |
# This one works as I originally wanted but requires a Class check and modifying new with I'm | |
# pretty sure can lead to bad things given how Ruby handles new and initialize. | |
class MyClass | |
attr_accessor :name | |
attr_accessor :description | |
def self.new(args = {}) | |
args.is_a?(MyClass) ? args : super(args) | |
end | |
def initialize(args = {}) | |
@name = args.fetch(:name, '') | |
@description = args.fetch(:description, '') | |
end | |
def fetch(key, default_value) | |
send(key) || default_value | |
end | |
end |
Ah ok. In order to memoize the return value, you will need to keep track of all instances of that class that have been created in the system (so you can return an existing one if it matches the parameters). You could probably make MyClass
store a reference to every instance it creates and then return one of them from initialize. That said, I think having a separate MyClassFactory
that does this magic would be cleaner.
BTW your example makes name
and description
mutable. This is probably a bad idea as you will couple every user of one of these objects together in a potentially hilarious way.
Thanks for the chewy problem ;-)
HTH
/Eoin/
@eoinkelly good catch. I'll look into that potential coupling. Guess I clone values to be save?
Also, would be keen on seeing how you would write your solution if you had a chance to fork this Gist sometime.
@eoinkelly yeah that is what I was going for at first. I wanted to just send back a pointer to that object if that object was already an instance of that class. Thinking it would save CPU and Mem by not copying the values over from one instance to another. Not that it is a huge deal (CPU/Mem) in my case but was more wondering if it could be done.