BrantDFaulkner
BrantDFaulkner

Reputation: 33

Returning Module Class instead of Model Class with self.class Ruby/Rails

I am trying to DRY my code by implementing modules. However, I have constants stored in models (not the module) that I am trying to access with self.class.

Here are (I hope) the relevant snippets:

module Conversion
  def constant(name_str)
    self.class.const_get(name_str.upcase)
  end
end

module DarkElixir
  def dark_elixir(th_level)
    structure.map { |name_str| structure_dark_elixir(name_str, th_level) if constant(name_str)[0][:dark_elixir_cost] }.compact.reduce(:+)
  end
end

class Army < ActiveRecord::Base
  include Conversion, DarkElixir

  TH_LEVEL = [...]
end

def structure_dark_elixir(name_str, th_level)
  name_sym = name_str.to_sym
  Array(0..send(name_sym)).map { |level| constant(name_str)[level][:dark_elixir_cost] }.reduce(:+) * TH_LEVEL[th_level][sym_qty(name)]
end

When I place the structure_dark_elixir method inside the DarkElixir module, I get an error, "uninitialized constant DarkElixir::TH_LEVEL"

While if I place it inside the Army class, it finds the appropriate constant.

I believe it is because I am not scoping the self.constant_get correctly. I would like to keep the method in question in the module as other models need to run the method referencing their own TH_LEVEL constants.

How might I accomplish this?

Upvotes: 1

Views: 952

Answers (2)

BrantDFaulkner
BrantDFaulkner

Reputation: 33

Ugh. Method in question uses two constants. It was the second constant that was tripping up, not the first. Added "self.class::" prior to the second constant--back in business.

def structure_dark_elixir(name_str, th_lvl)
  name_sym = name_str.to_sym
  Array(0..send(name_sym)).map { |level| constant(name_str)[level][:dark_elixir_cost] }.reduce(:+) * self.class::TH_LEVEL[th_lvl][sym_qty(name_str)]
end 

Upvotes: 1

EugZol
EugZol

Reputation: 6545

Why not just use class methods?

module DarkElixir
  def dark_elixir(th_level)
    # simplified example
    th_level * self.class.my_th_level
  end
end

class Army < ActiveRecord::Base
  include DarkElixir

  def self.my_th_level
    5
  end
end

Upvotes: 1

Related Questions