Создать экземпляр переменной экземпляра во вспомогательном методе из контроллера

У меня есть помощник, который создает экземпляр модели и отображает форму. Эта форма должна быть доступна любому представлению в приложении.

# support_form_helper
def support_form
  @support_stats = SupportForm::Stat.find(get_stats_id)
  @enquiry = SupportForm::Enquiry.new(stats_id: @support_stats.id)
  render partial: 'support_form/enquiries/form'
end

И это отображается в представлении:

# some_view.html.erb

<%= support_form %>

Это нормально, пока я не захочу отправить форму и проверить ее в контроллере.

# enquiries_controller.rb
def create

  @enquiry = SupportForm::Enquiry.new(params[:support_form_enquiry])

  topic = @enquiry.topic
  @stat = SupportForm::Stat.find(@enquiry.stats_id)

  @stat.stats[topic] = @stat.stats[topic].to_i.next
  respond_to do |format|
    if @enquiry.valid? && @stat.save
      format.html { redirect_to(root_path) }
    else
      format.html { redirect_to(:back) }
    end
  end
end

Здесь я не могу отобразить предыдущее представление с ошибками, связанными с недопустимым объектом. Помощник вызывается снова и инициализирует новый объект @enquiries, очевидно, без ошибок.

Как я могу отображать форму во многих представлениях в приложении и по-прежнему возвращаться к представлению с объектом вместе с ошибками, когда он недействителен?


Я нашел ответ, который отвечает на мой вопрос, но это плохая идея:

Визуализация действия, инициировавшего обновление

def create @enquiry = SupportForm::Enquiry.new(params[:support_form_enquiry])

  topic = @enquiry.topic
  @stat = SupportForm::Stat.find(@enquiry.stats_id)

  @stat.stats[topic] = @stat.stats[topic].to_i.next

  if @enquiry.valid? && @stat.save
    redirect_to(root_path)
  else
    render Rails.application.routes.recognize_path(request.referer).values.join("/")
  end
end

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

В настоящее время я рассматриваю возможность размещения ошибок во флэш-хэше ... не то, что я хочу делать. С возвращенным исходным объектом я могу повторно заполнить поля пользовательским вводом.


person iNulty    schedule 06.02.2014    source источник


Ответы (1)


Когда вы используете redirect_to, рельсы запустят совершенно новый контроллер и последовательность представлений. Использовать

визуализировать "путь/к/шаблону/из/представления/папки"`

вместо.

Типичное действие создания с использованием этого шаблона будет выглядеть так (в данном случае для объекта «post»):

def create
  @post = Post.new(params[:post])
  @created = @post.save
  respond_to do |format|
    if @created
      flash[:notice] = 'Post was successfully created.'
      format.html { redirect_to post_path(@post) }
      format.js
    else
      format.html { render :action => :new }
      format.js
    end
  end
end 

Обратите внимание, что если он успешно создан, мы делаем полное перенаправление на страницу «показать» для публикации, но если это не удается, мы просто делаем рендеринг.

Вероятно, вам следует изменить хелпер support_form так, чтобы он создавал новый @enquiry только в том случае, если он еще не создан:

def support_form
  @support_stats = SupportForm::Stat.find(get_stats_id)
  @enquiry ||= SupportForm::Enquiry.new(stats_id: @support_stats.id)
  render partial: 'support_form/enquiries/form'
end

||= является сокращением от «равно самому себе или». Если он не был определен (или имеет значение nil или false), то первая часть или будет пройдена неудачно, и он перейдет ко второй, где будет создан объект.

В партиале формы вы также должны убедиться, что используете form_for, который будет выполнять действие создания или обновления в зависимости от того, был ли объект уже сохранен.

person Max Williams    schedule 06.02.2014
comment
Моя проблема в том, что я не могу передать @enquiry от контроллера помощнику. Я пробовал сам равный или, но @enquiry всегда равен нулю. Кроме того, я знаю, что redirect_to и render. Я не знаю, какой контроллер или действие мне придется отображать, поэтому redirect_to :back казалось логичным решением, возвращая объект обратно с перенаправлением - person iNulty; 06.02.2014
comment
Когда вы говорите, что @enquiry всегда равен нулю, вы имеете в виду после перенаправления? Всякий раз, когда вы перенаправляете, вы начинаете с нуля, и все переменные экземпляра стираются. если вы рендерите, то он у вас все равно должен быть. - person Max Williams; 07.02.2014
comment
Я могу визуализировать этот фрагмент кода, на который я ссылаюсь в вопросе (Визуализировать действие, которое инициировало обновление), но затем мне нужно установить переменные экземпляра, которые могут быть установлены этим контроллером действий. Скажем, действие pages#show, например. Мне все еще нужно установить переменные экземпляра, которые действие pages#show устанавливает из действия enquiries#create, когда мне нужно вернуться к действию, которое отобразило форму. Может быть, если я просто выполню действие enquiries#new и полностью отключу контроллер последних страниц. Хотя для пользователя это нехорошо. На данный момент я рассматриваю перенаправление с помощью набора файлов cookie. - person iNulty; 07.02.2014