Rulebyをちょいと触ってみた

練習

簡単なローン審査を作ってみる

  • 年齢が25歳未満なら文句無しに却下
  • 年齢が25歳以上であっても、ローン完済時に65歳を越えるようなら却下

こんな感じか

$LOAD_PATH << File.join(File.dirname(__FILE__), '../trunk/lib/')
require 'ruleby'

include Ruleby

class Customer
  def initialize(name, age)
    @name = name
    @age = age
  end

  attr :name, true
  attr :age, true
end

class Loan
  def initialize(type, length)
    @type = type
    @length = length
  end
  attr :type, true
  attr :length, true
  attr :availability, true
end

class LoanRulebook < Rulebook
  def rules
    rule :too_young,
    [Customer, :c,  m.age < 25],
    [Loan, :l] do |context|
      puts "Customer #{context[:c].name} can't apply the loan #{context[:l].type}, 'cuz the customer is too young."
      context[:l].availability = false
    end

    rule :too_old,
    [Customer, :c], [Loan, :l] do |context|
      # このルール記述はルールエンジンの思想からすると美しくない
      # 現時点のRulebyは、引数を受け取る条件式を書けない模様
      # http://groups.google.com/group/ruleby/browse_thread/thread/9996492a1fc12255
      unless context[:c].age + context[:l].length < 70
        puts "Customer #{context[:c].name} can't apply the loan #{context[:l].type}, 'cuz the customer is too old."
        context[:l].availability = false
      end
    end
  end
end

engine :engine do |e|
  LoanRulebook.new(e).rules

  e.assert Customer.new('#1', 10)
  e.assert Customer.new('#2', 50)
  e.assert Customer.new('#3', 60)
  e.assert Loan.new('ARM 30', 30)
  e.assert Loan.new('ARM 10', 10)
  e.assert Loan.new('FRM 30', 30)  
  e.match
end

実行結果

Customer #3 can't apply the loan FRM 30, 'cuz the customer is too old.
Customer #1 can't apply the loan FRM 30, 'cuz the customer is too young.
Customer #3 can't apply the loan ARM 10, 'cuz the customer is too old.
Customer #1 can't apply the loan ARM 10, 'cuz the customer is too young.
Customer #3 can't apply the loan ARM 30, 'cuz the customer is too old.
Customer #2 can't apply the loan ARM 30, 'cuz the customer is too old.
Customer #1 can't apply the loan ARM 30, 'cuz the customer is too young.

Rulebyを使わない場合

  • Rulebyを使わない場合は、CustomerかCustomerのヘルパーにif文がずらりと並ぶ事になる
  • そして、Loanの種類が増える都度、そのif文の固まりに手が入る

もちろん、上記コードくらいのルールではルールエンジンを使う恩恵はあまりない。

明日以降の課題

  • ルールをyamlに外出しする
  • より複雑なルール記述
  • テスト機械化
  • Railsとの連携