0

I have class factory which looks like this:

class Base

  def self.attributes=(**keyvals)
    attr_accessor *@@attributes.keys
    define_singleton_method(:default) { new(**keyvals) }
  end

  def self.attributes
    @@attributes
  end

  def initialize(opts={})
    opts.each do |k,v|
      instance_variable_set("@#{k}", v)
    end
  end

end

Usage looks like this:

# the game
class Game < Base
  self.attributes = {
    players: {} # Hash of Player instances, keyed by name
  }
end

print Game.default.instance_variables
# => [:@player]

# a single tile
class Tile < Base
  self.attributes = {
    type: '',
    data: {}
  }
end

print Tile.default.instance_variables
# => [:@type, :@data]

# -----------------
# PROBLEM IS HERE:
# -----------------

print Game.default.instance_variables
# => [:@type, :@data]

The problem is that Game.attributes is being overwritten when I define Tile.attributes. I was expecting that the class instance variable set from Tile would be unique to Tile, but apparently this is not the case.

Is there a way to change class instance variables of a single descendent using an inherited method? Or what am I doing wrong here?

max pleaner
  • 26,189
  • 9
  • 66
  • 118
  • `@@var` is a class variable, whereas `@var` (within the scope of the class) is a class **instance** variable. See https://stackoverflow.com/q/15773552/477037 – Stefan Jan 10 '18 at 17:44
  • @Stefan sorry, i got my terminology wrong. I'm meaning to use a class variable. – max pleaner Jan 10 '18 at 17:46
  • Class variables don't work well with inheritance (did you read the linked question?). They are often considered a code smell: https://github.com/troessner/reek/blob/master/docs/Class-Variable.md – Stefan Jan 10 '18 at 17:52

0 Answers0