2013-05-07 28 views
5

Tôi đang gặp sự cố khi làm việc với bit mysql trong Rails và ActiveRecord. Chúng tôi lưu trữ một chút cho trạng thái được xuất bản của Địa phương.Rails/ActiveRecord làm việc với mysql BIT

`published` bit(1) NOT NULL 

Tôi dàn dựng nó là published:binary trong đường ray.

Locality.first.published trả về "\x01".

Làm cách nào để nhận được đường ray xử lý trường này dưới dạng boolean?

Có một vé có giá trị nhưng hack ActiveRecord không thực sự là một lựa chọn. https://rails.lighthouseapp.com/projects/8994/tickets/6102-activerecord-boolean-support-with-bit1-mysql-data-type

Trả lời

5

Bạn có thể ghi đè lên đọc thuộc tính của thuộc tính xuất bản của mình:

class Locality < ActiveRecord::Base 
    # overwrite the attribute reader of the published attribute 
    def published 
    self.read_attribute(:published) == "\x01" ? true : false 
    end 
end 

CẬP NHẬT

Hoặc tạo ra một phương pháp cho giá trị trả về boolean bạn

class Locality < ActiveRecord::Base 
    def to_boolean 
    self.published == "\x01" ? true : false 
    end 
end 

Vì vậy, bạn có thể gọi:

Locality.first.published.to_boolean => true || false 

Nhưng tôi nghĩ giải pháp đầu tiên (ghi đè trình đọc thuộc tính) là tốt hơn.

+0

Tôi đã nghĩ về cách làm theo cách đó, nhưng nó không có vẻ giống như một giải pháp tốt. –

+0

và tại sao không? tại sao bạn không sử dụng một trường boolean bình thường thay vì bit? – Mattherick

+0

đã cập nhật câu trả lời của tôi. – Mattherick

0

Heres một phương pháp khuyến nông dựa trên câu trả lời @ Mattherick của trên:

lib/extensions/active_record/bit_boolean.rb

module Extensions::ActiveRecord 
    module BitBoolean 
    extend ActiveSupport::Concern 

    class_methods do 
     def alias_bit_to_boolean(attribute) 
     define_method("#{attribute}?") do 
      self.send(attribute) == "\x01" ? true : false 
     end 
     end 
    end 

    end 
end 

ActiveRecord::Base.send(:include, Extensions::ActiveRecord::BitBoolean) 

và đòi hỏi trong một initializer:

config/initializers/extensions.rb

require File.join(Rails.root, 'lib/extensions/active_record/bit_boolean.rb') 

nào sau đó có thể được sử dụng:

class Locality < ActiveRecord::Base 
    alias_bit_to_boolean :published 
end 

này sẽ tạo ra một phương pháp locality.published?.

0

Cảm ơn sự giúp đỡ của bạn @Mattherick.

Với sự giúp đỡ của bạn tôi đã xây dựng một cái gì đó dễ dàng hơn:

def highlight 
    self.read_attribute(:highlight) == "\x01" ? true : false 
    end 

    def highlight=(value) 
    content_value = (value == false || value == 0 || value == "0") ? "\x00" : "\x01" 
    self.write_attribute(:highlight,content_value) 
    end 

Các highlight là tên của lĩnh vực lưu trữ như BIT trên cơ sở dữ liệu. Và giải pháp này cũng làm việc với checkbox vào xem mà không cần thay đổi:

<div class="field"> 
    <%= f.label :highlight %> 
    <%= f.check_box :highlight %> 
    </div> 
0

Cập nhật cho Rails 5: các thuộc tính API mới được thực hiện để xử lý tình huống như thế này.Trước tiên, bạn định nghĩa một lớp con của ActiveRecord::Type::Value xử lý deserialize ing từ chút để boolean, và cast ing trở lại từ boolean để bit:

module Values 
    class BitBoolean < ActiveRecord::Type::Value 
    BIT_FALSE = "\x00" 
    BIT_TRUE = "\x01" 

    def cast(value) 
     value ? BIT_TRUE : BIT_FALSE 
    end 

    def deserialize(value) 
     value == BIT_TRUE 
    end 
    end 
end 

Sau đó, bạn xác định các thuộc tính trên mô hình của bạn với attribute helper:

class MyModel < ApplicationRecord 
    attribute :published, Values::BitBoolean.new 
end 
Các vấn đề liên quan