2017-10-15 59 views
3

可以从父类中包含的模块中调用父类的子类的私有方法,尤其是在涉及到Rails中的ApplicationController,Controllers和lib模块时?从rails的父类中包含的模块中调用父类的子类的私有方法是否可行?

考虑是否需要更改控制器名称的方法名称以反映型号名称(至第条)的更改。

我觉得这是非常糟糕的编码,并想知道想着从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_controlle r.rb

class ApplicationController < ActionController::Base 
    include SomeModule 

    before_action :filtering_method 

end 

/app/controllers/notes_controller.rb

class NotesController < ApplicationController 

    def show 
    end 

    private 

    def note 
    @note ||= Note.find(param[:id])) 
    end 
end 
+0

我想知道你想达到什么目的?你为什么不在'show'方法中调用'note'或者在控制器中定义'before_action:note'。恕我直言,这将更易读,更容易理解。 – spickermann

+0

我在问这个,因为我在我正在研究的应用程序中看到过这段代码,我需要向其他人证明这是错误的编码方式。 – Satya

+2

你问过其他开发者为什么这么做吗?为什么他们认为用两个模块和几个间接步骤替换单行代码是一个好主意。我同意这个例子乍一看看起来很复杂,但是在决定引入这种复杂性的背后必定有一个理由或历史。 – spickermann

回答

1

我认为这是没有必要的不错,虽然当你想到某个接口(方法,变量,等等),其中包括模块我想补充以下类别:

module SomeModuleResource 
    def fetch_object 
    note 
    end 

    private 

    def note 
    raise NotImplementedError 
    end 
end 

这样,当#note被称为没有实现它(因为你忘了需要或W憎恨者)提出NotImplementedError

另一个选择是解决它并创建一个更一般的解决方案。例如,如果所有的控制器行为相同的方式,你上面的描述,你可以做到以下几点:

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_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_filter { @note ||= Note.find(params[:id]) }(包括后)。

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

参见:Alternatives to abstract classes in Ruby?。或者在Ruby中搜索抽象类,你会发现更多关于这个主题的内容。

+0

我同意第一个代码示例。如果一个子类的方法有望实现,那么我们应该确保它被实现。如果它不被迫这样做,并且在以后的更改中代码将会中断。 – Satya