maildropr/planify

View on GitHub
README.md

Summary

Maintainability
Test Coverage
Planify [![Build Status](https://secure.travis-ci.org/maildropr/planify.png?branch=master)](http://travis-ci.org/maildropr/planify) [![Code Climate](https://codeclimate.com/github/maildropr/planify.png)](https://codeclimate.com/github/maildropr/planify) [![Coverage Status](https://coveralls.io/repos/maildropr/planify/badge.png)](https://coveralls.io/r/maildropr/planify) [![Gem Version](https://badge.fury.io/rb/planify.png)](http://badge.fury.io/rb/planify)
========

Make subscription plans and enforce their limits with Planify.

## Requirements

Ruby:
* 1.9.3
* 2.0.0
* JRuby (1.9 mode)
* Rubinius (1.9 mode)

Mongoid 3 (Support for other ORMs will be a future improvement)

## Installation

Add this line to your application's Gemfile:

    gem 'planify'

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install planify

## Setup 

### Limitables
Limitables are classes which can be limited based on plan settings. To create a limitable, include the `Planify::Limitable` mixin in your class.

```ruby
# app/models/widget.rb
class Widget
  include Mongoid::Document
  include Planify::Limitable
  ...
end
```

### Plans
Plans hold information about how many instances of a `Limitable` can be created, as well as which features are available to users subscribed to this plan:

```ruby
# config/initializers/plans.rb
Planify::Plans.define :starter do
  price 5.00 # Costs 5 dollars
  description "The perfect plan to get you started"

  max Widget, 100 # Can only create up to 100 widgets before needing to upgrade

  feature :ajax_search # This plan supports ajax search
  enable_feature :live_reload # And live reloading

  disable_feature :guest_account # But no guest accounts
  feature :support_tickets, false # And no support tickets
end
```

### Users
Add the `Planify::User` mixin to your user class. This will keep track of how many limitables the user has created, as well as their plan and plan overrides:

```ruby
class User
  include Mongoid::Document
  include Planify::User
  ...
end
```

Then assign the user a plan:

```ruby
@user = User.create
@user.has_plan :starter
```

You can also assign user-specific overrides to plan limits and features:

```ruby
# This user has half the widgets and no ajax-search
@user.has_plan :starter do
  max Widget, 50
  disable_feature :ajax_search
end
```

## Usage

After creating your Limitables, Plans, and User, you are ready to start enforcing limits.

```ruby
# widgets_controller.rb

def create
  @user = current_user

  if @user.can_create? Widget # User has not hit their Widget cap
    @widget = Widget.create(params[:widget])
    @user.created :widget
  end
end

def destroy
  @user = current_user
  @widget = Widget.find(params[:id])

  @widget.destroy
  @user.destroyed @widget
end
```

You can also test for features:

```ruby
# _nav.haml

-if current_user.has_feature? :ajax_search
  =ajax_search_form
```

## Rails Integration

When used inside a Rails project, Planify automatically adds two methods to your controllers: `enforce_limit!` and `limit_exceeded!`. `enforce_limit!` will call `limit_exceeded!` if the user is over their limit.

```ruby
# app/controllers/widget_controller.rb
class WidgetController < ApplicationController
  before_filter :enforce_widget_limit, only: [:new, :create]

  ...

  private

  def enforce_widget_limit
    # If the user's Widget limit is exceeded, limit_exceeded! will be called
    enforce_limit! current_user, Widget
  end
end
```

The default behavior of `limit_exceeded!` is to raise an Exception. You can change this behavior by creating your own `limit_exceeded!` method in your `ApplicationController`.

```ruby
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  def limit_exceeded!
    redirect_to upgrade_plan_url, notice: "You must upgrade your account!"
  end
end
```


## Contributing

1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Add some specs (so I don't accidentally break your feature in the future)
4. Commit your changes (`git commit -am 'Add some feature'`)
5. Push to the branch (`git push origin my-new-feature`)
6. Create new Pull Request