首页 > 解决方案 > 如何在我的 ConnectionAdapter 回调中使用设计方法?

问题描述

我有一个 Rails 5.1 应用程序,它使用 Devise 处理我的User模型的身份验证。这个应用程序有一个 Oracle 数据库后端,需要在执行任何查询之前使用登录用户设置系统上下文变量,所以我希望在:checkoutConnectionAdapter 的回调中执行此操作。

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在块内似乎评估为current_userConnectionAdapter 中定义的方法,而不是 Devise 定义的方法。我怎样才能访问 Devise 的current_user

如何在此回调中使用这些 Devise 提供的方法?

标签: ruby-on-railsrubydevise

解决方案


您不能使用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 虽然不同的命令,但可能会有所帮助。


推荐阅读