为什么不包含之前包含的模块方法的包含模块方法?

问题描述:

我想有条件地覆盖在宝石内定义的方法。我的想法是有条件地包含一个模块和我希望覆盖的方法。但是我发现,在我希望重写的模块之后简单包含一个模块并不像我期望的那样覆盖方法。请看下面的例子:为什么不包含之前包含的模块方法的包含模块方法?

这些都是我想重写宝石方法的方法:

module SocializationsOverideConcern 
    extend ActiveSupport::Concern 

    def follow!(followable) 
    Socialization::RedisStores::Follow.follow!(self, followable) 
    Socialization::ActiveRecordStores::Follow.follow!(self, followable) 
    end 

    def unfollow!(followable) 
    Socialization::RedisStores::Follow.unfollow!(self, followable) 
    Socialization::ActiveRecordStores::Follow.unfollow!(self, followable) 

    NotificationDismissalService.new.call(followable, user: self, dont_match_trigger: true, destroy: true) 
    end 

    def like!(likeable) 
    Socialization::RedisStores::Like.like!(self, likeable) 
    Socialization::ActiveRecordStores::Like.like!(self, likeable) 
    end 

    def unlike!(likeable) 
    Socialization::RedisStores::Like.unlike!(self, likeable) 
    Socialization::ActiveRecordStores::Like.unlike!(self, likeable) 
    end 
end 

这里是我的类定义:

class User < ActiveRecord::Base 

    acts_as_liker 
    acts_as_likeable 
    acts_as_follower 
    acts_as_followable 
    acts_as_mentionable 

    include SocializationsOverideConcern if $rollout.active?(:redis_to_mysql) 

方法遵循!,取消关注!等等都是在社会化宝石里面定义的。并通过上面的acts_as调用包含。

无论如何,这基本上是我正在努力完成的,重写follow!,unfollow !,就像!,而不像!方法,如果redis_to_mysql转出活动。

我该如何做到这一点?

+0

有两个问题:1)你确定'$ rollout.active?(:redis_to_mysql)'是真的吗? 2)当它真的很好,你调用'User.ancestors'时,它输出了什么? –

+0

'如果$ rollout.active?(:redis_to_mysql)'实际上是无效的语法'include SocializationsOverideConcern'。我添加它只是为了表明意图。 – matthewalexander

+0

当我检查User.ancestors时,我想重写的模块显示在我希望覆盖它们的模块后面。不知道这是为什么...... – matthewalexander

如果条件在应用程序初始化后的某个时间点变为真,则条件成立后sendUserinclude方法。例如

def activate_rollout 
    $rollout.activate(:redis_to_msql) 
    User.send(:include, SocializationsOverideConcern) 
end 

$rollout.active?(:redis_to_mysql) # => false 

User.include? SocializationsOverideConcern # => false 

activate_rollout 

$rollout.active?(:redis_to_mysql) # => true 

User.include? SocializationsOverideConcern # => true 

另一种方法是添加的条件的方法中的身体和使用super

module SocializationsOverideConcern 
    extend ActiveSupport::Concern 

    def rollout_active? 
    $rollout.active?(:redis_to_mysql) 
    end 

    def follow!(followable) 
    return super unless rollout_active? 
    Socialization::RedisStores::Follow.follow!(self, followable) 
    Socialization::ActiveRecordStores::Follow.follow!(self, followable) 
    end 

    def unfollow!(followable) 
    return super unless rollout_active? 
    Socialization::RedisStores::Follow.unfollow!(self, followable) 
    Socialization::ActiveRecordStores::Follow.unfollow!(self, followable) 

    NotificationDismissalService.new.call(followable, user: self, dont_match_trigger: true, destroy: true) 
    end 

    def like!(likeable) 
    return super unless rollout_active? 
    Socialization::RedisStores::Like.like!(self, likeable) 
    Socialization::ActiveRecordStores::Like.like!(self, likeable) 
    end 

    def unlike!(likeable) 
    return super unless rollout_active? 
    Socialization::RedisStores::Like.unlike!(self, likeable) 
    Socialization::ActiveRecordStores::Like.unlike!(self, likeable) 
    end 
end 

class User < ActiveRecord::Base 

    acts_as_liker 
    acts_as_likeable 
    acts_as_follower 
    acts_as_followable 
    acts_as_mentionable 

    include SocializationsOverideConcern 
end 

通过这种方式,模块总是包括但条件移动到该方法的执行。如果你需要能够在条件返回时恢复默认功能,这可能会更好。false