pickle-dupe 0.1.0 → 0.2.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.
- 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
|