3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Enumerizeの値のクラスにカスタムクラスを利用する

Posted at

enumerize-2.1.0で試しています。

value_classというREADMEに記載されていないオプションを利用すると、Enumerizeの値のクラスをvalue_classで指定したクラスに差し替えることができる。123


# Enumerize::Valueを継承するとi18n関連のメソッドもついてくるので便利
class Role < Enumerize::Value
end

class User
  extend Enumerize

  enumerize :sex, in: [:male, :female]
  enumerize :role, in: [:user, :admin], value_class: Role
end

User.sex.values.first
# => "male"

User.sex.values.first.class
# => Enumerize::Value

User.role.values.first
# => "user"
User.role.values.first.class
# => Role  <- value_classで指定したクラスになっている。

べんりっぽい。

リッチなvalue_classを作る

Enumerize::Valueのコンストラクタを確認してみると次のようになっている

# https://github.com/brainspec/enumerize/blob/v2.1.0/lib/enumerize/value.rb#L9
def initialize(attr, name, value=nil)
end

attrEnumerize::Attributeのインスタンス。name, valueenumerize :role, in: [:user, :admin]で言う所のin:の値が入る。実装はこんな感じ

# https://github.com/brainspec/enumerize/blob/v2.1.0/lib/enumerize/attribute.rb#L15
@values = Array(options[:in]).map { |v| value_class.new(self, *v) }

この実装からすると、in:に配列の配列を渡すことによって、valueにいろんな情報を持たせるとこができそうだ。
試しにJava TutorialのEnumのサンプル4をEnumerizeで実装してみる。

class Planet < Enumerize::Value
  VALUES = [
    # name       value  mass        radius
    [ :mercury,  1,     3.303e+23,  2.4397e+6  ],
    [ :venus,    2,     4.869e+24,  6.0518e+6  ],
    [ :earth,    3,     5.976e+24,  6.37814e+6 ],
    [ :mars,     4,     6.421e+23,  3.3972e+6  ],
    [ :jupiter,  5,     1.9e+27,    7.1492e+7  ],
    [ :saturn,   6,     5.688e+26,  6.0268e+7  ],
    [ :uranus,   7,     8.686e+25,  2.5559e+7  ],
    [ :neptune,  8,     1.024e+26,  2.4746e+7  ],
  ]

  G = 6.67300e-11

  attr_reader :mass, :radius

  def initialize(attr, name, value, mass, radius)
    @mass = mass
    @radius = radius

    super(attr, name, value)
  end

  def surface_gravity
    G * mass / (radius * radius)
  end

  def surface_weight(other_mass)
    other_mass * surface_gravity
  end
end

class Hoge
  extend Enumerize

  enumerize :planet,
            in: Planet::VALUES, default: :earth, value_class: Planet,
            predicates: { prefix: true }

  def initialize(planet)
    self.planet = planet
  end
end

Hoge.new(:jupiter).planet_jupiter?
# => true

Hoge.new(:jupiter).planet.class
# => Planet

earth_weight = 175
mass = earth_weight/Hoge.planet.find_value(:earth).surface_gravity

Hoge.planet.values.map do |planet|
  [planet, planet.surface_weight(mass)]
end
# => [["mercury", 66.10758266016366], ["venus", 158.374842472183], ["earth", 175.0], ["mars", 66.27900720649755], ["jupiter", 442.84756696175464], ["saturn", 186.55271929202416], ["uranus", 158.3972598931494], ["neptune", 199.20741268219018]]

うまくいってる。

  1. けっこう前から使ってたけど知らなかった。。

  2. https://github.com/brainspec/enumerize/blob/v2.1.0/lib/enumerize/attribute.rb#L14

  3. https://github.com/brainspec/enumerize/blob/v2.1.0/test/attribute_test.rb#L22

  4. https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?