pseudo_entity 0.0.1

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.
@@ -0,0 +1,3 @@
1
+ class PseudoEntity
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,138 @@
1
+ class PseudoEntity
2
+
3
+ require 'pseudo_entity/randoms'
4
+
5
+ include Enumerable
6
+ include Randoms
7
+
8
+ def initialize(options={})
9
+ parse_options options
10
+ end
11
+
12
+ def address
13
+ "#{street_address}\n#{city}, #{state}. #{zip_code}"
14
+ end
15
+
16
+ def age
17
+ Date.today.year - birth_day.year
18
+ end
19
+
20
+ def apartment?
21
+ street_modifier_needed == :apartment
22
+ end
23
+
24
+ def birth_year
25
+ birth_day.year
26
+ end
27
+
28
+ def credit_card_last_four
29
+ credit_card_number[-4..-1]
30
+ end
31
+ alias :credit_card_last4 :credit_card_last_four
32
+
33
+ def full_name
34
+ "#{first_name} #{last_name}"
35
+ end
36
+
37
+ def google_map_url
38
+ "https://maps.google.com/maps?q=loc:#{latitude},#{longitude}"
39
+ end
40
+
41
+ # Reset all internal values causing them to be regenerated.
42
+ def reset!
43
+ self.instance_variables.each { |variable| instance_variable_set(variable, nil) }
44
+ self
45
+ end
46
+
47
+ def street_address
48
+ # Yes it is in 2-1 order because that's how the US Post Office says to do it.
49
+ # Apartment, Suites, etc go on the first line if there are two lines or at the end of the single line
50
+ # http://pe.usps.com/businessmail101/addressing/deliveryaddress.htm
51
+ "#{street_address_line_2} #{street_address_line_1}".strip
52
+ end
53
+
54
+ def street_address_line_1
55
+ if apartment?
56
+ "APT #{apartment_number}"
57
+ elsif suite?
58
+ "STE #{suite_number}"
59
+ else
60
+ street_position
61
+ end
62
+ end
63
+
64
+ def street_address_line_2
65
+ street_address_line_1 # Force the determination of line 1 as this effects line 2
66
+ street_modifier_needed? ? street_position : nil
67
+ end
68
+
69
+ def suite?
70
+ street_modifier_needed == :suite
71
+ end
72
+
73
+ def yelp_business_id
74
+ # Yelp API version 2.0 id
75
+ "#{company_name.gsub(' ', '-').delete('.')}-#{city.gsub(' ', '-').delete('.')}"
76
+ end
77
+
78
+ def yelp_business_url
79
+ "http://www.yelp.com/biz/#{yelp_business_id}"
80
+ end
81
+
82
+ def yelp_user_id
83
+ random_alpha_numeric(22)
84
+ end
85
+
86
+ def to_s
87
+ add = address.sub("\n","\n ")
88
+ [
89
+ "Name: #{full_name}",
90
+ "Age: #{age}",
91
+ "Sex: #{sex}",
92
+ "Email: #{email_address}",
93
+ "IP Address: #{ip_address}",
94
+ "Website: #{website}",
95
+ "Short Url: #{short_url}",
96
+ "Phone: #{phone_number}",
97
+ "Address: #{add}",
98
+ "Coordinates: #{latitude}, #{longitude}",
99
+ "Timezone: #{time_zone}",
100
+ "Bank: #{bank_name} #{bank_routing_number} #{bank_account_number}",
101
+ "Credit Union: #{credit_union_name}",
102
+ "Card: #{credit_card_issuer} #{credit_card_number}",
103
+ "Company: #{company_name}",
104
+ "Slogan: #{slogan}",
105
+ "Tax ID: #{federal_tax_id}",
106
+ "Login: #{login}",
107
+ "Password: #{password}"
108
+ ].join("\n")
109
+ end
110
+
111
+ def self.all
112
+ @all = Randoms.names.map { |name| new :first_name => name.first, :last_name => name.last }
113
+ end
114
+
115
+ def self.each(&block)
116
+ all.each(&block)
117
+ end
118
+
119
+ def self.to_a
120
+ all
121
+ end
122
+
123
+ def self.load_caches(verbose=false)
124
+ entity = new
125
+ RandomValues.each do |method|
126
+ puts method if verbose
127
+ begin
128
+ entity.send(method)
129
+ rescue => e
130
+ puts e.message
131
+ end
132
+ end
133
+ true
134
+ end
135
+
136
+ end
137
+
138
+ require 'pseudo_entity/version'
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'pseudo_entity/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'pseudo_entity'
8
+ spec.version = PseudoEntity::VERSION
9
+ spec.authors = ['Frank Hall']
10
+ spec.email = ['ChapterHouse.Dune@gmail.com']
11
+ spec.description = %q{A class for generating realistic looking data for people, companies, etc.}
12
+ spec.summary = %q{A class for generating realistic looking data for people, companies, etc.}
13
+ spec.homepage = 'http://chapterhouse.github.io/pseudo_entity'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.3'
22
+ spec.add_development_dependency 'rake'
23
+ spec.add_development_dependency 'rspec', '~> 2.13'
24
+
25
+ spec.add_runtime_dependency 'uuidtools', '~> 2.1'
26
+ spec.add_runtime_dependency 'active_support', '>= 2.0'
27
+ spec.add_runtime_dependency 'tzinfo'
28
+ spec.add_runtime_dependency 'huge_enumerable'
29
+
30
+ end
@@ -0,0 +1,276 @@
1
+ require 'spec_helper'
2
+
3
+ describe PseudoEntity::Randoms do
4
+
5
+ RSpec::Matchers.define :be_all_digits do
6
+ match do |string|
7
+ string.gsub(/[0-9]*/,'').empty?
8
+ end
9
+ end
10
+
11
+ RSpec::Matchers.define :be_all_alphabetic_characters do
12
+ match do |string|
13
+ string.gsub(/[a-z]|[A-Z]*/,'').empty?
14
+ end
15
+ end
16
+
17
+ RSpec::Matchers.define :be_all_alphanumeric_characters do
18
+ match do |string|
19
+ string.gsub(/[a-z]|[A-Z][0-9]*/,'').empty?
20
+ end
21
+ end
22
+
23
+
24
+ context "when included" do
25
+
26
+ let(:class_a_regex) { /^10\.(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){2}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ }
27
+ let(:class_b_regex) { /^172\.(?:(?:1[6-9]|2[0-9]|3[0-1]?)\.)(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.)(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ }
28
+ let(:class_c_regex) { /^192\.168\.(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.)(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ }
29
+
30
+ subject(:instance) do
31
+ klass = Class.new
32
+ klass.send(:include, PseudoEntity::Randoms)
33
+ klass.new
34
+ end
35
+
36
+ it "responds to all RandomValues" do
37
+ PseudoEntity::RandomValues.all? { |method| instance.respond_to?(method.to_sym) }.should be_true
38
+ end
39
+
40
+ it "lists all RandomValues as methods" do
41
+ (PseudoEntity::RandomValues - instance.methods).should be_empty
42
+ end
43
+
44
+ it "responds to ArityValues" do
45
+ methods = PseudoEntity::ArityValues.map { |regexp| regexp.to_s.match(/.*\^(.*_)\\d.*/)[1] + rand(100).to_s }
46
+ methods.all? { |method| instance.respond_to?(method.to_sym) }.should be_true
47
+ end
48
+
49
+ it "responds to ArityRandoms" do
50
+ methods = PseudoEntity::ArityRandoms.map { |regexp| regexp.to_s.match(/.*\^(.*_)\\d.*/)[1] + rand(100).to_s }
51
+ methods.all? { |method| instance.respond_to?(method.to_sym, true) }.should be_true
52
+ end
53
+
54
+ it "has private ArityRandoms" do
55
+ methods = PseudoEntity::ArityRandoms.map { |regexp| regexp.to_s.match(/.*\^(.*_)\\d.*/)[1] + rand(100).to_s }
56
+ methods.all? { |method| !instance.respond_to?(method.to_sym) }.should be_true
57
+ end
58
+
59
+ it "has corresponding private random_X methods for RandomValues" do
60
+ (PseudoEntity::RandomValues.map { |method| "random_#{method}".to_sym } - instance.private_methods).should be_empty
61
+ end
62
+
63
+ context "#parse_options" do
64
+
65
+ it "sets initial values" do
66
+ value_names = PseudoEntity::RandomValues
67
+ hash = value_names.inject({}) { |hsh, name| hsh[name] = "123 #{name}"; hsh}
68
+ instance.send(:parse_options, hash)
69
+ value_names.all? { |name| instance.send(name) == "123 #{name}" }.should be_true
70
+ end
71
+
72
+ end
73
+
74
+ context "#random_alpha" do
75
+
76
+ it "returns X characters" do
77
+ instance.send(:random_alpha, 256).size.should eql(256)
78
+ end
79
+
80
+ it "only generates alphabetic characters" do
81
+ instance.stub(:rand).and_return(*(0..51).to_a)
82
+ instance.send(:random_alpha, 256).should be_all_alphanumeric_characters
83
+ # If only alphabetic characters are available then nothing should show up at slot 52
84
+ instance.stub(:rand).and_return(52)
85
+ instance.send(:random_alpha, 1).size.should eq(0)
86
+ end
87
+
88
+ end
89
+
90
+ context "#random_alpha_numeric" do
91
+
92
+ it "returns X characters" do
93
+ instance.send(:random_alpha_numeric, 256).size.should eql(256)
94
+ end
95
+
96
+ it "only generates alphabetic characters or digits" do
97
+ instance.stub(:rand).and_return(*(0..61).to_a)
98
+ instance.send(:random_alpha, 256).should be_all_alphabetic_characters
99
+ # If only alphabetic characters and digits are available then nothing should show up at slot 62
100
+ instance.stub(:rand).and_return(62)
101
+ instance.send(:random_alpha_numeric, 1).size.should eq(0)
102
+ end
103
+
104
+ end
105
+
106
+ context "#random_apartment_number" do
107
+
108
+ it "never returns zero or less" do
109
+ instance.stub(:rand).and_return(0)
110
+ instance.send(:random_apartment_number).should > 0
111
+ end
112
+
113
+ end
114
+
115
+ context "#random_bank_account_number" do
116
+
117
+ it "is thirteen characters long" do
118
+ instance.send(:random_bank_account_number).size.should eql(13)
119
+ end
120
+
121
+ it "is all digits" do
122
+ instance.send(:random_bank_account_number).should be_all_digits
123
+ end
124
+
125
+ end
126
+
127
+ context "#random_bank_routing_number" do
128
+
129
+ it "is nine characters long" do
130
+ instance.send(:random_bank_routing_number).size.should eql(9)
131
+ end
132
+
133
+ it "is all digits" do
134
+ instance.send(:random_bank_routing_number).should be_all_digits
135
+ end
136
+
137
+ end
138
+
139
+ context "#random_numeric" do
140
+
141
+ it "return X characters" do
142
+ instance.send(:random_alpha_numeric, 256).size.should eql(256)
143
+ end
144
+
145
+ it "only generates digits" do
146
+ instance.send(:random_numeric, 256).should be_all_digits
147
+ end
148
+
149
+ end
150
+
151
+ context "#random_birth_day" do
152
+
153
+ it "is always be at least 21 years ago" do
154
+ instance.stub(:rand).and_return(0)
155
+ (Date.today.year - instance.send(:random_birth_day).year).should >= 21
156
+ end
157
+
158
+ end
159
+
160
+ context "#random_class_a_ip_address" do
161
+
162
+ it "is in the private class A range" do
163
+ instance.send(:random_class_a_ip_address).should =~ class_a_regex
164
+ end
165
+
166
+ end
167
+
168
+ context "#random_class_b_ip_address" do
169
+
170
+ it "is in the private class B range" do
171
+ instance.send(:random_class_b_ip_address).should =~ class_b_regex
172
+ end
173
+
174
+ end
175
+
176
+ context "#random_class_c_ip_address" do
177
+
178
+ it "is in the private class C range" do
179
+ instance.send(:random_class_c_ip_address).should =~ class_c_regex
180
+ end
181
+
182
+ end
183
+
184
+ context "#random_email_address" do
185
+
186
+ it "conforms to the pattern name@domain" do
187
+ simple_email_regex = /^.*@.*\..*$/
188
+ instance.send(:random_email_address) =~ simple_email_regex
189
+ end
190
+
191
+ end
192
+
193
+ context "#random_facebook_id" do
194
+
195
+ it "is all digits" do
196
+ instance.send(:random_facebook_id).should be_all_digits
197
+ end
198
+
199
+ it "is a maximum of 64 bits long" do
200
+ # This is a little brittle but not sure how else to test this
201
+ instance.should_receive(:rand).with(2**64).and_return(2**64)
202
+ instance.send(:random_facebook_id)
203
+ end
204
+
205
+ end
206
+
207
+ context "#random_federal_tax_id" do
208
+
209
+ it "is nine characters long" do
210
+ instance.send(:random_federal_tax_id).size.should eql(9)
211
+ end
212
+
213
+ it "is all digits" do
214
+ instance.send(:random_federal_tax_id).should be_all_digits
215
+ end
216
+
217
+ end
218
+
219
+ context "#random_google_analytics_account_id" do
220
+ it "conforms to Google's Analytic Account pattern" do
221
+ instance.send(:random_google_analytics_account_id).should =~ /^UA-\d{7}-\d{2}$/
222
+ end
223
+ end
224
+
225
+ context "#random_ip_address" do
226
+
227
+ it "is one of the non routable IP addresses" do
228
+ ip_address = instance.send(:random_ip_address)
229
+ [class_a_regex, class_b_regex, class_c_regex].any? { |regexp| ip_address =~ regexp }.should be_true
230
+ end
231
+
232
+ end
233
+
234
+ context "#random_phone_number" do
235
+
236
+ it "is a ten digit comma separated value" do
237
+ instance.send(:random_phone_number).should =~ /^[0-9]{3}-[0-9]{3}-[0-9]{4}$/
238
+ end
239
+
240
+ end
241
+
242
+ context "#random_property_number" do
243
+
244
+ it "will never be less than 10" do
245
+ instance.stub(:rand).and_return(0)
246
+ instance.send(:random_property_number).should >= 10
247
+ end
248
+
249
+ end
250
+
251
+ context "#random_sex" do
252
+
253
+ it "will never be less than 10" do
254
+ instance.stub(:rand).and_return(0)
255
+ instance.send(:random_property_number).should >= 10
256
+ end
257
+
258
+ end
259
+
260
+ end
261
+
262
+ context "as itself" do
263
+
264
+ subject(:random) { PseudoEntity::Randoms }
265
+
266
+ it "should create a token smaller than 32 characters" do
267
+ random.token(3).size.should eq(3)
268
+ end
269
+
270
+ it "should create a token larger than 32 characters" do
271
+ random.token(128).size.should eq(128)
272
+ end
273
+
274
+ end
275
+
276
+ end
@@ -0,0 +1,157 @@
1
+ require 'spec_helper'
2
+
3
+ describe PseudoEntity do
4
+
5
+ let(:age) { 10 }
6
+ let(:date) { age.years.ago }
7
+ let(:cc_last_four) { '4321' }
8
+ let(:latitude) { 1.2 }
9
+ let(:longitude) { 3.4 }
10
+ let(:street_position) { 'street_position' }
11
+ let(:company_name) { 'Some Company Ltd.'}
12
+ let(:city) { 'St. Archibald' }
13
+ let(:state) { 'ZZ' }
14
+ let(:zip_code) { 12345 }
15
+ let(:first_name) { 'John' }
16
+ let(:last_name) { 'Smith' }
17
+
18
+ subject(:pseudo_entity) do
19
+ PseudoEntity.new.tap{ |pe|
20
+ pe.stub(:birth_day).and_return(date)
21
+ pe.stub(:city).and_return(city)
22
+ pe.stub(:state).and_return(state)
23
+ pe.stub(:zip_code).and_return(zip_code)
24
+ pe.stub(:credit_card_number).and_return('98765' + cc_last_four)
25
+ pe.stub(:first_name).and_return(first_name)
26
+ pe.stub(:last_name).and_return(last_name)
27
+ pe.stub(:latitude).and_return(latitude)
28
+ pe.stub(:longitude).and_return(longitude)
29
+ pe.stub(:street_position).and_return(street_position)
30
+ pe.stub(:company_name).and_return(company_name)
31
+ pe.stub(:city).and_return(city)
32
+ }
33
+ end
34
+
35
+ it "should calculate age" do
36
+ pseudo_entity.age.should eql(age)
37
+ end
38
+
39
+ it "should combine components into a full address" do
40
+ pseudo_entity.stub(:street_address).and_return('street_address')
41
+ pseudo_entity.address.should eql("street_address\n#{city}, #{state}. #{zip_code}")
42
+ end
43
+
44
+ it "should identify when an address is and is not an apartment" do
45
+ pseudo_entity.stub(:street_modifier_needed).and_return(:apartment)
46
+ pseudo_entity.apartment?.should be_true
47
+ pseudo_entity.stub(:street_modifier_needed).and_return(:something_else)
48
+ pseudo_entity.apartment?.should be_false
49
+ end
50
+
51
+ it "should extract birth year" do
52
+ pseudo_entity.birth_year.should eql(date.year)
53
+ end
54
+
55
+ it "should extract the last four digits of the credit card number" do
56
+ pseudo_entity.credit_card_last_four.should eql(cc_last_four)
57
+ end
58
+
59
+ it "should combine names into a full name" do
60
+ pseudo_entity.full_name.should eql("#{first_name} #{last_name}")
61
+ end
62
+
63
+ it "should generate a google map url from latitude and longitude" do
64
+ pseudo_entity.google_map_url.should eql("https://maps.google.com/maps?q=loc:#{latitude},#{longitude}")
65
+ end
66
+
67
+ it "should not return new values without resetting" do
68
+ names = [ 'Jack', 'Jill' ]
69
+ pseudo_entity = PseudoEntity.new
70
+ pseudo_entity.stub(:random_first_name).and_return(names.shift)
71
+ pseudo_entity.first_name.should equal(pseudo_entity.first_name)
72
+ end
73
+
74
+ it "should return new values after a reset" do
75
+ names = [ 'Jack', 'Jill' ]
76
+ pseudo_entity = PseudoEntity.new
77
+ pseudo_entity.stub(:random_first_name).and_return(names.shift)
78
+ name = pseudo_entity.first_name
79
+ pseudo_entity.reset!
80
+ pseudo_entity.stub(:random_first_name).and_return(names.shift)
81
+ pseudo_entity.first_name.should_not eql(name)
82
+ end
83
+
84
+ it "should return self after a reset" do
85
+ pseudo_entity.reset!.should equal(pseudo_entity)
86
+ end
87
+
88
+ it "should combine addresses in 2,1 order" do
89
+ pseudo_entity.stub(:street_address_line_1).and_return(:street_address_line_1)
90
+ pseudo_entity.stub(:street_address_line_2).and_return(:street_address_line_2)
91
+ pseudo_entity.street_address.should eql('street_address_line_2 street_address_line_1')
92
+ end
93
+
94
+ it "should trim missing street information" do
95
+ pseudo_entity.stub(:street_address_line_1).and_return(:street_address_line_1)
96
+ pseudo_entity.stub(:street_address_line_2).and_return('')
97
+ pseudo_entity.street_address.should == 'street_address_line_1'
98
+ pseudo_entity.stub(:street_address_line_1).and_return('')
99
+ pseudo_entity.stub(:street_address_line_2).and_return(:street_address_line_2)
100
+ pseudo_entity.street_address.should eql('street_address_line_2')
101
+ end
102
+
103
+ it "should apartment number as street address line 1 when the address is at an apartment" do
104
+ apartment_number = 1234
105
+ pseudo_entity.stub(:apartment_number).and_return(apartment_number)
106
+ pseudo_entity.stub(:apartment?).and_return(true)
107
+ pseudo_entity.stub(:suite?).and_return(false)
108
+ pseudo_entity.street_address_line_1.should eql("APT #{apartment_number}")
109
+ end
110
+
111
+ it "should suite number as street address line 1 when the address is at a suite" do
112
+ suite_number = 1234
113
+ pseudo_entity.stub(:suite_number).and_return(suite_number)
114
+ pseudo_entity.stub(:apartment?).and_return(false)
115
+ pseudo_entity.stub(:suite?).and_return(true)
116
+ pseudo_entity.street_address_line_1.should eql("STE #{suite_number}")
117
+ end
118
+
119
+ it "should use the street position as street address line 1 when not at an apartment or suite" do
120
+ pseudo_entity.stub(:apartment?).and_return(false)
121
+ pseudo_entity.stub(:suite?).and_return(false)
122
+ pseudo_entity.street_address_line_1.should eql(street_position)
123
+ end
124
+
125
+ it "should use street position as street address line 2 when a street modifier is needed" do
126
+ pseudo_entity.stub(:street_modifier_needed?).and_return(true)
127
+ pseudo_entity.street_address_line_2.should eql(street_position)
128
+ end
129
+
130
+ it "should return nil as street address line 2 when a street modifier is not needed" do
131
+ pseudo_entity.stub(:street_modifier_needed?).and_return(false)
132
+ pseudo_entity.street_address_line_2.should be_nil
133
+ end
134
+
135
+ it "should identify when an address is and is not an suite" do
136
+ pseudo_entity.stub(:street_modifier_needed).and_return(:suite)
137
+ pseudo_entity.suite?.should be_true
138
+ pseudo_entity.stub(:street_modifier_needed).and_return(:something_else)
139
+ pseudo_entity.suite?.should be_false
140
+ end
141
+
142
+ it "should generate a yelp business id from the company name and the city" do
143
+ pseudo_entity.yelp_business_id.should == 'Some-Company-Ltd-St-Archibald'
144
+ end
145
+
146
+ it "should generate a yelp business url from the yelp business id" do
147
+ pseudo_entity.stub(:yelp_business_id).and_return(:yelp_business_id)
148
+ pseudo_entity.yelp_business_url.should == 'http://www.yelp.com/biz/yelp_business_id'
149
+ end
150
+
151
+ it "should generate a string 22 characters long for yelp user id" do
152
+ yelp_user_id = pseudo_entity.yelp_user_id
153
+ yelp_user_id.should be_an_instance_of(String)
154
+ yelp_user_id.size.should eql(22)
155
+ end
156
+
157
+ end
@@ -0,0 +1 @@
1
+ require 'pseudo_entity'