сохранить несколько значений в виде массива в переменные рельсы - PullRequest
0 голосов
/ 14 апреля 2020

Я получил переменную во вложенной модели (account), принадлежащую пользовательской модели, в которой есть столбец для :skills. в моем edit_user_path я хотел бы иметь возможность сохранять несколько навыков в этом столбце с помощью флажков. Для этого я разрешил skills в контроллере в виде массива, даже если он сохранен в виде строки в базе данных.

Мой контроллер:

    def user_params
        params.require(:user).permit(:email, :password, :password_confirmation, :account, 
            account_attributes:[:id, :username, {:skills => []}, :description, :location, :avatar, :tags, :tag_list])
    end

Если я сохраняю несколько значений через Флажки в эту переменную внутри вложенной формы, я делаю это так:

        <% skills = ["Coding", "Design", "Petting Cats"] %>
        <% skills.each do |skill| %>

        <div class="form-check form-check-inline">
          <div class="custom-control custom-checkbox">
            <%= form.check_box :skills, { multiple: true, class:"custom-control-input",id: skill }, skill, false %>
            <%= form.label skill, class:"custom-control-label", for: skill %>
          </div>
        </div>

        <% end %>

Это работает, и значения сохраняются в виде массива, но, как ни странно, массив после сохранения в базе данных выглядит следующим образом:

"[\"Artist\", \"Mixing\", \"Mastering\"]" 

вместо этого:

["Artist", "Mixing", "Mastering"] 

Что приводит к неприятностям, поскольку я хотел бы через всех пользователей впоследствии выполнять "фильтрацию" по определенным навыкам, например User.account.where(skills: "Petting Cats"), если пользователь Petting Cats сохранил где-то внутри массива.

Для разработки я использую SQLite, для производства PostgresQL. Как сохранить несколько строк в строковую переменную в виде чистого массива без беспорядка и как позже выполнить итерацию по массиву с помощью where метода запроса?

1 Ответ

4 голосов
/ 14 апреля 2020

Вы попадаете в общую двойную ловушку с использованием столбца массива и сериализации.

Причина, по которой вы храните "[\"Artist\", \"Mixing\", \"Mastering\"]", заключается в том, что вы используете serialize с собственным массивом колонка. serialize - это старый хак для хранения вещей в столбцах varchar / text, и драйвер фактически конвертирует его в массив. Когда вы используете serialize с собственным столбцом array / json / hstore, вы фактически преобразуете значение в строку до того, как драйвер преобразует его. Результат:

["[\"Artist\", \"Mixing\", \"Mastering\"]"]

Удаление serialize решит непосредственную проблему, но у вас все еще остается некачественное решение по сравнению с фактическим выполнением задания:

# rails g model skill name:string:uniq
class Skill < ApplicationRecord
  validates :name, uniqueness: true, presence: true
  has_many :user_skills, dependent: :destroy
  has_many :users, through: :user_skills
end
# rails g model user_skill user:belongs_to skill:belongs_to
# use `add_index :user_skills, [:user_id, :skill_id], unique: true` to ensure uniqueness
class UserSkill < ApplicationRecord
  validates_uniqueness_of :user_id, scope: :skill_id
  belongs_to :user
  belongs_to :skill
end
class User < ApplicationRecord
  has_many :user_skills, dependent: :destroy
  has_many :skills, through: :user_skills
end
<%= form_with(model: @user) do |form| %>
  <div class="field"> 
    <%= form.label :skill_ids %>
    <%= form.collection_select :skill_ids, Skill.all, :id, :name %>
  </div>
<% end %>
def user_params
  params.require(:user).permit(
    :email, :password, :password_confirmation, :account, 
    account_attributes: [
      :id, :username, :description, :location, :avatar, :tags, :tag_list,
    ],
    skill_ids: [] 
 )
end

Это дает вам:

  • Запрашиваемые данные
  • Ссылочная целостность
  • Нормализация
  • Инкапсуляция
  • ActiveRecord Assocations!
  • Удовольствие от того, что ты не выглядишь как идиот в обзоре / аудите
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...