用devise控制用户订阅

时间:2014-03-18 15:26:26

标签: ruby-on-rails ruby devise subscription

我在我的应用程序中添加了对订阅的支持。

我希望它的工作方式是用户从免费帐户开始,并可以切换到高级帐户。这将自动续订,但如果用户停止付款或取消订阅,将在月底停止。

我对如何使其工作感到困惑,我不太清楚如何处理它。

我为用户配置了使用cancan的权限。

来自models/user.rb

 ROLES = [:admin, :premium, :free]

  def roles=(roles)
    self.roles_mask= (roles & ROLES).map { |r| 2**ROLES.index(r) }.sum
  end

  def roles
    ROLES.reject { |r| ((roles_mask || 0) & 2**ROLES.index(r)).zero? }
  end

  def has_role?(role)
    roles.include? role
  end

  def has_one_of_roles?(roles_array)
    not (roles & roles_array).empty?
  end

  def upgrade_plan (role)
    return false unless ROLES.include? role
    self.roles = [ role ]
    self.save
  end

我有一个订阅控制器controllers/subscription_controller.rb

  def create

    @subscription = Subscription.new(params[:subscription])
    @subscription.user_id = current_user.id
    @subscription.expiration_date = 1.month.from_now

    respond_to do |format|
      if @subscription.save
        if current_user.upgrade_plan :premium
          format.html { redirect_to trades_path, notice: 'Subscription was successfully created. Compliments you are now subscribed to the premium plan' }
          format.json { render json: trades_path, status: :created, location: @subscription }
        else
          format.html { redirect_to home_pricing_path, notice: 'Error while upgrading your account, please contact us' }
          format.json { render json: home_pricing_path, status: :created, location: @subscription }
        end
      else
        format.html { render action: "new" }
        format.json { render json: @subscription.errors, status: :unprocessable_entity }
      end
    end
  end

虽然在我看来在数据库中订阅有点多余,但仍然只检查用户角色。

另外,通过这种方式,我应该在每次请求时检查订阅的有效性,这样我就可以在用户角色过期时更新它,这似乎太重了。

你会如何应对这种情况?

谢谢,

2 个答案:

答案 0 :(得分:4)

您不需要在每个请求上检查订阅,因为到期是基于时间的,您需要为到期订阅创建rake任务并将其添加到服务器上的cron以便每天调用一次。

您可以阅读自定义佣金任务here

答案 1 :(得分:2)

我最近也实施了付费专区,我有以下建议。

  • 首先,当您将User类过多地组合时,您的User类会很快被堵塞。考虑将帐户管理详细信息分成单独的模型,例如帐户模型。这样,可以更好地封装远离核心用户模型的有关升级,降级,续订和到期的功能。一旦你开始使用CanCan和Devise(如果你正在使用它),用户可以快速过度多路复用 - 尽可能保持用户的中心目的。我希望我早点完成这项工作:我最终必须重构账户,现在它更清洁(更可测试,更简单等)。这是一个简单的拥有/属于这种关系。
  • 使用单独的帐户(或订阅)类,您的控制器可能更容易管理? TDD测试可能有助于揭示在您处理用例时的情况。
  • 让您的到期日期变得简单。检查起来相当便宜 许多请求的日期,只要您只依赖本地数据。 如果您使用外部付费墙(比如Stripe或Recurly),您会想要 最小化检查,这取决于你关心的原始时间有多接近。我没有看到日常任务的需要,虽然这当然可行,但是你必须每天验证它是否正常运行。
  • 我只使用了一个单独的account_type字段(比如,基本与高级)来帮助支持有效期限的逻辑,这与您使用ROLES进行的操作相同。来回切换相当简单,并支持到期日期逻辑。鉴于你的平台的角色概念变得更加复杂或多维(现在将账户分开的另一个原因),考虑到你正在做的事情,但准备重构。我使用CanCan只是为了配合角色而不考虑到期。保持角色简单,让expiration逻辑根据需要处理切换角色。再次,将过期和帐户数据与用户分开可以帮助解决这个问题。我们在很大程度上将管理员与付费帐户分开,因为在某种程度上,他们可以被视为不同的维度"但这仅仅是基于我们规范动态的设计选择。

希望这有帮助。

更新:2014年3月18日 我意识到你的主题是指设计。你有更具体的问题吗?我的实现也涉及Devise,所以也许我可以提供更有针对性的建议。