pickle-dupe 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +14 -9
- data/Rakefile +3 -2
- data/VERSION +1 -1
- data/features/app/active_resources.rb +4 -0
- data/features/app/dupe_definitions.rb +15 -7
- data/features/pickle/create_from_dupe.feature +35 -20
- data/features/step_definitions/pickle_steps.rb +1 -1
- data/features/step_definitions/recipe_steps.rb +5 -3
- data/lib/pickle_dupe/adapter.rb +93 -1
- data/lib/pickle_dupe/parser.rb +56 -0
- data/lib/pickle_dupe.rb +1 -0
- metadata +37 -15
- data/spec/pickle_dupe_spec.rb +0 -7
- data/spec/spec.opts +0 -1
- data/spec/spec_helper.rb +0 -9
data/README.rdoc
CHANGED
@@ -2,15 +2,20 @@
|
|
2
2
|
|
3
3
|
Pickle-dupe is an add-on to pickle that works with Dupe, an Active Resource mocking/factory.
|
4
4
|
|
5
|
-
==
|
6
|
-
|
7
|
-
|
8
|
-
*
|
9
|
-
*
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
Pickle-dupe requires the following gems
|
8
|
+
* pickle
|
9
|
+
* dupe
|
10
|
+
|
11
|
+
To install pickle-dupe gem, do:
|
12
|
+
sudo gem install pickle-dupe
|
13
|
+
|
14
|
+
== Usage
|
15
|
+
In order to use pickle with dupe, you need to add :dupe to your pickle's configuration as follows:
|
16
|
+
Pickle.configure do |config|
|
17
|
+
config.adapters = [:dupe]
|
18
|
+
end
|
14
19
|
|
15
20
|
== Copyright
|
16
21
|
|
data/Rakefile
CHANGED
@@ -11,6 +11,7 @@ begin
|
|
11
11
|
gem.homepage = "http://github.com/iawgens/pickle-dupe"
|
12
12
|
gem.authors = ["iawgens"]
|
13
13
|
gem.add_dependency "pickle",">=0.2.1"
|
14
|
+
gem.add_dependency "dupe",">=0.4.8"
|
14
15
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
16
|
end
|
16
17
|
Jeweler::GemcutterTasks.new
|
@@ -28,8 +29,8 @@ end
|
|
28
29
|
begin
|
29
30
|
require 'rcov/rcovtask'
|
30
31
|
Rcov::RcovTask.new do |test|
|
31
|
-
test.libs << '
|
32
|
-
test.pattern = '
|
32
|
+
test.libs << 'spec'
|
33
|
+
test.pattern = 'spec/**/*_spec.rb'
|
33
34
|
test.verbose = true
|
34
35
|
end
|
35
36
|
rescue LoadError
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -11,19 +11,24 @@ Dupe.define :recipe do |recipe|
|
|
11
11
|
Dupe.next :recipe_title
|
12
12
|
end
|
13
13
|
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
#
|
18
|
-
|
19
|
-
# end
|
20
|
-
# end
|
14
|
+
# has_many ingredients
|
15
|
+
recipe.ingredients []
|
16
|
+
|
17
|
+
# has_many steps
|
18
|
+
recipe.steps []
|
21
19
|
|
22
20
|
recipe.after_create do |r|
|
23
21
|
r.label = labelize(r.title)
|
24
22
|
end
|
25
23
|
end
|
26
24
|
|
25
|
+
Dupe.define :step do |step|
|
26
|
+
step.uniquify :title
|
27
|
+
|
28
|
+
step.after_create do |s|
|
29
|
+
s.label = labelize(s.title)
|
30
|
+
end
|
31
|
+
end
|
27
32
|
|
28
33
|
# Not Applicable in Dupe
|
29
34
|
# Dupe.define :fancy_recipe, :class => Recipe do |t|
|
@@ -33,6 +38,9 @@ end
|
|
33
38
|
Dupe.define :ingredient do |ingredient|
|
34
39
|
ingredient.uniquify :name
|
35
40
|
|
41
|
+
#belongs_to_many recipes
|
42
|
+
ingredient.recipes []
|
43
|
+
|
36
44
|
ingredient.after_create do |i|
|
37
45
|
i.label = labelize(i.name)
|
38
46
|
end
|
@@ -6,7 +6,8 @@ Feature: I can easily create models from dupe
|
|
6
6
|
Scenario: I create a recipe, and see if it looks right
|
7
7
|
Given a recipe exists
|
8
8
|
Then a recipe should exist
|
9
|
-
|
9
|
+
|
10
|
+
@basic_test
|
10
11
|
Scenario: I create a recipe with specific name, and see if it looks right
|
11
12
|
Given a recipe exists with name: "Chicken Recipe"
|
12
13
|
Then a recipe should exist with name: "Chicken Recipe"
|
@@ -14,31 +15,45 @@ Feature: I can easily create models from dupe
|
|
14
15
|
Scenario: I create stub recipes, and see if it looks right
|
15
16
|
Given 3 recipes exist
|
16
17
|
Then 3 recipes should exist
|
17
|
-
|
18
|
-
|
18
|
+
|
19
|
+
@many_to_one_association
|
20
|
+
Scenario: I create some recipes, and some steps
|
19
21
|
Given a recipe: "one" exists
|
20
|
-
And
|
21
|
-
And another
|
22
|
+
And a step exists with recipe: recipe "one"
|
23
|
+
And another step exists with recipe: recipe "one"
|
22
24
|
And a recipe: "two" exists
|
23
|
-
And
|
24
|
-
|
25
|
-
# TODO: GC 02/05/2010 named factory definition is not yet supported by dupe
|
25
|
+
And a step exists with recipe: recipe "two"
|
26
|
+
|
27
|
+
# TODO: GC 02/05/2010 named factory definition is not yet supported by dupe
|
26
28
|
# And a fancy recipe exists
|
27
29
|
# And an ingredient exists with recipe: the fancy recipe
|
30
|
+
|
31
|
+
# testing custom step
|
32
|
+
Then the first step should be step of the recipe: "one"
|
33
|
+
And the 2nd step should be step of recipe "one"
|
34
|
+
And the last step should be step of recipe "two"
|
28
35
|
|
29
|
-
Then the first
|
30
|
-
And the 2nd
|
31
|
-
And the last
|
32
|
-
|
33
|
-
Then the first ingredient should be in recipe "one"'s ingredients
|
34
|
-
And the 2nd ingredient should be in recipe: "one"'s ingredients
|
35
|
-
And the last ingredient should be in recipe "two"'s ingredients
|
36
|
-
And recipe "two" should be the last ingredient's recipe
|
36
|
+
Then the first step should be in recipe "one"'s steps
|
37
|
+
And the 2nd step should be in recipe: "one"'s steps
|
38
|
+
And the last step should be in recipe "two"'s steps
|
39
|
+
And recipe "two" should be the last step's recipe
|
37
40
|
|
38
|
-
But the first ingredient should not be in the fancy recipe's ingredients
|
39
|
-
|
40
|
-
And
|
41
|
-
|
41
|
+
#But the first ingredient should not be in the fancy recipe's ingredients
|
42
|
+
But the last step should not be in recipe "one"'s steps
|
43
|
+
And recipe "two" should not be the first step's recipe
|
44
|
+
#And the fancy recipe should not be the first ingredient's recipe
|
45
|
+
|
46
|
+
@many_to_many_association
|
47
|
+
Scenario: I create some ingredients and associate to some recipe
|
48
|
+
Given an ingredient: "one" exists
|
49
|
+
And an ingredient: "two" exists
|
50
|
+
And a recipe exists with ingredients: ingredient "one"
|
51
|
+
And a recipe exists with ingredients: [ingredient "one", ingredient "two"]
|
52
|
+
Then the first recipe should be in ingredient "one"'s recipes
|
53
|
+
And the last recipe should be in ingredient "one"'s recipes
|
54
|
+
And the last recipe should be in ingredient "two"'s recipes
|
55
|
+
And the first recipe should not be in ingredient "two"'s recipes
|
56
|
+
|
42
57
|
Scenario: Create an ingredient and a recipe refs in a table
|
43
58
|
Given 2 recipes exist
|
44
59
|
And the following ingredients exist:
|
@@ -1,4 +1,6 @@
|
|
1
1
|
# example of making your own matcher with the pickle backend
|
2
|
-
Then(/^#{capture_model} should be
|
3
|
-
model(recipe).
|
4
|
-
end
|
2
|
+
Then(/^#{capture_model} should be step of #{capture_model}$/) do |step, recipe|
|
3
|
+
model(recipe).steps.should include(model(step))
|
4
|
+
end
|
5
|
+
|
6
|
+
# ((?:(?:\w+: (?:(?:(?:I|killah fork)|(?:(?:a|an|another|the|that) )?(?:(?:(?:(?:first|last|(?:\d+(?:st|nd|rd|th))) )?(?:step|recipe|ingredient))|(?:(?:step|recipe|ingredient)(?::? "(?:[^\"]|\.)*"))))|(?:"(?:[^\"]|\.)*"|nil|true|false|[+-]?\d+(?:\.\d+)?))), )*(?:\w+: (?:(?:(?:I|killah fork)|(?:(?:a|an|another|the|that) )?(?:(?:(?:(?:first|last|(?:\d+(?:st|nd|rd|th))) )?(?:step|recipe|ingredient))|(?:(?:step|recipe|ingredient)(?::? "(?:[^\"]|\.)*"))))|(?:"(?:[^\"]|\.)*"|nil|true|false|[+-]?\d+(?:\.\d+)?))))
|
data/lib/pickle_dupe/adapter.rb
CHANGED
@@ -21,8 +21,100 @@ module Pickle
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def create(attrs = {})
|
24
|
-
::Dupe.create(@name, attrs)
|
24
|
+
duped_object = ::Dupe.create(@name, attrs)
|
25
|
+
assign_missing_associations(duped_object, attrs) unless attrs.blank?
|
26
|
+
|
27
|
+
return duped_object
|
25
28
|
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# Since ActiveResource does not have the notion of relationship between models, when associating
|
33
|
+
# a duped object to another object, Dupe does not take care of the association in both ways.
|
34
|
+
#
|
35
|
+
# Consider the following example with Recipe and DirectionStep. A recipe has many direction_steps
|
36
|
+
# and a direction_step belongs to one recipe. To setup dupe data for the cucumber scenario, we do the following:
|
37
|
+
#
|
38
|
+
# @recipe = Dupe.create :recipe #=> <#Duped::Recipe id=1>
|
39
|
+
# @direction_step = Dupe.create(:direction_step, {:recipe => @recipe})
|
40
|
+
# #=> <#Duped:DirectionStep recipe=<#Duped::Recipe id=1> id=1>
|
41
|
+
#
|
42
|
+
# That would associate the duped recipe to the duped ingredient. However, the duped recipe has
|
43
|
+
# no knowledge of the direction_step.
|
44
|
+
#
|
45
|
+
# @recipe.direction_steps #=> nil
|
46
|
+
#
|
47
|
+
# Since Dupe does not handle the reverse association, this method thus assign the association to the
|
48
|
+
# has_many side when a duped object is assigned to the belongs_to side when using pickle steps.
|
49
|
+
#
|
50
|
+
# To implement this association, you must let Dupe knows that a has_many association is expected by defining
|
51
|
+
# it in dupe definition as follows:
|
52
|
+
#
|
53
|
+
# Dupe.define :recipe do |recipe|
|
54
|
+
# recipe.direction_steps []
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# Once defined, when you call a pickle step to assign a belongs_to association, like:
|
58
|
+
#
|
59
|
+
# Given a recipe: "one" exists
|
60
|
+
# And a direction step exists with recipe: recipe "one"
|
61
|
+
#
|
62
|
+
# Then the "Then" step would be able to get the direction steps through the recipe duped object, like:
|
63
|
+
#
|
64
|
+
# Then the first direction step should be in recipe "one"'s direction steps
|
65
|
+
#
|
66
|
+
# This hack took care of has side when assigning to belongs_to side when it's a many_to_one:
|
67
|
+
#
|
68
|
+
# Dupe.create :direction_step, {:recipe => recipe}
|
69
|
+
#
|
70
|
+
# but does not take care of the many_to_many relationship like:
|
71
|
+
#
|
72
|
+
# Dupe.create :recipe, {:ingredients => [<Duped::Ingredient>,<Duped::Ingredient>]}
|
73
|
+
#
|
74
|
+
def assign_missing_associations(duped_object, attrs)
|
75
|
+
association_objects = collect_association_objects(attrs)
|
76
|
+
association_objects.each {|association_object|
|
77
|
+
|
78
|
+
# When a pickle step causes Dupe to do the following:
|
79
|
+
#
|
80
|
+
# Dupe.create(:direction_step, :recipe => @recipe)
|
81
|
+
#
|
82
|
+
# Then duped_object would be of class Dupe::DirectionStep and association_object would be of
|
83
|
+
# class Dupe::Recipe.
|
84
|
+
#
|
85
|
+
if association_object.kind_of?(Array)
|
86
|
+
association_object.each {|a|
|
87
|
+
assign_association(a, duped_object)
|
88
|
+
}
|
89
|
+
else
|
90
|
+
assign_association(association_object, duped_object)
|
91
|
+
end
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
def assign_association(association_object, duped_object)
|
96
|
+
has_one_association = duped_object.__model__.name #=> :direction_step
|
97
|
+
has_many_association = has_one_association.to_s.pluralize.to_sym #=> :direction_steps
|
98
|
+
|
99
|
+
# The following would check for the existence of the key :direction_steps
|
100
|
+
# in the duped recipe's definition
|
101
|
+
if association_object.__model__.schema.attribute_templates.keys.include?(has_many_association)
|
102
|
+
association_object[has_many_association] << duped_object
|
103
|
+
else #assume it's a has_one association
|
104
|
+
association_object[has_one_association] = duped_object
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Selecting association objects from the attributes hash and return as array. Association objects are of class
|
109
|
+
# Dupe::Database::Record
|
110
|
+
# Given :association => <#Duped::Ingredient name="ingredient 1 name" recipes=[] label="ingredient-1-name" id=1> or
|
111
|
+
# :association => [<#Duped...>] will return [[<#Duped...>,<#Duped...>],<#Duped...>]
|
112
|
+
def collect_association_objects(attrs)
|
113
|
+
attrs.select {|k,v|
|
114
|
+
v.kind_of?(Array) || v.kind_of?(::Dupe::Database::Record)
|
115
|
+
}.collect {|i| i[1]}
|
116
|
+
end
|
117
|
+
|
26
118
|
end
|
27
119
|
|
28
120
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Pickle
|
2
|
+
class Parser
|
3
|
+
def parse_field_with_multi_values(field)
|
4
|
+
# Would handle multiple values like "ingredients: [ingredient \"one\", ingredient \"two"\]"
|
5
|
+
if session && field =~ /^(\w+): #{match_model_in_values}$/
|
6
|
+
field_key = $1
|
7
|
+
|
8
|
+
models = []
|
9
|
+
values = parse_values(field)
|
10
|
+
values.each do |value|
|
11
|
+
if value =~ /^#{capture_model}$/
|
12
|
+
models << session.model($1)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
{field_key => models}
|
17
|
+
else
|
18
|
+
parse_field_without_multi_values(field)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
alias_method_chain :parse_field, :multi_values
|
24
|
+
|
25
|
+
def match_field
|
26
|
+
"(?:\\w+: #{match_values})"
|
27
|
+
end
|
28
|
+
|
29
|
+
def match_value
|
30
|
+
"(?:#{match_model}|\"#{match_quoted}\"|nil|true|false|[+-]?\\d+(?:\\.\\d+)?)"
|
31
|
+
end
|
32
|
+
|
33
|
+
def match_values
|
34
|
+
# like [step "one", step "two"]
|
35
|
+
"(?:\\[?(?:#{match_value}, )*#{match_value}\\]?)"
|
36
|
+
end
|
37
|
+
|
38
|
+
def match_model_in_values
|
39
|
+
"\\[(?:#{match_model}, )*#{match_model}\\]"
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# Given field of "ingredients: [ingredient \"one\", ingredient \"two\"]" return
|
45
|
+
# ["ingredient \"one\"","ingredient \"two\""]
|
46
|
+
def parse_values(field)
|
47
|
+
if field =~ /^\w+: (#{match_values})$/
|
48
|
+
$1.scan(/(#{match_value})(?:,|$|\])/).inject([]) do |m, match|
|
49
|
+
m << match[0]
|
50
|
+
end
|
51
|
+
#TODO GC 02/26/2010 - What to do if it does not match the values pattern?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
data/lib/pickle_dupe.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pickle-dupe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- iawgens
|
@@ -9,19 +14,37 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-
|
17
|
+
date: 2010-03-01 00:00:00 -05:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: pickle
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 2
|
30
|
+
- 1
|
23
31
|
version: 0.2.1
|
24
|
-
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: dupe
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
- 4
|
44
|
+
- 8
|
45
|
+
version: 0.4.8
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
25
48
|
description: Dupe is Active Resource mocking/factory for use with cucumber. Pickle-dupe is a pickle add-on that works with Dupe
|
26
49
|
email: gary.s.cheong@gmail.com
|
27
50
|
executables: []
|
@@ -51,10 +74,8 @@ files:
|
|
51
74
|
- features/support/pickle_dupe_app.rb
|
52
75
|
- lib/pickle_dupe.rb
|
53
76
|
- lib/pickle_dupe/adapter.rb
|
77
|
+
- lib/pickle_dupe/parser.rb
|
54
78
|
- lib/pickle_dupe/session.rb
|
55
|
-
- spec/pickle_dupe_spec.rb
|
56
|
-
- spec/spec.opts
|
57
|
-
- spec/spec_helper.rb
|
58
79
|
has_rdoc: true
|
59
80
|
homepage: http://github.com/iawgens/pickle-dupe
|
60
81
|
licenses: []
|
@@ -68,21 +89,22 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
68
89
|
requirements:
|
69
90
|
- - ">="
|
70
91
|
- !ruby/object:Gem::Version
|
92
|
+
segments:
|
93
|
+
- 0
|
71
94
|
version: "0"
|
72
|
-
version:
|
73
95
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
96
|
requirements:
|
75
97
|
- - ">="
|
76
98
|
- !ruby/object:Gem::Version
|
99
|
+
segments:
|
100
|
+
- 0
|
77
101
|
version: "0"
|
78
|
-
version:
|
79
102
|
requirements: []
|
80
103
|
|
81
104
|
rubyforge_project:
|
82
|
-
rubygems_version: 1.3.
|
105
|
+
rubygems_version: 1.3.6
|
83
106
|
signing_key:
|
84
107
|
specification_version: 3
|
85
108
|
summary: Pickle that works with Dupe, an Active Resource mocking/factory
|
86
|
-
test_files:
|
87
|
-
|
88
|
-
- spec/spec_helper.rb
|
109
|
+
test_files: []
|
110
|
+
|
data/spec/pickle_dupe_spec.rb
DELETED
data/spec/spec.opts
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
--color
|