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 CHANGED
@@ -1 +1 @@
1
- 0.0.9
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
- r = total.times.map { model.make(attr.to_s.underscore => value) }
22
-
23
- r.length == 1 ? r.first : r
5
+ Transform /(?:an?|\d+) .+/ do |match|
6
+ materialize!(match)
24
7
  end
25
8
 
26
- Transform /the (.+) #{qc}$/ do |what, attr, value|
27
- class_for(what).find(:first, :conditions => {attr => value})
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 (.+) #{qc}$/ do |what, value|
31
- klass = class_for(what)
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
- class_for(what.singularize).tap do |model|
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
9
- version: 0.0.9
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-04-29 00:00:00 +01:00
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