2014-01-17 3 views
1

Как я могу обрабатывать перечисления в рельсах? Я искал это, но не нашел никаких чистых решений. До сих пор я придумал, в том числе, озабоченность, приведенную ниже, на моделях, которые используют interactive_type_id. Это мой внешний ключ для моей таблицы перечислений в базе данных. Используя этот подход, я не должен использовать идентификаторы во всем моем коде, но при сохранении объекта, который относится к interact_type я могу сказатьКак обращаться с рельсами?

myobject.interaction_type = :file_download 

Это может затем сохраняться в базе данных с правильным идентификатором, поскольку концерн (см. ниже приведенную ниже информацию о моделях, которые используют перечисление) вернет правильный идентификатор.

module InteractionTypeEnum 
    extend ActiveSupport::Concern 

    included do 
    INTERACTION_TYPE = { file_download: 1, email: 2, telesales: 3, registration: 4, enrolment: 5 } 
    end 

    def interaction_type 
    INTERACTION_TYPE.key(read_attribute(:interaction_type_id)).to_s.gsub('_',' ').capitalize 
    end 

    def interaction_type=(s) 
    write_attribute(:interaction_type_id, INTERACTION_TYPE[s]) 
    end 
end  

Это просто тяжело. Должен быть более простой/чистый способ. Теперь, пытаясь написать тесты для этого, он становится еще более грязным.

Большинство причин, по которым я хочу перечислять в коде и базе данных, - это производительность (код) и отчетность (база данных).

Любая помощь приветствуется. Благодарю.

ответ

1

Я рекомендую active_enum камень.

Пример из их документы, если у вас есть целое столбец с именем sex на классе User:

class User < ActiveRecord::Base 
    enumerate :sex do 
    value :name => 'Male' 
    value :name => 'Female' 
    end 
end 

Или вы можете определить перечисление в отдельном классе:

class Sex < ActiveEnum::Base 
    value 1 => 'Male' 
    value 2 => 'Female' 
end 

class User < ActiveRecord::Base 
    enumerate :sex, :with => Sex 
end 

Мне нравится абстракции, которую он предоставляет, и это избавляет вас от необходимости создавать всю таблицу базы данных только для хранения значений перечисления.

+0

Хорошее решение, но, допустим, теперь вы сохраняете пользователя в базе данных и хотите получить доступ к полу пользователя через задний конец. Вы говорите, что это должно храниться как строка в базе данных - мужчина, женщина. Что произойдет, если ваш набор перечислений увеличится до 10 пунктов и после этого не изменится. Не хотите ли вы эту информацию в таблице в базе данных? В некоторых случаях вам также может понадобиться расширение перечисления для включения другой информации, такой как rank/order or description. Я вижу, как это полезно и чисто, но это может быть немного ограниченным. –

+0

Он хранится как целое число в базе данных, и есть гораздо больше функциональности, чем то, что я скопировал здесь (например, вы можете добавить расширенную информацию в перечисление, как вы описываете.) Я бы порекомендовал вам пойти, если бы только узнать больше об этом и посмотреть, подходит ли оно для ваших целей; Я использовал его в нескольких проектах и ​​никогда не испытывал проблем. Но, конечно, это не единственное решение (я уверен, что есть и другие переименованные камни, или вы можете катить свой собственный, как и другой ответ), и я не слишком сильно инвестировал в него, другие предложения тоже будут работать. – GMA

+0

Я проверил github. Выглядит очень хорошо, но похоже, что он не поддерживает рельсы. 4. Когда я включаю config.extend_classes = [ActiveRecord :: Base] в код и пытаюсь запустить консоль rails, я получаю /Users/ryanme/.rvm/gems/ruby [email protected]_rails_4_0/gems/activerecord-4.0.2/lib/active_record/dynamic_matchers.rb: 22: в 'method_missing ': undefined method' class_inheritable_accessor' для ActiveRecord :: Base: Class (NoMethodError) --- ---- Из того, что я прочитал, class_inheritable_accessor устарел. –

0

Я использую следующий метод, скажем, у меня есть

class PersonInfo < ActiveRecord::Base 
    belongs_to :person_info_type 
end 

и PersonInfoType простой домен таблица, содержащая возможные типы информации.

Тогда я код моей модели следующим образом:

class PersonInfoType < ActiveRecord::Base 

    PHONE = 1 
    EMAIL = 2 
    URL = 3 

end 

У меня есть семя заполняет базу данных с соответствующими данными.

И поэтому при назначении какой-то человек-информация может сделать что-то вроде

person.person_infos << PersonInfo.create(:info => 'http://www.some-url.com', :person_info_type_id => PersonInfoType::URL) 

Этот код может быть дополнительно очищен с помощью соотношений:

class PersonInfo 

    belongs_to :person_info_type 

    def self.phones 
    PersonInfo.where(:person_info_type_id => PersonInfoType::PHONE) 
    end 

end 

person.person_infos << PersonInfo.phones.create(:info => '555 12345') 
Смежные вопросы