class Faker::Base

Constants

LLetters
Letters
NOT_GIVEN
Numbers
ULetters

Public Class Methods

bothify(string) click to toggle source
# File lib/faker.rb, line 57
def bothify(string)
  letterify(numerify(string))
end
disable_enforce_available_locales() { || ... } click to toggle source
# File lib/faker.rb, line 251
def disable_enforce_available_locales
  old_enforce_available_locales = I18n.enforce_available_locales
  I18n.enforce_available_locales = false
  yield
ensure
  I18n.enforce_available_locales = old_enforce_available_locales
end
fetch(key) click to toggle source

Helper for the common approach of grabbing a translation with an array of values and selecting one of them.

# File lib/faker.rb, line 97
def fetch(key)
  fetched = sample(translate("faker.#{key}"))
  if fetched&.match(%r{^/}) && fetched&.match(%r{/$}) # A regex
    regexify(fetched)
  else
    fetched
  end
end
fetch_all(key) click to toggle source

Helper for the common approach of grabbing a translation with an array of values and returning all of them.

# File lib/faker.rb, line 108
def fetch_all(key)
  fetched = translate("faker.#{key}")
  fetched = fetched.last if fetched.size <= 1
  if !fetched.respond_to?(:sample) && fetched.match(%r{^/}) && fetched.match(%r{/$}) # A regex
    regexify(fetched)
  else
    fetched
  end
end
flexible(key) click to toggle source
# File lib/faker.rb, line 178
def flexible(key)
  @flexible_key = key
end
letterify(letter_string) click to toggle source
# File lib/faker.rb, line 53
def letterify(letter_string)
  letter_string.gsub(/\?/) { sample(ULetters) }
end
method_missing(mth, *args, &block) click to toggle source

You can add whatever you want to the locale file, and it will get caught here. E.g., in your locale file, create a

name:
  girls_name: ["Alice", "Cheryl", "Tatiana"]

Then you can call Faker::Name.girls_name and it will act like first_name

Calls superclass method
# File lib/faker.rb, line 187
def method_missing(mth, *args, &block)
  super unless @flexible_key

  if (translation = translate("faker.#{@flexible_key}.#{mth}"))
    sample(translation)
  else
    super
  end
end
numerify(number_string, leading_zero: false) click to toggle source

by default numerify results do not start with a zero

# File lib/faker.rb, line 47
def numerify(number_string, leading_zero: false)
  return number_string.gsub(/#/) { rand(10).to_s } if leading_zero

  number_string.sub(/#/) { rand(1..9).to_s }.gsub(/#/) { rand(10).to_s }
end
parse(key) click to toggle source

Load formatted strings from the locale, “parsing” them into method calls that can be used to generate a formatted translation: e.g., “#{first_name} #{last_name}”.

# File lib/faker.rb, line 121
def parse(key)
  fetched = fetch(key)
  parts = fetched.scan(/(\(?)#\{([A-Za-z]+\.)?([^}]+)\}([^#]+)?/).map do |prefix, kls, meth, etc|
    # If the token had a class Prefix (e.g., Name.first_name)
    # grab the constant, otherwise use self
    cls = kls ? Faker.const_get(kls.chop) : self

    # If an optional leading parentheses is not present, prefix.should == "", otherwise prefix.should == "("
    # In either case the information will be retained for reconstruction of the string.
    text = prefix

    # If the class has the method, call it, otherwise fetch the translation
    # (e.g., faker.phone_number.area_code)
    text += if cls.respond_to?(meth)
              cls.send(meth)
            else
              # Do just enough snake casing to convert PhoneNumber to phone_number
              key_path = cls.to_s.split('::').last.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase
              fetch("#{key_path}.#{meth.downcase}")
            end

    # And tack on spaces, commas, etc. left over in the string
    text + etc.to_s
  end
  # If the fetched key couldn't be parsed, then fallback to numerify
  parts.any? ? parts.join : numerify(fetched)
end
rand(max = nil) click to toggle source
# File lib/faker.rb, line 241
def rand(max = nil)
  if max.nil?
    Faker::Config.random.rand
  elsif max.is_a?(Range) || max.to_i.positive?
    Faker::Config.random.rand(max)
  else
    0
  end
end
rand_in_range(from, to) click to toggle source

Generates a random value between the interval

# File lib/faker.rb, line 202
def rand_in_range(from, to)
  from, to = to, from if to < from
  rand(from..to)
end
regexify(reg) click to toggle source

Given a regular expression, attempt to generate a string that would match it. This is a rather simple implementation, so don't be shocked if it blows up on you in a spectacular fashion.

It does not handle ., *, unbounded ranges such as {1,}, extensions such as (?=), character classes, some abbreviations for character classes, and nested parentheses.

I told you it was simple. :) It's also probably dog-slow, so you shouldn't use it.

It will take a regex like this:

/^[A-PR-UWYZ0-9][AEHMNPRTVXY0-9]?? 1,2[ABD-HJLN-UW-Z]{2}$/

and generate a string like this:

“U3V 3TP”

# File lib/faker.rb, line 80
def regexify(reg)
  reg = reg.source if reg.respond_to?(:source) # Handle either a Regexp or a String that looks like a Regexp
  reg
    .gsub(%r{^/?\^?}, '').gsub(%r{\$?/?$}, '') # Ditch the anchors
    .gsub(/\{(\d+)\}/, '{\1,\1}').gsub(/\?/, '{0,1}') # All {2} become {2,2} and ? become {0,1}
    .gsub(/(\[[^\]]+\])\{(\d+),(\d+)\}/) { |_match| Regexp.last_match(1) * sample(Array(Range.new(Regexp.last_match(2).to_i, Regexp.last_match(3).to_i))) }                # [12]{1,2} becomes [12] or [12][12]
    .gsub(/(\([^)]+\))\{(\d+),(\d+)\}/) { |_match| Regexp.last_match(1) * sample(Array(Range.new(Regexp.last_match(2).to_i, Regexp.last_match(3).to_i))) }                 # (12|34){1,2} becomes (12|34) or (12|34)(12|34)
    .gsub(/(\\?.)\{(\d+),(\d+)\}/) { |_match| Regexp.last_match(1) * sample(Array(Range.new(Regexp.last_match(2).to_i, Regexp.last_match(3).to_i))) }                      # A{1,2} becomes A or AA or \d{3} becomes \d\d\d
    .gsub(/\((.*?)\)/) { |match| sample(match.gsub(/[()]/, '').split('|')) } # (this|that) becomes 'this' or 'that'
    .gsub(/\[([^\]]+)\]/) { |match| match.gsub(/(\w-\w)/) { |range| sample(Array(Range.new(*range.split('-')))) } } # All A-Z inside of [] become C (or X, or whatever)
    .gsub(/\[([^\]]+)\]/) { |_match| sample(Regexp.last_match(1).split('')) } # All [ABC] become B (or A or C)
    .gsub('\d') { |_match| sample(Numbers) }
    .gsub('\w') { |_match| sample(Letters) }
end
resolve(value) click to toggle source

If an array or range is passed, a random value will be selected. All other values are simply returned.

# File lib/faker.rb, line 209
def resolve(value)
  case value
  when Array then sample(value)
  when Range then rand value
  else value
  end
end
respond_to_missing?(method_name, include_private = false) click to toggle source
Calls superclass method
# File lib/faker.rb, line 197
def respond_to_missing?(method_name, include_private = false)
  super
end
sample(list, num = nil) click to toggle source
# File lib/faker.rb, line 225
def sample(list, num = nil)
  if list.respond_to?(:sample)
    if num
      list.sample(num, random: Faker::Config.random)
    else
      list.sample(random: Faker::Config.random)
    end
  else
    list
  end
end
shuffle(list) click to toggle source
# File lib/faker.rb, line 237
def shuffle(list)
  list.shuffle(random: Faker::Config.random)
end
translate(*args, **opts) click to toggle source

Call I18n.translate with our configured locale if no locale is specified

# File lib/faker.rb, line 151
def translate(*args, **opts)
  opts[:locale] ||= Faker::Config.locale
  opts[:raise] = true
  I18n.translate(*args, **opts)
rescue I18n::MissingTranslationData
  opts[:locale] = :en

  # Super-simple fallback -- fallback to en if the
  # translation was missing.  If the translation isn't
  # in en either, then it will raise again.
  disable_enforce_available_locales do
    I18n.translate(*args, **opts)
  end
end
unique(max_retries = 10_000) click to toggle source

Return unique values from the generator every time.

@param max_retries [Integer] The max number of retries that should be done before giving up. @return [self]

# File lib/faker.rb, line 221
def unique(max_retries = 10_000)
  @unique ||= UniqueGenerator.new(self, max_retries)
end
with_locale(tmp_locale = nil, &block) click to toggle source

Executes block with given locale set.

# File lib/faker.rb, line 167
def with_locale(tmp_locale = nil, &block)
  current_locale = Faker::Config.own_locale
  Faker::Config.locale = tmp_locale

  disable_enforce_available_locales do
    I18n.with_locale(tmp_locale, &block)
  end
ensure
  Faker::Config.locale = current_locale
end

Private Class Methods

parse_caller(at) click to toggle source
# File lib/faker.rb, line 301
def parse_caller(at)
  # rubocop:disable Style/GuardClause
  if /^(.+?):(\d+)(?::in `.*')?/ =~ at
    file = Regexp.last_match(1)
    line = Regexp.last_match(2).to_i
    [file, line]
  end
  # rubocop:enable Style/GuardClause
end
warn_for_deprecated_arguments() { |keywords| ... } click to toggle source
# File lib/faker.rb, line 261
      def warn_for_deprecated_arguments
        keywords = []
        yield(keywords)

        return if keywords.empty?

        method_name = caller.first.match(/`(?<method_name>.*)'/)[:method_name]

        keywords.each.with_index(1) do |keyword, index|
          i = case index
              when 1 then '1st'
              when 2 then '2nd'
              when 3 then '3rd'
              else "#{index}th"
              end

          warn_with_uplevel(<<~MSG, uplevel: 5)
            Passing `#{keyword}` with the #{i} argument of `#{method_name}` is deprecated. Use keyword argument like `#{method_name}(#{keyword}: ...)` instead.
          MSG
        end

        warn(<<~MSG)

          To automatically update from positional arguments to keyword arguments,
          install rubocop-faker and run:

          rubocop \\
            --require rubocop-faker \\
            --only Faker/DeprecatedArguments \\
            --auto-correct

        MSG
      end
warn_with_uplevel(message, uplevel: 1) click to toggle source

Workaround for emulating `warn '…', uplevel: 1` in Ruby 2.4 or lower.

# File lib/faker.rb, line 296
def warn_with_uplevel(message, uplevel: 1)
  at = parse_caller(caller[uplevel]).join(':')
  warn "#{at}: #{message}"
end