faker 0.9.5 → 1.0.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.
@@ -1,3 +1,30 @@
1
+ == 1.0.0 2011-09-05
2
+ * 2 major enhancements
3
+ * Moved all formats to locale files
4
+ * Stopped interfering with I18n's global settings for fallbacks
5
+ * 3 minor bug fixes:
6
+ * Ruby 1.9.2 fixes [eMxyzptlk]
7
+ * UTF8 fixes [maxmiliano]
8
+ * Updated IPv4 generator to return valid addresses [Sylvain Desbureaux]
9
+ * Many minor enhancements:
10
+ * Added bork locale for bork-ified lorem [johnbentcope]
11
+ * Added IPv6 address generator [jc00ke]
12
+ * Removed deprecation warnings for Array#rand [chrismarshall]
13
+ * Added German translation and I18n improvments [Matthias Kühnert]
14
+ * Added Dutch translation [moretea]
15
+ * Added Lat/Long generator [Andy Callaghan]
16
+ * Added buzzword-laden title generator [supercleanse]
17
+ * Added optional extended wordlist for lorem [chriskottom]
18
+ * Updated German translation [Jan Schwenzien]
19
+ * Locale improvements [suweller]
20
+ * Added limit to lorem generator [darrenterhune]
21
+ * Added Brazilian Portuguese translation [maxmiliano]
22
+ * Added Australian translation [madeindata]
23
+ * Added Canadian translation [igbanam]
24
+ * Added Norwegian translation [kytrinyx]
25
+ * Lots of translation-related cleanup [kytrinyx]
26
+
27
+
1
28
  == 0.9.5 2011-01-27
2
29
  * 1 minor bug fix:
3
30
  * Fixed YAML [Aaron Patterson]
data/README.md CHANGED
@@ -13,19 +13,6 @@ Usage
13
13
  * Faker::Name.name => "Christophe Bartell"
14
14
  * Faker::Internet.email => "kirsten.greenholt@corkeryfisher.info"
15
15
 
16
- Usage with Rails
17
- ----------------
18
-
19
- If you want to change your locale with Rails from the default of :en, change
20
- config/application.rb, setting config.i18n.locale to whatever locale you
21
- want. Change locale rather than default_locale (as suggested by the comments
22
- in that file) so that I18n's fallbacks will work properly and Faker can use
23
- the formats and data in en.yml (if there is no Faker localization for your
24
- locale). If you'd prefer to set default_locale rather than locale, then
25
- you'll also need to add config.i18n.fallbacks.defaults = [:en] to your
26
- configuration to make the fallbacks work for Faker.
27
-
28
-
29
16
  Customization
30
17
  ------------
31
18
  Since you may want to make addresses and other types of data look different
@@ -1,5 +1,7 @@
1
1
  class Array
2
- def rand
3
- self[Kernel.rand(length)]
2
+ unless self.method_defined? :sample
3
+ def sample
4
+ choice
5
+ end
4
6
  end
5
- end
7
+ end
@@ -1,4 +1,4 @@
1
- mydir = File.dirname(__FILE__)
1
+ mydir = File.expand_path(File.dirname(__FILE__))
2
2
 
3
3
  begin
4
4
  require 'psych'
@@ -6,36 +6,82 @@ rescue LoadError
6
6
  end
7
7
 
8
8
  require 'i18n'
9
- I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
10
9
  I18n.load_path += Dir[File.join(mydir, 'locales', '*.yml')]
10
+ I18n.reload!
11
11
 
12
12
 
13
13
  module Faker
14
14
  class Config
15
- def self.locale=(locale)
16
- I18n.locale = locale
15
+ @locale = nil
16
+
17
+ class << self
18
+ attr_writer :locale
19
+ def locale
20
+ @locale || I18n.locale
21
+ end
17
22
  end
18
23
  end
19
24
 
20
25
  class Base
21
26
  class << self
27
+ ## make sure numerify results doesn’t start with a zero
22
28
  def numerify(number_string)
23
- number_string.gsub(/#/) { rand(10).to_s }
29
+ number_string.sub(/#/) { (rand(9)+1).to_s }.gsub(/#/) { rand(10).to_s }
24
30
  end
25
31
 
26
32
  def letterify(letter_string)
27
- letter_string.gsub(/\?/) { ('a'..'z').to_a.rand }
33
+ letter_string.gsub(/\?/) { ('A'..'Z').to_a.sample }
28
34
  end
29
35
 
30
36
  def bothify(string)
31
37
  letterify(numerify(string))
32
38
  end
33
39
 
34
- # Helper for the common approach of grabbing a translation with an array
35
- # of values and selecting one of them
40
+ # Helper for the common approach of grabbing a translation
41
+ # with an array of values and selecting one of them.
36
42
  def fetch(key)
37
- I18n.translate("faker.#{key}").rand
43
+ translate("faker.#{key}").sample
44
+ end
45
+
46
+ # Load formatted strings from the locale, "parsing" them
47
+ # into method calls that can be used to generate a
48
+ # formatted translation: e.g., "#{first_name} #{last_name}".
49
+ def parse(key)
50
+ fetch(key).scan(/#\{([A-Za-z]+\.)?([^\}]+)\}([^#]+)?/).map {|kls, meth, etc| (kls ? Faker.const_get(kls.chop) : self).send(meth) + etc.to_s }.join
51
+ end
52
+
53
+ # Call I18n.translate with our configured locale if no
54
+ # locale is specified
55
+ def translate(*args)
56
+ opts = args.last.is_a?(Hash) ? args.pop : {}
57
+ opts[:locale] ||= Faker::Config.locale
58
+ opts[:throw] = true
59
+ I18n.translate(*(args.push(opts)))
60
+ rescue
61
+ # Super-simple fallback -- fallback to en if the
62
+ # translation was missing. If the translation isn't
63
+ # in en either, then it will raise again.
64
+ I18n.translate(*(args.push(opts.merge(:locale => :en))))
65
+ end
66
+
67
+ def flexible(key)
68
+ @flexible_key = key
38
69
  end
70
+
71
+ # You can add whatever you want to the locale file, and it will get caught here.
72
+ # E.g., in your locale file, create a
73
+ # name:
74
+ # girls_name: ["Alice", "Cheryl", "Tatiana"]
75
+ # Then you can call Faker::Name.girls_name and it will act like #first_name
76
+ def method_missing(m, *args, &block)
77
+ # Use the alternate form of translate to get a nil rather than a "missing translation" string
78
+ if translation = translate(:faker)[@flexible_key][m]
79
+ translation.respond_to?(:sample) ? translation.sample : translation
80
+ else
81
+ super
82
+ end
83
+ end
84
+
39
85
  end
40
86
  end
41
87
  end
@@ -1,24 +1,18 @@
1
1
  module Faker
2
2
  class Address < Base
3
+ flexible :address
4
+
3
5
  class << self
4
6
  def city
5
- [
6
- '%s %s%s' % [city_prefix, Name.first_name, city_suffix],
7
- '%s %s' % [city_prefix, Name.first_name],
8
- '%s%s' % [Name.first_name, city_suffix],
9
- '%s%s' % [Name.last_name, city_suffix],
10
- ].rand
7
+ parse('address.city')
11
8
  end
12
9
 
13
10
  def street_name
14
- [
15
- Proc.new { [Name.last_name, street_suffix].join(' ') },
16
- Proc.new { [Name.first_name, street_suffix].join(' ') }
17
- ].rand.call
11
+ parse('address.street_name')
18
12
  end
19
13
 
20
14
  def street_address(include_secondary = false)
21
- numerify("#{fetch('address.street_address')} #{street_name}#{' ' + secondary_address if include_secondary}")
15
+ numerify(parse('address.street_address') + (include_secondary ? ' ' + secondary_address : ''))
22
16
  end
23
17
 
24
18
  def secondary_address
@@ -26,7 +20,7 @@ module Faker
26
20
  end
27
21
 
28
22
  def zip_code
29
- bothify(fetch('address.postcode')).upcase
23
+ bothify(fetch('address.postcode'))
30
24
  end
31
25
  alias_method :zip, :zip_code
32
26
  alias_method :postcode, :zip_code
@@ -38,18 +32,14 @@ module Faker
38
32
  def state; fetch('address.state'); end
39
33
  def country; fetch('address.country'); end
40
34
 
41
- # You can add whatever you want to the locale file, and it will get
42
- # caught here... e.g., create a country_code array in your locale,
43
- # then you can call #country_code and it will act like #country
44
- def method_missing(m, *args, &block)
45
- # Use the alternate form of translate to get a nil rather than a "missing translation" string
46
- if translation = I18n.translate(:faker)[:address][m]
47
- translation.respond_to?(:rand) ? translation.rand : translation
48
- else
49
- super
50
- end
35
+ def latitude
36
+ ((rand * 180) - 90).to_s
51
37
  end
52
-
38
+
39
+ def longitude
40
+ ((rand * 360) - 180).to_s
41
+ end
42
+
53
43
  # Deprecated
54
44
  alias_method :earth_country, :country
55
45
  alias_method :us_state, :state
@@ -59,4 +49,4 @@ module Faker
59
49
 
60
50
  end
61
51
  end
62
- end
52
+ end
@@ -1,8 +1,10 @@
1
1
  module Faker
2
2
  class Company < Base
3
+ flexible :company
4
+
3
5
  class << self
4
6
  def name
5
- Formats.rand.call
7
+ parse('company.name')
6
8
  end
7
9
 
8
10
  def suffix
@@ -10,30 +12,15 @@ module Faker
10
12
  end
11
13
 
12
14
  # Generate a buzzword-laden catch phrase.
13
- # Wordlist from http://www.1728.com/buzzword.htm
14
15
  def catch_phrase
15
- [
16
- ["Adaptive", "Advanced", "Ameliorated", "Assimilated", "Automated", "Balanced", "Business-focused", "Centralized", "Cloned", "Compatible", "Configurable", "Cross-group", "Cross-platform", "Customer-focused", "Customizable", "Decentralized", "De-engineered", "Devolved", "Digitized", "Distributed", "Diverse", "Down-sized", "Enhanced", "Enterprise-wide", "Ergonomic", "Exclusive", "Expanded", "Extended", "Face to face", "Focused", "Front-line", "Fully-configurable", "Function-based", "Fundamental", "Future-proofed", "Grass-roots", "Horizontal", "Implemented", "Innovative", "Integrated", "Intuitive", "Inverse", "Managed", "Mandatory", "Monitored", "Multi-channelled", "Multi-lateral", "Multi-layered", "Multi-tiered", "Networked", "Object-based", "Open-architected", "Open-source", "Operative", "Optimized", "Optional", "Organic", "Organized", "Persevering", "Persistent", "Phased", "Polarised", "Pre-emptive", "Proactive", "Profit-focused", "Profound", "Programmable", "Progressive", "Public-key", "Quality-focused", "Reactive", "Realigned", "Re-contextualized", "Re-engineered", "Reduced", "Reverse-engineered", "Right-sized", "Robust", "Seamless", "Secured", "Self-enabling", "Sharable", "Stand-alone", "Streamlined", "Switchable", "Synchronised", "Synergistic", "Synergized", "Team-oriented", "Total", "Triple-buffered", "Universal", "Up-sized", "Upgradable", "User-centric", "User-friendly", "Versatile", "Virtual", "Visionary", "Vision-oriented"].rand,
17
- ["24 hour", "24/7", "3rd generation", "4th generation", "5th generation", "6th generation", "actuating", "analyzing", "assymetric", "asynchronous", "attitude-oriented", "background", "bandwidth-monitored", "bi-directional", "bifurcated", "bottom-line", "clear-thinking", "client-driven", "client-server", "coherent", "cohesive", "composite", "context-sensitive", "contextually-based", "content-based", "dedicated", "demand-driven", "didactic", "directional", "discrete", "disintermediate", "dynamic", "eco-centric", "empowering", "encompassing", "even-keeled", "executive", "explicit", "exuding", "fault-tolerant", "foreground", "fresh-thinking", "full-range", "global", "grid-enabled", "heuristic", "high-level", "holistic", "homogeneous", "human-resource", "hybrid", "impactful", "incremental", "intangible", "interactive", "intermediate", "leading edge", "local", "logistical", "maximized", "methodical", "mission-critical", "mobile", "modular", "motivating", "multimedia", "multi-state", "multi-tasking", "national", "needs-based", "neutral", "next generation", "non-volatile", "object-oriented", "optimal", "optimizing", "radical", "real-time", "reciprocal", "regional", "responsive", "scalable", "secondary", "solution-oriented", "stable", "static", "systematic", "systemic", "system-worthy", "tangible", "tertiary", "transitional", "uniform", "upward-trending", "user-facing", "value-added", "web-enabled", "well-modulated", "zero administration", "zero defect", "zero tolerance"].rand,
18
- ["ability", "access", "adapter", "algorithm", "alliance", "analyzer", "application", "approach", "architecture", "archive", "artificial intelligence", "array", "attitude", "benchmark", "budgetary management", "capability", "capacity", "challenge", "circuit", "collaboration", "complexity", "concept", "conglomeration", "contingency", "core", "customer loyalty", "database", "data-warehouse", "definition", "emulation", "encoding", "encryption", "extranet", "firmware", "flexibility", "focus group", "forecast", "frame", "framework", "function", "functionalities", "Graphic Interface", "groupware", "Graphical User Interface", "hardware", "help-desk", "hierarchy", "hub", "implementation", "info-mediaries", "infrastructure", "initiative", "installation", "instruction set", "interface", "internet solution", "intranet", "knowledge user", "knowledge base", "local area network", "leverage", "matrices", "matrix", "methodology", "middleware", "migration", "model", "moderator", "monitoring", "moratorium", "neural-net", "open architecture", "open system", "orchestration", "paradigm", "parallelism", "policy", "portal", "pricing structure", "process improvement", "product", "productivity", "project", "projection", "protocol", "secured line", "service-desk", "software", "solution", "standardization", "strategy", "structure", "success", "superstructure", "support", "synergy", "system engine", "task-force", "throughput", "time-frame", "toolset", "utilisation", "website", "workforce"].rand
19
- ].join(' ')
16
+ translate('faker.company.buzzwords').collect {|list| list.sample }.join(' ')
20
17
  end
21
18
 
22
19
  # When a straight answer won't do, BS to the rescue!
23
- # Wordlist from http://dack.com/web/bullshit.html
24
20
  def bs
25
- [
26
- ["implement", "utilize", "integrate", "streamline", "optimize", "evolve", "transform", "embrace", "enable", "orchestrate", "leverage", "reinvent", "aggregate", "architect", "enhance", "incentivize", "morph", "empower", "envisioneer", "monetize", "harness", "facilitate", "seize", "disintermediate", "synergize", "strategize", "deploy", "brand", "grow", "target", "syndicate", "synthesize", "deliver", "mesh", "incubate", "engage", "maximize", "benchmark", "expedite", "reintermediate", "whiteboard", "visualize", "repurpose", "innovate", "scale", "unleash", "drive", "extend", "engineer", "revolutionize", "generate", "exploit", "transition", "e-enable", "iterate", "cultivate", "matrix", "productize", "redefine", "recontextualize"].rand,
27
- ["clicks-and-mortar", "value-added", "vertical", "proactive", "robust", "revolutionary", "scalable", "leading-edge", "innovative", "intuitive", "strategic", "e-business", "mission-critical", "sticky", "one-to-one", "24/7", "end-to-end", "global", "B2B", "B2C", "granular", "frictionless", "virtual", "viral", "dynamic", "24/365", "best-of-breed", "killer", "magnetic", "bleeding-edge", "web-enabled", "interactive", "dot-com", "sexy", "back-end", "real-time", "efficient", "front-end", "distributed", "seamless", "extensible", "turn-key", "world-class", "open-source", "cross-platform", "cross-media", "synergistic", "bricks-and-clicks", "out-of-the-box", "enterprise", "integrated", "impactful", "wireless", "transparent", "next-generation", "cutting-edge", "user-centric", "visionary", "customized", "ubiquitous", "plug-and-play", "collaborative", "compelling", "holistic", "rich"].rand,
28
- ["synergies", "web-readiness", "paradigms", "markets", "partnerships", "infrastructures", "platforms", "initiatives", "channels", "eyeballs", "communities", "ROI", "solutions", "e-tailers", "e-services", "action-items", "portals", "niches", "technologies", "content", "vortals", "supply-chains", "convergence", "relationships", "architectures", "interfaces", "e-markets", "e-commerce", "systems", "bandwidth", "infomediaries", "models", "mindshare", "deliverables", "users", "schemas", "networks", "applications", "metrics", "e-business", "functionalities", "experiences", "web services", "methodologies"].rand
29
- ].join(' ')
21
+ translate('faker.company.bs').collect {|list| list.sample }.join(' ')
30
22
  end
31
23
  end
32
24
 
33
- Formats = [
34
- Proc.new { [ Name.last_name, suffix ].join(' ') },
35
- Proc.new { [ Name.last_name, Name.last_name ].join('-') },
36
- Proc.new { "%s, %s and %s" % [ Name.last_name, Name.last_name, Name.last_name ] }
37
- ]
38
25
  end
39
- end
26
+ end
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  module Faker
2
3
  class Internet < Base
3
4
  class << self
@@ -10,19 +11,30 @@ module Faker
10
11
  end
11
12
 
12
13
  def user_name(name = nil)
13
- return name.scan(/\w+/).shuffle.join(%w(. _).rand).downcase if name
14
+ return name.scan(/\w+/).shuffle.join(%w(. _).sample).downcase if name
14
15
 
15
- [
16
+ fix_umlauts([
16
17
  Proc.new { Name.first_name.gsub(/\W/, '').downcase },
17
18
  Proc.new {
18
19
  [ Name.first_name, Name.last_name ].map {|n|
19
20
  n.gsub(/\W/, '')
20
- }.join(%w(. _).rand).downcase }
21
- ].rand.call
21
+ }.join(%w(. _).sample).downcase }
22
+ ].sample.call)
22
23
  end
23
24
 
24
25
  def domain_name
25
- [ domain_word, domain_suffix ].join('.')
26
+ [ fix_umlauts(domain_word), domain_suffix ].join('.')
27
+ end
28
+
29
+ def fix_umlauts(string)
30
+ string.gsub(/[äöüß]/i) do |match|
31
+ case match.downcase
32
+ when "ä" 'ae'
33
+ when "ö" 'oe'
34
+ when "ü" 'ue'
35
+ when "ß" 'ss'
36
+ end
37
+ end
26
38
  end
27
39
 
28
40
  def domain_word
@@ -34,11 +46,22 @@ module Faker
34
46
  end
35
47
 
36
48
  def ip_v4_address
37
- [(0..255).to_a.rand,
38
- (0..255).to_a.rand,
39
- (0..255).to_a.rand,
40
- (0..255).to_a.rand].join('.')
49
+ ary = (2..254).to_a
50
+ [ary.sample,
51
+ ary.sample,
52
+ ary.sample,
53
+ ary.sample].join('.')
54
+ end
55
+
56
+ def ip_v6_address
57
+ @@ip_v6_space ||= (0..65535).to_a
58
+ container = (1..8).map{ |_| @@ip_v6_space.sample }
59
+ container.map{ |n| n.to_s(16) }.join(':')
60
+ end
61
+
62
+ def url
63
+ "http://#{domain_name}/#{user_name}"
41
64
  end
42
65
  end
43
66
  end
44
- end
67
+ end
@@ -1,32 +1,39 @@
1
1
  module Faker
2
2
  # Based on Perl's Text::Lorem
3
3
  class Lorem < Base
4
- def self.words(num = 3)
5
- I18n.translate('faker.lorem.words').shuffle[0, num]
4
+ def self.words(num = 3, supplemental = false)
5
+ (
6
+ translate('faker.lorem.words') +
7
+ (supplemental ? translate('faker.lorem.supplemental') : [])
8
+ ).shuffle[0, num]
9
+ end
10
+
11
+ def self.characters(char_count = 255)
12
+ rand(36**char_count).to_s(36)
6
13
  end
7
14
 
8
- def self.sentence(word_count = 4)
9
- words(word_count + rand(6)).join(' ').capitalize + '.'
15
+ def self.sentence(word_count = 4, supplemental = false)
16
+ words(word_count + rand(6), supplemental).join(' ').capitalize + '.'
10
17
  end
11
18
 
12
- def self.sentences(sentence_count = 3)
19
+ def self.sentences(sentence_count = 3, supplemental = false)
13
20
  [].tap do |sentences|
14
21
  1.upto(sentence_count) do
15
- sentences << sentence
22
+ sentences << sentence(3, supplemental)
16
23
  end
17
24
  end
18
25
  end
19
26
 
20
- def self.paragraph(sentence_count = 3)
21
- sentences(sentence_count + rand(3)).join(' ')
27
+ def self.paragraph(sentence_count = 3, supplemental = false)
28
+ sentences(sentence_count + rand(3), supplemental).join(' ')
22
29
  end
23
30
 
24
- def self.paragraphs(paragraph_count = 3)
31
+ def self.paragraphs(paragraph_count = 3, supplemental = false)
25
32
  [].tap do |paragraphs|
26
33
  1.upto(paragraph_count) do
27
- paragraphs << paragraph
34
+ paragraphs << paragraph(3, supplemental)
28
35
  end
29
36
  end
30
37
  end
31
38
  end
32
- end
39
+ end
@@ -1,9 +1,11 @@
1
1
  module Faker
2
2
  class Name < Base
3
+ flexible :name
4
+
3
5
  class << self
4
6
 
5
7
  def name
6
- fetch('name.formats').collect {|meth| self.send(meth) }.join(' ')
8
+ parse('name.name')
7
9
  end
8
10
 
9
11
  def first_name; fetch('name.first_name'); end
@@ -11,6 +13,10 @@ module Faker
11
13
  def prefix; fetch('name.prefix'); end
12
14
  def suffix; fetch('name.suffix'); end
13
15
 
16
+ # Generate a buzzword-laden job title
17
+ # Wordlist from http://www.bullshitjob.com/title/
18
+ def title; fetch('name.title.descriptor') + ' ' + fetch('name.title.level') + ' ' + fetch('name.title.job'); end
19
+
14
20
  end
15
21
  end
16
- end
22
+ end
@@ -4,6 +4,14 @@ module Faker
4
4
  def phone_number
5
5
  numerify(fetch('phone_number.formats'))
6
6
  end
7
+
8
+ def cell_phone
9
+ if (translation = translate(:faker)[:cell_phone]).is_a? Hash
10
+ numerify(translation[:formats].sample)
11
+ else
12
+ numerify(fetch('phone_number.formats'))
13
+ end
14
+ end
7
15
  end
8
16
  end
9
- end
17
+ end
@@ -1,3 +1,3 @@
1
1
  module Faker #:nodoc:
2
- VERSION = "0.9.5"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -3,9 +3,16 @@ de-ch:
3
3
  address:
4
4
  country_code: [CH, CH, CH, DE, AT, US, LI, US, HK, VN]
5
5
  postcode: ['1###', '2###', '3###', '4###', '5###', '6###', '7###', '8###', '9###']
6
+
6
7
  company:
7
8
  suffix: [AG, GmbH, und Söhne, und Partner, "& Co.", Gruppe, LLC, Inc.]
9
+ name:
10
+ - "#{Name.last_name} #{suffix}"
11
+ - "#{Name.last_name}-#{Name.last_name}"
12
+ - "#{Name.last_name}, #{Name.last_name} und #{Name.last_name}"
13
+
8
14
  internet:
9
15
  domain_suffix: [com, net, biz, ch, de, li, at, ch, ch]
16
+
10
17
  phone_number:
11
18
  formats: ['0800 ### ###', '0800 ## ## ##', '0## ### ## ##', '0## ### ## ##', '+41 ## ### ## ##', '0900 ### ###', '076 ### ## ##', '+4178 ### ## ##', '0041 79 ### ## ##']