第二段ruby代码的作用是,遍历ruby文件dsl_capybara.rb、dsl_sikuli.rb、dsl_restful.rb及dsl_savon.rb,这些被遍历的文件的共同点是,在模块DSLSet中都分别地定义了一个独有的模块,这些独有的模块中分别定义了一些公有的类方法,如第一段代码所示,注意,各个独有模块所定义的公有的类方法的方法名可能相同,同时,参数也可能相同。
第二段代码会收集嵌套在模块DSLSet中的模块(分布于文件dsl_capybara.rb、dsl_sikuli.rb、dsl_restful.rb及dsl_savon.rb中)所定义的公有类方法,然后,自动在模块DSLSet中直接定义同名的公有的类方法,调用这些类方法时都需要额外地提供一个参数:driver用于选择具体使用嵌套在模块DSLSet中的哪一个模块,然后,自动生成的直接定义在模块DSLSet中的公有的类方法将根据参数:driver的取值不同,去调用相应的子模块的公有的类方法。
总之,第二段代码的作用就是自动生成代码,用于为其他文件中定义的模块的类方法提供一个统一的分发接口。


点击(此处)折叠或打开

  1. module DSLSet
  2.     module DSLCapybara
  3.         require 'capybara'
  4.         require 'capybara/dsl'
  5.         require 'capybara/rspec/matchers'

  6.         extend Capybara::DSL   # include keywords defined in Capybara::DSL

  7.         ## override capybara methods or add new methods
  8.         class << self
  9.             def keyword1 # any kind of parameters combination
  10.                 #something, maybe 'yield'
  11.                 helper
  12.                 #something, maybe 'yield'
  13.             end

  14.             def keyword2 # any kind of parameters combination
  15.                 #something, maybe 'yield'
  16.             end

  17.             private
  18.                 def helper
  19.                     # something
  20.                 end
  21.         end
  22. end



点击(此处)折叠或打开

  1. require File.join(File.dirname(__FILE__), 'dsl_capybara.rb')
  2. require File.join(File.dirname(__FILE__), 'dsl_sikuli.rb')
  3. require File.join(File.dirname(__FILE__), 'dsl_restful.rb')
  4. require File.join(File.dirname(__FILE__), 'dsl_savon.rb')

  5. module DSLSet
  6.     def default_driver
  7.         @@default_driver
  8.     end

  9.     def set_default_driver driver
  10.         driver = "DSL#{driver.capitalize}" unless driver =~ /^DSL/
  11.         if @@dsl_set.keys.include?(driver.to_sym)
  12.             @@default_driver = driver if (driver != @@default_driver)
  13.         else
  14.             puts "Invalid parameter: #{driver}"
  15.         end
  16.     end

  17.     class << self

  18.         def key_words
  19.            @@dsl_set.values.flatten.uniq
  20.         end

  21.         def drivers
  22.             ds = {}

  23.             @@dsl_set.each do |key, value|
  24.                 ds[key] = {}
  25.                 dm = DSLSet.module_eval(key.to_s)
  26.                 value.each do |v|
  27.                     ds[key][v] = dm.public_method(v).parameters
  28.                 end
  29.             end

  30.             ds
  31.         end

  32.         def init
  33.             @@default_driver = "" # "DSLCapybara"
  34.             @@dsl_set = {}
  35.             DSLSet.constants.collect do |cnst_name|
  36.                 m = DSLSet.const_get(cnst_name)
  37.                 @@dsl_set[cnst_name] = []
  38.                 dm = DSLSet.module_eval(cnst_name.to_s)
  39.                 dm.singleton_methods.each do |k|
  40.                     @@dsl_set[cnst_name] << k
  41.                 end
  42.             end
  43.             key_words.each do |kw|
  44.                 define_method(kw) do |*args, &block|
  45.                     driver = @@default_driver
  46.                     ps = []
  47.                     args.each_with_index do |arg, idx|
  48.                         if arg.is_a?(Hash) and arg.keys.include?(:driver)
  49.                             driver = arg[:driver]
  50.                             th = arg.dup
  51.                             th.delete :driver
  52.                             ps << th unless th.empty?
  53.                             ps += args[(idx+1)..-1]
  54.                             break
  55.                         else
  56.                             ps << arg
  57.                         end
  58.                     end

  59.                     driver = "DSL#{driver.capitalize}" unless driver =~ /^DSL/
  60.                     unless driver and @@dsl_set.keys.include?(driver.to_sym)
  61.                         puts "You are setting #{driver} as driver, which is not valid."
  62.                         puts "Please choose a driver from #{@@dsl_set.keys.to_s}"
  63.                         raise "You are setting #{driver} as driver, which is not valid. Please choose a driver from #{@@dsl_set.keys.to_s}"
  64.                     end

  65.                     if @@dsl_set[driver.to_sym] and @@dsl_set[driver.to_sym].include?(kw)
  66.                         mtd = DSLSet.module_eval(driver).public_method(kw)
  67.                         begin
  68.                             mtd.call(*ps, &block)
  69.                         rescue ArgumentError=>e
  70.                             puts "="*50
  71.                             puts e.to_s
  72.                             puts "method \"#{kw}\" of driver \"#{driver}\" was called"
  73.                             puts "expected parameter is #{mtd.parameters.to_s}"
  74.                             puts "actual parameters input are " + ps.to_s
  75.                             project_dir = File.expand_path(File.join(File.expand_path(__FILE__), '..\..'))
  76.                             pd = Regexp.new("^#{project_dir}")
  77.                             e.backtrace.each {|line| puts line if line=~pd}
  78.                             puts "="*50
  79.                         end
  80.                     else
  81.                         raise "#### driver \"#{driver}\" doesn't exist or it has not method \"#{kw}\" ####"
  82.                     end
  83.                 end
  84.             end
  85.         end
  86.     end
  87. end

  88. DSLSet.init
  89. include DSLSet

  90. # if __FILE__
  91. # puts "\n\n"
  92. # puts DSLSet.drivers
  93. # puts "\n\n"
  94. # puts DSLSet.key_words.sort
  95. # puts "\n\n"
  96. # end

09-04 12:21