sevenwire-forgery 0.1.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 (52) hide show
  1. data/README.markdown +81 -0
  2. data/VERSION.yml +4 -0
  3. data/generators/forgery/USAGE +6 -0
  4. data/generators/forgery/forgery_generator.rb +12 -0
  5. data/lib/dictionaries/cities +478 -0
  6. data/lib/dictionaries/colors +19 -0
  7. data/lib/dictionaries/company_names +400 -0
  8. data/lib/dictionaries/countries +249 -0
  9. data/lib/dictionaries/female_first_names +100 -0
  10. data/lib/dictionaries/frequencies +8 -0
  11. data/lib/dictionaries/genders +2 -0
  12. data/lib/dictionaries/languages +97 -0
  13. data/lib/dictionaries/last_names +250 -0
  14. data/lib/dictionaries/lorem_ipsum +151 -0
  15. data/lib/dictionaries/male_first_names +100 -0
  16. data/lib/dictionaries/name_suffixes +5 -0
  17. data/lib/dictionaries/name_titles +6 -0
  18. data/lib/dictionaries/races +93 -0
  19. data/lib/dictionaries/shirt_sizes +7 -0
  20. data/lib/dictionaries/state_abbrevs +50 -0
  21. data/lib/dictionaries/states +50 -0
  22. data/lib/dictionaries/street_suffixes +21 -0
  23. data/lib/dictionaries/streets +500 -0
  24. data/lib/dictionaries/top_level_domains +9 -0
  25. data/lib/extensions/array.rb +11 -0
  26. data/lib/extensions/hash.rb +12 -0
  27. data/lib/extensions/range.rb +9 -0
  28. data/lib/extensions/string.rb +48 -0
  29. data/lib/forgeries/address_forgery.rb +117 -0
  30. data/lib/forgeries/basic_forgery.rb +73 -0
  31. data/lib/forgeries/internet_forgery.rb +19 -0
  32. data/lib/forgeries/lorem_ipsum_forgery.rb +107 -0
  33. data/lib/forgeries/monetary_forgery.rb +13 -0
  34. data/lib/forgeries/name_forgery.rb +36 -0
  35. data/lib/forgeries/personal_forgery.rb +23 -0
  36. data/lib/forgery.rb +82 -0
  37. data/lib/formats/phone +1 -0
  38. data/lib/formats/street_number +5 -0
  39. data/lib/formats/zip +2 -0
  40. data/spec/extensions/array_spec.rb +25 -0
  41. data/spec/extensions/range_spec.rb +17 -0
  42. data/spec/extensions/string_spec.rb +29 -0
  43. data/spec/forgeries/address_forgery_spec.rb +69 -0
  44. data/spec/forgeries/basic_forgery_spec.rb +175 -0
  45. data/spec/forgeries/internet_forgery_spec.rb +30 -0
  46. data/spec/forgeries/lorem_ipsum_forgery_spec.rb +128 -0
  47. data/spec/forgeries/monetary_forgery_spec.rb +4 -0
  48. data/spec/forgeries/name_forgery_spec.rb +4 -0
  49. data/spec/forgeries/personal_forgery_spec.rb +15 -0
  50. data/spec/forgery_spec.rb +36 -0
  51. data/spec/spec_helper.rb +31 -0
  52. metadata +110 -0
@@ -0,0 +1,117 @@
1
+ # Generates random address information.
2
+ class AddressForgery < Forgery
3
+ dictionaries :streets, :street_suffixes, :cities, :states, :state_abbrevs, :countries
4
+ formats :zip, :phone, :street_number
5
+
6
+ # Gets a random street name out of the 'streets' dictionary.
7
+ #
8
+ # AddressForgery.street_name
9
+ # # => "Atwood"
10
+ #
11
+ # AddressForgery.street_name
12
+ # # => "Fordem"
13
+ def self.street_name
14
+ STREETS.random
15
+ end
16
+
17
+ # Gets one of the formats from 'street_number_formats' and converts it to
18
+ # numbers.
19
+ #
20
+ # AddressForgery.street_number
21
+ # # => 1
22
+ #
23
+ # AddressForgery.street_number
24
+ # # => 1234
25
+ def self.street_number
26
+ STREET_NUMBER_FORMATS.random.to_numbers
27
+ end
28
+
29
+ # Gets a random street suffix out of the 'street_suffixes' dictionary.
30
+ #
31
+ # AddressForgery.street_suffix
32
+ # # => "Street"
33
+ #
34
+ # AddressForgery.street_suffix
35
+ # # => "Parkway"
36
+ def self.street_suffix
37
+ STREET_SUFFIXES.random
38
+ end
39
+
40
+ # Gets a full street address, including street number, street name, and
41
+ # street suffix.
42
+ #
43
+ # AddressForgery.street_address
44
+ # # => "92 West Circle"
45
+ #
46
+ # AddressForgery.street_address
47
+ # # => "93265 Harper Lane"
48
+ def self.street_address
49
+ "#{street_number} #{street_name} #{street_suffix}"
50
+ end
51
+
52
+ # Gets a random city out of the 'cities' dictionary.
53
+ #
54
+ # AddressForgery.city
55
+ # # => "Anaheim"
56
+ #
57
+ # AddressForgery.city
58
+ # # => "Sacramento"
59
+ def self.city
60
+ CITIES.random
61
+ end
62
+
63
+ # Gets a random state out of the 'states' dictionary.
64
+ #
65
+ # AddressForgery.state
66
+ # # => "Mississippi"
67
+ #
68
+ # AddressForgery.state
69
+ # # => "Minnesota"
70
+ def self.state
71
+ STATES.random
72
+ end
73
+
74
+ # Gets a random state abbreviation out of the 'state_abbrev' dictionary.
75
+ #
76
+ # AddressForgery.state_abbrev
77
+ # # => "GA"
78
+ #
79
+ # AddressForgery.state_abbrev
80
+ # # => "TX"
81
+ def self.state_abbrev
82
+ STATE_ABBREVS.random
83
+ end
84
+
85
+ # Gets one of the formats from 'zip_formats' and converts it to numbers.
86
+ #
87
+ # AddressForgery.zip
88
+ # # => "52474"
89
+ #
90
+ # AddressForgery.zip
91
+ # # => "66702-4349"
92
+ def self.zip
93
+ ZIP_FORMATS.random.to_numbers
94
+ end
95
+
96
+ # Gets one of the formats from 'phone_formats' and converts it to numbers.
97
+ #
98
+ # AddressForgery.phone
99
+ # # => "1-(416)185-8799"
100
+ #
101
+ # AddressForgery.phone
102
+ # # => "1-(589)248-0418"
103
+ def self.phone
104
+ PHONE_FORMATS.random.to_numbers
105
+ end
106
+
107
+ # Gets a random country out of the 'countries' dictionary.
108
+ #
109
+ # AddressForgery.country
110
+ # # => "Uruguay"
111
+ #
112
+ # AddressForgery.country
113
+ # # => "Romania"
114
+ def self.country
115
+ COUNTRIES.random
116
+ end
117
+ end
@@ -0,0 +1,73 @@
1
+ require 'digest/sha1'
2
+
3
+ class BasicForgery < Forgery
4
+ dictionaries :colors, :frequencies
5
+
6
+ HEX_DIGITS = %w{0 1 2 3 4 5 6 7 8 9 a b c d e f}
7
+ UPPER_ALPHA = ('A'..'Z').to_a
8
+ LOWER_ALPHA = ('a'..'z').to_a
9
+ NUMERIC = ('0'..'9').to_a
10
+ SPECIAL_CHARACTERS = %w{! ' @ # $ % ^ & * ( ) _ + - = [ ] { } ; : " , . / ?}
11
+ BOOLEAN = [true, false]
12
+
13
+ def self.password(options={})
14
+ options = {:at_least => 6,
15
+ :at_most => 12,
16
+ :allow_lower => true,
17
+ :allow_upper => true,
18
+ :allow_numeric => true,
19
+ :allow_special => false}.merge!(options)
20
+ self.text(options)
21
+ end
22
+
23
+ def self.encrypt(password="password", salt=Time.now.to_s)
24
+ Digest::SHA1.hexdigest("--#{salt}--#{password}--")
25
+ end
26
+
27
+ def self.boolean
28
+ BOOLEAN.random
29
+ end
30
+
31
+ def self.color
32
+ COLORS.random
33
+ end
34
+
35
+ def self.hex_color
36
+ hex_digits = (1..6).collect { HEX_DIGITS.random}
37
+ "##{hex_digits.join}"
38
+ end
39
+
40
+ def self.short_hex_color
41
+ hex_color[0,4]
42
+ end
43
+
44
+ def self.number(options={})
45
+ options = {:at_least => 1,
46
+ :at_most => 10}.merge(options)
47
+
48
+ (options[:at_least]..options[:at_most]).random
49
+ end
50
+
51
+ def self.text(options={})
52
+ options = {:at_least => 10,
53
+ :at_most => 15,
54
+ :allow_lower => true,
55
+ :allow_upper => true,
56
+ :allow_numeric => true,
57
+ :allow_special => false}.merge!(options)
58
+
59
+ allowed_characters = []
60
+ allowed_characters += LOWER_ALPHA if options[:allow_lower]
61
+ allowed_characters += UPPER_ALPHA if options[:allow_upper]
62
+ allowed_characters += NUMERIC if options[:allow_numeric]
63
+ allowed_characters += SPECIAL_CHARACTERS if options[:allow_special]
64
+
65
+ length = (options[:at_least]..options[:at_most]).random
66
+
67
+ allowed_characters.random_subset(length).join
68
+ end
69
+
70
+ def self.frequency
71
+ FREQUENCIES.random
72
+ end
73
+ end
@@ -0,0 +1,19 @@
1
+ class InternetForgery < Forgery
2
+ dictionaries :male_first_names, :female_first_names, :last_names, :top_level_domains, :company_names
3
+
4
+ def self.user_name
5
+ (MALE_FIRST_NAMES.random[0,1] + LAST_NAMES.random).downcase
6
+ end
7
+
8
+ def self.top_level_domain
9
+ TOP_LEVEL_DOMAINS.random
10
+ end
11
+
12
+ def self.domain_name
13
+ COMPANY_NAMES.random.downcase + '.' + self.top_level_domain
14
+ end
15
+
16
+ def self.email_address
17
+ self.user_name + '@' + self.domain_name
18
+ end
19
+ end
@@ -0,0 +1,107 @@
1
+ class LoremIpsumForgery < Forgery
2
+ dictionaries :lorem_ipsum
3
+ LOREM_IPSUM_WORDS = LOREM_IPSUM.join(" ").downcase.gsub(/\.|,|;/, '').split(" ")
4
+ LOREM_IPSUM_CHARACTERS = LOREM_IPSUM.join("").downcase.gsub(/[^a-z\s]/,'')
5
+
6
+ def self.text(what=:sentence, quantity=2, options={})
7
+ case what
8
+ when :character
9
+ self.character(options)
10
+ when :characters
11
+ self.characters(quantity, options)
12
+ when :word
13
+ self.word(options)
14
+ when :words
15
+ self.words(quantity, options)
16
+ when :sentence
17
+ self.sentence(options)
18
+ when :sentences
19
+ self.sentences(quantity, options)
20
+ when :paragraph
21
+ self.paragraph(options)
22
+ when :paragraphs
23
+ self.paragraphs(quantity, options)
24
+ end
25
+ end
26
+
27
+
28
+ def self.character(options={})
29
+ self.characters(1, options)
30
+ end
31
+
32
+ def self.characters(quantity=10, options={})
33
+ options.merge!(:random_limit => LOREM_IPSUM_CHARACTERS.length-quantity) if quantity.is_a?(Fixnum)
34
+
35
+ LOREM_IPSUM_CHARACTERS[range_from_quantity(quantity, options)]
36
+ end
37
+
38
+ def self.word(options={})
39
+ self.words(1, options)
40
+ end
41
+
42
+ def self.words(quantity=10, options={})
43
+ options.merge!(:random_limit => LOREM_IPSUM_WORDS.length-quantity) if quantity.is_a?(Fixnum)
44
+
45
+ LOREM_IPSUM_WORDS[range_from_quantity(quantity, options)].join(" ")
46
+ end
47
+
48
+ def self.sentence(options={})
49
+ self.sentences(1, options)
50
+ end
51
+
52
+ def self.sentences(quantity=2, options={})
53
+ options.merge!(:random_limit => (LOREM_IPSUM.length-quantity)) if quantity.is_a?(Fixnum)
54
+
55
+ LOREM_IPSUM[range_from_quantity(quantity, options)].join(" ")
56
+ end
57
+
58
+ def self.paragraph(options={})
59
+ self.paragraphs(1, options)
60
+ end
61
+
62
+ def self.paragraphs(quantity=2, options={})
63
+ options.reverse_merge!(:separator => "\n\n",
64
+ :wrap => {
65
+ :start => "",
66
+ :end => "" },
67
+ :html => false,
68
+ :sentences => 3)
69
+ options.merge!(:random_limit => (LOREM_IPSUM.length/options[:sentences])-quantity) if quantity.is_a?(Fixnum)
70
+
71
+ if options[:html]
72
+ options[:wrap] = { :start => "<p>",
73
+ :end => "</p>" }
74
+ end
75
+
76
+ range = range_from_quantity(quantity, options)
77
+ start = range.first * options[:sentences]
78
+
79
+ paragraphs = []
80
+
81
+ range.to_a.length.times do |i|
82
+ paragraphs << (
83
+ options[:wrap][:start] +
84
+ LOREM_IPSUM[start..(start+options[:sentences]-1)].join(" ") +
85
+ options[:wrap][:end]
86
+ )
87
+ start += options[:sentences]
88
+ end
89
+
90
+ paragraphs.join(options[:separator])
91
+ end
92
+
93
+
94
+ protected
95
+
96
+ def self.range_from_quantity(quantity, options={})
97
+ return quantity if quantity.is_a?(Range)
98
+
99
+ if options[:random]
100
+ start = (0..options[:random_limit]).random
101
+ start..(start+quantity-1)
102
+ else
103
+ 0..(quantity-1)
104
+ end
105
+ end
106
+
107
+ end
@@ -0,0 +1,13 @@
1
+ class MonetaryForgery < Forgery
2
+ def self.formatted_money(options={})
3
+ "$%1.2f" % money(options)
4
+ end
5
+
6
+ def self.money(options={})
7
+ options = {:max => 10,
8
+ :min => 0}.merge(options)
9
+
10
+ value = ((options[:min] * 100)..(options[:max] * 100)).random
11
+ "%1.2f" % (value.to_f / 100)
12
+ end
13
+ end
@@ -0,0 +1,36 @@
1
+ class NameForgery < Forgery
2
+ dictionaries :last_names, :male_first_names, :female_first_names, :company_names,
3
+ :name_suffixes, :name_titles
4
+
5
+ def self.last_name
6
+ LAST_NAMES.random
7
+ end
8
+
9
+ def self.first_name
10
+ [MALE_FIRST_NAMES, FEMALE_FIRST_NAMES].random.random
11
+ end
12
+
13
+ def self.full_name
14
+ "#{self.first_name} #{self.last_name}"
15
+ end
16
+
17
+ def self.male_first_name
18
+ MALE_FIRST_NAMES.random
19
+ end
20
+
21
+ def self.female_first_name
22
+ FEMALE_FIRST_NAMES.random
23
+ end
24
+
25
+ def self.company_name
26
+ COMPANY_NAMES.random
27
+ end
28
+
29
+ def self.title
30
+ NAME_TITLES.random
31
+ end
32
+
33
+ def self.suffix
34
+ NAME_SUFFIXES.random
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ class PersonalForgery < Forgery
2
+ dictionaries :races, :languages, :shirt_sizes, :genders
3
+
4
+ def self.gender
5
+ GENDERS.random
6
+ end
7
+
8
+ def self.abbreviated_gender
9
+ gender[0,1]
10
+ end
11
+
12
+ def self.shirt_size
13
+ SHIRT_SIZES.random
14
+ end
15
+
16
+ def self.race
17
+ RACES.random
18
+ end
19
+
20
+ def self.language
21
+ LANGUAGES.random
22
+ end
23
+ end
data/lib/forgery.rb ADDED
@@ -0,0 +1,82 @@
1
+ # Require forgeries at the bottom of the file so Forgery works as a gem
2
+
3
+ Dir[File.expand_path(File.dirname(__FILE__) + '/extensions/**/*.rb')].uniq.each do |file|
4
+ require file
5
+ end
6
+
7
+ class Forgery
8
+ def self.dictionaries(*dictionaries)
9
+ dictionaries.each do |dictionary|
10
+ const_set(dictionary.to_s.upcase, read_dictionary(dictionary))
11
+ end
12
+ end
13
+
14
+ def self.formats(*formats)
15
+ formats.each do |format|
16
+ const_set(format.to_s.upcase + "_FORMATS", read_format(format))
17
+ end
18
+ end
19
+
20
+ protected
21
+
22
+ def self.read_file(file)
23
+ lines = []
24
+ IO.foreach(file) do |line|
25
+ lines << line.chomp unless line.chomp == ''
26
+ end
27
+ lines
28
+ end
29
+
30
+ def self.read_dictionary(dictionary)
31
+ read_file(path_to_dictionary(dictionary))
32
+ end
33
+
34
+ def self.read_format(format)
35
+ read_file(path_to_format(format))
36
+ end
37
+
38
+ def self.path_to_format(format)
39
+ if external_path_to_format(format) && File.exists?(external_path_to_format(format))
40
+ external_path_to_format(format)
41
+ else
42
+ internal_path_to_format(format)
43
+ end
44
+ end
45
+
46
+ def self.external_path_to_format(format)
47
+ RAILS_ROOT + '/lib/forgery/formats/' + format.to_s if defined?(RAILS_ROOT)
48
+ end
49
+
50
+ def self.internal_path_to_format(format)
51
+ File.dirname(__FILE__) + '/formats/' + format.to_s
52
+ end
53
+
54
+ def self.path_to_dictionary(dictionary)
55
+ if external_path_to_dictionary(dictionary) && File.exists?(external_path_to_dictionary(dictionary))
56
+ external_path_to_dictionary(dictionary)
57
+ else
58
+ internal_path_to_dictionary(dictionary)
59
+ end
60
+ end
61
+
62
+ def self.external_path_to_dictionary(dictionary)
63
+ RAILS_ROOT + '/lib/forgery/dictionaries/' + dictionary.to_s if defined?(RAILS_ROOT)
64
+ end
65
+
66
+ def self.internal_path_to_dictionary(dictionary)
67
+ File.dirname(__FILE__) + '/dictionaries/' + dictionary.to_s
68
+ end
69
+ end
70
+
71
+ def Forgery(forgery, method=nil, *args)
72
+ klass = "#{forgery.to_s.camelize}Forgery".constantize
73
+ if method
74
+ klass.send(method, *args)
75
+ else
76
+ klass
77
+ end
78
+ end
79
+
80
+ Dir[File.expand_path(File.dirname(__FILE__) + '/forgeries/**/*.rb')].uniq.each do |file|
81
+ require file
82
+ end
data/lib/formats/phone ADDED
@@ -0,0 +1 @@
1
+ #-(###)###-####
@@ -0,0 +1,5 @@
1
+ #
2
+ ##
3
+ ###
4
+ ####
5
+ #####
data/lib/formats/zip ADDED
@@ -0,0 +1,2 @@
1
+ #####
2
+ #####-####
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Array do
4
+ before do
5
+ @array = [0,1,2,3,4,5,6,7,8,9]
6
+ end
7
+
8
+ it "should get a random item out of the array" do
9
+ 10.times { @array.should include(@array.random) }
10
+ end
11
+
12
+ it "should return nil if the array is empty" do
13
+ [].random.should be_nil
14
+ end
15
+
16
+ it "should return a random subset of the array" do
17
+ @array.random_subset(5).each do |i|
18
+ @array.should include(i)
19
+ end
20
+ end
21
+
22
+ it "should return a random subset of the array that is 3 long" do
23
+ @array.random_subset(3).size.should == 3
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Range do
4
+ it "should get a random number out of the range" do
5
+ range = (0..9)
6
+ 10.times { range.should include(range.random) }
7
+ end
8
+
9
+ it "should get a random string our of the range" do
10
+ range = ("a".."z")
11
+ 10.times { range.should include(range.random) }
12
+ end
13
+
14
+ it "should return nil if the maximum is less than the minimum" do
15
+ ("z".."a").random.should be_nil
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe String do
4
+ it "should change a single # to a number 0-9" do
5
+ (0..9).should include(Integer("#".to_numbers))
6
+ end
7
+
8
+ it "should change two #'s to two numbers 0-9" do
9
+ "##".to_numbers.split("").each do |s|
10
+ (0..9).should include(Integer(s))
11
+ end
12
+ end
13
+
14
+ it "should only replace #'s in the string with numbers 0-9" do
15
+ s = '###-###-####'
16
+ n = s.to_numbers
17
+ 0.upto(s.size - 1) do |i|
18
+ if s[i, 1] == "#"
19
+ ('0'..'9').should include(n[i, 1])
20
+ else
21
+ ('0'..'9').should_not include(n[i, 1])
22
+ end
23
+ end
24
+ end
25
+
26
+ it "should allow the replacing of a different character" do
27
+ (0..9).should include(Integer("-".to_numbers("-")))
28
+ end
29
+ end
@@ -0,0 +1,69 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe AddressForgery do
4
+ it "should return a random street" do
5
+ AddressForgery::STREETS.should include(AddressForgery.street_name)
6
+ end
7
+
8
+ it "should return a random street number" do
9
+ original_format = AddressForgery.street_number.gsub(/\d/, '#')
10
+ AddressForgery::STREET_NUMBER_FORMATS.should include(original_format)
11
+ end
12
+
13
+ it "should return a random street suffix" do
14
+ AddressForgery::STREET_SUFFIXES.should include(AddressForgery.street_suffix)
15
+ end
16
+
17
+ describe ".street_address" do
18
+ before do
19
+ @split_address = AddressForgery.street_address.split
20
+ end
21
+
22
+ it "should return a random street suffix" do
23
+ street_suffix = @split_address.pop
24
+ AddressForgery::STREET_SUFFIXES.should include(street_suffix)
25
+ end
26
+
27
+ it "should return a random street number" do
28
+ street_number_format = @split_address.shift.gsub(/\d/, '#')
29
+ AddressForgery::STREET_NUMBER_FORMATS.should include(street_number_format)
30
+ end
31
+
32
+ it "should return a random street" do
33
+ @split_address.pop
34
+ @split_address.shift
35
+ street = @split_address.join(" ")
36
+ AddressForgery::STREETS.should include(street)
37
+ end
38
+ end
39
+
40
+ it "should return a random city" do
41
+ city = AddressForgery.city
42
+ AddressForgery::CITIES.should include(city)
43
+ end
44
+
45
+ it "should return a random state" do
46
+ state = AddressForgery.state
47
+ AddressForgery::STATES.should include(state)
48
+ end
49
+
50
+ it "should return a random state abbreviation" do
51
+ state_abbrev = AddressForgery.state_abbrev
52
+ AddressForgery::STATE_ABBREVS.should include(state_abbrev)
53
+ end
54
+
55
+ it "should return a random country" do
56
+ country = AddressForgery.country
57
+ AddressForgery::COUNTRIES.should include(country)
58
+ end
59
+
60
+ it "should return a random zip code" do
61
+ zip_format = AddressForgery.zip.gsub(/\d/, '#')
62
+ AddressForgery::ZIP_FORMATS.should include(zip_format)
63
+ end
64
+
65
+ it "should return a random phone number" do
66
+ phone_format = AddressForgery.phone.gsub(/\d/, '#')
67
+ AddressForgery::PHONE_FORMATS.should include(phone_format)
68
+ end
69
+ end