Значение ассоциации по умолчанию

Модель работы

schema "jobs" do
  belongs_to :status, Test.JobStatus,
    foreign_key: :status_id,
    references: :id,
    type: :string
  timestamps()
end

и у меня есть модель статуса как:

@primary_key {:id, :string, autogenerate: false}
schema "job_statuses" do
  field :title, :string
  field :description, :string
end

Когда я вставляю задание, мне нужно указать статус задания по умолчанию (если его нет в параметрах). Я знаю о значениях по умолчанию в ассоциации exists_to, но эта вещь, возможно, предназначена для назначения значений по умолчанию, когда вы устанавливаете отношения. Может ли кто-нибудь указать мне, как я могу установить статус по умолчанию для любого вновь созданного задания (предполагаемый идентификатор статуса задания «acitve» и он уже находится в базе данных). пример уже здесь https://github.com/tanweerdev/jobs

После клонирования проекта просто сделайте это

Interactive Elixir (1.5.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Test.Jobs.create_job_status()
iex(2)> Test.Jobs.test_default_status()

(Postgrex.Error) ОШИБКА 23502 (not_null_violation): нулевое значение в столбце «status_id» нарушает ограничение ненулевого значения


person Tanweer    schedule 18.12.2017    source источник
comment
Примечание: если я добавлю значение по умолчанию в миграцию, при вставке не будет ошибки, и статус будет успешно связан, но объект набора изменений, который я возвращаю пользователю, не знает об изменении и возвращает null status_id   -  person Tanweer    schedule 18.12.2017


Ответы (2)


Вы можете поместить значение по умолчанию в миграцию и определить поле ассоциации как read_after_writes: true. Это гарантирует, что после вставки записи это поле будет считано из базы данных, что устранит проблему, о которой вы упомянули в своем комментарии, что поле все еще было nil после успешной вставки записи.

belongs_to :status, Test.JobStatus,
  foreign_key: :status_id,
  references: :id,
  type: :string,
  define_field: false

field :status_id, :integer, read_after_writes: true

Ознакомьтесь с документацией для получения более подробной информации о define_field здесь и read_after_writes здесь.

person Dogbert    schedule 18.12.2017

Наиболее подходящим местом для создания статуса будет обратный вызов Job.changeset/2:

  @doc false
  def changeset(%Job{} = job, attrs) do
    job
    |> cast(attrs, @fields)
    |> validate_required(...)
    |> create_and_put_default_status() # ⇐ HERE
    |> ...
  end

Где реализация create_and_put_default_status() будет соответствовать следующей спецификации:

@spec create_and_put_default_status(Plug.Conn.t) :: Plug.Conn.t
person Aleksei Matiushkin    schedule 18.12.2017