Fanli

Fanli is a new way to implement complex business logic in your application(e.g. Rails).

范蠡, 是实现复杂业务逻辑的一种新思路。(如果你的Rails model超过了200行代码,也许你该试试它~~)

Installation

Add this line to your application's Gemfile:

gem 'fanli'

And then execute:

$ bundle

Or install it yourself as:

$ gem install fanli

Usage

Assume you run an ecommerce site, and you may want to do the following things after user registeration:

  1. Send welcome email
  2. Give 20% off coupon if its xmas
  3. Give $5 cash if he's from Beijing
  4. And many more business rules in the future...

In your rails code, you may implement these rules ALL in the User model like this:

class User < ActiveRecord::Base
  validates :name, :email, presence: true

  after_create :send_welcome_email
  after_create :give_coupon_if_xmas
  after_create :give_initial_cash

  # add more `after_commit` callbacks...

  private

  def send_welcome_email
    # business logic goes here...
  end

  def give_coupon_if_xmas
    # business logic goes here...
  end

  def give_initial_cash
    # business logic goes here...
  end
end

This will result in "Fat Models" that violate the SRP("Single responsibility principle").

To solve this problem and prevent messy code, you should write code in "The Fanli Way":

  1. Create a new folder containing all the business code:

    $ cd [/path/to/your/rails_project]
    $ mkdir app/business
    
  2. Create a new "business processing class":

    # app/business/create_user.rb
    class CreateUser < Fanli::Base
      def perform(args)
        User.create!(args)
      end
    end
    
  3. Implement each business login using separate "Plain Old Ruby Class":

    # app/business/send_welcome_email.rb
    class SendWelcomeEmail
      def self.on_create_user(ev)
        # business logic goes here...
      end
    end
    
    # app/business/give_coupon_if_xmas.rb
    class GiveCouponIfXmas
      def self.on_create_user(ev)
        # business logic goes here...
      end
    end
    
    # app/business/give_initial_cash.rb
    class GiveInitialCash
      def self.on_create_user(ev)
        # business logic goes here...
      end
    end
    
  4. Register each business logic class:

    # app/business/registry.rb
    Fanli.on(:create_user,
      SendWelcomeEmail,
      GiveCouponIfXmas,
      GiveInitialCash
    )
    
  5. Use your business processing class in your controller:

    # app/controllers/users_controller.rb
    class UsersController < ApplicationController
      def create
        CreateUser.with(params.require(:user).permit(:name, :email))
      end
    end
    
  6. Done! Enjoy!

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/daqing/fanli. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.