Rails: использование Devise с наследованием одной таблицы - PullRequest
11 голосов
/ 17 апреля 2011

У меня проблема с тем, чтобы Разработать для работы так, как мне хотелось бы, с наследованием одной таблицы.

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

class Account < ActiveRecord::Base
  devise :database_authenticatable, :registerable
end

class User < Account
end

class Company < Account
end

У меня есть следующие маршруты:

devise_for :account, :user, :company

Пользователи регистрируются на /user/sign_up, а компании регистрируются на /company/sign_up.Все пользователи входят в систему, используя единственную форму в /account/sign_in (Account является родительским классом).

Однако вход в систему с помощью этой формы только подтверждает их подлинность для области действия Account.Последующие запросы на действия, такие как /user/edit или /company/edit, направляют пользователя на экран входа в систему для соответствующей области.

Как я могу заставить Devise распознавать тип учетной записи и аутентифицировать их для соответствующей области?

Любые предложения очень ценятся.

Ответы [ 4 ]

15 голосов
/ 25 сентября 2013

Существует простой способ справиться с ИППП на маршрутах.

Допустим, у вас есть следующие модели STI:

def Account < ActiveRecord::Base
# put the devise stuff here
devise :database_authenticatable, :registerable,
    :recoverable, :rememberable, :trackable, :validatable
end

def User < Account
end

def Company < Account

Метод, который часто упускается из виду, заключается в том, что вы можете указать блок в методе аутентификации в вашем файле rout.rb:

## config/routes.rb

devise_for :accounts, :skip => :registrations
devise_for :users, :companies, :skip => :sessions

# routes for all users
authenticated :account do
end

# routes only for users
authenticated :user, lambda {|u| u.type == "User"} do
end

# routes only for companies
authenticated :user, lambda {|u| u.type == "Company"} do
end

Чтобы получить различные вспомогательные методы, такие как "current_user" и "authenticate_user!"(«current_account» и «authenticate_account!» уже определены) без необходимости определения отдельного метода для каждого (который быстро становится недоступным при добавлении новых типов пользователей), вы можете определить динамические вспомогательные методы в ApplicationController:

## controllers/application_controller.rb
def ApplicationController < ActionController::Base
  %w(User Company).each do |k| 
    define_method "current_#{k.underscore}" do 
        current_account if current_account.is_a?(k.constantize)
    end 

    define_method "authenticate_#{k.underscore}!" do 
    |opts={}| send("current_#{k.underscore}") || not_authorized 
    end 
  end
end

Вот так я решил проблему с ИППП для рельсов.

10 голосов
/ 28 марта 2013

Я просто столкнулся с точным сценарием (с измененными именами классов), как указано в вопросе.Вот мое решение (Devise 2.2.3, Rails 3.2.13):

в config / rout.rb:

devise_for :accounts, :controllers => { :sessions => 'sessions' }, :skip => :registrations
devise_for :users, :companies, :skip => :sessions

в app / controllers / session_controller.rb:

class SessionsController < Devise::SessionsController
    def create
        rtn = super
        sign_in(resource.type.underscore, resource.type.constantize.send(:find, resource.id)) unless resource.type.nil?
        rtn
    end
end

Примечание: поскольку ваш класс учетных записей по-прежнему будет: registerable, ссылки по умолчанию в views / devise / shared / _links.erb будут пытаться быть отправленными, но new_registration_path (Accounts) не будет работать (мы: пропустите его вмаршрут маршрута) и вызвать ошибку.Вам нужно будет сгенерировать виды устройства и вручную удалить его.

Подсказка к https://groups.google.com/forum/?fromgroups=#!topic/plataformatec-devise/s4Gg3BjhG0E, чтобы указать мне правильное направление.

1 голос
/ 18 апреля 2011

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

Возможно, можно использовать одну и ту же страницу sign_in для нескольких пользовательских областей, используя функцию devise_scope в вашем файле маршрутов, чтобы заставить и пользователей, и: компании использовать одну и ту же страницу входа (руководство можно найти здесь ), но я вполне уверен, что вам придется изменить контроллер сессий, чтобы выполнить некоторую настраиваемую логику, чтобы определить, какой тип пользователя выполняет вход.

0 голосов
/ 17 апреля 2011

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

Пожалуйста, дайте мне знать, если это поможет вам

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