如何使用关注事项在模型上存储自定义的类级别数据

时间:2018-12-26 18:25:13

标签: ruby-on-rails activerecord

我正在尝试检查用户是否已订阅我的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级别的类级变量?

3 个答案:

答案 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