最初に throw(:warden) を使用してこれを解決しましたが、これは機能しますが、おそらく最善の解決策ではありません。その後、r00kによるカスタム デバイス戦略の例に出くわし、独自のバリエーションを実装しました。以下に両方のソリューションを含めました。
r00k-esque ソリューション
NB いくつかのコードがありましたが、それは私にとってはうまくいかなかった r00k のソリューションです。r00k のソリューションがうまくいかない場合は、「fail!」との違いに注意してください。および「valid_password?」。
# config/initializers/local_override.rb
require 'devise/strategies/authenticatable'
module Devise
module Strategies
class LocalOverride < Authenticatable
def valid?
true
end
def authenticate!
if params[:user]
user = User.find_by_username(params["user"]["username"])
if user.present?
code = params["user"]["check_org_code"].downcase
codes = user.locations.pluck(:org_code).map{ |code| code.downcase }
check_code = code.in?(codes)
check_password = user.valid_password?(params["user"]["password"])
if check_code && check_password
success!(user)
else
fail!(:invalid)
end
else
fail!(:invalid)
end
else
fail!(:invalid)
end
end
end
end
end
Warden::Strategies.add(:local_override, Devise::Strategies::LocalOverride)
# config/initializers/devise.rb
config.warden do |manager|
manager.default_strategies(:scope => :user).unshift :local_override
end
初期ソリューション
class SessionsController < Devise::SessionsController
def create
user = User.find_by_username(params["user"]["username"])
org_code = params["user"]["check_org_code"].downcase
matching = false
user.locations.each do |location|
if location.org_code == org_code
super
session[:location] = location
matching = true
break
end
end
if matching == false
throw(:warden, :message => :invalid)
end
end
end