Как установить ограничения ActiveRecord по типу плана подписки в приложении Rails 4.2?

У меня есть мультитенантное приложение Rails 4.2, использующее Devise для аутентификации. Я настроил планы подписки следующим образом: Индивидуальный {Ежемесячный и Ежегодный}, Бизнес {Ежемесячный и Ежегодный}. Индивидуальный план имеет ограничение в 5 пользователей и 5 планов. Бизнес-план имеет неограниченное количество пользователей и планов.

Я пытался настроить способ запретить пользователям индивидуальных планов создавать новые планы и записи пользователей, когда они достигли своего предела.

Я пробовал это: в рельсах, как ограничить количество сообщений пользователей, сохраненных в базе данных, прежде чем просить обновить свою учетную запись

Мой код выглядел так в модели "план":

before_save :check_plan_quota
private

def check_plan_quota
if self.account.plans.count >= 5
  @quota_warning = "Plan limit reached."
  return false
 end
end

И у меня было это в моем контроллере "приборной панели" (потому что именно здесь создаются и перечислены планы):

before_filter :check_quota
  private

 def check_quota
  if Plan.count >= 5
    @quota_warning = "Plan limit reached."
  end
end

Я смог заставить его работать, когда пользователь не мог добавить больше записей, когда они достигли 5 планов, а также сделал так, чтобы кнопка "добавить план" исчезла, основываясь на @quota_warning.

          <p>
      <% if @quota_warning.present? %>
       <button type="button" class="btn btn-default"> You have <%= Plan.count %> Plans </button> &nbsp;&nbsp; - &nbsp;&nbsp; <button type="button" class="btn btn-secondary"> <%= @quota_warning %></button> 
       <% else %>
        <a href="/plans/new" class="btn btn-primary" data-toggle="modal" data-target="#styledModal">New Plan</a> &nbsp;&nbsp; - &nbsp;&nbsp; <button type="button" class="btn btn-default"> You have <%= Plan.count %> Plans </button>
        <% end %> 
      </p>

НО это ограничивало всех пользователей только 5 планами, и, как я понимаю, я не смог получить работающее заявление "если", которое применило бы это ограничение только к пользователям индивидуальных месячных или годовых планов.

Затем я попробовал это на "пользовательском" контроллере.

before_filter :check_user_limit, :only => :create

def check_user_limit
  redirect_to new_user_url if current_account.reached_user_limit?
end

А в модель "аккаунт" я положил.

class Account < ActiveRecord::Base

has_many :users, dependent: :destroy, :inverse_of => :account
accepts_nested_attributes_for :users

has_one :admin, -> { where(admin: true) }, :class_name => "User"
accepts_nested_attributes_for :admin

:user_limit => Proc.new {|a| a.users.count }

has_many :plans, dependent: :destroy, :inverse_of => :account
accepts_nested_attributes_for :plans

:plan_limit => Proc.new {|a| a.plans.count }

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

Первый способ, который я попробовал, казался простым, но я не мог заставить его работать с чем-то вроде

if account.user.plan.stripe_id = 'monthly' or 'yearly and Plan.count >= 5
@quota_warning = "Limit reached"
end

Моя структура приложения выглядит так:

  • Аккаунт - владеет всеми функциями и пользователем.
  • Пользователь - принадлежит учетной записи и владеет подпиской через User.plan, но функции не принадлежат пользователю. Я не хочу, чтобы функции были привязаны к пользователю с помощью принадлежащего.

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

Кажется, что использование кода user_limit и plan_limit в модели и простая проверка на создание в контроллере немного лучше, чем другие, но я не могу заставить его работать. Я не уверен, что мне нравится иметь поля db для этого. Я понимаю, что делает код Proc.new, но не то, к чему я могу его применить. Я попытался применить его к концу has_one: admin, но получил следующую ошибку:

Unknown key: :user_limit. Valid keys are: :class_name, :class, :foreign_key, :validate, :autosave, :dependent, :primary_key, :inverse_of, :required, :as, :foreign_type

Я не уверен, достаточно ли это информации, чтобы помочь мне, но если мне нужно добавить больше информации, пожалуйста, дайте мне знать.

1 ответ

Решение

Я бы разбил это на методы / куски логики размером с кусочек, а затем создал бы функциональность, которую вы хотите, основываясь на этом. Что-то вроде:

INDIVIDUAL_USER_LIMIT = 5
INDIVIDUAL_PLAN_LIMIT = 5

def individual_plan?
  self.plan.type == :individual # or some such logic.
end

def over_user_limit?
  self.individual_plan? && self.users.count > INDIVIDUAL_USER_LIMIT
end

def over_plan_limit?
  self.individual_plan? && self.plans.count > INDIVIDUAL_PLANS_LIMIT
end

Вероятно, также стоит потратить время на тщательный анализ реализации пользовательского валидатора, который будет выглядеть примерно так:

class UserLimitValidator < ActiveModel::Validator
  def validate(account)
    if account.over_user_limit?
      account.errors[:users] << 'Too many users for your plan!'
    end
  end
end

И позволяют вам проверить, что модели, которые вы сохраняете, имеют намеченные ограничения.

Как вещь, о которой следует помнить при реализации этого, будьте осторожны с вызовом self.plans.count или же self.users.count, поскольку он делает дополнительный запрос к базе данных и может вызвать некоторые неприятные проблемы с производительностью в масштабе, такие как проблема запроса N+1.

Другие вопросы по тегам