Allows you to define a set of 'rules' or dynamic methods to apply to a class.
> gem update --system
> gem install rulebook
The format is back to what it was before 0.2.2!
require 'rulebook'
class User
def initialize(name)
@name = name
end
rule /say_(.+)/ do |what_to_say|
puts "#{@name} says '#{what_to_say.gsub(/_/, ' ')}'"
end
end
User.new('Ryan').say_hello_world # => Ryan says 'hello world'
When you call the rule
method in a class, it defines the constant INSTANCE_RULEBOOK
and sets it to a new RuleBook
instance; but only if the constant wasn't already defined. This way, it only defines the constant the first time you call the rule
method.
When the first time rule
is called in a class, we also include the RuleBook::IncludeMethods
module which overrides the classes method_missing
. So when you call an undefined method on your class's instance, we will try to match the method against the rules you've defined in INSTANCE_RULEBOOK
.
There is also a method called class_rule
which does the same as rules does, only it defines the CLASS_RULEBOOK
constance in the class; which is a different RuleBook
instance. The first time class_rules
is called, it extends the class with the RuleBook::ExtendMethods
module, which also contains a method_missing
method.
require 'rulebook'
class User
attr :name, :title
def initialize(name)
@name = name
@title = :user
end
rule /is_(admin|moderator|super_user|user)/ do |title|
@title = title.to_sym
end
end
You can now do things like
users = [
User.new('Ryan'),
User.new('Natale'),
User.new('Joe'),
User.new('Monica'),
User.new('Matt'),
User.new('Jess')
].shuffle
users[0].is_admin
users[1].is_moderator
users[2].is_super_user
users.each do |user|
puts "#{user.name} is a #{user.title}"
end
require 'rulebook'
class Car
attr :make, :model
def initialize(make, model)
@make, @model = make.capitalize, model.capitalize
end
class_rule /new_([a-z]+)_(.+)/ do |make, model|
new(make, model)
end
end
my_cars = [
Car.new_honda_accord,
Car.new_dodge_neon,
Car.new_volkswagen_beetle
]
p my_cars.first.make # => "Honda"
p my_cars.first.model # => "Accord"
class Car
rule /is_(.+)\?/ do |make_or_model|
make_or_model.capitalize!
@make == make_or_model || @model == make_or_model
end
end
p my_cars.first.is_honda? # => true
p my_cars.first.is_beetle? # => false
Since rule
and class_rule
are both class methods,
you can call them all outside of a class block:
Car.rule(...){}
Car.class_rule(...){}
Since 0.2 you can call the class methods rules
and class_rules
to wrap your rules in a block:
Car.rules do
rule(...){}
end
Car.class_rules do
rule(...){}
end
The result is exactly the same. These are also callable from inside the class.
class Car
rules do
rule(...){}
end
class_rules do
rule(...){}
end
end
There are more examples in the examples and test directories and Rubular is a great place to test your Regexp.
- Fork the project.
- Make your feature addition or bug fix.
- Add tests for it. This is important so I don't break it in a future version unintentionally.
- Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
- Send me a pull request. Bonus points for topic branches.
Copyright (c) 2010 Ryan Lewis. See LICENSE for details.