Module: Quant::Attributes::InstanceMethods

Defined in:
lib/quant/attributes.rb

Instance Method Summary collapse

Instance Method Details

#default_value_for(entry, new_tick) ⇒ Object

The default value can be one of the following:

  • A symbol that is a method on the instance responds to

  • A symbol that is a method that the instance’s tick responds to

  • A Proc that is bound to the instance

  • An immediate value (Integer, Float, Boolean, etc.)



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/quant/attributes.rb', line 132

def default_value_for(entry, new_tick)
  # let's not assume tick is always available/implemented
  # can get from instance or from initializer passed here as `new_tick`
  current_tick = new_tick
  current_tick ||= tick if respond_to?(:tick)

  if entry[:default].is_a?(Symbol) && respond_to?(entry[:default])
    send(entry[:default])

  elsif entry[:default].is_a?(Symbol) && current_tick.respond_to?(entry[:default])
    current_tick.send(entry[:default])

  elsif entry[:default].is_a?(Proc)
    instance_exec(&entry[:default])

  else
    entry[:default]
  end
end

#each_attribute(&block) ⇒ Object

Iterates over all defined attributes in a child => parent hierarchy, and yields the name and entry for each.



116
117
118
119
120
121
122
123
124
125
# File 'lib/quant/attributes.rb', line 116

def each_attribute(&block)
  klass = self.class
  loop do
    attributes = Attributes.registry[klass]
    break if attributes.nil?

    attributes.each{ |name, entry| block.call(name, entry) }
    klass = klass.superclass
  end
end

#initialize(*args, **kwargs) ⇒ Object

Makes some assumptions about the class’s initialization having a tick keyword argument.

The challenge here is that we prepend this module to the class, and we are initializing attributes before the owning class gets the opportunity to initialize variables that we wanted to depend on with being able to define a default value that could set default values from a tick method.

Ok for now. May need to be more flexible in the future. Alternative strategy could be to lazy eval the default value the first time it is accessed.



109
110
111
112
# File 'lib/quant/attributes.rb', line 109

def initialize(*args, **kwargs)
  initialize_attributes(tick: kwargs[:tick])
  super(*args, **kwargs)
end

#initialize_attributes(tick:) ⇒ Object

Initializes the defined attributes with default values and defines accessor methods for each attribute. If a child class redefines a parent’s attribute, the child’s definition will be used.



156
157
158
159
160
161
162
163
164
165
166
# File 'lib/quant/attributes.rb', line 156

def initialize_attributes(tick:)
  each_attribute do |name, entry|
    # use the child's definition, skipping the parent's
    next if respond_to?(name)

    ivar_name = "@#{name}"
    instance_variable_set(ivar_name, default_value_for(entry, tick))
    define_singleton_method(name) { instance_variable_get(ivar_name) }
    define_singleton_method("#{name}=") { |value| instance_variable_set(ivar_name, value) }
  end
end

#to_hHash

Serializes keys that have been defined as serializeable attributes Key values that are nil are removed from the hash

Returns:

  • (Hash)

    The serialized attributes as a Ruby Hash.



171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/quant/attributes.rb', line 171

def to_h
  {}.tap do |key_values|
    each_attribute do |name, entry|
      next unless entry[:key]

      ivar_name = "@#{name}"
      value = instance_variable_get(ivar_name)

      key_values[entry[:key]] = value if value
    end
  end
end

#to_json(*args) ⇒ String

Serializes keys that have been defined as serializeable attributes Key values that are nil are removed from the hash

Returns:

  • (String)

    The serialized attributes as a JSON string.



187
188
189
# File 'lib/quant/attributes.rb', line 187

def to_json(*args)
  Oj.dump(to_h, *args)
end