Как хранить пользовательские данные уровня класса на моделях, используя Concerns - PullRequest
0 голосов
/ 26 декабря 2018

Я пытаюсь решить, подписан ли пользователь на соответствующий план для моего приложения 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, кажется, ограничен КОНЦЕРНОМ, а не МОДЕЛЬЮ.Так что это значение одинаково для всех моделей.Таким образом, какая бы модель не загружалась последней, это значение устанавливается для всех моделей.

Например: если загружено в следующем порядке:

Model1 -> sets @@perms to [:pro]
Model2 -> sets @@perms to [:business]

Для модели 1 и модели 2 требуется только подписка на: business

Есть ли способ хранения переменных уровня класса в рамках задачи, которые вступают в силу для каждой модели для реализации этого API?

Ответы [ 3 ]

0 голосов
/ 27 декабря 2018

Таким образом, я нашел правильный способ сделать это, используя 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

, при этом права доступа ограничены классом, а не проблемой.

0 голосов
/ 27 декабря 2018

Я думаю, вы слишком усложняете это.Вам не нужен метод 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
0 голосов
/ 26 декабря 2018

У меня сейчас нет интерпретатора Ruby, но я вполне уверен, что использование единственного @ в методе класса должно помочь.Еще одна вещь, которая приходит на ум, - это что-то вроде

included do
  define_singleton_method :requires_subscription_to do |new_perm|
    @@perms ||= []
    @@perms << Array(new_perm)
  end
end

Так как это будет создавать новый метод каждый раз, когда возникает проблема, он должен работать.Кажется, я просто помню, что методы, определенные таким образом, немного медленнее, но, поскольку они, вероятно, будут вызываться только во время инициализации, в любом случае это не должно вызывать проблем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...