Access class name from mixin

mixins, ruby, ruby-on-rails

Solution

The name of a class is the `name` of a class:

module Foo
  def whoami
    self.name
  end
end

class Bar
  extend Foo
end

p Bar.whoami #=> "Bar"

I would not create some string; I would either create a new hash of settings per class:

module Settings
  def setting(name,value=:GIT_DA_VALUE)
    @_class_settings ||= {}  # Create a new hash on this object, if needed
    if value==:GIT_DA_VALUE
      @_class_settings[name]
    else
      @_class_settings[name] = value
    end
  end
end

class Foo
  extend Settings
end
class Bar
  extend Settings
end
Foo.setting(:a,42)

p Foo.setting(:a), #=> 42
  Foo.setting(:b), #=> nil
  Bar.setting(:a)  #=> nil  (showing that settings are per class)

...or else I would index a single global hash (if required) by the class object itself:

module Settings
  # A single two-level hash for all settings, indexed by the object
  # upon which the settings are applied; automatically creates
  # a new settings hash for each object when a new object is peeked at
  SETTINGS = Hash.new{ |h,obj| h[obj]={} }
  def setting(name,value=:GIT_DA_VALUE)
    if value==:GIT_DA_VALUE
      SETTINGS[self][name]
    else
      SETTINGS[self][name] = value
    end
  end
end

# Usage is the same as the above; settings are unique per class

Problem

In my Rails project, I store global settings in a string-indexed hash where each class (model) has a "namespace" for its own settings. For example, the News model might have the settings 'news.stories_per_page' or 'news.show_date'. To avoid having to name-mangle everywhere, I have a mixin which provides general class methods for accessing these settings. Using this mixin, I could access 'news.show_date' with code like: ``` News.setting :show_date => true ``` Now, here's the problem. In order to generate the string 'news.show_date', I need to know the class name of the model that mixes my module in. But within a class method, ``` self.class => Class ``` which is not very helpful to me. In my naïve implemetation, this caused all models to store their settings under the 'class.' namespace, which is unacceptable. I apologise for not being able to state the problem more clearly. I'm somewhat new to Ruby and have not understood its object model fully. The problem may have something to do with the kludge which seems to be required in Ruby to mix in class methods.

Original source