Skip to content

Instantly share code, notes, and snippets.

@Integralist
Last active August 29, 2015 13:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Integralist/9910271 to your computer and use it in GitHub Desktop.
Save Integralist/9910271 to your computer and use it in GitHub Desktop.
Refactoring Ruby -> not all conditionals can be removed, and those that can can't necessarily use the standard refactoring methods such as "Replace Type Code with Module Extension", "Replace Type Code with Polymorphism" or "Replace Type Code with State/Strategy". The below examples demonstrate this.
class Foo
def initialize(a=[], b=[])
@a = a
@b = b
end
def add(item)
if item.is_a? A
@a.push item
else
@b.push item
end
end
end
class A
def initialize(name="Unknown")
@name = "A: #{name}"
@time = Time.now
end
end
class B
def initialize(name="Unknown")
@name = "B: #{name}"
@time = Time.now
end
end
foo = Foo.new
foo.add(A.new)
foo.add(B.new)
# Thanks to @clauswitt for his guidance
class Foo
def initialize(storage={})
@storage = storage
end
def add(item)
@storage[item.class] = [] unless @storage.has_key?(item.class)
@storage[item.class] << item
end
end
class A
def initialize(name="Unknown")
@name = "A: #{name}"
@time = Time.now
end
end
class B
def initialize(name="Unknown")
@name = "B: #{name}"
@time = Time.now
end
end
foo = Foo.new
foo.add(A.new)
foo.add(B.new)
# - I've assumed you've separated the items into two arrays
# because you want to select those items at some point later.
# I've refactored to 'filter' the items on the way out, rather
# than filtering them on the way in.
# - Also added a :type method rather than class checking.
# - You could even use Set instead of [] here
class Foo
def initialize(initial_items = [])
@items = initial_items
end
def add(item)
@items << item
end
def a
select(:a)
end
def b
select(:b)
end
private
def select(type)
@items.select { |item| item.type == type }
end
end
# If you wanted to create more types in the future, say :c, you
# could dynamically generate the accessors?
class A
def initialize(name="Unknown")
@name = "A: #{name}"
@time = Time.now
end
def type
:a
end
end
class B
def initialize(name="Unknown")
@name = "B: #{name}"
@time = Time.now
end
def type
:b
end
end
foo = Foo.new
foo.add(A.new)
foo.add(B.new)
@clauswitt
Copy link

of the top of my head:

class Foo
def initialize(storage={})
@storage = storage
end
def add(item)
@storage[item.class] = [] unless @storage.has_key?(item.class)
@storage[item.class] << item
end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment