Форма не будет сохранять локальные переменные после сбоя проверки

У меня есть форма, которая содержит итерацию по массиву хэшей:

<% @user.profile["addresses"].each_with_index do |(k,v), i| %>
    <%= render partial: 'users/form/addresses_fields', locals: { f: f, i: i } %>
<% end %>

Обратите внимание, что я не передаю k и v через локальные переменные, потому что вместо этого я использую вспомогательные теги формы, и мне нужно использовать только индекс, например:

<%= label_tag "user[profile][addresses]["+i.to_s+"][street]", "Street" %>
<%= text_field_tag "user[profile][addresses]["+i.to_s+"][street]" %>

При отправке всякий раз, когда проверка не проходит, и контроллер повторно отображает представление, у меня есть Name Error, который говорит undefined local variable or method 'i' for #<#<Class:0x007fc53e26b690>:0x007fc53f5ba688>

Означает ли это, что Rails не принимает во внимание встроенные или локально определенные переменные при повторном рендеринге представлений после неудачной проверки?

Я также пытался определить переменные в представлении, такие как <% i = 0 %>, а затем увеличивать их с каждой итерацией, и проблема, конечно, сохраняется, так как теперь я уверен, в чем проблема.

Другие соображения: каждое поле, которое заполняет пользователь, остается идеально корректным после сбоя проверки, проблема связана с локальными переменными, в данном случае индексом each_with_index

Как решить эту проблему? user.profile – это столбец типа данных JSONB.

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

Другой соответствующий код:

Контроллер:

def update
  if @user.custom_update_attributes(user_params)
    flash[:success] = "Updated!"
    redirect_to current_user
  else
    render 'edit'
  end
end

Модельный метод:

def custom_update_attributes(params)
    name = params["profile"]["name"]
    gender = params["profile"]["gender"]
    birthday = params["profile"]["birthday"]
    phone = params["profile"]["phone"]
    addresses = params["profile"]["addresses"]

    self.profile["name"] = name
    self.profile["gender"] = gender
    self.profile["birthday"] = birthday
    self.profile["phone"] = phone

    #addresses
    updated_addresses = {}
    i = 0
    unless addresses.blank?
      addresses.each do |key, val|
        if val["_destroy"] == "1"
          #pass
        else
          #add
          updated_addresses[i] = val.except("_destroy")
          i = i + 1
        end
      end
    end
    self.profile["addresses"] = updated_addresses

    self.profile_will_change!
    self.save
  end

Я думаю, что нашел, что происходит, используя драгоценный камень BYEBUG:

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

<%= text_field_tag "user[profile][addresses]["+i.to_s+"][street]", @user.profile["addresses"][i.to_s]["street"] %>

Когда страница изначально загружает форму, эта строка кода работает отлично. Но если проверка не пройдена, [i.to_s] из @user.profile["addresses"][i.to_s]["street"] становится неопределенным, и если я изменю его на [i] без преобразования в строку, страница с ошибками проверки загрузится отлично!

Я думаю, что это просто проблема с тем, как Rails обрабатывает массив хэшей, потому что сначала он рассматривает каждый индекс массива как ключ подхэша, а затем, когда проверка не проходит, он рассматривает каждый индекс как номер индекса массива. , больше не ключ (не строка). Странный.


person aleherzko    schedule 20.03.2017    source источник
comment
Пожалуйста, опубликуйте свой метод контроллера   -  person Gaston    schedule 21.03.2017
comment
@Gaston обновлен методом контроллера   -  person aleherzko    schedule 21.03.2017
comment
@Gaston, контроллер и метод модели работают отлично после успешной проверки.   -  person aleherzko    schedule 21.03.2017


Ответы (1)


Чтобы решить эту проблему, я просто добавил следующее перед любым входом формы:

<% if @user.profile["addresses"][i.to_s] != nil %>
  <% i = i.to_s %>
<% else %>
  <% i = i %>
<% end %>
person aleherzko    schedule 21.03.2017