sandwich 0.0.9 → 0.0.11
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/VERSION +1 -1
- data/lib/sandwich/cucumber/model_steps.rb +10 -47
- data/lib/sandwich/cucumber/world.rb +0 -13
- data/lib/sandwich/helpers/base.rb +0 -11
- data/lib/sandwich/model/base.rb +106 -0
- data/lib/sandwich/model/machinist.rb +131 -0
- metadata +5 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.11
|
@@ -1,35 +1,17 @@
|
|
1
1
|
require 'sandwich/ext/string'
|
2
|
-
require 'sandwich/cucumber/world'
|
3
2
|
|
4
|
-
Given /^((?:an?|the|\d+) .+)$/ do |what|
|
5
|
-
# la la la la
|
6
|
-
end
|
7
|
-
|
8
|
-
Transform /(an?|\d+) (.+) #{qc}$/ do |total, what, value|
|
9
|
-
model = attr = nil
|
10
|
-
|
11
|
-
begin
|
12
|
-
model = class_for(what)
|
13
|
-
attr = model.default_attribute
|
14
|
-
rescue NameError
|
15
|
-
what, attr = *what.split(/(?:with|in)/).map(&:strip)
|
16
|
-
model = class_for(what)
|
17
|
-
end
|
18
|
-
|
19
|
-
raise "No attribute passed and no default attribute defined for #{model}" if attr.nil?
|
3
|
+
Given /^((?:an?|the|\d+) .+)$/ do |what| end
|
20
4
|
|
21
|
-
|
22
|
-
|
23
|
-
r.length == 1 ? r.first : r
|
5
|
+
Transform /(?:an?|\d+) .+/ do |match|
|
6
|
+
materialize!(match)
|
24
7
|
end
|
25
8
|
|
26
|
-
|
27
|
-
|
9
|
+
Given /^(an?|the|\d+) (.+) with the following attributes:$/ do |total, what, table|
|
10
|
+
total.times { record!(what, table.rows_hash) }
|
28
11
|
end
|
29
12
|
|
30
|
-
Transform /the (
|
31
|
-
|
32
|
-
klass.find(:first, :conditions => {klass.default_attribute => value})
|
13
|
+
Transform /the (.+?) "([^\"]*)"$/ do |what, value|
|
14
|
+
record(what, value)
|
33
15
|
end
|
34
16
|
|
35
17
|
Given /^(.+) belong(?:ing|s) to (.+)$/ do |child, parent|
|
@@ -41,27 +23,8 @@ Given /^(.+) has (.+)$/ do |parent, child|
|
|
41
23
|
parent.send(child.class.name.underscore.pluralize) << child
|
42
24
|
end
|
43
25
|
|
44
|
-
Given /^no (.+) exists?$/ do |what|
|
45
|
-
class_for(what).delete_all
|
46
|
-
end
|
47
|
-
|
48
|
-
Given /^no (.+) (?:with|in) (.+) #{qc} exists?$/ do |what, attr, value|
|
49
|
-
class_for(what).delete_all
|
50
|
-
end
|
51
|
-
|
52
|
-
Given /^(an?|the|\d+) (.+) with the following attributes:$/ do |total, what, table|
|
53
|
-
class_for(what).tap do |model|
|
54
|
-
total.times do
|
55
|
-
model.make(Hash[*table.raw.map { |k, v| [k.underscore, value_for(model, k, v)] }.flatten])
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
26
|
Given /^the following (.+):$/ do |what, table|
|
61
|
-
|
62
|
-
table.hashes.each do |h|
|
63
|
-
model.make(Hash[*h.each_pair.map { |(k, v)| [k.underscore, value_for(model, k, v)] }.flatten])
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
27
|
+
model = what.singularize
|
67
28
|
|
29
|
+
table.hashes.each { |h| record!(model, h) }
|
30
|
+
end
|
@@ -1,18 +1,5 @@
|
|
1
1
|
module Sandwich
|
2
2
|
module World
|
3
|
-
def class_for(name)
|
4
|
-
name.underscore.classify.constantize
|
5
|
-
end
|
6
|
-
|
7
|
-
def value_for(model, attr, value)
|
8
|
-
if assoc = model.reflect_on_association(attr.to_sym)
|
9
|
-
assoc_class = assoc.class_name.constantize
|
10
|
-
assoc_class.find_or_make(assoc_class.default_attribute_query(value))
|
11
|
-
else
|
12
|
-
value
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
3
|
def xpath(unknown_selector)
|
17
4
|
kind, selector = if Array === unknown_selector
|
18
5
|
[unknown_selector[0].to_sym, unknown_selector[1]]
|
@@ -1,17 +1,6 @@
|
|
1
1
|
module Sandwich
|
2
2
|
module Base
|
3
3
|
module ClassMethods
|
4
|
-
def default_attribute(name = nil)
|
5
|
-
if name
|
6
|
-
@default_attribute = name
|
7
|
-
else
|
8
|
-
@default_attribute or raise "No default attribute defined for #{self}"
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def default_attribute_query(value)
|
13
|
-
{default_attribute => value}
|
14
|
-
end
|
15
4
|
end
|
16
5
|
end
|
17
6
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'strscan'
|
2
|
+
|
3
|
+
module Sandwich
|
4
|
+
module StringScannerExt
|
5
|
+
def words
|
6
|
+
if w = scan(/\s*(?:\w+ ?)+/) then w.strip end
|
7
|
+
end
|
8
|
+
|
9
|
+
alias_method :model_name, :words
|
10
|
+
alias_method :attribute_name, :words
|
11
|
+
|
12
|
+
def attribute_value
|
13
|
+
skip(/\s*"/)
|
14
|
+
|
15
|
+
scan(/[^"]+/).tap { |val| skip(/(?:"|\s+)/) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def attribute_pairs
|
19
|
+
result = []
|
20
|
+
|
21
|
+
while p = attribute_pair
|
22
|
+
result << p
|
23
|
+
|
24
|
+
scan(/\s*(?:and|,)\s*/)
|
25
|
+
end
|
26
|
+
|
27
|
+
Hash[*result.flatten]
|
28
|
+
end
|
29
|
+
|
30
|
+
::StringScanner.send(:include, self)
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def attribute_pair
|
35
|
+
w = attribute_name
|
36
|
+
v = attribute_value
|
37
|
+
|
38
|
+
if w.nil? || v.nil?
|
39
|
+
nil
|
40
|
+
else
|
41
|
+
[w, v]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
module Model
|
47
|
+
def self.attr_separators
|
48
|
+
@attr_separators = %w(with)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.attr_sep_str
|
52
|
+
"(?:#{attr_separators.join('|')})"
|
53
|
+
end
|
54
|
+
|
55
|
+
module Base
|
56
|
+
def materialize!(match)
|
57
|
+
scanner = StringScanner.new(match)
|
58
|
+
|
59
|
+
determiner = scanner.scan(/(?:an?|\d+)/)
|
60
|
+
scanner.skip(/\s+/)
|
61
|
+
|
62
|
+
model, values = if scanner.check_until(/#{_model.attr_sep_str}/)
|
63
|
+
model = scanner.scan_until(/(?=\s+#{_model.attr_sep_str})/)
|
64
|
+
scanner.skip(/\s+#{_model.attr_sep_str}\s+/)
|
65
|
+
|
66
|
+
[model, scanner.attribute_pairs]
|
67
|
+
else
|
68
|
+
[scanner.model_name, scanner.attribute_value]
|
69
|
+
end
|
70
|
+
|
71
|
+
if determiner.to_i == 1
|
72
|
+
record!(model, values)
|
73
|
+
else
|
74
|
+
determiner.times.map { record!(model, values) }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def _model
|
79
|
+
Sandwich::Model
|
80
|
+
end
|
81
|
+
|
82
|
+
module Extensions
|
83
|
+
def default_attribute(name = nil, &block)
|
84
|
+
if name
|
85
|
+
@default_attribute = name
|
86
|
+
elsif block_given?
|
87
|
+
@default_attribute = block
|
88
|
+
else
|
89
|
+
raise "Need an attribute name or a block for #{self}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def default_attribute_args(value, op)
|
94
|
+
if @default_attribute.respond_to?(:call)
|
95
|
+
@default_attribute.call(value, op)
|
96
|
+
elsif @default_attribute
|
97
|
+
{@default_attribute => value}
|
98
|
+
else
|
99
|
+
raise "No default attribute defined for #{self}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'sandwich/model/base'
|
2
|
+
|
3
|
+
module Sandwich
|
4
|
+
module Model
|
5
|
+
module Machinist
|
6
|
+
include Model::Base
|
7
|
+
|
8
|
+
class Materializer
|
9
|
+
def self.named_fixtures
|
10
|
+
@named_fixtures ||= {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.[](key)
|
14
|
+
key = prepare_key(key)
|
15
|
+
|
16
|
+
if model = named_fixtures[key]
|
17
|
+
new(key, model)
|
18
|
+
else
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.[]=(key, value)
|
24
|
+
key = prepare_key(key)
|
25
|
+
|
26
|
+
raise "Named fixture '#{key}' already exists for class #{self[key]}" if self[key]
|
27
|
+
|
28
|
+
named_fixtures[key] = value
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.prepare_key(key)
|
32
|
+
key.to_s.underscore.to_sym
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(key, model)
|
36
|
+
@key, @model = key, model
|
37
|
+
end
|
38
|
+
|
39
|
+
def get(args)
|
40
|
+
args = prepare_args(args)
|
41
|
+
|
42
|
+
result = case args
|
43
|
+
when Hash
|
44
|
+
@model.find(:first, :conditions => args)
|
45
|
+
else
|
46
|
+
@model.find(:first, :conditions => @model.default_attribute_args(args, :find))
|
47
|
+
end
|
48
|
+
|
49
|
+
raise "Could not find model for args: #{args.inspect}" if result.nil?
|
50
|
+
|
51
|
+
result
|
52
|
+
end
|
53
|
+
|
54
|
+
def create(args = nil)
|
55
|
+
args = prepare_args(args)
|
56
|
+
|
57
|
+
case args
|
58
|
+
when Hash
|
59
|
+
@model.make(@key, args)
|
60
|
+
else
|
61
|
+
@model.make(@key, @model.default_attribute_args(args, :create))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def prepare_args(args)
|
68
|
+
case args
|
69
|
+
when Hash
|
70
|
+
Hash[*args.each_pair.map { |k, v| [k.underscore, prepare_value(k, v)] }.flatten]
|
71
|
+
when nil
|
72
|
+
{}
|
73
|
+
else
|
74
|
+
args
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def prepare_value(key, value)
|
79
|
+
if assoc = @model.reflect_on_association(key.to_sym)
|
80
|
+
self.class[assoc.class_name].get(value)
|
81
|
+
else
|
82
|
+
value
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
module Extensions
|
88
|
+
include Sandwich::Model::Base::Extensions
|
89
|
+
|
90
|
+
def blueprint(name = :master, &blueprints)
|
91
|
+
if block_given?
|
92
|
+
m = Sandwich::Model::Machinist::Materializer
|
93
|
+
m[name == :master ? self.name.underscore : name] = self
|
94
|
+
end
|
95
|
+
|
96
|
+
super
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
##
|
102
|
+
# Create a record
|
103
|
+
def record!(name, args)
|
104
|
+
materializer = Materializer[name]
|
105
|
+
|
106
|
+
return name if materializer.nil?
|
107
|
+
|
108
|
+
materializer.create(args)
|
109
|
+
end
|
110
|
+
|
111
|
+
def record(name, args)
|
112
|
+
materializer = Materializer[name]
|
113
|
+
|
114
|
+
return name if materializer.nil?
|
115
|
+
|
116
|
+
materializer.get(args)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
if defined?(ActiveRecord::Base)
|
123
|
+
require 'machinist/active_record'
|
124
|
+
|
125
|
+
ActiveRecord::Base.send(:extend, Sandwich::Model::Machinist::Extensions)
|
126
|
+
else
|
127
|
+
raise "Don't know which machinist adapter to use."
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
World(Sandwich::Model::Machinist)
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 11
|
9
|
+
version: 0.0.11
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- David Leal
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-05-06 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -110,6 +110,8 @@ files:
|
|
110
110
|
- lib/sandwich/helpers/amounts.rb
|
111
111
|
- lib/sandwich/helpers/associations.rb
|
112
112
|
- lib/sandwich/helpers/base.rb
|
113
|
+
- lib/sandwich/model/base.rb
|
114
|
+
- lib/sandwich/model/machinist.rb
|
113
115
|
- spec/sandwich_spec.rb
|
114
116
|
- spec/spec.opts
|
115
117
|
- spec/spec_helper.rb
|