Real-World Cases
Complete, production-ready examples from real-world use cases.
Overview
These examples demonstrate:
- Complete implementations
- Production patterns
- Error handling
- Testing strategies
- Performance considerations
Case 1: E-commerce Order Validation
Business Requirements
An e-commerce platform needs to validate orders before processing:
- Check inventory availability
- Validate customer eligibility
- Apply business rules for special cases
- Handle regional restrictions
Implementation
ruby
class OrderValidationEngine
def self.engine
@engine ||= Ruleur.define do
# Inventory Check
rule 'check_inventory', salience: 100 do
conditions do
all?(
order(:items).present,
order(:items_in_stock?)
)
end
actions do
set :inventory_valid, true
set :validation_step, 'inventory_passed'
end
end
rule 'insufficient_inventory', salience: 100 do
conditions do
all?(
order(:items).present,
not?(order(:items_in_stock?))
)
end
actions do
items = context[:order].out_of_stock_items
set :validation_failed, true
set :error_code, 'INSUFFICIENT_INVENTORY'
set :error_message, "Items out of stock: #{items.join(', ')}"
end
end
# Customer Validation
rule 'validate_customer', salience: 90 do
conditions do
all?(
flag(:inventory_valid),
customer(:active?),
not?(customer(:suspended?))
)
end
actions do
set :customer_valid, true
set :validation_step, 'customer_passed'
end
end
rule 'suspended_customer', salience: 90 do
conditions do
all?(customer(:suspended?))
end
actions do
set :validation_failed, true
set :error_code, 'CUSTOMER_SUSPENDED'
set :error_message, 'Customer account is suspended'
end
end
# Payment Method Validation
rule 'validate_payment', salience: 80 do
conditions do
all?(
flag(:customer_valid),
order(:payment_method).present,
order(:payment_valid?)
)
end
actions do
set :payment_valid, true
set :validation_step, 'payment_passed'
end
end
# Regional Restrictions
rule 'check_shipping_restrictions', salience: 70 do
conditions do
all?(
flag(:payment_valid),
order(:shipping_address).present
)
end
actions do
address = context[:order].shipping_address
restricted = context[:order].has_restricted_items?(address.country)
if restricted
set :validation_failed, true
set :error_code, 'SHIPPING_RESTRICTED'
set :error_message, "Some items cannot be shipped to #{address.country}"
else
set :shipping_valid, true
set :validation_step, 'shipping_passed'
end
end
end
# Business Days Check
rule 'business_days_validation', salience: 60 do
conditions do
all?(
flag(:shipping_valid),
order(:expedited_shipping?)
)
end
actions do
today = Date.today
is_business_day = (1..5).include?(today.wday)
if is_business_day
set :expedited_available, true
else
set :expedited_available, false
set :warning_message, 'Expedited shipping not available on weekends'
end
end
end
# Final Validation
rule 'order_valid', salience: 10 do
conditions do
all?(
flag(:inventory_valid),
flag(:customer_valid),
flag(:payment_valid),
flag(:shipping_valid),
not?(flag(:validation_failed))
)
end
actions do
set :order_valid, true
set :ready_to_process, true
end
end
end
end
ValidationResult = Struct.new(:valid, :errors, :error_code, :warnings)
def self.validate(order, customer)
result = engine.run(order: order, customer: customer)
ValidationResult.new(
valid: result[:order_valid] == true,
errors: result[:validation_failed] ? [result[:error_message]] : [],
error_code: result[:error_code],
warnings: result[:warning_message] ? [result[:warning_message]] : []
)
end
end
# Usage in controller
class OrdersController < ApplicationController
def create
@order = Order.new(order_params)
validation = OrderValidationEngine.validate(@order, current_user)
if validation.valid?
@order.save
redirect_to @order, notice: 'Order created successfully'
else
flash.now[:error] = validation.errors.join(', ')
render :new
end
end
endCase 2: SaaS Feature Access Control
Business Requirements
A SaaS platform needs to control feature access based on:
- Subscription tier
- Usage limits
- Trial status
- Add-on purchases
Implementation
ruby
class FeatureAccessEngine
def self.engine
@engine ||= Ruleur.define do
# Basic Features (All tiers)
rule 'basic_features', salience: 100 do
conditions do
all?(user(:subscription, :active?))
end
actions do
allow! :dashboard
allow! :basic_reports
allow! :profile
set :max_projects, 3
set :storage_gb, 5
end
end
# Pro Features
rule 'pro_features', salience: 90 do
conditions do
all?(
user(:subscription, :tier).in(%w[pro enterprise]),
user(:subscription, :active?)
)
end
actions do
allow! :advanced_analytics
allow! :custom_reports
allow! :api_access
allow! :integrations
set :max_projects, 25
set :storage_gb, 100
set :api_rate_limit, 1000
end
end
# Enterprise Features
rule 'enterprise_features', salience: 80 do
conditions do
all?(
user(:subscription, :tier).eq?('enterprise'),
user(:subscription, :active?)
)
end
actions do
allow! :sso
allow! :audit_logs
allow! :white_label
allow! :priority_support
allow! :custom_contracts
set :max_projects, Float::INFINITY
set :storage_gb, 1000
set :api_rate_limit, 10_000
end
end
# Trial Limitations
rule 'trial_limitations', salience: 110 do
conditions do
all?(
user(:subscription, :trial?),
user(:subscription, :active?)
)
end
actions do
allow! :dashboard
allow! :basic_reports
set :max_projects, 1
set :storage_gb, 1
set :trial_days_remaining, (user.subscription.trial_end - Date.today).to_i
end
end
# Add-on: Extra Storage
rule 'storage_addon', salience: 70 do
conditions do
all?(user(:has_addon?, 'extra_storage'))
end
actions do
current_storage = context[:storage_gb] || 5
set :storage_gb, current_storage + 50
end
end
# Add-on: API Access for Basic Users
rule 'api_addon', salience: 70 do
conditions do
all?(
user(:subscription, :tier).eq?('basic'),
user(:has_addon?, 'api_access')
)
end
actions do
allow! :api_access
set :api_rate_limit, 100
end
end
# Usage Limits
rule 'check_project_limit', salience: 50 do
conditions do
all?(
flag(:max_projects).present,
user(:projects_count).gte?(flag(:max_projects))
)
end
actions do
deny! :create_project
set :limit_reached, 'projects'
set :upgrade_required, true
end
end
rule 'check_storage_limit', salience: 50 do
conditions do
all?(
flag(:storage_gb).present,
user(:storage_used_gb).gte?(flag(:storage_gb))
)
end
actions do
deny! :upload_files
set :limit_reached, 'storage'
set :upgrade_required, true
end
end
# Expired Subscription
rule 'expired_subscription', salience: 120 do
conditions do
all?(not?(user(:subscription, :active?)))
end
actions do
allow! :dashboard
allow! :billing
deny! :create_project
deny! :upload_files
deny! :api_access
set :subscription_expired, true
end
end
end
end
def self.check_access?(user, feature)
result = engine.run(user: user)
result[:"allow_#{feature}"] == true
end
LimitsResult = Struct.new(:max_projects, :storage_gb, :api_rate_limit, :upgrade_required)
def self.get_limits(user)
result = engine.run(user: user)
LimitsResult.new(
max_projects: result[:max_projects],
storage_gb: result[:storage_gb],
api_rate_limit: result[:api_rate_limit],
upgrade_required: result[:upgrade_required] == true
)
end
end
# Usage in application
class ProjectsController < ApplicationController
before_action :check_project_limit, only: [:create]
def check_project_limit
return if FeatureAccessEngine.check_access(current_user, :create_project)
limits = FeatureAccessEngine.get_limits(current_user)
redirect_to upgrade_path, alert: "Project limit reached (#{limits.max_projects})"
end
endCase 3: Content Moderation System
Business Requirements
A social platform needs automated content moderation:
- Flag inappropriate content
- Auto-approve trusted users
- Queue suspicious content for review
- Handle different content types
Implementation
ruby
class ContentModerationEngine
def self.engine
@engine ||= Ruleur.define do
# Trusted User Auto-Approve
rule 'trusted_user_auto_approve', salience: 100 do
conditions do
all?(
user(:trusted?),
user(:violations_count).eq?(0),
content(:type).in(%w[text image])
)
end
actions do
set :moderation_action, 'approve'
set :auto_approved, true
set :reason, 'Trusted user with clean history'
end
end
# Spam Detection
rule 'spam_detection', salience: 110 do
conditions do
all?(
any?(
content(:contains_spam_keywords?),
content(:excessive_links?),
content(:repetitive_content?)
)
)
end
actions do
set :moderation_action, 'reject'
set :flag_reason, 'Potential spam detected'
set :notify_user, true
end
end
# Profanity Check
rule 'profanity_check', salience: 105 do
conditions do
all?(content(:contains_profanity?))
end
actions do
severity = context[:content].profanity_severity
if severity >= 8
set :moderation_action, 'reject'
set :flag_reason, 'Severe profanity'
else
set :moderation_action, 'review'
set :flag_reason, 'Mild profanity - manual review'
end
end
end
# New User Content
rule 'new_user_review', salience: 90 do
conditions do
all?(
user(:account_age_days).lt?(7),
not?(flag(:auto_approved)),
not?(flag(:moderation_action).present)
)
end
actions do
set :moderation_action, 'review'
set :flag_reason, 'New user - pending review'
set :review_priority, 'low'
end
end
# Sensitive Content
rule 'sensitive_content', salience: 95 do
conditions do
all?(
content(:type).in(%w[image video]),
content(:ai_flagged?)
)
end
actions do
confidence = context[:content].ai_confidence
if confidence >= 0.9
set :moderation_action, 'reject'
set :flag_reason, "AI detected policy violation (#{confidence})"
elsif confidence >= 0.5
set :moderation_action, 'review'
set :flag_reason, "AI flagged for review (#{confidence})"
set :review_priority, 'high'
end
end
end
# Copyright Claims
rule 'copyright_check', salience: 100 do
conditions do
all?(
content(:type).in(%w[image video audio]),
content(:copyright_match?)
)
end
actions do
set :moderation_action, 'remove'
set :flag_reason, 'Copyright violation detected'
set :dmca_takedown, true
set :notify_user, true
end
end
# Rate Limiting
rule 'rate_limit_exceeded', salience: 120 do
conditions do
all?(user(:posts_last_hour).gt?(10))
end
actions do
set :moderation_action, 'rate_limit'
set :flag_reason, 'Posting too frequently'
set :cooldown_minutes, 60
end
end
# Default: Queue for Review
rule 'default_review', salience: 1 do
conditions do
all?(not?(flag(:moderation_action).present))
end
actions do
set :moderation_action, 'review'
set :flag_reason, 'Standard review process'
set :review_priority, 'normal'
end
end
end
end
def self.moderate(content, user)
result = engine.run(content: content, user: user)
ModerationResult.new(
execute: result[:moderation_action],
reason: result[:flag_reason],
auto_approved: result[:auto_approved] == true,
review_priority: result[:review_priority],
notify_user: result[:notify_user] == true,
metadata: result.to_h
)
end
end
# Usage
class PostsController < ApplicationController
def create
@post = current_user.posts.build(post_params)
moderation = ContentModerationEngine.moderate(@post, current_user)
case moderation.action
when 'approve'
@post.approved!
redirect_to @post, notice: 'Post published'
when 'reject'
flash[:error] = "Post rejected: #{moderation.reason}"
render :new
when 'review'
@post.pending_review!
ModerationQueue.enqueue(@post, priority: moderation.review_priority)
redirect_to root_path, notice: 'Post submitted for review'
when 'rate_limit'
flash[:error] = moderation.reason
render :new
end
end
endCase 4: Insurance Policy Evaluation
Business Requirements
An insurance company needs to evaluate policy applications:
- Calculate risk scores
- Determine eligibility
- Set premium rates
- Flag for manual underwriting
Implementation
ruby
class InsurancePolicyEngine
def self.engine
@engine ||= Ruleur.define do
# Base Risk Assessment
rule 'age_risk_low', salience: 100 do
conditions do
all?(
applicant(:age).gte?(25),
applicant(:age).lte?(60)
)
end
actions { set :age_risk_score, 0 }
end
rule 'age_risk_high', salience: 100 do
conditions do
all?(
any?(
applicant(:age).lt?(25),
applicant(:age).gt?(60)
)
)
end
actions { set :age_risk_score, 20 }
end
# Driving History
rule 'clean_driving_record', salience: 90 do
conditions do
all?(
applicant(:accidents_last_5_years).eq?(0),
applicant(:violations_last_3_years).eq?(0)
)
end
actions do
set :driving_risk_score, 0
set :safe_driver_discount, 0.15
end
end
rule 'moderate_driving_risk', salience: 90 do
conditions do
all?(
applicant(:accidents_last_5_years).in([1, 2]),
applicant(:violations_last_3_years).lt?(3)
)
end
actions { set :driving_risk_score, 30 }
end
rule 'high_driving_risk', salience: 90 do
conditions do
all?(
any?(
applicant(:accidents_last_5_years).gt?(2),
applicant(:violations_last_3_years).gte?(3),
applicant(:dui_history?)
)
)
end
actions do
set :driving_risk_score, 100
set :requires_underwriting, true
end
end
# Credit Score Impact
rule 'excellent_credit', salience: 85 do
conditions do
all?(
applicant(:credit_score).gte?(750)
)
end
actions do
set :credit_risk_score, -10
set :credit_discount, 0.10
end
end
rule 'poor_credit', salience: 85 do
conditions do
all?(
applicant(:credit_score).lt?(600)
)
end
actions { set :credit_risk_score, 25 }
end
# Calculate Total Risk Score
rule 'calculate_risk', salience: 50, no_loop: true do
conditions do
all?(
flag(:age_risk_score).present,
flag(:driving_risk_score).present
)
end
actions do
age = context[:age_risk_score]
driving = context[:driving_risk_score]
credit = context[:credit_risk_score] || 0
total_risk = age + driving + credit
set :total_risk_score, total_risk
end
end
# Eligibility Determination
rule 'eligible_standard', salience: 40 do
conditions do
all?(
flag(:total_risk_score).lt?(50),
not?(flag(:requires_underwriting))
)
end
actions do
set :eligible, true
set :policy_tier, 'standard'
end
end
rule 'eligible_high_risk', salience: 40 do
conditions do
all?(
flag(:total_risk_score).gte?(50),
flag(:total_risk_score).lt?(80),
not?(flag(:requires_underwriting))
)
end
actions do
set :eligible, true
set :policy_tier, 'high_risk'
end
end
rule 'requires_manual_review', salience: 40 do
conditions do
all?(
any?(
flag(:total_risk_score).gte?(80),
flag(:requires_underwriting)
)
)
end
actions do
set :eligible, false
set :manual_underwriting_required, true
set :reason, 'Risk score too high - manual review needed'
end
end
# Premium Calculation
rule 'calculate_premium', salience: 30 do
conditions do
all?(
flag(:eligible),
flag(:policy_tier).present
)
end
actions do
base_premium = 1000
risk_score = context[:total_risk_score]
tier = context[:policy_tier]
# Risk multiplier
risk_multiplier = 1 + (risk_score / 100.0)
# Tier multiplier
tier_multiplier = tier == 'high_risk' ? 1.5 : 1.0
premium = base_premium * risk_multiplier * tier_multiplier
# Apply discounts
safe_driver = context[:safe_driver_discount] || 0
credit = context[:credit_discount] || 0
total_discount = safe_driver + credit
final_premium = premium * (1 - total_discount)
set :monthly_premium, final_premium.round(2)
set :annual_premium, (final_premium * 12).round(2)
set :discounts_applied, total_discount
end
end
end
end
def self.evaluate(applicant)
result = engine.run(applicant: applicant)
PolicyEvaluation.new(
eligible: result[:eligible] == true,
policy_tier: result[:policy_tier],
risk_score: result[:total_risk_score],
monthly_premium: result[:monthly_premium],
annual_premium: result[:annual_premium],
discounts: result[:discounts_applied],
requires_review: result[:manual_underwriting_required] == true,
reason: result[:reason]
)
end
end
# Usage
evaluation = InsurancePolicyEngine.evaluate(applicant)
if evaluation.eligible?
# Show quote
render :quote, locals: { evaluation: evaluation }
elsif evaluation.requires_review?
# Queue for underwriter
UnderwritingQueue.enqueue(applicant)
render :pending_review
else
# Declined
render :declined, locals: { reason: evaluation.reason }
endTesting Real-World Rules
ruby
RSpec.describe ContentModerationEngine do
describe '.moderate' do
it 'auto-approves trusted users' do
user = build(:user, :trusted, violations_count: 0)
content = build(:post, :text)
result = ContentModerationEngine.moderate(content, user)
expect(result.action).to eq('approve')
expect(result.auto_approved).to be true
end
it 'rejects spam content' do
user = build(:user)
content = build(:post, spam_keywords: true)
result = ContentModerationEngine.moderate(content, user)
expect(result.action).to eq('reject')
expect(result.reason).to include('spam')
end
it 'queues new user content for review' do
user = build(:user, created_at: 2.days.ago)
content = build(:post, :text)
result = ContentModerationEngine.moderate(content, user)
expect(result.action).to eq('review')
expect(result.review_priority).to eq('low')
end
end
endPerformance Considerations
Caching Rules
ruby
class CachedRuleEngine
def self.engine
@engine ||= Rails.cache.fetch("rule_engine/#{cache_key}", expires_in: 1.hour) do
load_engine
end
end
def self.cache_key
Rule.maximum(:updated_at).to_i
end
def self.reload!
@engine = nil
Rails.cache.delete("rule_engine/#{cache_key}")
end
endAsync Processing
ruby
class AsyncModerationJob < ApplicationJob
def perform(content_id, user_id)
content = Content.find(content_id)
user = User.find(user_id)
result = ContentModerationEngine.moderate(content, user)
content.update(
moderation_status: result.action,
moderation_reason: result.reason
)
end
endSee Also
- Permission Rules - Authorization patterns
- Workflow Automation - Process automation
- Dynamic Pricing - Pricing rules
- Performance Guide - Optimization techniques