I am playing around with creating a DSL. I am using http://jroll开发者_运维问答er.com/rolsen/entry/building_a_dsl_in_ruby as a guide.
Given this DSL:
question 'Who was the first president of the USA?'
wrong 'Fred Flintstone'
wrong 'Martha Washington'
right 'George Washington'
wrong 'George Jetson'
is there a way to make sure that question() is called at least once, right() exactly once and wrong() n or more times?
Sure. Just add the line
(@question_count ||= 0) += 1
to whatever your current implementation of the question
method looks like (and similarly for right
and wrong
) and then check those variables.
The handling of answering is missing in the following code, but you have control of only one right answer
class Question
def initialize(text)
@text = text
@answers = []
@correct = nil #index of the correct answer inside @answers
end
def self.define(text, &block)
raise ArgumentError, "Block missing" unless block_given?
q = self.new(text)
q.instance_eval(&block)
q
end
def wrong( answer )
@answers << answer
end
def right(answer )
raise "Two right answers" if @correct
@answers << answer
@correct = @answers.size
end
def ask()
puts @text
@answers.each_with_index{|answer, i|
puts "\t%2i %s?" % [i+1,answer]
}
puts "correct is %i" % @correct
end
end
def question( text, &block )
raise ArgumentError, "Block missing" unless block_given?
Question.define(text, &block)
end
Now you can define your question with block syntax:
question( 'Who was the first president of the USA?' ) {
wrong 'Fred Flintstone'
wrong 'Martha Washington'
right 'George Washington'
wrong 'George Jetson'
}.ask
You may use also another definition of questions:
q = Question.new( 'Who was the first president of the USA?' )
q.wrong 'Fred Flintstone'
q.wrong 'Martha Washington'
q.right 'George Washington'
q.wrong 'George Jetson'
q.ask
精彩评论