как (заменить | создать) поле enum на миграциях rails 2.0? - PullRequest
28 голосов
/ 29 марта 2009

Я хотел бы создать поле enum при sone-миграции. Я пытаюсь выполнить поиск в Google, но не могу найти способ сделать это в процессе миграции.

единственное, что я нашел, было

  t.column :status, :enum, :limit => [:accepted, :cancelled, :pending]

но похоже, что приведенный выше код работает только на rails 1.xxx и, так как я использую rails 2.0

это то, что я пытался, но это не удается

class CreatePayments < ActiveRecord::Migration
  def self.up
    create_table :payments do |t|
      t.string :concept
      t.integer :user_id
      t.text :notes
      t.enum :status, :limit => [:accepted, :cancelled, :pending]

      t.timestamps
    end
  end

  def self.down
    drop_table :payments
  end
end

Итак, если это не разрешено, как вы думаете, что может быть хорошим решением? просто текстовое поле, и проверка по модели?

Ответы [ 10 ]

36 голосов
/ 10 июля 2009

Вы можете вручную указать тип, используя вместо этого метод t.column. Rails интерпретирует это как строковый столбец, и вы можете просто добавить валидатор в модель, как предложил Павел:

class CreatePayments < ActiveRecord::Migration
  def self.up
    create_table :payments do |t|
      t.string :concept
      t.integer :user_id
      t.text :notes
      t.column :status, "ENUM('accepted', 'cancelled', 'pending')"

      t.timestamps
    end    
  end

  def self.down
    drop_table :payments
  end
end

class Payment < ActiveRecord::Base
  validates_inclusion_of :status, :in => %w(accepted cancelled pending)
end
24 голосов
/ 12 мая 2009

Посмотрите на совет № 3 на http://zargony.com/2008/04/28/five-tips-for-developing-rails-applications

Это именно то, что вам нужно!

 class User < ActiveRecord::Base
   validates_inclusion_of :status, :in => [:active, :inactive]

   def status
     read_attribute(:status).to_sym
   end

   def status= (value)
     write_attribute(:status, value.to_s)
   end
 end

НТН

9 голосов
/ 12 августа 2009

Вы можете попробовать (очень) исчерпывающий gem enumerated_attribute gem ИЛИ пойти с этим простым обходным путем:

class Person < ActiveRecord::Base
  SEX = [:male, :female]

  def sex
    SEX[read_attribute(:sex)]
  end

  def sex=(value)
    write_attribute(:sex, SEX.index(value))
  end
end

А затем объявить атрибут sex как целое число:

t.integer :sex

Это сработало очень хорошо для меня! = D

4 голосов
/ 30 марта 2009

У меня есть десятки этих маленьких перечислений, по 3-300 записей в каждом. Я реализую их как справочные таблицы. У меня нет файла модели для каждого; Я использую метапрограммирование для генерации модели для каждой из них, поскольку каждая таблица имеет одинаковый набор столбцов (идентификатор, имя, описание).

Поскольку в некоторых наборах было достаточно элементов, чтобы оправдать собственную таблицу, было более логично переместить их все в таблицы. Еще один вариант, если у вас будет больше перечислений позже.

РЕДАКТИРОВАТЬ: Вот как я генерирую модели:

ACTIVE_RECORD_ENUMS = %w{
  AccountState
  ClientType
  Country
  # ...
}

ACTIVE_RECORD_ENUMS.each do |klass|
  eval "class #{klass} < ActiveRecord::Base; end"
  klass.constantize.class_eval do
    class << self

      def id_for(name)
        ids[name.to_s.strip.humanize.downcase]
      end

      def value_for(id)
        values[id.to_i]
      end

      def values
        @values ||= find(:all).inject({}) {|h,m| h[m.send(primary_key)] = m.name; h}
      end

      def ids
        @ids ||= self.values.inject({}) {|h, {k, v}| h[v.downcase] = k; h}
      end

    end
  end
end

Этот файл находится в каталоге моделей и включен в application_config.rb. Это позволяет мне делать такие вещи:

AccountState.ids 
# => {"active" => 1, "deleted" => 2}
AccountState.values 
# => {1 => "Active", 2 => "Deleted"}
AccountState.id_for("Active") 
# => 1
AccountState.value_for(1) 
# => "active"
3 голосов
/ 15 июля 2009

Аналогично, камень enumerated_attribute управляет перечислениями на уровне объекта.

enum_attr :status, %w(accepted cancelled ^pending)

Определить строку в миграции

t.string :status 

Также предоставляет некоторые полезные функции, такие как методы динамических предикатов.

http://github.com/jeffp/enumerated_attribute/tree/master

3 голосов
/ 10 апреля 2009

Вы смотрели на плагин enum-column на RubyForge?

2 голосов
/ 29 марта 2009

Добавить следующее:

module ActiveRecord
  module ConnectionAdapters #:nodoc:
    class TableDefinition
      def enum(*args)
        options = args.extract_options!
        column_names = args

        column_names.each { |name| column(name, 'enum', options) }
      end
    end
  end
end

в lib / enum / table_definition.rb и включите его в свой init.rb.

0 голосов
/ 25 февраля 2012

С simple_form я использую это:

<%= f.input :gender, :collection => {'Male' => 'male','Female' => 'female'}, :include_blank => false %>
0 голосов
/ 31 марта 2009

Другой вариант: перейти на SQL.

def self.up
  execute "ALTER TABLE `payments` ADD `status` ENUM('accepted', 'cancelled', 'pending')"
end
0 голосов
/ 30 марта 2009

хорошо, просто прочитайте API всех рельсов и нашли то, что мне нужно, и мне это не нравится :( Rails не поддерживает emum как нативный тип при переносе, здесь - это информация, мне нужно найти плагин или другой метод.

Я буду держать вас в курсе.

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