2008-11-05 28 views
42

Tôi có một số hằng số đại diện cho các tùy chọn hợp lệ trong một trong các trường của mô hình của tôi. Cách tốt nhất để xử lý các hằng số này trong Ruby là gì?Cách tốt nhất để xử lý các hằng số trong Ruby khi sử dụng Rails là gì?

+0

[Câu hỏi này khác về Enumerations trong Ruby có vẻ là rất rất giống nhau] (http://stackoverflow.com/questions/164714/how-can-i-use-c-style-enumerations-in-ruby) –

Trả lời

38

Bạn có thể sử dụng một mảng hoặc băm cho mục đích này (trong môi trường của bạn.rb):

OPTIONS = ['one', 'two', 'three'] 
OPTIONS = {:one => 1, :two => 2, :three => 3} 

hoặc cách khác là liệt kê c lass, cho phép bạn liệt kê trên các hằng số của bạn cũng như các phím sử dụng để kết hợp chúng:

class Enumeration 
    def Enumeration.add_item(key,value) 
    @hash ||= {} 
    @hash[key]=value 
    end 

    def Enumeration.const_missing(key) 
    @hash[key] 
    end 

    def Enumeration.each 
    @hash.each {|key,value| yield(key,value)} 
    end 

    def Enumeration.values 
    @hash.values || [] 
    end 

    def Enumeration.keys 
    @hash.keys || [] 
    end 

    def Enumeration.[](key) 
    @hash[key] 
    end 
end 

mà sau đó bạn có thể xuất phát từ:

class Values < Enumeration 
    self.add_item(:RED, '#f00') 
    self.add_item(:GREEN, '#0f0') 
    self.add_item(:BLUE, '#00f') 
end 

và sử dụng như thế này:

Values::RED => '#f00' 
Values::GREEN => '#0f0' 
Values::BLUE => '#00f' 

Values.keys => [:RED, :GREEN, :BLUE] 
Values.values => ['#f00', '#0f0', '#00f'] 
+2

Tôi quyết định đi với giải pháp này. Tôi phải nói, nó chỉ là những gì tôi muốn và chơi độc đáo với ActiveRecord. Cảm ơn bạn!: D – Miles

11

tôi đặt chúng trực tiếp trong lớp mô hình, như vậy:

class MyClass < ActiveRecord::Base 
    ACTIVE_STATUS = "active" 
    INACTIVE_STATUS = "inactive" 
    PENDING_STATUS = "pending" 
end 

Sau đó, khi sử dụng mô hình từ một lớp khác, tôi tham khảo các hằng

@model.status = MyClass::ACTIVE_STATUS 
@model.save 
+2

Đó là một phương pháp không phải là một lớp học. Cần sử dụng "class" thay vì "def". – weexpectedTHIS

5

Bạn cũng có thể sử dụng nó trong mô hình của mình bên trong một hàm băm như sau:


class MyModel 

    SOME_ATTR_OPTIONS = { 
    :first_option => 1, 
    :second_option => 2, 
    :third_option => 3 
    } 
end 

Và sử dụng nó như thế này:



if x == MyModel::SOME_ATTR_OPTIONS[:first_option] 
    do this 
end 

+0

Cảm ơn vì điều này. Đó là một nguồn cảm hứng cho các biểu tượng nhóm trong một mảng. – chipairon

9

Nếu đó là hành vi lái xe mô hình, sau đó các hằng số nên là một phần của mô hình:

class Model < ActiveRecord::Base 
    ONE = 1 
    TWO = 2 

    validates_inclusion_of :value, :in => [ONE, TWO] 
end 

này sẽ cho phép bạn sử dụng được xây dựng trong Chức năng đường ray:

>> m=Model.new 
=> #<Model id: nil, value: nil, created_at: nil, updated_at: nil> 
>> m.valid? 
=> false 
>> m.value = 1 
=> 1 
>> m.valid? 
=> true 

Hoặc, nếu cơ sở dữ liệu của bạn hỗ trợ liệt kê, bạn có thể sử dụng plugin như Enum Column .

6

Đường ray 4.1 được thêm support for ActiveRecord enums.

Khai báo thuộc tính enum trong đó các giá trị ánh xạ tới số nguyên trong cơ sở dữ liệu, nhưng có thể được truy vấn theo tên.

class Conversation < ActiveRecord::Base 
    enum status: [ :active, :archived ] 
end 

conversation.archived! 
conversation.active? # => false 
conversation.status # => "archived" 

Conversation.archived # => Relation for all archived Conversations 

Xem its documentation để biết chi tiết ghi lên.

+0

Tôi nghĩ đây là câu trả lời hay nhất. –

+1

Hãy sẵn sàng nhận ngoại lệ khi bạn cố gắng chỉ định một số giá trị không có trong danh sách cho trường trạng thái và sẵn sàng nhận xung đột tên nếu bạn thêm một trường enum khác có giá trị [: active]. Việc triển khai đường ray của tính năng này thực sự khó xử. – BitOfUniverse

+0

tôi đã tạo ra một viên ngọc để xác nhận tính hợp lệ của enums https://github.com/CristiRazvi/enum_attributes_validation –

0

Bạn cũng có thể nhóm hằng vào đối tượng, sử dụng một mô-đun -

class Runner < ApplicationRecord 
    module RUN_TYPES 
     SYNC = 0 
     ASYNC = 1 
    end 
end 

Và sau đó có,

> Runner::RUN_TYPES::SYNC 
=> 0 
> Runner::RUN_TYPES::ASYNC 
=> 1 
Các vấn đề liên quan