Форма Rails: как хранить (и извлекать) массив? - PullRequest
0 голосов
/ 05 апреля 2020

Я довольно новичок в Rails и хочу сохранить значения флажков из формы Rails в массив в поле базы данных.

Я хотел бы сделать это без связей базы данных / таблицы соединений ( значения формы будут очень редко, если вообще изменятся), поэтому я предоставляю опции-флажки в форме ha sh внутри формы.

Я получил что-то наполовину работающее, используя this ответ в качестве руководства .

Форма отображает опции флажков, и когда я обновляю запись, она сохраняет массив с проверенными значениями в поле базы данных (в виде строки). Однако, когда я редактирую запись, все флажки в форме остаются пустыми.

Мне кажется, мне нужно указать форме, как предварительно «проверять» соответствующие поля в первом параметре (: частота, которая текстовое поле в базе данных), но я не уверен, как это сделать. Я пробовал:

  1. : частота [] и другие варианты
  2. добавление сериализации в модель здания

Я видел ссылки на использование hstore в Postgres, но я незнаком с этим и не пробовал.

Большое спасибо ...

Использование: Rails 6.0.2.2, Postgres 12

_form.html.erb

<%= form_with(model: building, local: true) do |f| %>
...
<%= f.collection_check_boxes(:frequency, { 'Yearly': 1, 'Quarterly': 2, 'Monthly': 3, 'Weekly': 4 }, :last, :first) %>

building.rb

class Building < ApplicationRecord

  serialize :frequency, Array

Server log (после проверки 3-го поля в форме):

Processing by BuildingsController#update as HTML
  Parameters: {"authenticity_token"=>"p2fFVpKZnw5HroZvy3qGAbguTxf+3oEOjOrhEGTu4ImS7GpVwXrcj78XPt5ENcN6GQx9K9Cn/c3ZvMwOSqVYbQ==", "building"=>{"frequency"=>["", "3"]}, "commit"=>"Update Building", "id"=>"5"}

Building Update (0.8ms)  UPDATE "buildings" SET "frequency" = $1, "updated_at" = $2 WHERE "buildings"."id" = $3  [["frequency", "---\n- ''\n- '3'\n"], ["updated_at", "2020-04-05 17:56:22.142645"], ["id", 5]]
  ↳ app/controllers/buildings_controller.rb:40:in `update'
   (1.4ms)  COMMIT
  ↳ app/controllers/buildings_controller.rb:40:in `update'
Redirected to http://localhost:3000/buildings/5
Completed 302 Found in 14ms (ActiveRecord: 3.7ms | Allocations: 6210)

1 Ответ

0 голосов
/ 06 апреля 2020

Все, что вы не используете serialize. Это грязный хак из темных веков, который хранит сложные типы в столбцах text / varchar путем сериализации данных как JSON или YAML. Он не должен использоваться с собственными типами массивов / json / hstore, поскольку сериализация выполняется адаптером базы данных. Если вы используете serialize со столбцом массива, вы получите что-то вроде ["[1,2,3]"], вставленное в базу данных, если вы используете его с JSON, вы получите "{ \"foo\":\"bar\" }".

Вместо этого, если вы хотите использовать массив битовых масок, просто создайте столбец как массив:

create_table :buildings do |t|
  t.integer 'frequency', array: true
end

Адаптер базы данных автоматически обработает преобразование его в массив и из него.

Если вы хотите использовать HStore или JSON, которые оба могут выполнять хеши заданий в ruby use:

create_table :buildings do |t|
  t.json 'frequency'
  # or
  t.hstore 'frequency'
end

Но ИМХО, я бы просто взял программу и создал таблицу соединений , Это не стоит суеты и дурацких возникающих запросов / проблем, которые могут решить объединения. ActiveRecord был построен вокруг таблиц и реляционной модели. Не hstore / array / json столбцы.

class Frequency
  has_many :building_frequencies
  has_many :frequencies, through: :building_frequencies
end

class BuildingFrequency
  belongs_to :building
  belongs_to :frequency
end

class Building
  has_many :building_frequencies
  has_many :frequencies, through: :building_frequencies
end

<%= f.collection_check_boxes(:frequency_ids, Frequency.all, :id, :name) %>

def building_params
  params.require(:building)
        .permit(
          :foo, :bar,
          frequency_ids: []
        )
end

Он выполняет работу, обеспечивает ссылочную целостность и позволяет использовать внутренние объединения для фильтрации строк. на частоте, которая на самом деле намного эффективнее, чем тыкать в массив / hstore.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...