Ruby gem 方法只能在控制器中使用?如果是这样,如何使其在其他文件中可用?
Ruby gem method only available in controller? If so, how to make it available in other files?
我的印象是 gem 的方法可以在 Rails 应用程序的任何地方访问,一旦它与捆绑器一起安装。但事实并非如此吗?我很困惑,因为 controller
中可访问的方法在移出文件时无法识别。
有什么方法可以要求 gem 到 运行 下面的代码 command
文件而不是 controller
?
我正在使用名为 sorcery
to implement an OAuth login system. There are some methods 的身份验证 gem,类似于 gem 提供的 login_from(provider)
,可以从我的控制器访问它。
# app/controllers/oauths_controller.rb
class OauthsController < ApplicationController
skip_before_action :require_login
def callback
provider = params[:provider]
if @user = login_from(provider)
# method continues
end
但是,我们正在尝试在我们的应用程序中采用命令查询分离方法,因此我尝试将包含 login_from(provider)
方法的这个进程移动到另一个名为 app/commands/authentication/login_command.rb
的文件中。这导致无法识别该方法:
NoMethodError (undefined method 'login_from' for #<Authentication::LoginCommand:>)
提前致谢。
I was under the impression that a gem's methods can be accessed anywhere in the Rails app once it's been installed with bundler.
这是一种错误的印象。
如您所见,Sorcery::Engine
导致 ActionController::Base
包含 Sorcery::Controller
中定义的方法,此处:
require 'sorcery'
require 'rails'
module Sorcery
# The Sorcery engine takes care of extending ActiveRecord (if used) and ActionController,
# With the plugin logic.
class Engine < Rails::Engine
config.sorcery = ::Sorcery::Controller::Config
initializer 'extend Controller with sorcery' do
# TODO: Should this include a modified version of the helper methods?
if defined?(ActionController::API)
ActionController::API.send(:include, Sorcery::Controller)
end
if defined?(ActionController::Base)
ActionController::Base.send(:include, Sorcery::Controller)
ActionController::Base.helper_method :current_user
ActionController::Base.helper_method :logged_in?
end
end
end
end
Sorcer::Controller
依次包含一系列子模块:
module Sorcery
module Controller
def self.included(klass)
klass.class_eval do
include InstanceMethods
Config.submodules.each do |mod|
# FIXME: Is there a cleaner way to handle missing submodules?
# rubocop:disable Lint/HandleExceptions
begin
include Submodules.const_get(mod.to_s.split('_').map(&:capitalize).join)
rescue NameError
# don't stop on a missing submodule.
end
# rubocop:enable Lint/HandleExceptions
end
end
Config.update!
Config.configure!
end
...
end
end
这些子模块之一是 Sourcery::Controller::Submodules::External
,当包含时,还包含 Sourcery::Controller::Submodules::External::InstanceMethods
,此处:
module Sorcery
module Controller
module Submodules
# This submodule helps you login users from external auth providers such as Twitter.
# This is the controller part which handles the http requests and tokens passed between the app and the @provider.
module External
def self.included(base)
base.send(:include, InstanceMethods)
...
end
end
end
end
end
并且,InstanceMethods
包含方法 login_from
,此处:
module Sorcery
module Controller
module Submodules
# This submodule helps you login users from external auth providers such as Twitter.
# This is the controller part which handles the http requests and tokens passed between the app and the @provider.
module External
def self.included(base)
base.send(:include, InstanceMethods)
module InstanceMethods
protected
...
# tries to login the user from provider's callback
def login_from(provider_name, should_remember = false)
sorcery_fetch_user_hash provider_name
return unless (user = user_class.load_from_provider(provider_name, @user_hash[:uid].to_s))
# we found the user.
# clear the session
return_to_url = session[:return_to_url]
reset_sorcery_session
session[:return_to_url] = return_to_url
# sign in the user
auto_login(user, should_remember)
after_login!(user)
# return the user
user
end
...
end
end
end
end
end
Soooo,说 login_from
被定义为继承自 ActionController::Base
的 类 上的受保护实例方法并没有被定义为 类 不从 ActionController::Base
继承,这就是为什么你得到 NoMethodError
。
Is there some way I could require the gem to run the code below in the command file instead of the controller?
也许吧。也许不吧。如您所见,login_from
正在使用其他 sorcery
方法和继承自 ActionController::Base
的方法。因此,您需要确保所有这些方法都在 Authentication::LoginCommand
中可用,以便 login_from
正常运行。
我的印象是 gem 的方法可以在 Rails 应用程序的任何地方访问,一旦它与捆绑器一起安装。但事实并非如此吗?我很困惑,因为 controller
中可访问的方法在移出文件时无法识别。
有什么方法可以要求 gem 到 运行 下面的代码 command
文件而不是 controller
?
我正在使用名为 sorcery
to implement an OAuth login system. There are some methods 的身份验证 gem,类似于 gem 提供的 login_from(provider)
,可以从我的控制器访问它。
# app/controllers/oauths_controller.rb
class OauthsController < ApplicationController
skip_before_action :require_login
def callback
provider = params[:provider]
if @user = login_from(provider)
# method continues
end
但是,我们正在尝试在我们的应用程序中采用命令查询分离方法,因此我尝试将包含 login_from(provider)
方法的这个进程移动到另一个名为 app/commands/authentication/login_command.rb
的文件中。这导致无法识别该方法:
NoMethodError (undefined method 'login_from' for #<Authentication::LoginCommand:>)
提前致谢。
I was under the impression that a gem's methods can be accessed anywhere in the Rails app once it's been installed with bundler.
这是一种错误的印象。
如您所见,Sorcery::Engine
导致 ActionController::Base
包含 Sorcery::Controller
中定义的方法,此处:
require 'sorcery'
require 'rails'
module Sorcery
# The Sorcery engine takes care of extending ActiveRecord (if used) and ActionController,
# With the plugin logic.
class Engine < Rails::Engine
config.sorcery = ::Sorcery::Controller::Config
initializer 'extend Controller with sorcery' do
# TODO: Should this include a modified version of the helper methods?
if defined?(ActionController::API)
ActionController::API.send(:include, Sorcery::Controller)
end
if defined?(ActionController::Base)
ActionController::Base.send(:include, Sorcery::Controller)
ActionController::Base.helper_method :current_user
ActionController::Base.helper_method :logged_in?
end
end
end
end
Sorcer::Controller
依次包含一系列子模块:
module Sorcery
module Controller
def self.included(klass)
klass.class_eval do
include InstanceMethods
Config.submodules.each do |mod|
# FIXME: Is there a cleaner way to handle missing submodules?
# rubocop:disable Lint/HandleExceptions
begin
include Submodules.const_get(mod.to_s.split('_').map(&:capitalize).join)
rescue NameError
# don't stop on a missing submodule.
end
# rubocop:enable Lint/HandleExceptions
end
end
Config.update!
Config.configure!
end
...
end
end
这些子模块之一是 Sourcery::Controller::Submodules::External
,当包含时,还包含 Sourcery::Controller::Submodules::External::InstanceMethods
,此处:
module Sorcery
module Controller
module Submodules
# This submodule helps you login users from external auth providers such as Twitter.
# This is the controller part which handles the http requests and tokens passed between the app and the @provider.
module External
def self.included(base)
base.send(:include, InstanceMethods)
...
end
end
end
end
end
并且,InstanceMethods
包含方法 login_from
,此处:
module Sorcery
module Controller
module Submodules
# This submodule helps you login users from external auth providers such as Twitter.
# This is the controller part which handles the http requests and tokens passed between the app and the @provider.
module External
def self.included(base)
base.send(:include, InstanceMethods)
module InstanceMethods
protected
...
# tries to login the user from provider's callback
def login_from(provider_name, should_remember = false)
sorcery_fetch_user_hash provider_name
return unless (user = user_class.load_from_provider(provider_name, @user_hash[:uid].to_s))
# we found the user.
# clear the session
return_to_url = session[:return_to_url]
reset_sorcery_session
session[:return_to_url] = return_to_url
# sign in the user
auto_login(user, should_remember)
after_login!(user)
# return the user
user
end
...
end
end
end
end
end
Soooo,说 login_from
被定义为继承自 ActionController::Base
的 类 上的受保护实例方法并没有被定义为 类 不从 ActionController::Base
继承,这就是为什么你得到 NoMethodError
。
Is there some way I could require the gem to run the code below in the command file instead of the controller?
也许吧。也许不吧。如您所见,login_from
正在使用其他 sorcery
方法和继承自 ActionController::Base
的方法。因此,您需要确保所有这些方法都在 Authentication::LoginCommand
中可用,以便 login_from
正常运行。