sandwich 0.0.9 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- 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
|