diff --git a/Gemfile.lock b/Gemfile.lock index d987ab40e4..2d23233062 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,26 +3,27 @@ PATH specs: faker (1.9.1) i18n (>= 0.7) + thor (= 0.20.0) GEM remote: https://rubygems.org/ specs: ast (2.4.0) concurrent-ruby (1.0.5) - docile (1.3.0) - i18n (1.0.1) + docile (1.3.1) + i18n (1.1.0) concurrent-ruby (~> 1.0) jaro_winkler (1.5.1) json (2.1.0) - minitest (5.10.3) + minitest (5.11.3) parallel (1.12.1) parser (2.5.1.2) ast (~> 2.4.0) - power_assert (1.1.1) + power_assert (1.1.3) powerpack (0.1.2) rainbow (3.0.0) - rake (12.3.0) - rubocop (0.58.1) + rake (12.3.1) + rubocop (0.59.1) jaro_winkler (~> 1.5.1) parallel (~> 1.10) parser (>= 2.5, != 2.5.1.1) @@ -30,14 +31,15 @@ GEM rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) - ruby-progressbar (1.9.0) + ruby-progressbar (1.10.0) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) - test-unit (3.2.6) + test-unit (3.2.8) power_assert + thor (0.20.0) timecop (0.9.1) unicode-display_width (1.4.0) @@ -45,13 +47,14 @@ PLATFORMS ruby DEPENDENCIES + bundler (= 1.16.4) faker! - minitest - rake - rubocop - simplecov - test-unit - timecop + minitest (= 5.11.3) + rake (= 12.3.1) + rubocop (= 0.59.1) + simplecov (= 0.16.1) + test-unit (= 3.2.8) + timecop (= 0.9.1) BUNDLED WITH 1.16.4 diff --git a/exe/faker b/exe/faker new file mode 100755 index 0000000000..b3550f3ffc --- /dev/null +++ b/exe/faker @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'faker' + +Faker::CLI.start(ARGV) diff --git a/faker.gemspec b/faker.gemspec index f98027161f..af15720393 100644 --- a/faker.gemspec +++ b/faker.gemspec @@ -3,26 +3,35 @@ $LOAD_PATH.push File.expand_path('lib', __dir__) require 'faker/version' -Gem::Specification.new do |s| - s.name = 'faker' - s.version = Faker::VERSION - s.platform = Gem::Platform::RUBY - s.authors = ['Benjamin Curtis'] - s.email = ['benjamin.curtis@gmail.com'] - s.homepage = 'https://github.com/stympy/faker' - s.summary = 'Easily generate fake data' - s.description = 'Faker, a port of Data::Faker from Perl, is used to easily generate fake data: names, addresses, phone numbers, etc.' - s.license = 'MIT' +Gem::Specification.new do |spec| + spec.name = 'faker' + spec.version = Faker::VERSION + spec.platform = Gem::Platform::RUBY + spec.authors = ['Benjamin Curtis'] + spec.email = ['benjamin.curtis@gmail.com'] - s.add_runtime_dependency('i18n', '>= 0.7') - s.add_development_dependency('minitest') - s.add_development_dependency('rake') - s.add_development_dependency('rubocop') - s.add_development_dependency('simplecov') - s.add_development_dependency('test-unit') - s.add_development_dependency('timecop') - s.required_ruby_version = '>= 2.3' + spec.summary = 'Easily generate fake data' + spec.description = 'Faker, a port of Data::Faker from Perl, is used to easily generate fake data: names, addresses, phone numbers, etc.' + spec.homepage = 'https://github.com/stympy/faker' + spec.license = 'MIT' - s.files = Dir['lib/**/*'] + %w[History.md License.txt CHANGELOG.md README.md] - s.require_paths = ['lib'] + spec.files = Dir['lib/**/*'] + %w[History.md License.txt CHANGELOG.md README.md] + spec.bindir = 'exe' + spec.executables = spec.files.grep(%r{^exe/}) do |file| + File.basename(file) + end + spec.require_paths = ['lib'] + spec.required_ruby_version = '>= 2.3' + + spec.add_dependency('thor', '0.20.0') + + spec.add_development_dependency('bundler', '1.16.4') + spec.add_development_dependency('minitest', '5.11.3') + spec.add_development_dependency('rake', '12.3.1') + spec.add_development_dependency('rubocop', '0.59.1') + spec.add_development_dependency('simplecov', '0.16.1') + spec.add_development_dependency('test-unit', '3.2.8') + spec.add_development_dependency('timecop', '0.9.1') + + spec.add_runtime_dependency('i18n', '>= 0.7') end diff --git a/lib/faker.rb b/lib/faker.rb index 3202688f2a..d652d6f4e7 100644 --- a/lib/faker.rb +++ b/lib/faker.rb @@ -47,6 +47,7 @@ class << self ## by default numerify results do not start with a zero 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 @@ -222,12 +223,17 @@ def rand(max = nil) 0 end end + + # TODO: Remove this evil eval method + # rubocop:disable Style/EvalWithLocation, Security/Eval + def module_methods(subclass) + eval("Faker::#{subclass}.public_methods(false)") - Faker::Base.public_methods(false) + end + # rubocop:enable Style/EvalWithLocation, Security/Eval end end end -Dir.glob(File.join(File.dirname(__FILE__), 'faker', '*.rb')).sort.each { |f| require f } - -require 'helpers/char' -require 'helpers/unique_generator' -require 'helpers/base58' +%w[faker helpers].each do |path| + Dir.glob(File.join(File.dirname(__FILE__), path, '*.rb')).sort.each { |file| require file } +end diff --git a/lib/faker/avatar.rb b/lib/faker/avatar.rb index 852346957f..8c3f27982f 100644 --- a/lib/faker/avatar.rb +++ b/lib/faker/avatar.rb @@ -8,6 +8,7 @@ class << self def image(slug = nil, size = '300x300', format = 'png', set = 'set1', bgset = nil) raise ArgumentError, 'Size should be specified in format 300x300' unless size =~ /^[0-9]+x[0-9]+$/ raise ArgumentError, "Supported formats are #{SUPPORTED_FORMATS.join(', ')}" unless SUPPORTED_FORMATS.include?(format) + slug ||= Faker::Lorem.words.join bgset_query = "&bgset=#{bgset}" if bgset "https://robohash.org/#{slug}.#{format}?size=#{size}&set=#{set}#{bgset_query}" diff --git a/lib/faker/cli.rb b/lib/faker/cli.rb new file mode 100644 index 0000000000..386c12eb50 --- /dev/null +++ b/lib/faker/cli.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require 'thor' + +module Faker + class CLI < Thor + Faker.constants.sort.each do |constant| + desc "#{constant.downcase} [-f #{Faker::Base.module_methods(constant).join('|')}]", + "Returns fake #{constant.downcase} data" + option :faker_type, aliases: '-f', desc: 'the faker data type' + + define_method :"#{constant.downcase}" do + begin + puts Object.const_get("Faker::#{constant.capitalize}.#{options.faker_type}") + rescue I18n::MissingTranslationData + puts "Usage: `faker #{constant.downcase} -f=#{options.faker_type}`" + puts "Run `faker help #{constant.downcase}` for a list of valid types" + end + end + end + end +end diff --git a/lib/faker/commerce.rb b/lib/faker/commerce.rb index 0c11b56b02..933202290f 100644 --- a/lib/faker/commerce.rb +++ b/lib/faker/commerce.rb @@ -22,6 +22,7 @@ def department(max = 3, fixed_amount = false) categories = categories(num) return merge_categories(categories) if num > 1 + categories[0] end diff --git a/lib/faker/company.rb b/lib/faker/company.rb index 53c2bc0960..e24593252f 100644 --- a/lib/faker/company.rb +++ b/lib/faker/company.rb @@ -128,6 +128,7 @@ def polish_taxpayer_identification_number # Get a random Polish register of national economy number. More info https://pl.wikipedia.org/wiki/REGON def polish_register_of_national_economy(length = 9) raise ArgumentError, 'Length should be 9 or 14' unless [9, 14].include? length + random_digits = [] loop do random_digits = Array.new(length) { rand(10) } diff --git a/lib/faker/date.rb b/lib/faker/date.rb index 97b42ce77b..ecb3be383d 100644 --- a/lib/faker/date.rb +++ b/lib/faker/date.rb @@ -12,6 +12,7 @@ def between(from, to) def between_except(from, to, excepted) raise ArgumentError, 'From date, to date and excepted date must not be the same' if from == to && to == excepted + excepted = get_date_object(excepted) loop do diff --git a/lib/faker/hipster.rb b/lib/faker/hipster.rb index a6265cf633..3d7d194e40 100644 --- a/lib/faker/hipster.rb +++ b/lib/faker/hipster.rb @@ -17,6 +17,7 @@ def words(num = 3, supplemental = false, spaces_allowed = false) word_list *= ((resolved_num / word_list.length) + 1) return shuffle(word_list)[0, resolved_num] if spaces_allowed + words = shuffle(word_list)[0, resolved_num] words.each_with_index { |w, i| words[i] = word if w =~ /\s/ } end diff --git a/lib/faker/internet.rb b/lib/faker/internet.rb index 74725e7efc..62ffc1b7e4 100644 --- a/lib/faker/internet.rb +++ b/lib/faker/internet.rb @@ -22,9 +22,11 @@ def safe_email(name = nil) def username(specifier = nil, separators = %w[. _]) with_locale(:en) do return shuffle(specifier.scan(/\w+/)).join(sample(separators)).downcase if specifier.respond_to?(:scan) + if specifier.is_a?(Integer) # If specifier is Integer and has large value, Argument error exception is raised to overcome memory full error raise ArgumentError, 'Given argument is too large' if specifier > 10**6 + tries = 0 # Don't try forever in case we get something like 1_000_000. result = nil loop do diff --git a/lib/faker/lorem.rb b/lib/faker/lorem.rb index 8379b9e334..c734b38f84 100644 --- a/lib/faker/lorem.rb +++ b/lib/faker/lorem.rb @@ -27,6 +27,7 @@ def character def characters(char_count = 255) char_count = resolve(char_count) return '' if char_count.to_i < 1 + Array.new(char_count) { sample(CHARACTERS) }.join end diff --git a/lib/faker/lovecraft.rb b/lib/faker/lovecraft.rb index 7ca5ca3fc6..893c49100c 100644 --- a/lib/faker/lovecraft.rb +++ b/lib/faker/lovecraft.rb @@ -34,6 +34,7 @@ def words(num = 3, spaces_allowed = false) word_list *= ((resolved_num / word_list.length) + 1) return shuffle(word_list)[0, resolved_num] if spaces_allowed + words = shuffle(word_list)[0, resolved_num] words.each_with_index { |w, i| words[i] = word if w =~ /\s/ } end diff --git a/lib/faker/time.rb b/lib/faker/time.rb index 99b4abe3a4..5004f876a8 100644 --- a/lib/faker/time.rb +++ b/lib/faker/time.rb @@ -38,6 +38,7 @@ def time_with_format(time, format) def hours(period) raise ArgumentError, 'invalid period' unless TIME_RANGES.key? period + sample(TIME_RANGES[period].to_a) end diff --git a/script/txt2html b/script/txt2html index a30dbfccd3..fa7411ed22 100755 --- a/script/txt2html +++ b/script/txt2html @@ -21,6 +21,7 @@ class Fixnum def ordinal # teens return 'th' if (10..19).cover?(self % 100) + # others case self % 10 when 1 diff --git a/test/test_determinism.rb b/test/test_determinism.rb index e655ab2a16..1d1d3990c5 100644 --- a/test/test_determinism.rb +++ b/test/test_determinism.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require_relative 'test_helper' -# rubocop:disable Security/Eval,Style/EvalWithLocation +# rubocop:disable Security/Eval class TestDeterminism < Test::Unit::TestCase def setup @all_methods = all_methods.freeze @@ -45,14 +45,14 @@ def all_methods def subclasses Faker.constants.delete_if do |subclass| - %i[Base Bank Char Base58 ChileRut Config Date Internet Time VERSION].include?(subclass) + %i[Base Bank Base58 Char CLI ChileRut Config Date Internet Time VERSION].include?(subclass) end.sort end def subclass_methods(subclass) - eval("Faker::#{subclass}.public_methods(false) - Faker::Base.public_methods(false)").sort.map do |method| + Faker::Base.module_methods(subclass).sort.map do |method| "Faker::#{subclass}.#{method}" end.sort end end -# rubocop:enable Security/Eval,Style/EvalWithLocation +# rubocop:enable Security/Eval diff --git a/test/test_no-NO_locale.rb b/test/test_no_no_locale.rb similarity index 100% rename from test/test_no-NO_locale.rb rename to test/test_no_no_locale.rb