Хранение данных массива в поле jsonb с помощью Rails и Postgresql

#ruby-on-rails #ruby #postgresql #jsonb

#ruby-on-rails #ruby #postgresql #jsonb

Вопрос:

Допустим, у меня есть модель автомобиля, в которой я хочу отображать разные виды данных. Я добавляю data столбец в таблицу:

 class AddDataToCars < ActiveRecord::Migration[5.0]
  def change
    add_column :cars, :data, :jsonb, null: false, default: '{}'
    add_index  :cars, :data, using: :gin
  end
end
  

Затем я добавляю средство доступа для поля, которое я хочу присутствовать ( extra_options ):

 class Car < ApplicationRecord
  store_accessor :data, :wheel_count, :extra_options

  validates :extra_options, presence: true
end
  

Я удостоверяюсь, что это разрешенный параметр в cars_controller.rb :

 def car_params
  params.require(:car).permit(:make, :model, :data, :wheel_count, :extra_options)
end
  

Теперь я могу создать текстовый ввод в моем _form.html.erb partial, который помещает данные следующим wheel_count образом:

 <div class="field">
  <%= f.label :wheel_count %>
  <%= f.text_field :wheel_count %>
</div>
  

И это работает так, как ожидалось. Затем я хотел бы получить список выбора (множественный выбор) или набор флажков, в которых хранятся выбранные параметры extra_options .

Я пробовал с:

 <%= f.select :extra_options, options_for_select(["1", "2", "3", "4", "5"], car.extra_options), { include_blank: true }, { multiple: true } %>
  

что привело к следующей разметке:

 <input name="car[extra_options][]" type="hidden" value="" />     
<select multiple="multiple" name="car[extra_options][]" id="car_extra_options">
  <option value=""></option>
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
  <option value="5">5</option>
</select>
  

Очевидно, что метки параметров должны иметь больше смысла, чем просто 1, 2, 3, 4 и 5, но что еще хуже, так это то, что при отправке формы ничего не сохраняется.

При отправке, если я выберу 2 и 3, параметры будут выглядеть так:

 "extra_options"=>["", "2", "3"]
  

что приводит к сообщению Unpermitted parameter: extra_options , поэтому кажется, что мне не разрешено помещать массивы в это поле.

Может показаться глупым создавать поле jsonb только для некоторых дополнительных опций, но оно, естественно, также будет содержать всевозможные другие данные.

Итак, как я могу создать список множественного выбора или, предпочтительно, набор флажков, который правильно сохраняет данные в поле jsonb (и, конечно, при редактировании отправки отображаются уже выбранные / отмеченные элементы)?

Ответ №1:

Попробуйте это, в car_params

 params.require(:car).permit(:make, :model, :data, :wheel_count, extra_options: [])
  

Для флажков попробуйте следующее

     <%= hidden_field_tag "car[extra_options][]", [] %>
    <% ["1", "2", "3", "4", "5"].each do |o| %>
      <% default_checked = car.extra_options.include?(o.to_s) rescue false %>
      <label class="rightpad">
        <%= check_box_tag "car[extra_options][]", o, default_checked %>
      </label>
      <span>
        <%= o %>
      </span>
    <% end %>
  

Комментарии:

1. Это полностью работает. Знаете ли вы, как сделать это флажками вместо списка выбора. Кажется, я не могу найти однострочный вариант, подобный приведенному выше (если это вообще возможно).

2.Вы случайно не знаете, почему я не могу создать новый объект таким образом: c = Car.new c.extra_options = [1, 3] Разве я не должен быть в состоянии это сделать?