factory-helper 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/History.txt +126 -0
- data/License.txt +20 -0
- data/README.md +445 -0
- data/lib/extensions/array.rb +22 -0
- data/lib/extensions/symbol.rb +9 -0
- data/lib/factory-helper.rb +182 -0
- data/lib/factory-helper/address.rb +59 -0
- data/lib/factory-helper/app.rb +22 -0
- data/lib/factory-helper/avatar.rb +14 -0
- data/lib/factory-helper/bitcoin.rb +49 -0
- data/lib/factory-helper/business.rb +22 -0
- data/lib/factory-helper/code.rb +63 -0
- data/lib/factory-helper/commerce.rb +51 -0
- data/lib/factory-helper/company.rb +40 -0
- data/lib/factory-helper/date.rb +42 -0
- data/lib/factory-helper/finance.rb +26 -0
- data/lib/factory-helper/hacker.rb +31 -0
- data/lib/factory-helper/internet.rb +116 -0
- data/lib/factory-helper/lorem.rb +66 -0
- data/lib/factory-helper/name.rb +22 -0
- data/lib/factory-helper/number.rb +57 -0
- data/lib/factory-helper/phone_number.rb +52 -0
- data/lib/factory-helper/team.rb +20 -0
- data/lib/factory-helper/time.rb +48 -0
- data/lib/factory-helper/version.rb +3 -0
- data/lib/locales/de-AT.yml +49 -0
- data/lib/locales/de-CH.yml +19 -0
- data/lib/locales/de.yml +57 -0
- data/lib/locales/en-AU.yml +22 -0
- data/lib/locales/en-BORK.yml +4 -0
- data/lib/locales/en-CA.yml +14 -0
- data/lib/locales/en-GB.yml +13 -0
- data/lib/locales/en-IND.yml +20 -0
- data/lib/locales/en-NEP.yml +39 -0
- data/lib/locales/en-US.yml +83 -0
- data/lib/locales/en-au-ocker.yml +31 -0
- data/lib/locales/en.yml +155 -0
- data/lib/locales/es.yml +62 -0
- data/lib/locales/fa.yml +6 -0
- data/lib/locales/fr.yml +55 -0
- data/lib/locales/it.yml +59 -0
- data/lib/locales/ja.yml +25 -0
- data/lib/locales/ko.yml +37 -0
- data/lib/locales/nb-NO.yml +52 -0
- data/lib/locales/nl.yml +77 -0
- data/lib/locales/pl.yml +66 -0
- data/lib/locales/pt-BR.yml +57 -0
- data/lib/locales/ru.yml +65 -0
- data/lib/locales/sk.yml +72 -0
- data/lib/locales/sv.yml +76 -0
- data/lib/locales/vi.yml +63 -0
- data/lib/locales/zh-CN.yml +27 -0
- data/lib/locales/zh-TW.yml +27 -0
- metadata +140 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
class Array
|
2
|
+
unless self.method_defined? :sample
|
3
|
+
def sample(n = nil)
|
4
|
+
#based on code from https://github.com/marcandre/backports
|
5
|
+
size = self.length
|
6
|
+
return self[Kernel.rand(size)] if n.nil?
|
7
|
+
|
8
|
+
n = n.to_int
|
9
|
+
raise ArgumentError, "negative array size" if n < 0
|
10
|
+
|
11
|
+
n = size if n > size
|
12
|
+
|
13
|
+
result = Array.new(self)
|
14
|
+
n.times do |i|
|
15
|
+
r = i + Kernel.rand(size - i)
|
16
|
+
result[i], result[r] = result[r], result[i]
|
17
|
+
end
|
18
|
+
result[n..size] = []
|
19
|
+
result
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
mydir = File.expand_path(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'psych'
|
6
|
+
rescue LoadError
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'i18n'
|
10
|
+
require 'set' # Fixes a bug in i18n 0.6.11
|
11
|
+
|
12
|
+
if I18n.respond_to?(:enforce_available_locales=)
|
13
|
+
I18n.enforce_available_locales = true
|
14
|
+
end
|
15
|
+
I18n.load_path += Dir[File.join(mydir, 'locales', '*.yml')]
|
16
|
+
|
17
|
+
|
18
|
+
module Faker
|
19
|
+
class Config
|
20
|
+
@locale = nil
|
21
|
+
|
22
|
+
class << self
|
23
|
+
attr_writer :locale
|
24
|
+
def locale
|
25
|
+
@locale || I18n.locale
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Base
|
31
|
+
Numbers = Array(0..9)
|
32
|
+
ULetters = Array('A'..'Z')
|
33
|
+
Letters = ULetters + Array('a'..'z')
|
34
|
+
|
35
|
+
class << self
|
36
|
+
## make sure numerify results doesn’t start with a zero
|
37
|
+
def numerify(number_string)
|
38
|
+
number_string.sub(/#/) { (rand(9)+1).to_s }.gsub(/#/) { rand(10).to_s }
|
39
|
+
end
|
40
|
+
|
41
|
+
def letterify(letter_string)
|
42
|
+
letter_string.gsub(/\?/) { ULetters.sample }
|
43
|
+
end
|
44
|
+
|
45
|
+
def bothify(string)
|
46
|
+
letterify(numerify(string))
|
47
|
+
end
|
48
|
+
|
49
|
+
# Given a regular expression, attempt to generate a string
|
50
|
+
# that would match it. This is a rather simple implementation,
|
51
|
+
# so don't be shocked if it blows up on you in a spectacular fashion.
|
52
|
+
#
|
53
|
+
# It does not handle ., *, unbounded ranges such as {1,},
|
54
|
+
# extensions such as (?=), character classes, some abbreviations
|
55
|
+
# for character classes, and nested parentheses.
|
56
|
+
#
|
57
|
+
# I told you it was simple. :) It's also probably dog-slow,
|
58
|
+
# so you shouldn't use it.
|
59
|
+
#
|
60
|
+
# It will take a regex like this:
|
61
|
+
#
|
62
|
+
# /^[A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {1,2}[0-9][ABD-HJLN-UW-Z]{2}$/
|
63
|
+
#
|
64
|
+
# and generate a string like this:
|
65
|
+
#
|
66
|
+
# "U3V 3TP"
|
67
|
+
#
|
68
|
+
def regexify(re)
|
69
|
+
re = re.source if re.respond_to?(:source) # Handle either a Regexp or a String that looks like a Regexp
|
70
|
+
re.
|
71
|
+
gsub(/^\/?\^?/, '').gsub(/\$?\/?$/, ''). # Ditch the anchors
|
72
|
+
gsub(/\{(\d+)\}/, '{\1,\1}').gsub(/\?/, '{0,1}'). # All {2} become {2,2} and ? become {0,1}
|
73
|
+
gsub(/(\[[^\]]+\])\{(\d+),(\d+)\}/) {|match| $1 * Array(Range.new($2.to_i, $3.to_i)).sample }. # [12]{1,2} becomes [12] or [12][12]
|
74
|
+
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)
|
75
|
+
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
|
76
|
+
gsub(/\((.*?)\)/) {|match| match.gsub(/[\(\)]/, '').split('|').sample }. # (this|that) becomes 'this' or 'that'
|
77
|
+
gsub(/\[([^\]]+)\]/) {|match| match.gsub(/(\w\-\w)/) {|range| Array(Range.new(*range.split('-'))).sample } }. # All A-Z inside of [] become C (or X, or whatever)
|
78
|
+
gsub(/\[([^\]]+)\]/) {|match| $1.split('').sample }. # All [ABC] become B (or A or C)
|
79
|
+
gsub('\d') {|match| Numbers.sample }.
|
80
|
+
gsub('\w') {|match| Letters.sample }
|
81
|
+
end
|
82
|
+
|
83
|
+
# Helper for the common approach of grabbing a translation
|
84
|
+
# with an array of values and selecting one of them.
|
85
|
+
def fetch(key)
|
86
|
+
fetched = translate("faker.#{key}")
|
87
|
+
fetched = fetched.sample if fetched.respond_to?(:sample)
|
88
|
+
if fetched.match(/^\//) and fetched.match(/\/$/) # A regex
|
89
|
+
regexify(fetched)
|
90
|
+
else
|
91
|
+
fetched
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Load formatted strings from the locale, "parsing" them
|
96
|
+
# into method calls that can be used to generate a
|
97
|
+
# formatted translation: e.g., "#{first_name} #{last_name}".
|
98
|
+
def parse(key)
|
99
|
+
fetch(key).scan(/(\(?)#\{([A-Za-z]+\.)?([^\}]+)\}([^#]+)?/).map {|prefix, kls, meth, etc|
|
100
|
+
# If the token had a class Prefix (e.g., Name.first_name)
|
101
|
+
# grab the constant, otherwise use self
|
102
|
+
cls = kls ? Faker.const_get(kls.chop) : self
|
103
|
+
|
104
|
+
# If an optional leading parentheses is not present, prefix.should == "", otherwise prefix.should == "("
|
105
|
+
# In either case the information will be retained for reconstruction of the string.
|
106
|
+
text = prefix
|
107
|
+
|
108
|
+
# If the class has the method, call it, otherwise
|
109
|
+
# fetch the transation (i.e., faker.name.first_name)
|
110
|
+
text += cls.respond_to?(meth) ? cls.send(meth) : fetch("#{(kls || self).to_s.split('::').last.downcase}.#{meth.downcase}")
|
111
|
+
|
112
|
+
# And tack on spaces, commas, etc. left over in the string
|
113
|
+
text += etc.to_s
|
114
|
+
}.join
|
115
|
+
end
|
116
|
+
|
117
|
+
# Call I18n.translate with our configured locale if no
|
118
|
+
# locale is specified
|
119
|
+
def translate(*args)
|
120
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
121
|
+
opts[:locale] ||= Faker::Config.locale
|
122
|
+
opts[:raise] = true
|
123
|
+
I18n.translate(*(args.push(opts)))
|
124
|
+
rescue I18n::MissingTranslationData
|
125
|
+
# Super-simple fallback -- fallback to en if the
|
126
|
+
# translation was missing. If the translation isn't
|
127
|
+
# in en either, then it will raise again.
|
128
|
+
I18n.translate(*(args.push(opts.merge(:locale => :en))))
|
129
|
+
end
|
130
|
+
|
131
|
+
def flexible(key)
|
132
|
+
@flexible_key = key
|
133
|
+
end
|
134
|
+
|
135
|
+
# You can add whatever you want to the locale file, and it will get caught here.
|
136
|
+
# E.g., in your locale file, create a
|
137
|
+
# name:
|
138
|
+
# girls_name: ["Alice", "Cheryl", "Tatiana"]
|
139
|
+
# Then you can call Faker::Name.girls_name and it will act like #first_name
|
140
|
+
def method_missing(m, *args, &block)
|
141
|
+
super unless @flexible_key
|
142
|
+
|
143
|
+
# Use the alternate form of translate to get a nil rather than a "missing translation" string
|
144
|
+
if translation = translate(:faker)[@flexible_key][m]
|
145
|
+
translation.respond_to?(:sample) ? translation.sample : translation
|
146
|
+
else
|
147
|
+
super
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# Generates a random value between the interval
|
152
|
+
def rand_in_range(from, to)
|
153
|
+
from, to = to, from if to < from
|
154
|
+
Random.new.rand(from..to)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
require_relative 'factory-helper/address'
|
161
|
+
require_relative 'factory-helper/code'
|
162
|
+
require_relative 'factory-helper/company'
|
163
|
+
require_relative 'factory-helper/finance'
|
164
|
+
require_relative 'factory-helper/internet'
|
165
|
+
require_relative 'factory-helper/lorem'
|
166
|
+
require_relative 'factory-helper/name'
|
167
|
+
require_relative 'factory-helper/team'
|
168
|
+
require_relative 'factory-helper/phone_number'
|
169
|
+
require_relative 'factory-helper/business'
|
170
|
+
require_relative 'factory-helper/commerce'
|
171
|
+
require_relative 'factory-helper/version'
|
172
|
+
require_relative 'factory-helper/number'
|
173
|
+
require_relative 'factory-helper/bitcoin'
|
174
|
+
require_relative 'factory-helper/avatar'
|
175
|
+
require_relative 'factory-helper/date'
|
176
|
+
require_relative 'factory-helper/time'
|
177
|
+
require_relative 'factory-helper/number'
|
178
|
+
require_relative 'factory-helper/hacker'
|
179
|
+
require_relative 'factory-helper/app'
|
180
|
+
|
181
|
+
require_relative 'extensions/array'
|
182
|
+
require_relative 'extensions/symbol'
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Faker
|
2
|
+
class Address < Base
|
3
|
+
flexible :address
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def city
|
7
|
+
parse('address.city')
|
8
|
+
end
|
9
|
+
|
10
|
+
def street_name
|
11
|
+
parse('address.street_name')
|
12
|
+
end
|
13
|
+
|
14
|
+
def street_address(include_secondary = false)
|
15
|
+
numerify(parse('address.street_address') + (include_secondary ? ' ' + secondary_address : ''))
|
16
|
+
end
|
17
|
+
|
18
|
+
def secondary_address
|
19
|
+
numerify(fetch('address.secondary_address'))
|
20
|
+
end
|
21
|
+
|
22
|
+
def building_number
|
23
|
+
bothify(fetch('address.building_number'))
|
24
|
+
end
|
25
|
+
|
26
|
+
def zip_code(state_abbreviation = '')
|
27
|
+
return bothify(fetch('address.postcode')) if state_abbreviation === ''
|
28
|
+
|
29
|
+
# provide a zip code that is valid for the state provided
|
30
|
+
# see http://www.fincen.gov/forms/files/us_state_territory_zip_codes.pdf
|
31
|
+
bothify(fetch('address.postcode_by_state.' + state_abbreviation))
|
32
|
+
end
|
33
|
+
|
34
|
+
def time_zone
|
35
|
+
fetch('address.time_zone')
|
36
|
+
end
|
37
|
+
|
38
|
+
alias_method :zip, :zip_code
|
39
|
+
alias_method :postcode, :zip_code
|
40
|
+
|
41
|
+
def street_suffix; fetch('address.street_suffix'); end
|
42
|
+
def city_suffix; fetch('address.city_suffix'); end
|
43
|
+
def city_prefix; fetch('address.city_prefix'); end
|
44
|
+
def state_abbr; fetch('address.state_abbr'); end
|
45
|
+
def state; fetch('address.state'); end
|
46
|
+
def country; fetch('address.country'); end
|
47
|
+
def country_code; fetch('address.country_code'); end
|
48
|
+
|
49
|
+
def latitude
|
50
|
+
((rand * 180) - 90).to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
def longitude
|
54
|
+
((rand * 360) - 180).to_s
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Faker
|
2
|
+
class App < Base
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def name
|
6
|
+
fetch('app.name')
|
7
|
+
end
|
8
|
+
|
9
|
+
def version
|
10
|
+
if parse('app.version') == ""
|
11
|
+
numerify(fetch('app.version'))
|
12
|
+
else
|
13
|
+
parse('app.version')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def author
|
18
|
+
parse('app.author')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Faker
|
2
|
+
class Avatar < Base
|
3
|
+
class << self
|
4
|
+
SUPPORTED_FORMATS = %w(png jpg bmp)
|
5
|
+
|
6
|
+
def image(slug = nil, size = '300x300', format = 'png')
|
7
|
+
raise ArgumentError, "Size should be specified in format 300x300" unless size.match(/^[0-9]+x[0-9]+$/)
|
8
|
+
raise ArgumentError, "Supported formats are #{SUPPORTED_FORMATS.join(', ')}" unless SUPPORTED_FORMATS.include?(format)
|
9
|
+
slug ||= Faker::Lorem.words.join
|
10
|
+
"http://robohash.org/#{slug}.#{format}?size=#{size}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'digest'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
module Faker
|
5
|
+
class Bitcoin < Base
|
6
|
+
class << self
|
7
|
+
|
8
|
+
PROTOCOL_VERSIONS = {
|
9
|
+
main: 0,
|
10
|
+
testnet: 111
|
11
|
+
}
|
12
|
+
|
13
|
+
def address
|
14
|
+
address_for(:main)
|
15
|
+
end
|
16
|
+
|
17
|
+
def testnet_address
|
18
|
+
address_for(:testnet)
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def base58(str)
|
24
|
+
alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
25
|
+
base = alphabet.size
|
26
|
+
|
27
|
+
lv = 0
|
28
|
+
str.split('').reverse.each_with_index { |v,i| lv += v.unpack('C')[0] * 256**i }
|
29
|
+
|
30
|
+
ret = ''
|
31
|
+
while lv > 0 do
|
32
|
+
lv, mod = lv.divmod(base)
|
33
|
+
ret << alphabet[mod]
|
34
|
+
end
|
35
|
+
|
36
|
+
npad = str.match(/^#{0.chr}*/)[0].to_s.size
|
37
|
+
'1'*npad + ret.reverse
|
38
|
+
end
|
39
|
+
|
40
|
+
def address_for(network)
|
41
|
+
version = PROTOCOL_VERSIONS.fetch(network)
|
42
|
+
hash = SecureRandom.hex(20)
|
43
|
+
packed = version.chr + [hash].pack("H*")
|
44
|
+
checksum = Digest::SHA2.digest(Digest::SHA2.digest(packed))[0..3]
|
45
|
+
base58(packed + checksum)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module Faker
|
4
|
+
class Business < Base
|
5
|
+
flexible :business
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def credit_card_number
|
9
|
+
fetch('business.credit_card_numbers')
|
10
|
+
end
|
11
|
+
|
12
|
+
def credit_card_expiry_date
|
13
|
+
::Date.parse(fetch('business.credit_card_expiry_dates'))
|
14
|
+
end
|
15
|
+
|
16
|
+
def credit_card_type
|
17
|
+
fetch('business.credit_card_types')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Faker
|
2
|
+
class Code < Base
|
3
|
+
class << self
|
4
|
+
# By default generates 10 sign isbn code in format 123456789-X
|
5
|
+
# You can pass 13 to generate new 13 sign code
|
6
|
+
def isbn(base = 10)
|
7
|
+
base == 13 ? generate_base13_isbn : generate_base10_isbn
|
8
|
+
end
|
9
|
+
|
10
|
+
# By default generates 13 sign ean code in format 1234567890123
|
11
|
+
# You can pass 8 to generate ean8 code
|
12
|
+
def ean(base = 13)
|
13
|
+
base == 8 ? generate_base8_ean : generate_base13_ean
|
14
|
+
end
|
15
|
+
|
16
|
+
def rut
|
17
|
+
value = Number.number(8)
|
18
|
+
vd = rut_verificator_digit(value)
|
19
|
+
value << "-#{vd}"
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def generate_base10_isbn
|
25
|
+
values = regexify(/\d{9}/)
|
26
|
+
remainder = sum(values) { |value, index| (index + 1) * value.to_i } % 11
|
27
|
+
values << "-#{remainder == 10 ? 'X' : remainder}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def generate_base13_isbn
|
31
|
+
values = regexify(/\d{12}/)
|
32
|
+
remainder = sum(values) { |value, index| index.even? ? value.to_i : value.to_i * 3 } % 10
|
33
|
+
values << "-#{((10 - remainder) % 10)}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def sum(values, &block)
|
37
|
+
values.split(//).each_with_index.inject(0) do |sum, (value, index)|
|
38
|
+
sum + block.call(value, index)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def generate_base8_ean
|
43
|
+
values = regexify(/\d{7}/)
|
44
|
+
check_digit = 10 - values.split(//).each_with_index.inject(0){ |s, (v, i)| s + v.to_i * EAN_CHECK_DIGIT8[i] } % 10
|
45
|
+
values << (check_digit == 10 ? 0 : check_digit).to_s
|
46
|
+
end
|
47
|
+
|
48
|
+
def generate_base13_ean
|
49
|
+
values = regexify(/\d{12}/)
|
50
|
+
check_digit = 10 - values.split(//).each_with_index.inject(0){ |s, (v, i)| s + v.to_i * EAN_CHECK_DIGIT13[i] } % 10
|
51
|
+
values << (check_digit == 10 ? 0 : check_digit).to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
EAN_CHECK_DIGIT8 = [3, 1, 3, 1, 3, 1, 3]
|
55
|
+
EAN_CHECK_DIGIT13 = [1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3]
|
56
|
+
|
57
|
+
def rut_verificator_digit(rut)
|
58
|
+
total = rut.to_s.rjust(8, '0').split(//).zip(%w(3 2 7 6 5 4 3 2)).collect{|a, b| a.to_i * b.to_i}.inject(:+)
|
59
|
+
(11 - total % 11).to_s.gsub(/10/, 'k').gsub(/11/, '0')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|