Ruby on rails 调用父类的私有方法';是rails中父类中包含的模块的子类吗?

Ruby on rails 调用父类的私有方法';是rails中父类中包含的模块的子类吗?,ruby-on-rails,ruby,Ruby On Rails,Ruby,从父类中包含的模块调用父类子类的私有方法可以吗?特别是当它涉及Rails中的ApplicationController、Controller和lib模块时 如果需要更改控制器名称,请考虑更改方法名称以反映模型名称(to Article)的更改 我觉得这是非常糟糕的编码,我想知道社区对此有何看法 Rails应用程序的示例: /lib/some_module.rb module SomeModule include SomeModuleResource def filtering_meth

从父类中包含的模块调用父类子类的私有方法可以吗?特别是当它涉及Rails中的ApplicationController、Controller和lib模块时

如果需要更改控制器名称,请考虑更改方法名称以反映模型名称(to Article)的更改

我觉得这是非常糟糕的编码,我想知道社区对此有何看法

Rails应用程序的示例:

/lib/some_module.rb

module SomeModule
  include SomeModuleResource

  def filtering_method
    calling_method
  end

  def calling_method
    fetch_object
  end
end
/lib/some_module_resource.rb

module SomeModuleResource
  def fetch_object
    note
  end
end
/app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  include SomeModule

  before_action :filtering_method

end
class NotesController < ApplicationController

  def show
  end

  private

  def note
    @note ||= Note.find(param[:id]))
  end
end
class ApplicationController
/app/controllers/notes_controller.rb

class ApplicationController < ActionController::Base
  include SomeModule

  before_action :filtering_method

end
class NotesController < ApplicationController

  def show
  end

  private

  def note
    @note ||= Note.find(param[:id]))
  end
end
class NotesController
我认为这并不是坏事,尽管当您期望从包含模块的类中获得某个接口(方法、变量等)时,我会添加以下内容:

module SomeModuleResource
  def fetch_object
    note
  end

  private

  def note
    raise NotImplementedError
  end
end
module SomeModuleResource
  def fetch_object
    note
  end

  private

  def note
    klass = params[:controller].classify.constantize
    instance = klass.find(params[:id])

    var_name = "@#{klass.underscore}"
    instance_variable_set(var_name, instance) unless instance_variable_get(var_name)
  end
end
这样,当调用
#note
而不实现它时(因为您忘记了它是必需的或其他什么),将引发
NotImplementedError

另一个选择是解决这个问题,并创建一个更通用的解决方案。例如,如果所有控制器的行为方式与上述相同,则可以执行以下操作:

module SomeModuleResource
  def fetch_object
    note
  end

  private

  def note
    raise NotImplementedError
  end
end
module SomeModuleResource
  def fetch_object
    note
  end

  private

  def note
    klass = params[:controller].classify.constantize
    instance = klass.find(params[:id])

    var_name = "@#{klass.underscore}"
    instance_variable_set(var_name, instance) unless instance_variable_get(var_name)
  end
end
您还可以创建一个类助手方法,如
before\u action
,以便传递您自己的实现

module SomeModule
  include SomeModuleResource

  def self.included(base)
    base.extend(ClassMethods)
  end

  def filtering_method
    calling_method
  end

  def calling_method
    fetch_object
  end

  module ClassMethods
    def custom_before_action(&block)
      define_method(:note, &block)
      private :note

      before_action :filtering_method
    end
  end
end
现在,您可以在每个控制器(包括之后)中使用
custom_before_过滤器{@note | |=note.find(params[:id])}

以上只是给你一些想法。我相信您可以找到更好的解决方案,但这有望为您指明正确的方向。


请参阅:。或者在Ruby中搜索抽象类,您会发现更多关于这个主题的信息

我想知道你想达到什么目的?为什么不在
show
方法中调用
note
,或者在控制器中的操作:note
之前定义一个
。我想这会更易读,更容易理解。我问这个问题是因为我在我正在开发的应用程序中看到了这段代码,我需要向其他人证明这是错误的编码方式。你问过其他开发人员为什么这样做吗?他们认为用两个模块和几个间接步骤替换一行代码是个好主意,这肯定有原因。我同意这个例子乍看起来很复杂,但引入这种复杂性的决定背后一定有一个原因或历史。他们这样做是为了避免在模块中重新编写note方法(准确地说,rubocop说模块太长)。这种情况发生在以类似方式访问所有控制器时。因此,如果我改变某些东西,特别是在如此大的代码库中重命名方法,我们将导致代码失败,这就是我的观点。顺便说一句,这里的方法是表示,而不是实际代码。因为我不能分享确切的代码,因为我受保密协议的约束。我同意第一个代码示例。如果希望实现子类中的方法,那么我们应该确保它已实现。如果不强制这样做,并且在以后的更改中,代码将被破坏。