olfactory 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ matrix:
3
+ allow_failures:
4
+ - rvm: ruby-head
5
+ rvm:
6
+ - 1.9.3
7
+ - 2.0.0
8
+ - 2.1.0
9
+ - ruby-head
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2014 StreetEasy
3
+ Copyright (c) 2014 David Elner
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  Olfactory
2
2
  ==========
3
3
 
4
+ [![Build Status](https://travis-ci.org/delner/olfactory.svg?branch=master)](https://travis-ci.org/delner/olfactory) ![Gem Version](https://badge.fury.io/rb/olfactory.svg)
5
+ ###### *For Ruby 1.9.3, 2.0.0, 2.1.0*
6
+
4
7
  ### Introduction
5
8
 
6
9
  Olfactory is a factory extension for creating complex object sets, as a supplement to `factory_girl`, `fabrication`, or other factories.
@@ -40,7 +43,7 @@ Instead, we can use templates to define shorthand notation:
40
43
  ```ruby
41
44
  context "networkable people" do
42
45
  let(:user_group) do
43
- Olfactory.create_template :user_group do |group|
46
+ Olfactory.create :user_group do |group|
44
47
  group.user :desktop_user { |user| user.phone { |phone| phone.apps :facebook, :twitter } }
45
48
  group.user :tablet_user { |user| user.tablet { |tablet| tablet.app :facebook } }
46
49
  group.user :phone_user { |user| user.desktop { |desktop| desktop.app :twitter } }
@@ -61,10 +64,10 @@ Templates are defined in `spec/templates/**/*.rb` files. Define a template using
61
64
  ...
62
65
  end
63
66
 
64
- Once defined, these templates can be instantiated using `build_template` and `create_template`, which are analogous to the same `factory_girl`/`fabrication` methods
67
+ Once defined, these templates can be instantiated using `build` and `create`, which are analogous to the same `factory_girl`/`fabrication` methods
65
68
 
66
- Olfactory.build_template :computer # Creates objects, but does not implictly save them
67
- Olfactory.create_template :computer # Creates objects, and attempts to save all items that respond to #save!
69
+ Olfactory.build :computer # Creates objects, but does not implictly save them
70
+ Olfactory.create :computer # Creates objects, and attempts to save all items that respond to #save!
68
71
 
69
72
  ##### #has_one
70
73
 
@@ -87,7 +90,7 @@ Sample:
87
90
  t.has_one :cpu, :alias => :processor
88
91
  end
89
92
  # Build instance of template
90
- Olfactory.build_template :computer do |c|
93
+ Olfactory.build :computer do |c|
91
94
  c.keyboard "X4 Sidewinder"
92
95
  c.mouse { FactoryGirl::build(:mouse) }
93
96
  c.processor "Intel Xeon"
@@ -152,7 +155,7 @@ Sample:
152
155
  t.has_many :drives, :singular => :drive, :named => true
153
156
  end
154
157
  # Build instance of template
155
- Olfactory.build_template :computer do |c|
158
+ Olfactory.build :computer do |c|
156
159
  # Generic
157
160
  c.cpus "Intel i7", "Onboard graphics"
158
161
  c.memory_stick "2GB"
@@ -206,7 +209,7 @@ Sample:
206
209
  end
207
210
  end
208
211
  # Build instance of template
209
- Olfactory.build_template :computer do |computer|
212
+ Olfactory.build :computer do |computer|
210
213
  computer.cpu do |cpu|
211
214
  cpu.cores "Intel Core", "Intel Core"
212
215
  end
@@ -294,7 +297,7 @@ Sample:
294
297
  end
295
298
  end
296
299
  # Build instance of template
297
- Olfactory.build_template :computer do |c|
300
+ Olfactory.build :computer do |c|
298
301
  # Generic
299
302
  computer.cpu :amd
300
303
  computer.cpu do |cpu|
@@ -315,6 +318,133 @@ Sample:
315
318
  end
316
319
  end
317
320
 
321
+ ##### #sequence
322
+
323
+ Defines a sequence, similar to `factory_girl`'s sequences. Can be combined with `Faker` to provide auto-generated test data. They can be defined at the global level, or nested within a template.
324
+
325
+ ###### When defining at the global level
326
+
327
+ Definition:
328
+ > **Olfactory.sequence** :name*[, :seed => Integer]* { |iterator[,options]| &block }
329
+
330
+ - `seed` defines the starting value, which increments by 1 after each invocation. Default 0.
331
+ - `options` in the form of hash args can be passed to the block.
332
+ - `iterator` is the current seed, which starts at 0 by default.
333
+ - `block` generates and returns the value.
334
+
335
+ Usage:
336
+ > **Olfactory.generate** :name
337
+ >
338
+ > **Olfactory.generate** :name, :option1 => Object, :option2 => Object...
339
+ >
340
+ > **Olfactory.generate** :name, :seed => Integer
341
+ >
342
+ > **Olfactory.generate** :name, :seed => Integer, :option1 => Object, :option2 => Object...
343
+ >
344
+ > **Olfactory.generate** :name { |iterator, options| &block }
345
+
346
+ - `seed` can be provided to override whatever the current seed is. When you provide an overriding seed, the sequence will *not* increment its internal seed. (Will act like it was never called.)
347
+ - `options` in the form of hash args can be passed to the block.
348
+ - `block` can be provided to override the block used for the call. When you provide an overriding block, the sequence will still increment its internal seed.
349
+
350
+ Sample:
351
+
352
+ Olfactory.sequence :ip_address, :seed => 1 do |n, options|
353
+ options[:ipv6] ? "fe80::2a18:78ff:feba:#{n}" : "192.168.1.#{n % 255}"
354
+ end
355
+ Olfactory.generate(:ip_address) # => "192.168.1.1"
356
+ Olfactory.generate(:ip_address, :seed => 255) # => "192.168.1.255"
357
+ Olfactory.generate(:ip_address) # => "192.168.1.2"
358
+ Olfactory.generate(:ip_address, :ipv6 => true) # => "fe80::2a18:78ff:feba:3"
359
+ Olfactory.generate(:ip_address) do |n|
360
+ "172.168.1.#{n % 255}"
361
+ end # => "172.168.1.4"
362
+
363
+ ###### When defining at the template level
364
+
365
+ `Olfactory` sequences don't provide much benefit over other gems at the global level, but they really shine when used within templates. Sequences work exactly the same within templates, except they can be bound by `scope`, allowing the author a great deal of control over when sequences reset.
366
+
367
+ `scope` can either be `:instance`, which resets the seed for each instance of the template, or `:template`, which shares the seed across all instances of the template.
368
+
369
+ Sample:
370
+
371
+ # Template definition
372
+ Olfactory.template :computer do |t|
373
+ t.has_one :serial_number
374
+ t.sequence :serial_number, :scope => :template do |n|
375
+ (10000 + n)
376
+ end
377
+ t.has_many :registers, :singular => :register
378
+ t.sequence :register, :scope => :instance do |n|
379
+ "Register #{n+1}"
380
+ end
381
+ end
382
+
383
+ Olfactory.build :computer do |c|
384
+ c.serial_number { c.generate(:serial_number) }
385
+ c.registers 2 { c.generate(:register) }
386
+ end
387
+ # => { :serial_number => 10000, :registers => ["Register 1", "Register 2"] }
388
+
389
+ Olfactory.build :computer do |c|
390
+ c.serial_number { c.generate(:serial_number) }
391
+ c.registers 2 { c.generate(:register) }
392
+ end
393
+ # => { :serial_number => 10001, :registers => ["Register 1", "Register 2"] }
394
+
395
+ ##### #dictionary
396
+
397
+ Defines a dictionary, which is just a simple data store (Hash.) They can be defined at the global level, or nested within a template.
398
+
399
+ ###### When defining at the global level
400
+
401
+ Definition:
402
+ > **Olfactory.dictionary** :name
403
+
404
+ Usage:
405
+ > **Olfactory.dictionaries**[name] # Returns Hash to read/write from
406
+
407
+ Sample:
408
+
409
+ Olfactory.dictionary :manfacturer_codes
410
+ Olfactory.dictionaries[:manfacturer_codes]["DELL"] = "Dell Computing"
411
+
412
+ ###### When defining at the template level
413
+
414
+ A hash data-store isn't that special at the global level, but is much more useful within templates. Definition is the same, but the usage only differs by name. Like sequences, dictionaries can define `scope` to separate or share data across templates. Combining them with sequences, we can synchronize data in some really cool ways.
415
+
416
+ `scope` can either be `:instance`, which resets the hash for each instance of the template, or `:template`, which shares the hash across all instances of the template.
417
+
418
+ Sample:
419
+
420
+ Olfactory.template :computer do |t|
421
+ t.has_one :hdd_manfacturer_code
422
+ t.has_one :gpu_manfacturer_code
423
+ t.has_one :cpu_manfacturer_code
424
+ t.dictionary :manfacturer_codes, :scope => :template
425
+ t.sequence :manfacturer_code, :scope => :template do |n|
426
+ (10000 + n)
427
+ end
428
+ end
429
+
430
+ Olfactory.build :computer do |c|
431
+ c.hdd_manfacturer_code { c.manfacturer_codes["SAMSUNG"] ||= c.generate(:manfacturer_code) }
432
+ c.cpu_manfacturer_code { c.manfacturer_codes["AMD"] ||= c.generate(:manfacturer_code) }
433
+ c.gpu_manfacturer_code { c.manfacturer_codes["AMD"] ||= c.generate(:manfacturer_code) }
434
+ end
435
+ # => { :hdd_manfacturer_code => 10001,
436
+ # :cpu_manfacturer_code => 10002,
437
+ # :cpu_manfacturer_code => 10002 }
438
+
439
+ Olfactory.build :computer do |c|
440
+ c.hdd_manfacturer_code { c.manfacturer_codes["SEAGATE"] ||= c.generate(:manfacturer_code) }
441
+ c.cpu_manfacturer_code { c.manfacturer_codes["AMD"] ||= c.generate(:manfacturer_code) }
442
+ c.gpu_manfacturer_code { c.manfacturer_codes["INTEL"] ||= c.generate(:manfacturer_code) }
443
+ end
444
+ # => { :hdd_manfacturer_code => 10003,
445
+ # :cpu_manfacturer_code => 10002,
446
+ # :cpu_manfacturer_code => 10004 }
447
+
318
448
  ##### #preset
319
449
 
320
450
  Defines a preset of values.
@@ -323,7 +453,7 @@ Definition:
323
453
  > **preset** :name { |instance| &block }
324
454
 
325
455
  When using:
326
- > Olfactory.build_template template_name, :preset => preset_name, :quantity => quantity:Integer
456
+ > Olfactory.build template_name, :preset => preset_name, :quantity => quantity:Integer
327
457
 
328
458
  See above sections for usage within templates.
329
459
 
@@ -342,7 +472,7 @@ Sample:
342
472
  t.has_one :cpu_core
343
473
  end
344
474
  # Build instance of template
345
- Olfactory.build_template :computer, :preset => :dual_core
475
+ Olfactory.build :computer, :preset => :dual_core
346
476
  # Result
347
477
  {
348
478
  :cpus => [{
@@ -373,7 +503,7 @@ Sample:
373
503
  end
374
504
  end
375
505
  # Build instance of template
376
- Olfactory.build_template :computer do |c|
506
+ Olfactory.build :computer do |c|
377
507
  c.memory_sticks 2
378
508
  end
379
509
  # Result
@@ -407,7 +537,7 @@ Sample:
407
537
  t.has_one :available_memory
408
538
  end
409
539
  # Build instance of template
410
- Olfactory.build_template :computer do |c|
540
+ Olfactory.build :computer do |c|
411
541
  c.memory_stick_size 2
412
542
  c.memory_sticks 2
413
543
  c.cpu do |cpu|
@@ -443,7 +573,7 @@ Sample:
443
573
  end
444
574
  end
445
575
  # Build instance of template
446
- Olfactory.build_template :computer do |c|
576
+ Olfactory.build :computer do |c|
447
577
  c.cpu "AMD Athlon"
448
578
  end
449
579
  # Result
@@ -462,7 +592,7 @@ Sample:
462
592
  end
463
593
  end
464
594
  # Build instance of template
465
- Olfactory.build_template :phone do |c|
595
+ Olfactory.build :phone do |c|
466
596
  c.memory_size "1GB"
467
597
  end
468
598
  # Result
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new
6
+ task :default => :spec
7
+ task :test => :spec
8
+
9
+ namespace :doc do
10
+ begin
11
+ require 'yard'
12
+ rescue LoadError
13
+ # ignore
14
+ else
15
+ YARD::Rake::YardocTask.new do |task|
16
+ task.files = ['lib/**/*.rb']
17
+ task.options = [
18
+ '--protected',
19
+ '--output-dir', 'doc/yard',
20
+ '--tag', 'format:Supported formats',
21
+ '--markup', 'markdown',
22
+ ]
23
+ end
24
+ end
25
+ end
26
+
27
+ desc "Open an irb session preloaded with this library"
28
+ task :console do
29
+ sh "irb -rubygems -I lib -r olfactory.rb"
30
+ end
@@ -0,0 +1,13 @@
1
+ module Olfactory
2
+ class Dictionary < Hash
3
+ attr_accessor :name, :scope
4
+
5
+ def initialize(name, options = {})
6
+ self.name = name
7
+ self.scope = (options[:scope] || :global)
8
+ end
9
+ def reset
10
+ self.clear
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Olfactory
3
+ class Sequence < Hash
4
+ def initialize(name, options, block)
5
+ self[:name] = name
6
+ self[:evaluator] = block
7
+ self[:scope] = (options[:scope] || :global)
8
+ self[:seed] = (options[:seed] || 0)
9
+ self[:current_seed] = (options[:seed] || 0)
10
+ end
11
+
12
+ def generate(name, options, block)
13
+ seed = options[:seed] || self[:current_seed]
14
+ target = block || self[:evaluator]
15
+ value = target.call(seed, options.reject { |k,v| k == :seed })
16
+ self[:current_seed] += 1 if !options.has_key?(:seed)
17
+
18
+ value
19
+ end
20
+ def reset
21
+ self[:current_seed] = self[:seed]
22
+ end
23
+ end
24
+ end
@@ -1,11 +1,13 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module Olfactory
3
3
  class Template < Hash
4
- attr_accessor :definition, :transients, :default_mode
4
+ attr_accessor :definition, :transients, :sequences, :dictionaries, :default_mode
5
5
 
6
6
  def initialize(definition, options = {})
7
7
  self.definition = definition
8
8
  self.transients = options[:transients] ? options[:transients].clone : {}
9
+ self.sequences = options[:sequences] ? options[:sequences].clone : {}
10
+ self.dictionaries = options[:dictionaries] ? options[:dictionaries].clone : {}
9
11
  end
10
12
 
11
13
  def build(block, options = {})
@@ -155,6 +157,13 @@ module Olfactory
155
157
 
156
158
  field_value = build_one_item(field_definition, obj, block)
157
159
  end
160
+ elsif field_definition.class == Olfactory::Dictionary
161
+ if field_definition.scope == :template
162
+ return_value = field_definition
163
+ elsif field_definition.scope == :instance
164
+ return_value = (self.dictionaries[meth] ||= {})
165
+ end
166
+ do_not_set_value = true
158
167
  else
159
168
  do_not_set_value = true
160
169
  end
@@ -185,6 +194,21 @@ module Olfactory
185
194
  def transient(name, value)
186
195
  self.transients[name] = value if !(self.default_mode && self.transients.has_key?(name))
187
196
  end
197
+ def generate(name, options = {}, &block)
198
+ sequence = self.definition.t_sequences[name]
199
+ # Template scope
200
+ if sequence && sequence[:scope] == :template
201
+ value = sequence.generate(name, options, block)
202
+ # Instance scope
203
+ elsif sequence && sequence[:scope] == :instance
204
+ self.sequences[name] ||= { :current_seed => (options[:seed] || sequence[:seed]) }
205
+ value = sequence.generate(name, options.merge(:seed => self.sequences[name][:current_seed]), block)
206
+ self.sequences[name][:current_seed] += 1 if !options.has_key?(:seed)
207
+ else
208
+ raise "Unknown sequence '#{name}'!"
209
+ end
210
+ value
211
+ end
188
212
  def add_defaults(mode)
189
213
  # Prevents overwrites of custom values by defaults
190
214
  self.default_mode = true # Hackish for sure, but its efficient...
@@ -257,5 +281,13 @@ module Olfactory
257
281
  args
258
282
  end
259
283
  end
284
+ def reset_sequences(*names)
285
+ names = self.sequences.keys if names.empty?
286
+ names.each { |name| self.sequences[name].reset }
287
+ end
288
+ def reset_dictionaries(*names)
289
+ names = self.dictionaries.keys if names.empty?
290
+ names.each { |name| self.dictionaries[name].reset }
291
+ end
260
292
  end
261
293
  end
@@ -1,11 +1,13 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module Olfactory
3
3
  class TemplateDefinition
4
- attr_accessor :t_items, :t_subtemplates, :t_macros, :t_presets, :t_before, :t_after
4
+ attr_accessor :t_items, :t_subtemplates, :t_sequences, :t_dictionaries, :t_macros, :t_presets, :t_before, :t_after
5
5
 
6
6
  def initialize
7
7
  self.t_items = {}
8
8
  self.t_subtemplates = {}
9
+ self.t_sequences = {}
10
+ self.t_dictionaries = {}
9
11
  self.t_macros = {}
10
12
  self.t_presets = {}
11
13
  self.t_before = {}
@@ -55,6 +57,7 @@ module Olfactory
55
57
  definition = find_macro_definition(name)
56
58
  definition ||= find_subtemplate_definition(name)
57
59
  definition ||= find_item_definition(name)
60
+ definition ||= find_dictionary_definition(name)
58
61
  definition
59
62
  end
60
63
 
@@ -82,6 +85,10 @@ module Olfactory
82
85
  definition
83
86
  end
84
87
 
88
+ def find_dictionary_definition(name)
89
+ self.t_dictionaries[name]
90
+ end
91
+
85
92
  def find_preset_definition(name)
86
93
  preset_definition = self.find_definition_in_list(name, self.t_presets)
87
94
  if preset_definition.nil?
@@ -92,6 +99,15 @@ module Olfactory
92
99
  preset_definition
93
100
  end
94
101
 
102
+ def reset_sequences(*names)
103
+ names = self.t_sequences.keys if names.empty?
104
+ names.each { |name| self.t_sequences[name].reset }
105
+ end
106
+ def reset_dictionaries(*names)
107
+ names = self.t_dictionaries.keys if names.empty?
108
+ names.each { |name| self.t_dictionaries[name].reset }
109
+ end
110
+
95
111
  # Defines a value holding field
96
112
  def has_one(name, options = {}, &block)
97
113
  self.t_items[name] = { :type => :item,
@@ -114,6 +130,16 @@ module Olfactory
114
130
  self.embeds_one(name, options.merge(:collection => (options[:named] ? Hash : Array)), &block)
115
131
  end
116
132
 
133
+ # Defines a sequence
134
+ def sequence(name, options = {}, &block)
135
+ self.t_sequences[name] = Olfactory::Sequence.new(name, { :scope => :instance }.merge(options), block)
136
+ end
137
+
138
+ # Defines a dictionary
139
+ def dictionary(name, options = {})
140
+ self.t_dictionaries[name] = Olfactory::Dictionary.new(name, { :scope => :instance }.merge(options))
141
+ end
142
+
117
143
  # Defines a macro
118
144
  def macro(name, options = {}, &block)
119
145
  self.t_macros[name] = { :type => :macro,
@@ -1,3 +1,3 @@
1
1
  module Olfactory
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/olfactory.rb CHANGED
@@ -1,29 +1,86 @@
1
1
  # -*- encoding : utf-8 -*-
2
+ require 'olfactory/dictionary'
3
+ require 'olfactory/sequence'
2
4
  require 'olfactory/template_definition'
3
5
  require 'olfactory/template'
4
6
 
5
7
  module Olfactory
6
8
  @@templates = {}
9
+ @@sequences = {}
10
+ @@dictionaries = {}
11
+
12
+ # Getters
7
13
  def self.templates
8
14
  @@templates
9
15
  end
16
+ def self.sequences
17
+ @@sequences
18
+ end
19
+ def self.dictionaries
20
+ @@dictionaries
21
+ end
10
22
 
23
+ # Definitions
11
24
  def self.template(name, &block)
12
- new_template_definition = TemplateDefinition.new
25
+ new_template_definition = Olfactory::TemplateDefinition.new
13
26
  block.call(new_template_definition)
14
27
  self.templates[name] = new_template_definition
15
28
  end
29
+ def self.sequence(name, options = {}, &block)
30
+ sequences[name] = Olfactory::Sequence.new(name, options, block)
31
+ end
32
+ def self.dictionary(name)
33
+ dictionaries[name] = Olfactory::Dictionary.new(name)
34
+ end
16
35
 
17
- def self.build_template(name, options = {}, &block)
36
+ # Invocations
37
+ def self.build(name, options = {}, &block)
18
38
  self.templates[name].build(block, options)
19
39
  end
20
- def self.create_template(name, options = {}, &block)
40
+ def self.create(name, options = {}, &block)
21
41
  template = self.templates[name].build(block, options)
22
42
  template.save!
23
43
  template
24
44
  end
45
+ def self.generate(name, options = {}, &block)
46
+ if sequence = self.sequences[name]
47
+ sequence.generate(name, options, block)
48
+ else
49
+ raise "Unknown sequence '#{name}'!"
50
+ end
51
+ end
25
52
 
26
- def self.reload
53
+ def self.clear
27
54
  @@templates = {}
55
+ @@sequences = {}
56
+ @@dictionaries = {}
57
+ end
58
+ def self.reset
59
+ self.reset_sequences
60
+ self.reset_dictionaries
61
+ self.reset_template_sequences
62
+ self.reset_template_dictionaries
63
+ end
64
+ def self.reset_sequences(*names)
65
+ names = self.sequences.keys if names.empty?
66
+ names.each do |name|
67
+ self.sequences[name].reset
68
+ end
69
+ end
70
+ def self.reset_template_sequences(template, *names)
71
+ if template = self.templates[template]
72
+ template.reset_sequences(*names)
73
+ end
74
+ end
75
+ def self.reset_dictionaries(*names)
76
+ names = self.dictionaries.keys if names.empty?
77
+ names.each do |name|
78
+ self.dictionaries[name].reset
79
+ end
80
+ end
81
+ def self.reset_template_dictionaries(template, *names)
82
+ if template = self.templates[template]
83
+ template.reset_dictionaries(*names)
84
+ end
28
85
  end
29
86
  end
data/olfactory.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
10
10
  s.email = 'david@davidelner.com'
11
11
  s.files = `git ls-files`.split("\n")
12
12
  s.test_files = `git ls-files -- {spec,features,gemfiles}/*`.split("\n")
13
- s.homepage = 'https://github.com/StreetEasy/olfactory'
13
+ s.homepage = 'https://github.com/delner/olfactory'
14
14
  s.license = 'MIT'
15
15
 
16
16
  s.require_paths = ['lib']
@@ -20,4 +20,6 @@ Gem::Specification.new do |s|
20
20
  s.add_development_dependency("pry", "~> 0.10")
21
21
  s.add_development_dependency("pry-nav", "~> 0.2")
22
22
  s.add_development_dependency("pry-stack_explorer", "~> 0.4.9")
23
+ s.add_development_dependency('rake', '~> 10.0.4')
24
+ s.add_development_dependency('yard', '~> 0.8.7.6')
23
25
  end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Olfactory::Dictionary do
4
+ before(:context) do
5
+ Olfactory.dictionary :streets
6
+ end
7
+
8
+ context "given a value" do
9
+ before(:context) do
10
+ Olfactory.dictionaries[:streets][:borough => 1, :street => "BROADWAY"] = 10001
11
+ end
12
+ let(:key) do
13
+ { :borough => 1, :street => "BROADWAY" }
14
+ end
15
+ let(:value) { 10001 }
16
+
17
+ subject { Olfactory.dictionaries[:streets][key] }
18
+ it { expect(subject).to eq(value) }
19
+ end
20
+ end
File without changes
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ describe Olfactory::Sequence do
4
+ context "with no seed" do
5
+ before(:example) do
6
+ Olfactory.sequence :address do |n, options|
7
+ "#{(n + (n % 2)) + 2} #{"#{options[:prefix]} " if options[:prefix]}BROADWAY"
8
+ end
9
+ end
10
+ context "given nothing" do
11
+ subject do
12
+ Olfactory.generate(:address)
13
+ end
14
+ it { expect(subject).to eq("2 BROADWAY") }
15
+ end
16
+ context "given options" do
17
+ subject do
18
+ Olfactory.generate(:address, :prefix => "WEST")
19
+ end
20
+ it { expect(subject).to eq("2 WEST BROADWAY") }
21
+ end
22
+ context "given a block" do
23
+ subject do
24
+ Olfactory.generate(:address) do |n|
25
+ "#{(n + (n % 2)) + 2} JOHN STREET"
26
+ end
27
+ end
28
+ it { expect(subject).to eq("2 JOHN STREET") }
29
+ end
30
+ context "given options and a block" do
31
+ subject do
32
+ Olfactory.generate(:address, :suffix => "ROAD") do |n, options|
33
+ "#{(n + (n % 2)) + 2} JOHN#{options[:suffix] ? " #{options[:suffix]}" : " STREET"}"
34
+ end
35
+ end
36
+ it { expect(subject).to eq("2 JOHN ROAD") }
37
+ end
38
+ end
39
+ context "with a seed" do
40
+ before(:example) do
41
+ Olfactory.sequence :address, :seed => 10 do |n, options|
42
+ "#{(n + (n % 2))} #{"#{options[:prefix]} " if options[:prefix]}BROADWAY"
43
+ end
44
+ end
45
+ context "given nothing" do
46
+ subject do
47
+ Olfactory.generate(:address)
48
+ end
49
+ it { expect(subject).to eq("10 BROADWAY") }
50
+ end
51
+ context "given options" do
52
+ subject do
53
+ Olfactory.generate(:address, :prefix => "WEST")
54
+ end
55
+ it { expect(subject).to eq("10 WEST BROADWAY") }
56
+ end
57
+ context "given a block" do
58
+ subject do
59
+ Olfactory.generate(:address) do |n|
60
+ "#{(n + (n % 2))} JOHN STREET"
61
+ end
62
+ end
63
+ it { expect(subject).to eq("10 JOHN STREET") }
64
+ end
65
+ context "given options and a block" do
66
+ subject do
67
+ Olfactory.generate(:address, :suffix => "ROAD") do |n, options|
68
+ "#{(n + (n % 2))} JOHN#{options[:suffix] ? " #{options[:suffix]}" : " STREET"}"
69
+ end
70
+ end
71
+ it { expect(subject).to eq("10 JOHN ROAD") }
72
+ end
73
+ end
74
+ context "given sequential invocations" do
75
+ before(:context) do
76
+ Olfactory.sequence :address do |n, options|
77
+ "#{(n + (n % 2)) + 2} #{"#{options[:prefix]} " if options[:prefix]}BROADWAY"
78
+ end
79
+ end
80
+ it { expect(Olfactory.generate(:address)).to eq("2 BROADWAY") }
81
+ it { expect(Olfactory.generate(:address)).to eq("4 BROADWAY") }
82
+ end
83
+ end