Предложите пользователю войти в систему после того, как он предпримет определенные действия - PullRequest
8 голосов
/ 18 января 2010

Одна вещь, которую вы можете сделать на моем сайте с пояснениями к рэп-тексту - это "похожие" объяснения (после входа в систему):

http://dl.getdropbox.com/u/2792776/screenshots/2010-01-17_1645.png

Я хотел бы показать ссылки «Мне нравится» пользователям, которые не вошли в систему, а затем, когда не авторизованный пользователь нажимает кнопку «Мне нравится», показать ему лайтбокс с формой «Войти или Зарегистрироваться» (например, Digg / Reddit)

http://dl.getdropbox.com/u/2792776/screenshots/2010-01-17_1650.png

Какой лучший способ сделать это?

В настоящее время я использую этот подход:

  1. Нажатие «Like» POST на /annotations/:id/vote (тело POST указывает, нравится ли пользователю или «не нравится»).
  2. Действие контроллера vote Annotation имеет require_user before_filter, который выглядит следующим образом:

    def require_user
      unless current_user
        store_desired_location
        flash[:notice] = "You'll need to login or register to do that"
        redirect_to login_path # map.login '/login', :controller => 'user_sessions', :action => 'new'
        return false
      end
    end
    
  3. user_sessions#new выглядит так:

    def new
      @user_session = UserSession.new
      respond_to do |format|
        format.html {}
        format.js {
          render :layout => false
        }
      end
    end
    

Проблема в том, что перенаправление не работает должным образом над JavaScript:

http://dl.getdropbox.com/u/2792776/screenshots/2010-01-17_1700.png

Как мне заставить это перенаправить правильно?

Кроме того, это правильный общий подход? Еще одна мысль, которая у меня была, заключалась в том, чтобы прикрепить другой обработчик к ссылкам «Мне нравится» в javascript, когда не было зарегистрированного пользователя (но я не думаю, что этот метод хорошо масштабируется для других действий, которые я хотел бы обработать таким же образом)

Ответы [ 2 ]

3 голосов
/ 18 января 2010

Здесь нужно преодолеть несколько проблем.

  1. Браузеры в целом не позволяют перенаправлять запросы POST.

  2. redirect_to не сохраняет формат без дополнительного ввода.

  3. Местоположение магазина не сохраняет данные формы.

Все эти проблемы можно решить путем устранения перенаправлений.

Вот как я передал это в прошлом:

Вместо перенаправления в required_user, рендер. Если фильтр before перенаправляет или рендерит, ожидающее действие отменяется. (Нет необходимости возвращать false). К сожалению, этот маршрут стирает границы контроллера. Но допускает простой html-запасной вариант и делает его сухим.

Высокоуровневое представление нового рабочего процесса будет:

  1. Запрос аннотации # голосование (POST)
  2. Сбой фильтра обязательного пользователя
  3. рендеринг новой сессии
  4. отправить информацию для входа и исходные данные POST обратно в аннотации # голосование (POST)
  5. новый фильтр при голосовании собирает информацию о сеансе и регистрируется. Голосование проходит, как и ожидалось. Если войти не удается, вернитесь к 3.
  6. аннотации # голос перенаправляет / отображает, как следует

Начните с доработки require_user для рендеринга user_sessions # new template.

def require_user
  unless current_user
    flash[:notice] = "You'll need to login or register to do that"
    @user_session ||= UserSession.new
    respond_to do |format|
      format.html {render :template => 'user_sessions/new'}
      format.js {
        render :template => 'user_sessions/new', :layout => false
      }
    end
  end
end

@user_session ||= UserSession.new гарантирует, что мы можем вернуть ошибки проверки в форму.

Теперь мы должны улучшить ваш новый шаблон user_session #, чтобы он мог запомнить действие. Также, если вы планируете использовать лайтбоксы, это должен быть частичный рендеринг, выполненный соответствующим RJS или new.html.erb.

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

<% if params[:controller] == "annotations" %>
  <% content_for :old_form do %>
    <%= hidden_field_tag "annotation[song_id]", params[:annotation][:song_id] %>
    <%= hidden_field_tag "annotation[vote]", params[:annotation][:vote] %>
  <% end %>
<% end %>

Затем визуализируйте это частичное в частичном логине, которое займет ваш лайтбокс:

<%= render :partial => vote_form_replica %>

<% url = params[:controller] == "user_sessions ? user_sessions_url : {} %>
<% form_tag @user_session, :url => url do |f| %>
  <%= yield :old_form %>
  <%= f.label :user_name %>
  <%= f.text_field :user_name %>
  <%= f.label :password %>
  <%= f.password_field :password %>
  <%= submit_tag %>
<%end%>

Пустой хеш для url в form_tag выглядит как ошибка, но это не так. Это гарантирует, что данные формы будут отправлены на URL, который отобразил форму. Которые на данный момент должны быть аннотациями /: id / voice

Теперь для нового фильтра войдите. По сути, он будет делать то, что когда-либо UserSessionsController # create делает без рендеринга / перенаправления. Следующее скопировано из плагина аутентификации RESTful.

def authenticate
  self.current_user = User.authenticate(params[:login], params[:password])
  if logged_in?
    if params[:remember_me] == "1"
       current_user.remember_me unless current_user.remember_token?
       cookies[:auth_token] = { :value => self.current_user.remember_token, 
         :expires => self.current_user.remember_token_expires_at }
    end
  end
end

Осталось только убедиться, что порядок фильтров правильный.

before_filter :authenticate, :require_user, :only => :vote

N.B.: Вероятно, вы не собираетесь использовать эту версию require_user без этой версии authenticate, поэтому имеет смысл объединить их в один фильтр.

И это все. То, как это было настроено, позволяет создать надежный, СУХОЙ, легко повторно используемый код. Помещая новые фильтры в ApplicationController, они доступны в любом контроллере. С этого момента добавление этой функциональности к любым другим контроллерам / действиям занимает всего 3 простых шага:

  1. Создать новый частичный объект, смоделированный после частичного элемента voice_form_replica.
  2. Добавить соответствующий оператор рендеринга в новый шаблон сеанса.
  3. Примените фильтры к своим действиям.
0 голосов
/ 18 января 2010

Я бы подошел к этому так, как вы описываете внизу вашего вопроса. Прежде чем отображать страницу вначале, проверьте, вошел ли пользователь в систему. Если это так, ссылки «Мне нравится» должны работать в обычном режиме. Если нет, привязайте событие click, чтобы отобразить панель регистрации / входа. В этом нет ничего, что нельзя было бы использовать повторно. На самом деле, мы используем этот точный метод на моей работе. Любое действие пользователя, требующее аутентификации, либо следует его обычному поведению, либо вызывает общую панель входа в систему в зависимости от состояния входа в систему во время загрузки страницы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...