2013-05-07 9 views
5

Mam problemy z pracą z bitem mysql w Railsach i ActiveRecord. Przechowujemy trochę dla opublikowanego stanu Lokalności.Railsy/ActiveRecord praca z mysql BIT

`published` bit(1) NOT NULL 

Poskonstruowałem to jako published:binary w szynach.

Locality.first.published zwraca "\x01".

Jak uzyskać tory, aby traktować to pole jako wartość logiczną?

Istnieje zablokowany bilet, ale hackowanie ActiveRecord nie jest tak naprawdę opcją. https://rails.lighthouseapp.com/projects/8994/tickets/6102-activerecord-boolean-support-with-bit1-mysql-data-type

Odpowiedz

5

można zastąpić czytnik atrybutem opublikowanego atrybutu:

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

UPDATE

lub wygenerować metodę do logicznej wartości zwracanej

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

Więc może zadzwoń:

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

Ale myślę, że pierwsze rozwiązanie (nadpisanie czytnika atrybutów) jest lepsze.

+0

Już myślałem o zrobieniu tego w ten sposób, ale nie wydaje się to dobrym rozwiązaniem. –

+0

i dlaczego nie? dlaczego nie używasz normalnego pola boolowskiego zamiast bitu? – Mattherick

+0

zaktualizowałem moją odpowiedź. – Mattherick

0

Herezje metodę rozszerzenia na podstawie @ odpowiedź Mattherick jest powyżej:

lib/rozszerzenia/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) 

i wymagają do inicjowania:

config/initializers/extensions.rb

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

które następnie mogą być wykorzystane:

class Locality < ActiveRecord::Base 
    alias_bit_to_boolean :published 
end 

To będzie produkować metodę locality.published?.

0

Dziękuję za pomoc @Mattherick.

Z twoją pomocą zbudowałem coś łatwiejszego:

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 

highlight to nazwa pola przechowywane jako BIT na bazie. I to rozwiązanie działa także z checkbox na widoku bez konieczności zmian:

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

Aktualizacja dla Rails 5: nowe atrybuty API jest do obsługi sytuacje takie jak ta.Najpierw trzeba określić podklasę ActiveRecord::Type::Value który obsługuje deserialize ing z kawałka boolean i cast ing z powrotem od wartości logicznej do bitów:

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 

Następnie należy zdefiniować atrybut modelu z attribute pomocnika:

class MyModel < ApplicationRecord 
    attribute :published, Values::BitBoolean.new 
end