Devise: настройка пользовательских шаблонов по умолчанию после подтверждения пользователя

Что я хочу: использовать Devise для регистрации пользователя, входа в систему и т. д. Когда пользователь регистрируется и подтверждается, я хотел бы создать набор шаблонов пользователя по умолчанию для этого пользователя.

Что я пробовал: я пытался переопределить Confirmations#show, чтобы show.html.erb был представлением, а #setup_user_defaults() вызывался после успешного подтверждения. класс ConfirmationsController Devise::ConfirmationsController

    def show
      render('show')
      setup_user_defaults()
      super
    end

Я продолжаю получать сообщение об ошибке, в котором говорится, что я могу иметь только 1 перенаправление или рендеринг в действии. Причина, по которой наличие этого представления важно для меня, заключается в том, что #setup_user_defaults() занимает слишком много времени для удобства пользователя, который может нажать кнопку обновления или что-то еще, что испортит процесс.

Мои мысли: я новичок и еще не узнал о фоновых работах. Итак, мой вопрос: это фоновая работа? Или как я могу заставить #show иметь вид, который говорит: «Ваша учетная запись настраивается. Это может занять несколько минут». Без использования AJAX (я еще не в этом).

Или есть другие идеи?


person v8soup    schedule 26.09.2015    source источник


Ответы (2)


Вы получаете сообщение об ошибке, потому что вы вызываете render, а затем вызываете super, внутри которого также есть рендеринг или перенаправление. Вы не можете вызывать ни рендеринг, ни перенаправление более одного раза в методе (если только он не инкапсулирован в условный оператор if).

Кроме того, вам не нужны пустые скобки для вызова метода, как в javascript.

Сейчас. Любая крупная или медленно работающая задача идеально подходит для фонового режима. И даже если вы новичок, если вы используете rails 4.2, фоновые задания в наши дни настолько просты!

Я бы использовал delayed_job, это просто и гибко. Итак, вот шаги:

<сильный>1. Добавьте delayed_job и демонов в свой gemfile и запустите установку пакета

gem 'delayed_job_active_record'
gem 'daemons'

<сильный>2. Убедитесь, что метод настройки ваших шаблонов находится в модели User

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable, :confirmable,
         :recoverable, :rememberable, :trackable, :validatable

  def set_default_templates
    ### this is where all your setup code will go, remember that you're inside the object itself, so if you need to reference data stored already you'll use self, e.g. self.name or self.confirmed_at
  end
  handle_asynchronously :set_default_templates
end

ПРИМЕЧАНИЕ Убедитесь, что вы добавили строку handle_asyncronously с именем вашего метода. Это сообщает модели, что этот метод ВСЕГДА следует вызывать с помощью ActiveJob (это оболочка, которая позволяет вы используете любую фоновую службу, которую хотите, но ваш код не меняется в режиме)

<сильный>3. Теперь пришло время вызвать метод, 2 варианта: вызвать метод из контроллера или вызвать метод в обратном вызове after_create

Я рекомендую делать это в after_create, это немного чище. Итак, в вашей модели используйте тот же код, что и выше, но добавьте эту строку в объявление устройства:

after_create :set_default_tempaltes

Если вы предпочитаете делать это в контроллере, вы можете, но помните, что с devise это должно быть сделано внутри контроллера регистрации, поэтому, когда новый пользователь регистрируется, это происходит в методе create:

def create
  super
  if resource.save
    resource.set_default_templates
  end
end

ПРИМЕЧАНИЕ Имейте в виду, что пока вы полностью не поймете, что делают эти методы devise, я не рекомендую переопределять их и думаю, что вам будет безопаснее использовать обратный вызов after_create< /эм>

<сильный>4. Теперь создайте отложенное задание

rails generate delayed_job:active_record

<сильный>5. Запустите фоновый процесс из командной строки

bin/delayed_job start

Кроме того, если вы используете единорога и мастера для своего сервера приложений, вам нужно будет предпринять другие шаги, но они изложены в учебниках и здесь, в StackOverflow, поэтому просто найдите или создайте новый вопрос, если вы застряли

person trh    schedule 26.09.2015
comment
Я просмотрел ваш очень четкий учебник, а также просмотрел документацию, но я запутался. Я думал, что весь смысл «handle_asynchronously» заключался в том, что мне не нужно было выходить из сервера rails, а затем запускать «rake jobs: work», затем выходить из этого и снова запускать rails? Я не понимаю, как работает delayed_job. Не могли бы вы указать мне учебник по delayed_jobs или объяснить этот процесс использования delayed_job? Огромное спасибо - person v8soup; 29.09.2015

Вы не можете повторно отображать одну и ту же страницу из одного и того же действия. Но вы можете разделить их на два действия. Сначала убедитесь, что подтверждение по электронной почте прошло успешно, и если это так, перенаправьте их на другое действие (должно переопределить Подтверждения разработки#показать без вызова super):

def show
  self.resource = resource_class.confirm_by_token(params[:confirmation_token])
  yield resource if block_given?

  if resource.errors.empty?
    flash[:notice] = "Your account is being set up. This may take a few minutes. 
                      Please wait to be redirected."
    redirect_to setup_defaults_path
  else
    respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
  end
end

Во втором действии установленное выше быстрое сообщение должно отображаться, пока пользователь ожидает завершения setup_user_defaults. Как только это удастся, наконец, перенаправьте их в свой профиль или куда угодно.

def setup_defaults
  if setup_user_defaults()
    redirect_to after_confirmation_path_for(resource_name, resource)
  end
end

В идеале вы должны создать фоновое задание, но для достижения того, что вы пытались сделать, вышеперечисленное должно сделать это. Надеюсь, это поможет!

Также здесь есть отличное руководство по фоновой обработке с помощью sidekiq: https://ryanboland.com/blog/writing-your-first-background-worker/

person Bryan Dimas    schedule 26.09.2015