类上下文会覆盖具有相同名称的模块方法吗?

时间:2017-01-27 20:16:46

标签: ruby-on-rails ruby devise

我正在尝试解决Devise gem的问题。问题在于使用带有devise_token_auth的标准设计。

在application_controller.rb中,devise_token_auth要求您添加模块:

class ApplicationController < ActionController::Base
  include DeviseTokenAuth::Concerns::SetUserByToken

添加此SetUserBytToken模块后,我在浏览器中加载users / sign_in路径(而不是/ api / v1 / auth / sign_in)。 users / sign_in路径应该加载设计,而不是devise_token_auth。

然而,我收到错误:

  

错误的参数数量(给定1,预期为0)def resource_class

devise_token_auth在set_user_by_token.rb中调用它:

  def set_user_by_token(mapping=nil)
    # determine target authentication class
    rc = resource_class(mapping)

同一个文件中有一个方法如下:

def resource_class(m=nil)

因此该方法接受DEFAULT参数。但是,你看到了错误,对吗?

  

错误的参数数量(给定1,预期为0)

所以这个方法必须覆盖一些方法。看看这个:

http://www.rubydoc.info/github/plataformatec/devise/DeviseController%3Aresource_class

Devise有一个同名的方法,不带可选参数。我不明白该方法如何覆盖SetUserByToken模块中定义的方法。因为我在SetUserByToken中调用该方法,所以不应该看看模块中定义的那个而不是其他地方吗? https://github.com/lynndylanhurley/devise_token_auth/blob/master/app/controllers/devise_token_auth/concerns/set_user_by_token.rb

1 个答案:

答案 0 :(得分:0)

  

类上下文会覆盖具有相同名称的模块方法吗?

是的,这就是它的工作原理。

class C
  include M
end

使M成为C的超类,就是这样。

由于MC的超类(或从另一侧C查看它是M的子类),因此C中定义的方法覆盖M中定义的方法,这就是继承的工作原理。

如果您希望M的方法覆盖C,则需要使用prepend将M放在ancestors列表前面。

更准确地说,创建了一个 include M′,其类变量表指针,常量表指针和方法表指针指向M的类变量表, M的常量表和M的方法表。 M′的超类指针设置为C的超类,然后C的超类指针设置为M′Object#classClass#superclass方法知道“跳过”单例类并包含类,Module#ancestors知道返回相应的模块而不是include类,因此你不会这个有效,但这就是发生的事情。

这解释了为什么类中定义的方法会覆盖包含模块中定义的方法。它还解释了super与模块的行为。这只是简单的类继承。