2016-02-19 53 views
1

我:添加功能回调的条件列表模块中

  • 用的before_filter回调控制器定义(UPDATE:控制器是在Rails应用程序,我不能修改)
  • 一一些新的功能,这被添加到控制器模块(UPDATE:模块是我的插件)

我想这个回调到这些功能之前执行过。

class MyController < ApplicationController 
    before_filter :prepare, :only => :show 

    def show 
    end 

    def edit 
    end 

    private 

    def prepare 
    end 
end 

module MyModule 
    def self.included(base) 
    base.send(:include, InstanceMethods) 
    base.before_filter :prepare, :only => [:a, :b] 
    end 

    module InstanceMethods 
    def a 
     ... 
    end 
    def b 
     ... 
    end 
    end 
end 

如果我这样做,这样一来,该列表将被重新定义,而“准备”不会被前“秀”之称。

的选项我看到:

def self.included(base) 
    base.send(:include, InstanceMethods) 
    base.before_filter :prepare, :only => [:a, :b, :show] 
    end 

def a 
     prepare 
     ... 
    end 
    def b 
     prepare 
     ... 
    end 

module MyModule 
    def self.included(base) 
    base.send(:include, InstanceMethods) 
    base.before_filter :prep, :only => [:a, :b] 
    end 
    module InstanceMethods 
    def prep 
     prepare 
    end 
    ... 
    end 
end 

是如此的丑陋和未干的。

有没有自然的方法可以做到这一点?

回答

0

也许你应该

before_filter :prepare, :except => [:foo, :bar, :etc] 

我想这会拿起:a:b

顺便说一句,你的控制器好像可能很胖。也许,也是重构的机会?

+0

什么告诉你控制器很胖? – max

+0

这只是一个让我使用模块来包含其他方法的想法。这暗示了我(可能错误地)在控制器中可能会发生很多事情。因此,也许是重新思考某种设计的机会。但是,也许不是,也许控制器是不可能的。 – jvillian

+0

控制器来自供应商的导轨应用程序(所以我不想碰它)和模块在我的插件。控制器中的函数列表可能会发生变化,所以我不想在将来的应用程序更新中使用它。 – marlett

0

也许你正在寻找的东西是这样的:

module MyModule 
    def self.included(base) 
    base.send(:include, InstanceMethods) 
    base.extend ClassMethods 
    end 

    module ClassMethods 
    def prepare(*actions) 
     # optional - add defaults 
     actions = ([:a, :b] + (actions || [])).uniq 
     # self here is the singelton class object 
     self.instance_eval do 
     before_filter :prep, only: actions 
     end 
    end 
    end 

    module InstanceMethods 
    def prep 
     prepare 
    end 
    ... 
    end 
end 

我们创建一个prepare类方法,它需要一个图示,然后计算一个用的before_filter行动的图示使用默认值合并。

class ThingsController < ApplicationController 
    include MyModule 
    prepare :show 
end