Rails 关于子类复用父类 before_fitler 的问题

itsvoid · 2013年03月28日 · 最后由 itsvoid 回复于 2013年03月28日 · 3105 次阅读

父类 ParentController 里面有一个 before_fitler x,应用在父类 action A,B,C 上。

Class ParentController
before_filter :x, only: [:A, :B, :C]

子类 ChildController 继承于 ParentController,但是有一个新 action D,同样需要将 x 应用在其 D 上,而且继承而来的 A,B,C 的 before_filter x 保留。

如果这样写:

before_filter :x, only: [:D]

那么,子类中 A,B,C 就没有 before_fitler X 了。

求解?

我需要的很像这样:

before_filter :x, add: [:D]
before_filter :x, only: [A, B, C, D]  
or
before_filter :x, except: [E, F, G]

#1 楼 @zgm 你这个解不了我的问题。 子类继承了父类的 before_fitler。而子类有新方法同样需要父类的这个 before_filter x。

我需要在子类中,对 before_filter x 增加 一个 action D

#3 楼 @afeicool 我是要复用父类的 before_filter X,而不是另写一个。

#2 楼 @itsvoid 不是没理解你的需求,只是你说的需求没办法实现。

@itsvoid actionpack/lib/abstract_controller/callbacks.rb, line 33 或许你可以 hack 一下这个方法

我的需求是这样

Class ParentController
  before_filter :x, only: [:A, :B, :C]
  def A
  end
  def B
  end
  def C
  end
 protected 
 def x
    ...
  end
end

Class ChildController < ParentController
  before_filter :x, add: [:D]
end

但是,好像没有 add 这类方法。

不过,我理解这应该是一个比较普遍的需求,为什么 rails 的 before_filter 没有呢。

before_filter 接受 if 参数,用 proc 来处理

class ParentController
  before_filter :x, if => proc {|controller| controller.filter_names_for_x.include?(action_name) }

  def filter_names_for_x
    [:A, :B, :C]
  end
end

class ChildController
  def filter_names_for_x
    super << :D
  end
end

是否可以换一个思路:

class ChildController
  before_filter :y, only: [:D]

  protected
  def y; x; end
end

在我看来,ChildController 了解 ParentController 中有 x 是必然的,但不是太应该让它去关心其他 actions。

未测试,仅供讨论参考。

不明白!直接在子类里面使用 before_filter :x, only: [:D] 不行吗?

#11 楼 @zlx_star 子类还有其他从父类继承而来的 action,比如 A,B,C。如果像你这样写,子类的 A,B,C 就无法应用 X 了

#8 楼 @quakewang 有点过于 hack 了。子类复用父类过滤器,同时应用到子类自己新的 action 上,这应该是一个很普遍的需求阿。

#10 楼 @ashchan 这个方法我也想过,不过总得要增加 1 个函数,而且这个函数还仅仅是调用父类的 X

#16 楼 @itsvoid 不要管父类,直接在子类里面使用 before_filter :x, only: [:A, :B, :C, :D]

@itsvoid 直接在子类加 before_filter :x , only: [:d] , 是没有问题的 因为每一个 before_filter :name ,即使相同名称 ,都会执行, 如果想跳过可以用 :skip_before_filter, 请查阅这段代码,你会发现 before_filter 实际是是调用 _insert_callbacks https://github.com/rails/rails/blob/master/actionpack/lib/abstract_controller/callbacks.rb#L178-L213

#18 楼 @hysios 如何子类这样写 before_filter :x , only: [:d],子类的 a,b,c 方法都不会运用 x 了。你可以试试。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号