factory-helper 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/History.txt +126 -0
  3. data/License.txt +20 -0
  4. data/README.md +445 -0
  5. data/lib/extensions/array.rb +22 -0
  6. data/lib/extensions/symbol.rb +9 -0
  7. data/lib/factory-helper.rb +182 -0
  8. data/lib/factory-helper/address.rb +59 -0
  9. data/lib/factory-helper/app.rb +22 -0
  10. data/lib/factory-helper/avatar.rb +14 -0
  11. data/lib/factory-helper/bitcoin.rb +49 -0
  12. data/lib/factory-helper/business.rb +22 -0
  13. data/lib/factory-helper/code.rb +63 -0
  14. data/lib/factory-helper/commerce.rb +51 -0
  15. data/lib/factory-helper/company.rb +40 -0
  16. data/lib/factory-helper/date.rb +42 -0
  17. data/lib/factory-helper/finance.rb +26 -0
  18. data/lib/factory-helper/hacker.rb +31 -0
  19. data/lib/factory-helper/internet.rb +116 -0
  20. data/lib/factory-helper/lorem.rb +66 -0
  21. data/lib/factory-helper/name.rb +22 -0
  22. data/lib/factory-helper/number.rb +57 -0
  23. data/lib/factory-helper/phone_number.rb +52 -0
  24. data/lib/factory-helper/team.rb +20 -0
  25. data/lib/factory-helper/time.rb +48 -0
  26. data/lib/factory-helper/version.rb +3 -0
  27. data/lib/locales/de-AT.yml +49 -0
  28. data/lib/locales/de-CH.yml +19 -0
  29. data/lib/locales/de.yml +57 -0
  30. data/lib/locales/en-AU.yml +22 -0
  31. data/lib/locales/en-BORK.yml +4 -0
  32. data/lib/locales/en-CA.yml +14 -0
  33. data/lib/locales/en-GB.yml +13 -0
  34. data/lib/locales/en-IND.yml +20 -0
  35. data/lib/locales/en-NEP.yml +39 -0
  36. data/lib/locales/en-US.yml +83 -0
  37. data/lib/locales/en-au-ocker.yml +31 -0
  38. data/lib/locales/en.yml +155 -0
  39. data/lib/locales/es.yml +62 -0
  40. data/lib/locales/fa.yml +6 -0
  41. data/lib/locales/fr.yml +55 -0
  42. data/lib/locales/it.yml +59 -0
  43. data/lib/locales/ja.yml +25 -0
  44. data/lib/locales/ko.yml +37 -0
  45. data/lib/locales/nb-NO.yml +52 -0
  46. data/lib/locales/nl.yml +77 -0
  47. data/lib/locales/pl.yml +66 -0
  48. data/lib/locales/pt-BR.yml +57 -0
  49. data/lib/locales/ru.yml +65 -0
  50. data/lib/locales/sk.yml +72 -0
  51. data/lib/locales/sv.yml +76 -0
  52. data/lib/locales/vi.yml +63 -0
  53. data/lib/locales/zh-CN.yml +27 -0
  54. data/lib/locales/zh-TW.yml +27 -0
  55. 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,9 @@
1
+ # For Ruby 1.8
2
+ unless :symbol.respond_to?(:downcase)
3
+ Symbol.class_eval do
4
+ def downcase
5
+ to_s.downcase.intern
6
+ end
7
+ end
8
+ end
9
+
@@ -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