Listigeblaj datumeroj en ActiveRecord

Foje oni volas limigi la eblajn valorojn por datumero en ActiveRecord. Unu ebleco estas krei liston de la simboloj kaj tiam krei datumkontrolilon. Ekzemple:


class Konkursanto
  konkursaj_tipoj = [:komencanto, :progresanto]

  validates :konkurstipo, inclusion: { in: konkursaj_tipoj }
end

class KreiKonkursantoj < ActiveRecord::Migration
  def change
    create_table :konkursantos do |tablo|
      tablo.string :konkurstipo, default: "komencanto"
    end
  end
end

kaj en la datumbazo vi aldonas la konkurstipo kiel ĉeno.

Rails 4.1 kaj poste

Versioj de Rails >= 4.1 enhavas novan klasfunkcion nomitan: enum. La supra ekzemplo uzanta ĉi tion estas:

class Konkursanto
  enum konkurstipo: %i(komencanto progresanto)
end

class KreiKonkursantoj < ActiveRecord::Migration
  def change
    create_table :konkursantos do |tablo|
      tablo.integer :konkurstipo, default: 0
    end
  end
end

Averto la datumbazo por ĉi tio bezonas esti entjero anstantaŭ ĉeno.

Nun vi povas atribui la datumero la rekte jene:

zam = Konkursanto.new
zam.konkurstipo = "komencanto"

ActiveRecord ankaŭ donas kelkajn helpemajn funkcojn:

  • Por legi
zam.konkurstipo #=> komencanto
  • Por atribuigi
zam.konkurstipo = "progresanto"
zam.konkurstipo = 0
zam.progresanto!
zam.konkurstipo = nil
  • Por demandi
zam.komencanto?
zam.progresanto?
zam.status.nil?
  • Por trovi
Konkursanto.komencanto

Kio okozas aŭtomate estas ke ActiveRecord tradukos la eblajn valorojn al entjeroj kaj konservas tiujn je la datumbazo. Por vidi ĉi tion vi povas demandi ActiveRecord

Konkursanto.konkurstipos
#=> {"komencanto"=>0, "progresanto"=>1}

Averto ni bezonas entajpi konkurstipos anstantaŭ konkurstipoj ĉar ActiveRecord antaŭsupozas ke la angla estas uzata.

Kiel vi vidas la tradukon al nombroj okazas laŭorde. Do vi ne povas ŝanĝi la ordon krom se vi ankaŭ ŝanĝas ĉiun valoron en la datumbazo. Vi ja povas aldoni al la fino, ĉar la nova nombro ne estos jam uzita aŭ vi povas doni malimplice la nombrojn:

class Konkursanto
  enum konkurstipo: {progresanto: 1, komencanto: 0}
end