Вопрос для Ruby Gurus (помощь в Enum-подобной реализации) - PullRequest
1 голос
/ 26 декабря 2010

Я пытаюсь сделать что-то вроде "enum".Вот моя реализация:

# Format of input hash to AnEnum::initialize is :
# {
#   Symbol => [Fixnum => String]
# }
# Example:
# {
#   :active => [1 => "Active"]
# }

class AnEnum
  @@values = nil
  def initialize(hash)
    @@values = hash
  end

  def values
    @@values
  end

  def [](symbol)
    values[symbol][0] # return the number for the symbol. e.g. 1
  end

  def text(symbol)
    values[symbol][1] # return the text for the symbol. e.g. "Active"
  end
end

Пример использования:

class MyClass1

  @@status = AnEnum.new({
      :open => [1, 'Active'],
      :closed => [2, 'Closed']
    })

  def self.Status
    @@status
  end      

end

# test it (it works!)

MyClass1.Status[:open] # => 1
MyClass1.Status.text(:open) # => "Active"

Это работает, но я хочу сделать его более "элегантным" и "динамичным":

Можно ли определить AnEnum в MyClass2 следующим образом:

class MyClass2
  define_enum "Status", :as => {
    :open => [1, 'Active'],
    :closed => [2, 'Closed']
  }
end

, чтобы они работали:

MyClass2.Status[:open] # => 1
MyClass2.Status.text(:open) # => "Active"

Таким образом, определены @@status и self.Statusв MyClass1 и выше автоматически включаются в класс при помощи «макро» -подобного вызова define_enum.

define_enum предназначен для работы подобно тому, как, например, вызов before_filter в Rails.

Возможно ли это?

Ответы [ 2 ]

1 голос
/ 17 марта 2011

Посмотрите на это: http://code.dblock.org/ShowPost.aspx?id=184 (небольшое улучшение по сравнению с http://www.rubyfleebie.com/enumerations-and-ruby/). Позволяет написать следующее.

class Gender
  include Enum

  Gender.define :MALE, "male"
  Gender.define :FEMALE, "female"
end

И, конечно,

Gender.all
Gender::MALE
1 голос
/ 26 декабря 2010

Замечательно, если вы решаете эту проблему для своей личной выгоды, однако, если это потому, что вам действительно нужна эта функциональность, существует множество драгоценных камней Ruby, которые уже делают это.Если вам нужно, чтобы каждое «Состояние» демонстрировало различное поведение, я написал полезный гем под названием classy_enum .В противном случае, - это тонна других .

Чтобы ответить на ваш вопрос, да, безусловно, возможно добавить методы класса или макросы, как вы описываете.Обзор высокого уровня будет выглядеть примерно так:

module MyEnum
  def define_enum(name, states)
    ... meta code here ...
  end
end

Тогда в вашем классе:

MyClass
  extend MyEnum

  define_enum :name, :state1 => [], :state2 => []
end

«Мета-код» - это то, где он становится сложным в зависимости от того, что вы пытаетесь сделать,Если вы собираетесь пойти по этому пути, я все равно рекомендую проверить, как другие сделали это в первую очередь.В вашем примере есть несколько странных вещей, таких как прописные имена методов (def self.Status) и переменные класса @@my_var.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...