PageRenderTime 66ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/faker.rb

https://bitbucket.org/ToadJamb/forks_faker
Ruby | 155 lines | 93 code | 21 blank | 41 comment | 5 complexity | 354a0503b596a10a8a72b8e0b1595601 MD5 | raw file
  1. mydir = File.expand_path(File.dirname(__FILE__))
  2. begin
  3. require 'psych'
  4. rescue LoadError
  5. end
  6. require 'i18n'
  7. I18n.load_path += Dir[File.join(mydir, 'locales', '*.yml')]
  8. I18n.reload!
  9. module Faker
  10. class Config
  11. @locale = nil
  12. class << self
  13. attr_writer :locale
  14. def locale
  15. @locale || I18n.locale.downcase
  16. end
  17. end
  18. end
  19. class Base
  20. Numbers = Array(0..9)
  21. ULetters = Array('A'..'Z')
  22. Letters = ULetters + Array('a'..'z')
  23. class << self
  24. ## make sure numerify results doesnt start with a zero
  25. def numerify(number_string)
  26. number_string.sub(/#/) { (rand(9)+1).to_s }.gsub(/#/) { rand(10).to_s }
  27. end
  28. def letterify(letter_string)
  29. letter_string.gsub(/\?/) { ULetters.sample }
  30. end
  31. def bothify(string)
  32. letterify(numerify(string))
  33. end
  34. # Given a regular expression, attempt to generate a string
  35. # that would match it. This is a rather simple implementation,
  36. # so don't be shocked if it blows up on you in a spectacular fashion.
  37. #
  38. # It does not handle ., *, unbounded ranges such as {1,},
  39. # extensions such as (?=), character classes, some abbreviations
  40. # for character classes, and nested parentheses.
  41. #
  42. # I told you it was simple. :) It's also probably dog-slow,
  43. # so you shouldn't use it.
  44. #
  45. # It will take a regex like this:
  46. #
  47. # /^[A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {1,2}[0-9][ABD-HJLN-UW-Z]{2}$/
  48. #
  49. # and generate a string like this:
  50. #
  51. # "U3V 3TP"
  52. #
  53. def regexify(re)
  54. re = re.source if re.respond_to?(:source) # Handle either a Regexp or a String that looks like a Regexp
  55. re.
  56. gsub(/^\/?\^?/, '').gsub(/\$?\/?$/, ''). # Ditch the anchors
  57. gsub(/\{(\d+)\}/, '{\1,\1}').gsub(/\?/, '{0,1}'). # All {2} become {2,2} and ? become {0,1}
  58. gsub(/(\[[^\]]+\])\{(\d+),(\d+)\}/) {|match| $1 * Array(Range.new($2.to_i, $3.to_i)).sample }. # [12]{1,2} becomes [12] or [12][12]
  59. gsub(/(\([^\)]+\))\{(\d+),(\d+)\}/) {|match| $1 * Array(Range.new($2.to_i, $3.to_i)).sample }. # (12|34){1,2} becomes (12|34) or (12|34)(12|34)
  60. gsub(/(\\?.)\{(\d+),(\d+)\}/) {|match| $1 * Array(Range.new($2.to_i, $3.to_i)).sample }. # A{1,2} becomes A or AA or \d{3} becomes \d\d\d
  61. gsub(/\((.*?)\)/) {|match| match.gsub(/[\(\)]/, '').split('|').sample }. # (this|that) becomes 'this' or 'that'
  62. gsub(/\[([^\]]+)\]/) {|match| match.gsub(/(\w\-\w)/) {|range| Array(Range.new(*range.split('-'))).sample } }. # All A-Z inside of [] become C (or X, or whatever)
  63. gsub(/\[([^\]]+)\]/) {|match| $1.split('').sample }. # All [ABC] become B (or A or C)
  64. gsub('\d') {|match| Numbers.sample }.
  65. gsub('\w') {|match| Letters.sample }
  66. end
  67. # Helper for the common approach of grabbing a translation
  68. # with an array of values and selecting one of them.
  69. def fetch(key)
  70. fetched = translate("faker.#{key}")
  71. fetched = fetched.sample if fetched.respond_to?(:sample)
  72. if fetched.match(/^\//) and fetched.match(/\/$/) # A regex
  73. regexify(fetched)
  74. else
  75. fetched
  76. end
  77. end
  78. # Load formatted strings from the locale, "parsing" them
  79. # into method calls that can be used to generate a
  80. # formatted translation: e.g., "#{first_name} #{last_name}".
  81. def parse(key)
  82. fetch(key).scan(/#\{([A-Za-z]+\.)?([^\}]+)\}([^#]+)?/).map {|kls, meth, etc|
  83. # If the token had a class Prefix (e.g., Name.first_name)
  84. # grab the constant, otherwise use self
  85. cls = kls ? Faker.const_get(kls.chop) : self
  86. # If the class has the method, call it, otherwise
  87. # fetch the transation (i.e., faker.name.first_name)
  88. text = cls.respond_to?(meth) ? cls.send(meth) : fetch("#{(kls || self).to_s.split('::').last.downcase}.#{meth.downcase}")
  89. # And tack on spaces, commas, etc. left over in the string
  90. text += etc.to_s
  91. }.join
  92. end
  93. # Call I18n.translate with our configured locale if no
  94. # locale is specified
  95. def translate(*args)
  96. opts = args.last.is_a?(Hash) ? args.pop : {}
  97. opts[:locale] ||= Faker::Config.locale
  98. opts[:raise] = true
  99. I18n.translate(*(args.push(opts)))
  100. rescue I18n::MissingTranslationData
  101. # Super-simple fallback -- fallback to en if the
  102. # translation was missing. If the translation isn't
  103. # in en either, then it will raise again.
  104. I18n.translate(*(args.push(opts.merge(:locale => :en))))
  105. end
  106. def flexible(key)
  107. @flexible_key = key
  108. end
  109. # You can add whatever you want to the locale file, and it will get caught here.
  110. # E.g., in your locale file, create a
  111. # name:
  112. # girls_name: ["Alice", "Cheryl", "Tatiana"]
  113. # Then you can call Faker::Name.girls_name and it will act like #first_name
  114. def method_missing(m, *args, &block)
  115. super unless @flexible_key
  116. # Use the alternate form of translate to get a nil rather than a "missing translation" string
  117. if translation = translate(:faker)[@flexible_key][m]
  118. translation.respond_to?(:sample) ? translation.sample : translation
  119. else
  120. super
  121. end
  122. end
  123. end
  124. end
  125. end
  126. require 'faker/address'
  127. require 'faker/company'
  128. require 'faker/internet'
  129. require 'faker/lorem'
  130. require 'faker/name'
  131. require 'faker/phone_number'
  132. require 'faker/version'
  133. require 'extensions/array'
  134. require 'extensions/symbol'