我有一个Rails 5.1应用程序,该应用程序使用Devise来处理我的User
模型的身份验证。此应用程序具有一个Oracle数据库后端,该后端需要在执行任何查询之前与登录用户设置系统上下文变量,因此我希望在ConnectionAdapter的:checkout
回调中进行此操作。
class ApplicationController < ActionController::Base
before_action :log_user
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.set_callback :checkout, :after do
# Would like to get the logged-in user's username here so I can apply
# it to the oracle sys_context.
# The below throws "undefined method 'user_signed_in?'"
username = current_user.username if user_signed_in?
end
def log_user
# When in this method, user_signed_in? and current_user work fine.
puts "User is #{current_user.username}" if user_signed_in?
end
end
在user_signed_in?
回调块中运行时,找不到:checkout
方法,尽管该方法通常在控制器中可用。为什么?
此外,该块中的current_user
似乎对ConnectionAdapter中定义的current_user
方法求值,而不是由Devise定义的方法求值。如何获得Devise的current_user
的访问权限?
如何在此回调中使用这些Devise提供的方法?
答案 0 :(得分:1)
您不能使用checkout
回调,因为它在执行时与控制器上下文没有任何关系。您在ApplicationController
中已在此处定义它的事实与它实际在其中执行的上下文无关。
您将需要在before_action
中设置连接选项,以便在控制器上下文中运行。像这样:
before_action :set_user_context
def set_user_context
if current_user
ApplicationRecord.connection.execute "DBMS_SESSION.SET_CONTEXT('whatever', 'goes', 'here', '#{current_user.username}')"
end
end
...或类似的东西。请注意,您可能需要添加checkin
回调以在连接完成后清除该值。
顺便说一句,几天前,我回答了一个几乎相同的问题:https://stackoverflow.com/a/54837596/152786尽管使用了不同的命令,但可能会有所帮助。