开发者

Enforcing method calls

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜