我正在尝试检查用户是否已订阅我的SaaS应用程序的适当计划。
基本上,这就是我想要做的:
module SubscriptionControlled extend ActiveSupport::Concern
class_methods do
def requires_subscription_to(perm)
@@perms = [perm]
end
end
included do
validate :check_subscription
end
def check_subscription
@@perms.each do |perm|
self.errors.add(:base, "Subscription upgrade required for access to this feature") unless self.user[perm]
end
end
end
这为模型提供了此api:
class SomeModel < ApplicationModel
include SubscriptionControlled
requires_subscription_to :pro
end
我遇到的问题是@@perms
的范围似乎是CONCERN而不是MODEL。因此,所有型号的该值均相同。因此,无论哪个模型最后加载,都将为所有模型设置该值。
例如:如果按此顺序加载:
Model1 -> sets @@perms to [:pro]
Model2 -> sets @@perms to [:business]
模型1和模型2都只需要订阅:business
是否存在一种方法来存储关注于每个模型的API级别的类级变量?
答案 0 :(得分:0)
我现在没有Ruby解释器,但是我很确定在类方法中使用单个@
应该可以解决问题。想到的另一件事是
included do
define_singleton_method :requires_subscription_to do |new_perm|
@@perms ||= []
@@perms << Array(new_perm)
end
end
由于每次包含关注点时都会创建一个新方法,因此它应该可以工作。我似乎只是记得,这样定义的方法会稍微慢一些-但由于它可能只会在初始化期间被调用,因此在任何情况下都不会造成问题。
答案 1 :(得分:0)
因此,我找到了使用ClassMethods
模块执行此操作的正确方法
module SubscriptionControlled extend ActiveSupport::Concern
module ClassMethods
@perms = []
def requires_subscription_to(perm)
@perms = [perm]
end
def perms
@perms
end
end
included do
validate :check_subscription
end
def check_subscription
self.class.perms.each do |perm|
self.errors.add(:base, "Subscription upgrade required for access to this feature") unless self.user[perm]
end
end
end
这将权限限制在类而不是关注范围内。
答案 2 :(得分:0)
我认为您过于复杂了。您完全不需要check_subscription
方法,而该方法就是您试图使@@perms
(或@perm
)工作的原因。
validate
只是一个类方法,您可以给validate
块。您可以使用该块来捕获perm
,并消除所有额外的机械设备:
module SubscriptionControlled extend ActiveSupport::Concern
module ClassMethods
def requires_subscription_to(perm)
validate do
self.errors.add(:base, "Subscription upgrade required for access to this feature") unless self.user[perm]
end
end
end
end