Rails 5, sqlite3 с использованием массива в качестве столбца / атрибута - PullRequest
1 голос
/ 06 октября 2019

Вот как я использую массив в модели rails 5 при миграции

  t.text :diagnoses, array: true, default: []

в модели

class Patient < ApplicationRecord
  serialize :diagnoses, Array
end

в моем методе семени Я делаю это как

  patient = Patient.create(first_name: 'John', last_name: 'Smith', admission: a)
  patient.diagnoses = [1, 2]
  patient.save!

Выдает ошибку как

ActiveRecord::SerializationTypeMismatch: can't dump `diagnoses`: was supposed to be a Array, but was a Integer. -- 0

Спасибо за любую помощь!

Ответы [ 2 ]

1 голос
/ 06 октября 2019

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

# since diagnosis is highly irregular we most likely need to configure rails 
# to pluralize it correctly
# config/initializers/inflections.rb
ActiveSupport::Inflector.inflections(:en) do |inflect|
  inflect.irregular 'diagnosis', 'diagnoses'
end

class Patient < ApplicationRecord
  has_many :patient_diagnoses
  has_many :diagnoses, through: patient_diagnoses
end

# this table provides data normalization 
class Diagnosis < ApplicationRecord
  has_many :patient_diagnoses
  has_many :patients, through: patient_diagnoses
end

# this is just a join table
class PatientDiagnosis < ApplicationRecord
  belongs_to :patient
  belongs_to :diagnosis
end

Это позволяет вам использовать внешние ключи для обеспечения ссылочной целостности и позволяет использовать ассоциации ActiveRecord вместо того, чтобы просто объединять что-то непонятное. Здесь очень мало реальных преимуществ использования типа массива.

Если вы все еще хотите использовать столбец массива, вам не следует использовать ActiveRecord :: AttributeMethods :: Serialization . Он используется с простыми старыми столбцами varchar / text для хранения строк YAML, которые сериализуются / не сериализуются в Rails. Это пережиток мрачных дней до того, как у нас появились нативные типы JSON / массивов, и он действительно не имеет никакого применения, кроме как в устаревших приложениях.

1 голос
/ 06 октября 2019

Некоторое время назад я столкнулся с этой проблемой. Я нашел следующий обходной путь:

  • В вашем файле миграции:

    t.text :diagnoses, array: true
    
  • Затем в модели:

    class Patient < ApplicationRecord
      serialize :diagnoses
    
      after_initialize do |patient|
        patient.diagnoses= [] if patient.diagnoses == nil
      end
    end
    
  • Обратный вызов after_initialize будет вызываться всякий раз, когда создается экземпляр объекта Active Record, либо путем непосредственного использования new, либо при загрузке записи из базы данных.

...