2009-07-24 108 views
3

我在我的数据库架构中有一个整数的项目,它们被设置为与项目相关的特定数字。例如,一个名为appointment_type的列的值可以设置为0 =未知,1 =医疗,3 =试用等等......我不想在我的rails代码中使用幻数,而更喜欢类似Enum的解决方案使代码更易于维护和阅读。此外,有多个表具有此appointment_type列,所以我希望能够使用“枚举”来解决其他列。Rails全局枚举?

我想有一个像项目的全局枚举,因为我需要访问我的模型,控制器和视图。我可能不太可能需要在我的模型中访问它,但肯定在控制器和视图中。

有没有很好的方法来处理这个问题?

回答

4

它可能不太可能,我需要 访问它在我的模型,但肯定 内的控制器和视图。

确定吗?当您谈论数据库和模式时,您正在讨论应用程序的模型部分。 我认为存储这些变量的最佳位置就是使用它们的模型。

如果这些变量属于一个单一的模式,你可以在模型本身直接存储他们:

class Item < ActiveRecord::Base 
    STATUS_UNKNOWN = 0 
    STATUS_MEDICAL = 3 
end 

那么你可以参考内部和模型范围以外的值

class Item 
    def my_method 
    STATUS_UNKNOWN 
    end 
end 

Item::STATUS_UNKNOWN # => 0 
Item.new.my_method # => 0 

当是值的枚举,Rubyists通常使用散列或数组。

class Item 
    AVAILABLE_STATUSES = { :unkwnown => 0, :medical => 3 } 

    def self.statuses 
    self.AVAILABLE_STATUSES.keys.sort 
    end 

    def self.status_value(key) 
    self.AVAILABLE_STATUSES[:key] 
    end 

end 

Item::AVAILABLE_STATUS # => { :unkwnown => 0, :medical => 3 } 
Item.statuses # => [:medical, :unkwnown] 
Item.status_value(:medical) # => 3 

如果多个模型共享相同的逻辑,可以将它放在模块中,并将模块混合到需要它的所有模型中。

+0

我会在哪里把模块?在lib /? – intargc 2009-07-24 20:35:57

+0

您可以使用/ lib,但我通常更喜欢使用所有控制器/模型自定义混合创建一个名为/ apps/concern的文件夹。 – 2009-07-24 21:43:40

0

我的通话将提出,在相关模型

1

这个代码可以帮助你......

首先,在lib文件夹命名一个文件:

integer_to_enum.rb 

在该文件把这个代码:

module IntegerToEnum 

    class << self 

    def included(klass) 
     klass.extend(ModelClassMethods) 
    end 

    end 

    module ModelClassMethods 

    def fields_to_enum(options={}) 
     class_eval <<-end_eval 
     def set_enum_options 
      @enum_options = #{options.inspect} 
     end 
     end_eval 

     options.each_pair do |k,v| 
     class_eval <<-end_eval 
      def #{k.to_s} 
      self.set_enum_options 
      @enum_options[:#{k.to_s}][read_attribute(:#{k.to_s}).to_i] 
      end 

      def #{k.to_s}=(v) 
      self.set_enum_options 
      unless @enum_options[:#{k.to_s}].include?(v) 
       return false 
      end 

      write_attribute(:#{k.to_s}, @enum_options[:#{k.to_s}].index(v)) 
      @#{k.to_s} 
      end 
     end_eval 
     end 
    end 
    end 

end 

在enviroment.rb,把这个在底部,'结束“

ActiveRecord::Base.send :include, IntegerToEnum 

而在去年,在你想要的模型 '翻译' 的整型字段放:

class YourModel < ActiveRecord::Base 

    fields_to_enum :appointment_type => [:unknown, :medical, :trial], :other_field_type => [:type_a, :type_b, :type_c] 

end 

有了这个,你可以这样做:

m = YourModel.find(1) 
m.appointment_type #=> :unknown 
m.appointment_type = :trial #=> :trial 
m.save #=> and this will save with the index value of the array definition, since ':trial' is in the 3er position, the sql resulting will save with this number 

和所有..希望对您有所帮助

0

您可以拥有一张表,其中包含所有这些信息并缓存初始表选择环境负载。

这样,您甚至可以在其他表上实现appointment_types表和appointment_type_id表之间的参照完整性。