为什么不包含之前包含的模块方法的包含模块方法?
问题描述:
我想有条件地覆盖在宝石内定义的方法。我的想法是有条件地包含一个模块和我希望覆盖的方法。但是我发现,在我希望重写的模块之后简单包含一个模块并不像我期望的那样覆盖方法。请看下面的例子:为什么不包含之前包含的模块方法的包含模块方法?
这些都是我想重写宝石方法的方法:
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
转出活动。
我该如何做到这一点?
答
如果条件在应用程序初始化后的某个时间点变为真,则条件成立后send
User
include
方法。例如
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
有两个问题:1)你确定'$ rollout.active?(:redis_to_mysql)'是真的吗? 2)当它真的很好,你调用'User.ancestors'时,它输出了什么? –
'如果$ rollout.active?(:redis_to_mysql)'实际上是无效的语法'include SocializationsOverideConcern'。我添加它只是为了表明意图。 – matthewalexander
当我检查User.ancestors时,我想重写的模块显示在我希望覆盖它们的模块后面。不知道这是为什么...... – matthewalexander