dupe 0.4.5 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -4,11 +4,10 @@ There are lots of great tools out there to ease the burden of prototyping Active
4
4
 
5
5
  But what about prototyping ActiveResource records? That's where Dupe steps in.
6
6
 
7
-
8
7
  == Motivation
9
8
 
10
- Dupe is ideally suited for cuking the client side of a service-oriented (ActiveResource) application.
11
-
9
+ If you're going to create a service-oriented rails app with ActiveResource, why not cuke the front end first?
10
+ Let the behavior of the front-end drive the services you build on the backend. That's exactly what Dupe makes possible.
12
11
 
13
12
  == Installation
14
13
 
@@ -18,7 +17,7 @@ If you want to install this for use in something other than a rails project, sim
18
17
 
19
18
  If you're going to use this in a rails project, add this to your cucumber.rb environment (config/environments/cucumber.rb)
20
19
 
21
- config.gem 'dupe', :lib => 'dupe', :version => '>=0.4.0'
20
+ config.gem 'dupe'
22
21
 
23
22
  Then run this rake task to install the gem:
24
23
 
@@ -124,17 +123,15 @@ Notice that by using the plural form of the model name, we ensure that we receiv
124
123
 
125
124
  ==Finding or Creating Resources
126
125
 
127
- You might have seen this one coming:
126
+ You might have seen this one coming.
127
+
128
+ Let's assume no genres currently exist. If we call the "find_or_create" method, it will create a new :genre.
128
129
 
129
- irb# Dupe.find :genre
130
- Dupe::Database::TableDoesNotExistError: The table ':genre' does not exist.
131
- from /Library/Ruby/Gems/1.8/gems/dupe-0.4.0/lib/dupe/database.rb:30:in `select'
132
- from /Library/Ruby/Gems/1.8/gems/dupe-0.4.0/lib/dupe/dupe.rb:295:in `find'
133
- from (irb):40
134
-
135
130
  irb# Dupe.find_or_create :genre
136
131
  ==> <#Duped::Genre id=1>
137
132
 
133
+ If we call it again, it will find the :genre we already created:
134
+
138
135
  irb# Dupe.find_or_create :genre
139
136
  ==> <#Duped::Genre id=1>
140
137
 
@@ -263,7 +260,7 @@ Now, let's create a book:
263
260
 
264
261
  === Uniquify attributes
265
262
 
266
- If you'd just like to make sure that some attributes get a unique value (probably), then you can use the uniquify
263
+ If you'd just like to make sure that some attributes get a unique value, then you can use the uniquify
267
264
  method:
268
265
 
269
266
  irb# Dupe.define :book do |attrs|
@@ -280,6 +277,29 @@ any records it creates:
280
277
  ==> <#Duped::Book author="book 2 author" title="Rooby" genre="book 2 genre" id=2>
281
278
 
282
279
 
280
+ === Sequences
281
+
282
+ The "uniquify" method is great if don't care too much about the format of the values it creates. But what if you'd like to ensure
283
+ that the value of an attribute conforms to a specific format?
284
+
285
+ irb# Dupe.sequence :email do |n|
286
+ --# "email-#{n}@somewhere.com"
287
+ --# end
288
+
289
+ irb# Dupe.define :user do |user|
290
+ --# user.uniquify :name
291
+ --# user.email do
292
+ --# Dupe.next :email
293
+ --# end
294
+ --# end
295
+
296
+ irb# Dupe.create :user
297
+ ==> <#Duped::User name="user 1 name" id=1 email="email-1@somewhere.com">
298
+
299
+ irb# Dupe.create :user
300
+ ==> <#Duped::User name="user 2 name" id=2 email="email-2@somewhere.com">
301
+
302
+
283
303
  === Callbacks
284
304
 
285
305
  Suppose we'd like to make sure that our books get a unique label. We can accomplish that with an after_create callback:
@@ -302,6 +322,9 @@ Suppose we'd like to make sure that our books get a unique label. We can accompl
302
322
  ==> <#Duped::Book author=nil label="rooby-on-rails--1" title="Rooby on Rails" publish_date=nil id=1 isbn=842518>
303
323
 
304
324
 
325
+
326
+
327
+
305
328
  = ActiveResource
306
329
 
307
330
  So how does Dupe actually help us to spec/test ActiveResource-based applications? It uses a simple, yet sophisticated "intercept-mocking" technique, whereby failed network requests sent by ActiveResource fallback to the "Duped" network. Consider the following:
data/lib/dupe/dupe.rb CHANGED
@@ -5,6 +5,7 @@ class Dupe
5
5
  class << self
6
6
 
7
7
  attr_reader :models #:nodoc:
8
+ attr_reader :sequences #:nodoc:
8
9
  attr_reader :database #:nodoc:
9
10
 
10
11
  # set this to "true" if you Dupe to spit out mocked requests
@@ -385,6 +386,15 @@ class Dupe
385
386
  results
386
387
  end
387
388
  end
389
+
390
+ def sequence(name, &block)
391
+ sequences[name.to_sym] = Sequence.new 1, block
392
+ end
393
+
394
+ def next(name)
395
+ raise ArgumentError, "Unknown sequence \":#{name}\"" unless sequences.has_key?(name)
396
+ sequences[name].next
397
+ end
388
398
 
389
399
  def models #:nodoc:
390
400
  @models ||= {}
@@ -397,14 +407,23 @@ class Dupe
397
407
  def database #:nodoc:
398
408
  @database ||= Dupe::Database.new
399
409
  end
410
+
411
+ def sequences #:nodoc:
412
+ @sequences ||= {}
413
+ end
400
414
 
401
- # clears out all model definitions and database records / tables.
415
+ # clears out all model definitions, sequences, and database records / tables.
402
416
  def reset
403
417
  reset_models
404
418
  reset_database
405
419
  reset_network
420
+ reset_sequences
406
421
  end
407
422
 
423
+ def reset_sequences
424
+ @sequences = {}
425
+ end
426
+
408
427
  def reset_models
409
428
  @models = {}
410
429
  end
data/lib/dupe/sequence.rb CHANGED
@@ -1,12 +1,20 @@
1
1
  class Sequence #:nodoc:
2
2
  attr_reader :current_value
3
3
 
4
- def initialize(starting_at=1)
4
+ def initialize(starting_at=1, sequencer=nil)
5
5
  @current_value = starting_at
6
+ if sequencer && sequencer.arity != 1
7
+ raise ArgumentError, "Your block must accept a single parameter"
8
+ end
9
+ @transformer = sequencer
6
10
  end
7
11
 
8
12
  def next
9
13
  @current_value += 1
10
- @current_value - 1
14
+ if @transformer
15
+ @transformer.call(@current_value - 1)
16
+ else
17
+ @current_value - 1
18
+ end
11
19
  end
12
- end
20
+ end
@@ -5,14 +5,67 @@ describe Dupe do
5
5
  Dupe.reset
6
6
  end
7
7
 
8
+ describe "#sequences" do
9
+ it "should be empty on initialization" do
10
+ Dupe.sequences.should == {}
11
+ end
12
+ end
13
+
14
+ describe "#sequence" do
15
+ it "should require a sequence name and a block" do
16
+ proc {Dupe.sequence}.should raise_error(ArgumentError)
17
+ proc {Dupe.sequence :name}.should_not raise_error
18
+ proc {Dupe.sequence(:name) {}}.should raise_error(ArgumentError, "Your block must accept a single parameter")
19
+ proc {Dupe.sequence(:name) {|n| n}}.should_not raise_error
20
+ end
21
+
22
+ it "should store the sequence in a sequences hash" do
23
+ Dupe.sequences.should be_empty
24
+
25
+ Dupe.sequence :email do |n|
26
+ "email-#{n}@address.com"
27
+ end
28
+
29
+ Dupe.sequences.should_not be_empty
30
+ Dupe.sequences.keys.include?(:email).should == true
31
+ Dupe.sequences[:email].should be_kind_of(Sequence)
32
+ end
33
+ end
34
+
35
+ describe "#next" do
36
+ it "should require a sequence name" do
37
+ Dupe.sequence :email do |n|
38
+ "email-#{n}@address.com"
39
+ end
40
+
41
+ proc {Dupe.next}.should raise_error(ArgumentError)
42
+ proc {Dupe.next :title}.should raise_error(ArgumentError, 'Unknown sequence ":title"')
43
+ Dupe.next(:email).should == "email-1@address.com"
44
+ Dupe.next(:email).should == "email-2@address.com"
45
+ end
46
+ end
47
+
8
48
  describe "reset" do
9
49
  it "should call reset_models, reset_database, and reset_network" do
10
50
  Dupe.should_receive(:reset_models).once
11
51
  Dupe.should_receive(:reset_database).once
12
52
  Dupe.should_receive(:reset_network).once
53
+ Dupe.should_receive(:reset_sequences).once
13
54
  Dupe.reset
14
55
  end
15
56
  end
57
+
58
+ describe "reset_sequences" do
59
+ it "should reset the sequences to an empty hash" do
60
+ Dupe.sequences.should == {}
61
+ Dupe.sequence :email do |n|
62
+ n
63
+ end
64
+ Dupe.sequences.should_not be_empty
65
+ Dupe.reset_sequences
66
+ Dupe.sequences.should == {}
67
+ end
68
+ end
16
69
 
17
70
  describe "reset_models" do
18
71
  it "should reset @models to an empty hash" do
@@ -6,6 +6,14 @@ describe Sequence do
6
6
  Sequence.new.current_value.should == 1
7
7
  Sequence.new(500).current_value.should == 500
8
8
  end
9
+
10
+ it "should accept a block that takes a single parameter" do
11
+ proc {Sequence.new 1, proc {}}.should raise_error(ArgumentError, "Your block must accept a single parameter")
12
+ proc {Sequence.new 1, proc {|n| n}}.should_not raise_error
13
+ proc {Sequence.new 1, proc {|n,m| n}}.should raise_error(ArgumentError, "Your block must accept a single parameter")
14
+ s = Sequence.new 1, proc {|n| "email-#{n}@address.com"}
15
+ s.current_value.should == 1
16
+ end
9
17
  end
10
18
 
11
19
  describe "next" do
@@ -21,6 +29,11 @@ describe Sequence do
21
29
  s.current_value.should == 501
22
30
  s.next.should == 501
23
31
  s.current_value.should == 502
32
+
33
+ s = Sequence.new 1, proc {|n| "email-#{n}@address.com"}
34
+ s.next.should == "email-1@address.com"
35
+ s.next.should == "email-2@address.com"
36
+ s.current_value.should == 3
24
37
  end
25
38
  end
26
- end
39
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dupe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Parker
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-25 00:00:00 -05:00
12
+ date: 2010-01-31 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency