pickle-has_many_support 0.3.1

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.
Files changed (70) hide show
  1. data/.gitignore +5 -0
  2. data/History.txt +331 -0
  3. data/License.txt +20 -0
  4. data/README.rdoc +299 -0
  5. data/Rakefile +20 -0
  6. data/Rakefile.d/cucumber.rake +24 -0
  7. data/Rakefile.d/jeweller.rake +19 -0
  8. data/Rakefile.d/rcov.rake +18 -0
  9. data/Rakefile.d/rspec.rake +7 -0
  10. data/Rakefile.d/yard.rake +5 -0
  11. data/Todo.txt +3 -0
  12. data/VERSION +1 -0
  13. data/features/app/app.rb +122 -0
  14. data/features/app/blueprints.rb +11 -0
  15. data/features/app/factories.rb +23 -0
  16. data/features/app/views/notifier/email.erb +1 -0
  17. data/features/app/views/notifier/user_email.erb +6 -0
  18. data/features/email/email.feature +64 -0
  19. data/features/generator/generators.feature +59 -0
  20. data/features/path/models_page.feature +44 -0
  21. data/features/path/named_route_page.feature +10 -0
  22. data/features/pickle/create_from_active_record.feature +76 -0
  23. data/features/pickle/create_from_factory_girl.feature +59 -0
  24. data/features/pickle/create_from_machinist.feature +39 -0
  25. data/features/step_definitions/email_steps.rb +63 -0
  26. data/features/step_definitions/extra_email_steps.rb +7 -0
  27. data/features/step_definitions/fork_steps.rb +4 -0
  28. data/features/step_definitions/generator_steps.rb +46 -0
  29. data/features/step_definitions/path_steps.rb +14 -0
  30. data/features/step_definitions/pickle_steps.rb +100 -0
  31. data/features/support/email.rb +21 -0
  32. data/features/support/env.rb +52 -0
  33. data/features/support/paths.rb +47 -0
  34. data/features/support/pickle.rb +26 -0
  35. data/features/support/pickle_app.rb +4 -0
  36. data/init.rb +0 -0
  37. data/lib/pickle/adapter.rb +127 -0
  38. data/lib/pickle/adapters/active_record.rb +46 -0
  39. data/lib/pickle/adapters/data_mapper.rb +37 -0
  40. data/lib/pickle/config.rb +48 -0
  41. data/lib/pickle/email/parser.rb +18 -0
  42. data/lib/pickle/email/world.rb +13 -0
  43. data/lib/pickle/email.rb +79 -0
  44. data/lib/pickle/parser/matchers.rb +95 -0
  45. data/lib/pickle/parser.rb +71 -0
  46. data/lib/pickle/path/world.rb +5 -0
  47. data/lib/pickle/path.rb +45 -0
  48. data/lib/pickle/session/parser.rb +34 -0
  49. data/lib/pickle/session.rb +195 -0
  50. data/lib/pickle/version.rb +9 -0
  51. data/lib/pickle/world.rb +13 -0
  52. data/lib/pickle.rb +26 -0
  53. data/pickle.gemspec +117 -0
  54. data/rails_generators/pickle/pickle_generator.rb +33 -0
  55. data/rails_generators/pickle/templates/email.rb +21 -0
  56. data/rails_generators/pickle/templates/email_steps.rb +63 -0
  57. data/rails_generators/pickle/templates/paths.rb +47 -0
  58. data/rails_generators/pickle/templates/pickle.rb +28 -0
  59. data/rails_generators/pickle/templates/pickle_steps.rb +100 -0
  60. data/spec/pickle/adapter_spec.rb +163 -0
  61. data/spec/pickle/config_spec.rb +105 -0
  62. data/spec/pickle/email/parser_spec.rb +51 -0
  63. data/spec/pickle/email_spec.rb +160 -0
  64. data/spec/pickle/parser/matchers_spec.rb +74 -0
  65. data/spec/pickle/parser_spec.rb +165 -0
  66. data/spec/pickle/path_spec.rb +101 -0
  67. data/spec/pickle/session_spec.rb +451 -0
  68. data/spec/pickle_spec.rb +24 -0
  69. data/spec/spec_helper.rb +8 -0
  70. metadata +144 -0
@@ -0,0 +1,79 @@
1
+ module Pickle
2
+ module Email
3
+ # return the deliveries array, optionally selected by the passed fields
4
+ def emails(fields = nil)
5
+ @emails = ActionMailer::Base.deliveries.select {|m| email_has_fields?(m, fields)}
6
+ end
7
+
8
+ def email(ref, fields = nil)
9
+ (match = ref.match(/^#{capture_index_in_email}$/)) or raise ArgumentError, "argument should match #{match_email}"
10
+ @emails or raise RuntimeError, "Call #emails before calling #email"
11
+ index = parse_index(match[1])
12
+ email_has_fields?(@emails[index], fields) ? @emails[index] : nil
13
+ end
14
+
15
+ def email_has_fields?(email, fields)
16
+ parse_fields(fields).each do |key, val|
17
+ return false unless (Array(email.send(key)) & Array(val)).any?
18
+ end
19
+ true
20
+ end
21
+
22
+ def visit_in_email(email, link_text)
23
+ visit(parse_email_for_link(email, link_text))
24
+ end
25
+
26
+ def click_first_link_in_email(email)
27
+ link = links_in_email(email).first
28
+ request_uri = URI::parse(link).request_uri
29
+ visit request_uri
30
+ end
31
+
32
+ protected
33
+ def open_in_browser(path) # :nodoc
34
+ require "launchy"
35
+ Launchy::Browser.run(path)
36
+ rescue LoadError
37
+ warn "Sorry, you need to install launchy to open emails: `gem install launchy`"
38
+ end
39
+
40
+ # Saves the emails out to RAILS_ROOT/tmp/ and opens it in the default
41
+ # web browser if on OS X. (depends on webrat)
42
+ def save_and_open_emails
43
+ emails_to_open = @emails || emails
44
+ filename = "pickle-email-#{Time.now.to_i}.html"
45
+ File.open(filename, "w") do |f|
46
+ emails_to_open.each_with_index do |e, i|
47
+ f.write "<h1>Email #{i+1}</h1><pre>#{e}</pre><hr />"
48
+ end
49
+ end
50
+ open_in_browser(filename)
51
+ end
52
+
53
+ def parse_email_for_link(email, text_or_regex)
54
+ url = parse_email_for_explicit_link(email, text_or_regex)
55
+ url ||= parse_email_for_anchor_text_link(email, text_or_regex)
56
+ raise "No link found matching #{text_or_regex.inspect} in #{email}" unless url
57
+ url
58
+ end
59
+
60
+ # e.g. confirm in http://confirm
61
+ def parse_email_for_explicit_link(email, regex)
62
+ regex = /#{Regexp.escape(regex)}/ unless regex.is_a?(Regexp)
63
+ url = links_in_email(email).detect { |link| link =~ regex }
64
+ URI::parse(url).request_uri if url
65
+ end
66
+
67
+ # e.g. Click here in <a href="http://confirm">Click here</a>
68
+ def parse_email_for_anchor_text_link(email, link_text)
69
+ email.body =~ %r{<a[^>]*href=['"]?([^'"]*)['"]?[^>]*?>[^<]*?#{link_text}[^<]*?</a>}
70
+ URI.split($~[1])[5..-1].compact!.join("?").gsub("&amp;", "&")
71
+ # sub correct ampersand after rails switches it (http://dev.rubyonrails.org/ticket/4002)
72
+ end
73
+
74
+ def links_in_email(email, protos=['http', 'https'])
75
+ URI.extract(email.body, protos)
76
+ end
77
+
78
+ end
79
+ end
@@ -0,0 +1,95 @@
1
+ module Pickle
2
+ class Parser
3
+ module Matchers
4
+ def match_ordinal
5
+ '(?:\d+(?:st|nd|rd|th))'
6
+ end
7
+
8
+ def match_index
9
+ "(?:first|last|#{match_ordinal})"
10
+ end
11
+
12
+ def match_prefix
13
+ '(?:(?:a|an|another|the|that) )'
14
+ end
15
+
16
+ def match_quoted
17
+ '(?:[^\\"]|\\.)*'
18
+ end
19
+
20
+ def match_collection
21
+ "(?:\\[(?:#{match_model}, )*#{match_model}\\])"
22
+ end
23
+
24
+ def match_label
25
+ "(?::? \"#{match_quoted}\")"
26
+ end
27
+
28
+ def match_value
29
+ "(?:\"#{match_quoted}\"|#{match_collection}|nil|true|false|[+-]?\\d+(?:\\.\\d+)?)"
30
+ end
31
+
32
+ def match_field
33
+ "(?:\\w+: #{match_value})"
34
+ end
35
+
36
+ def match_fields
37
+ "(?:#{match_field}, )*#{match_field}"
38
+ end
39
+
40
+ def match_mapping
41
+ "(?:#{config.mappings.map(&:search).join('|')})"
42
+ end
43
+
44
+ def match_factory
45
+ "(?:#{config.factories.keys.map{|n| n.gsub('_','[_ ]')}.join('|')})"
46
+ end
47
+
48
+ def match_plural_factory
49
+ "(?:#{config.factories.keys.map{|n| n.pluralize.gsub('_','[_ ]')}.join('|')})"
50
+ end
51
+
52
+ def match_indexed_model
53
+ "(?:(?:#{match_index} )?#{match_factory})"
54
+ end
55
+
56
+ def match_labeled_model
57
+ "(?:#{match_factory}#{match_label})"
58
+ end
59
+
60
+ def match_model
61
+ "(?:#{match_mapping}|#{match_prefix}?(?:#{match_indexed_model}|#{match_labeled_model}))"
62
+ end
63
+
64
+ def match_predicate
65
+ "(?:#{config.predicates.map{|m| m.to_s.sub(/^has_/,'').sub(/\?$/,'').gsub('_','[_ ]')}.join('|')})"
66
+ end
67
+
68
+ # create capture analogues of match methods
69
+ instance_methods.select{|m| m =~ /^match_/}.each do |method|
70
+ eval <<-end_eval
71
+ def #{method.to_s.sub('match_', 'capture_')} # def capture_field
72
+ "(" + #{method} + ")" # "(" + match_field + ")"
73
+ end # end
74
+ end_eval
75
+ end
76
+
77
+ # special capture methods
78
+ def capture_number_in_ordinal
79
+ '(?:(\d+)(?:st|nd|rd|th))'
80
+ end
81
+
82
+ def capture_name_in_label
83
+ "(?::? \"(#{match_quoted})\")"
84
+ end
85
+
86
+ def capture_key_and_value_in_field
87
+ "(?:(\\w+): #{capture_value})"
88
+ end
89
+
90
+ def capture_models_in_collection
91
+ "(?:\\[(?:(#{match_model}), )*(#{match_model})\\])"
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,71 @@
1
+ require 'pickle/parser/matchers'
2
+
3
+ module Pickle
4
+ class Parser
5
+ include Matchers
6
+
7
+ attr_reader :config
8
+
9
+ def initialize(options = {})
10
+ @config = options[:config] || raise(ArgumentError, "Parser.new requires a :config")
11
+ end
12
+
13
+ # given a string like 'foo: "bar", bar: "baz"' returns {"foo" => "bar", "bar" => "baz"}
14
+ def parse_fields(fields)
15
+ if fields.blank?
16
+ {}
17
+ elsif fields =~ /^#{match_fields}$/
18
+ fields.scan(/(#{match_field})(?:,|$)/).inject({}) do |m, match|
19
+ m.merge(parse_field(match[0]))
20
+ end
21
+ else
22
+ raise ArgumentError, "The fields string is not in the correct format.\n\n'#{fields}' did not match: #{match_fields}"
23
+ end
24
+ end
25
+
26
+ # given a string like 'foo: expr' returns {key => value}
27
+ def parse_field(field)
28
+ if field =~ /^#{capture_key_and_value_in_field}$/
29
+ key, value = $1, $2
30
+ if value =~ /^#{match_collection}$/
31
+ match = value.match(/^#{capture_models_in_collection}$/)
32
+ { key => match.to_a.compact[1..-1] }
33
+ else
34
+ { key => eval(value) }
35
+ end
36
+ else
37
+ raise ArgumentError, "The field argument is not in the correct format.\n\n'#{field}' did not match: #{match_field}"
38
+ end
39
+ end
40
+
41
+ # returns really underscored name
42
+ def canonical(str)
43
+ str.to_s.underscore.gsub(' ','_').gsub('/','_')
44
+ end
45
+
46
+ # return [factory_name, name or integer index]
47
+ def parse_model(model_name)
48
+ apply_mappings!(model_name)
49
+ if /#{capture_index} #{capture_factory}$/ =~ model_name
50
+ [canonical($2), parse_index($1)]
51
+ elsif /#{capture_factory}#{capture_name_in_label}?$/ =~ model_name
52
+ [canonical($1), canonical($2)]
53
+ end
54
+ end
55
+
56
+ def parse_index(index)
57
+ case index
58
+ when nil, '', 'last' then -1
59
+ when /#{capture_number_in_ordinal}/ then $1.to_i - 1
60
+ when 'first' then 0
61
+ end
62
+ end
63
+
64
+ private
65
+ def apply_mappings!(string)
66
+ config.mappings.each do |mapping|
67
+ string.sub! /^#{mapping.search}$/, mapping.replacement
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,5 @@
1
+ require 'pickle'
2
+ require 'pickle/path'
3
+
4
+ # make world pickle/path aware
5
+ World(Pickle::Path)
@@ -0,0 +1,45 @@
1
+ module Pickle
2
+ module Path
3
+ # given args of pickle model name, and an optional extra action, or segment, will attempt to find
4
+ # a matching named route
5
+ #
6
+ # path_to_pickle 'the user', :action => 'edit' # => /users/3/edit
7
+ # path_to_pickle 'the user', 'the comment' # => /users/3/comments/1
8
+ # path_to_pickle 'the user', :segment => 'comments' # => /users/3/comments
9
+ #
10
+ # If you don;t know if the 'extra' part of the path is an action or a segment, then just
11
+ # pass it as 'extra' and this method will run through the possibilities
12
+ #
13
+ # path_to_pickle 'the user', :extra => 'new comment' # => /users/3/comments/new
14
+ def path_to_pickle(*pickle_names)
15
+ options = pickle_names.extract_options!
16
+ resources = pickle_names.map{|n| model(n) || n.to_sym}
17
+ if options[:extra]
18
+ parts = options[:extra].underscore.gsub(' ','_').split("_")
19
+ find_pickle_path_using_action_segment_combinations(resources, parts)
20
+ else
21
+ pickle_path_for_resources_action_segment(resources, options[:action], options[:segment])
22
+ end or raise "Could not figure out a path for #{pickle_names.inspect} #{options.inspect}"
23
+ end
24
+
25
+ protected
26
+ def find_pickle_path_using_action_segment_combinations(resources, parts)
27
+ path = nil
28
+ (0..parts.length).each do |idx|
29
+ action = parts.slice(0, idx).join('_')
30
+ segment = parts.slice(idx, parts.length).join('_')
31
+ path = pickle_path_for_resources_action_segment(resources, action, segment) and break
32
+ end
33
+ path
34
+ end
35
+
36
+ def pickle_path_for_resources_action_segment(resources, action, segment)
37
+ action.blank? or action = action.downcase.gsub(' ','_')
38
+ segment.blank? or segment = segment.downcase.gsub(' ','_')
39
+ resource_names = resources.map{|s| s.is_a?(Symbol) ? s.to_s : s.class.name.underscore}.join("_")
40
+ models = resources.reject{|s| s.is_a?(Symbol)}
41
+ parts = [action, resource_names, segment].reject(&:blank?)
42
+ send("#{parts.join('_')}_path", *models) rescue nil
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,34 @@
1
+ module Pickle
2
+ module Session
3
+ # add ability to parse model names as fields, using a session
4
+ module Parser
5
+ def self.included(parser_class)
6
+ parser_class.alias_method_chain :parse_field, :model
7
+ end
8
+
9
+ attr_accessor :session
10
+
11
+ def match_field
12
+ "(?:\\w+: (?:#{match_model}|#{match_value}))"
13
+ end
14
+
15
+ def parse_field_with_model(field)
16
+ if session && field =~ /^(\w+): #{capture_model}$/
17
+ {$1 => session.model($2)}
18
+ else
19
+ parse_field_without_model(field)
20
+ end
21
+ end
22
+
23
+ def parse_hash(hash)
24
+ hash.inject({}) do |parsed, (key, val)|
25
+ if session && val =~ /^#{capture_model}$/
26
+ parsed.merge(key => session.model($1))
27
+ else
28
+ parsed.merge(key => val)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,195 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Pickle
3
+ module Session
4
+ class << self
5
+ def included(world_class)
6
+ proxy_to_pickle_parser(world_class)
7
+ end
8
+
9
+ def extended(world_object)
10
+ proxy_to_pickle_parser(class << world_object; self; end) # metaclass is not 2.1 compatible
11
+ end
12
+
13
+ protected
14
+ def proxy_to_pickle_parser(world_class)
15
+ world_class.class_eval do
16
+ unless methods.include?('method_missing_with_pickle_parser')
17
+ alias_method_chain :method_missing, :pickle_parser
18
+ alias_method_chain :respond_to?, :pickle_parser
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ def create_model(pickle_ref, fields = nil)
25
+ factory, label = *parse_model(pickle_ref)
26
+ raise ArgumentError, "Can't create with an ordinal (e.g. 1st user)" if label.is_a?(Integer)
27
+ fields = fields.is_a?(Hash) ? parse_hash(fields) : parse_fields(fields)
28
+ fields = fields.inject({}) do |hash, (key, value)|
29
+ value = value.is_a?(Array) ? value.reject(&:empty?).map{ |name| model(name) } : value
30
+ hash.merge({ key => value })
31
+ end
32
+ record = pickle_config.factories[factory].create(fields)
33
+ store_model(factory, label, record)
34
+ record
35
+ end
36
+
37
+ # if a column exists in the table which matches the singular factory name, this is used as the pickle ref
38
+ def create_models_from_table(plural_factory, table)
39
+ factory = plural_factory.singularize
40
+ table.hashes.map do |hash|
41
+ pickle_ref = factory + (hash[factory] ? " \"#{hash.delete(factory)}\"" : "")
42
+ create_model(pickle_ref, hash)
43
+ end
44
+ end
45
+
46
+ def find_model(a_model_name, fields = nil)
47
+ factory, name = *parse_model(a_model_name)
48
+
49
+ raise ArgumentError, "Can't find a model with an ordinal (e.g. 1st user)" if name.is_a?(Integer)
50
+
51
+ model_class = pickle_config.factories[factory].klass
52
+ fields = fields.is_a?(Hash) ? parse_hash(fields) : parse_fields(fields)
53
+ conditions = convert_models_to_attributes(model_class, fields)
54
+ record = Pickle::Adapter.find_first_model(model_class, conditions)
55
+
56
+ store_model(factory, name, record) if record
57
+
58
+ record
59
+ end
60
+
61
+ def find_model!(a_model_name, fields = nil)
62
+ find_model(a_model_name, fields) or raise "Can't find pickle model: '#{a_model_name}' in this scenario"
63
+ end
64
+
65
+ def find_models(factory, fields = nil)
66
+ models_by_index(factory).clear
67
+
68
+ model_class = pickle_config.factories[factory].klass
69
+ conditions = convert_models_to_attributes(model_class, parse_fields(fields))
70
+ records = Pickle::Adapter.find_all_models(model_class, conditions)
71
+
72
+ records.each {|record| store_model(factory, nil, record)}
73
+ end
74
+
75
+ # if a column exists in the table which matches the singular factory name, this is used as the pickle ref
76
+ def find_models_from_table(plural_factory, table)
77
+ factory = plural_factory.singularize
78
+ table.hashes.map do |hash|
79
+ pickle_ref = factory + (hash[factory] ? " \"#{hash.delete(factory)}\"" : "")
80
+ find_model(pickle_ref, hash)
81
+ end
82
+ end
83
+
84
+ # return the original model stored by create_model or find_model
85
+ def created_model(name)
86
+ factory, name_or_index = *parse_model(name)
87
+
88
+ if name_or_index.blank?
89
+ models_by_index(factory).last
90
+ elsif name_or_index.is_a?(Integer)
91
+ models_by_index(factory)[name_or_index]
92
+ else
93
+ models_by_name(factory)[name_or_index] or raise "Can't find pickle model: '#{name}' in this scenario"
94
+ end
95
+ end
96
+
97
+ # predicate version which raises no errors
98
+ def created_model?(name)
99
+ (created_model(name) rescue nil) ? true : false
100
+ end
101
+
102
+ # return a newly selected model
103
+ def model(name)
104
+ model = created_model(name)
105
+ return nil unless model
106
+ Pickle::Adapter.get_model(model.class, model.id)
107
+ end
108
+
109
+ # predicate version which raises no errors
110
+ def model?(name)
111
+ (model(name) rescue nil) ? true : false
112
+ end
113
+
114
+ # like model, but raise an error if it can't be found
115
+ def model!(name)
116
+ model(name) or raise "Can't find pickle model: '#{name}' in this scenario"
117
+ end
118
+
119
+ # like created_model, but raise an error if it can't be found
120
+ def created_model!(name)
121
+ created_model(name) or raise "Can't find pickle model: '#{name}' in this scenario"
122
+ end
123
+
124
+ # return all original models of specified type
125
+ def created_models(factory)
126
+ models_by_index(factory)
127
+ end
128
+
129
+ # return all models of specified type (freshly selected from the database)
130
+ def models(factory)
131
+ created_models(factory).map do |model|
132
+ Pickle::Adapter.get_model(model.class, model.id)
133
+ end
134
+ end
135
+
136
+ def respond_to_with_pickle_parser?(method, include_private = false)
137
+ respond_to_without_pickle_parser?(method, include_private) || pickle_parser.respond_to?(method, include_private)
138
+ end
139
+
140
+ protected
141
+ def method_missing_with_pickle_parser(method, *args, &block)
142
+ if pickle_parser.respond_to?(method)
143
+ pickle_parser.send(method, *args, &block)
144
+ else
145
+ method_missing_without_pickle_parser(method, *args, &block)
146
+ end
147
+ end
148
+
149
+ def pickle_parser=(parser)
150
+ parser.session = self
151
+ @pickle_parser = parser
152
+ end
153
+
154
+ def pickle_parser
155
+ @pickle_parser or self.pickle_parser = Pickle.parser
156
+ end
157
+
158
+ def pickle_config
159
+ pickle_parser.config
160
+ end
161
+
162
+ def convert_models_to_attributes(ar_class, attrs)
163
+ attrs.each do |key, val|
164
+ if ((defined?(ActiveRecord::Base) && val.is_a?(ActiveRecord::Base)) ||
165
+ (defined?(DataMapper::Model) && val.is_a?(DataMapper::Model))) &&
166
+ Pickle::Adapter.column_names(ar_class).include?("#{key}_id")
167
+ attrs["#{key}_id"] = val.id
168
+ attrs["#{key}_type"] = val.class.base_class.name if ar_class.column_names.include?("#{key}_type")
169
+ attrs.delete(key)
170
+ end
171
+ end
172
+ end
173
+
174
+ def models_by_name(factory)
175
+ @models_by_name ||= {}
176
+ @models_by_name[pickle_parser.canonical(factory)] ||= {}
177
+ end
178
+
179
+ def models_by_index(factory)
180
+ @models_by_index ||= {}
181
+ @models_by_index[pickle_parser.canonical(factory)] ||= []
182
+ end
183
+
184
+ # if the factory name != the model name, store under both names
185
+ def store_model(factory, name, record)
186
+ store_record(record.class.name, name, record) unless pickle_parser.canonical(factory) == pickle_parser.canonical(record.class.name)
187
+ store_record(factory, name, record)
188
+ end
189
+
190
+ def store_record(factory, name, record)
191
+ models_by_name(factory)[name] = record
192
+ models_by_index(factory) << record
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,9 @@
1
+ module Pickle
2
+ module Version
3
+ String = File.read(File.dirname(__FILE__) + '/../../VERSION').strip
4
+ Array = String.split('.').map{|i| i.to_i}
5
+ Major = Array[0]
6
+ Minor = Array[1]
7
+ Patch = Array[2]
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ require 'pickle'
2
+
3
+ # auto require for active record and datamapper
4
+ require 'pickle/adapters/active_record' if defined?(ActiveRecord::Base)
5
+ require 'pickle/adapters/data_mapper' if defined?(DataMapper::Resource)
6
+
7
+ # make cucumber world pickle aware
8
+ World(Pickle::Session)
9
+
10
+ # shortcuts to regexps for use in step definition regexps
11
+ class << self
12
+ delegate :capture_model, :capture_fields, :capture_factory, :capture_plural_factory, :capture_predicate, :capture_value, :to => 'Pickle.parser'
13
+ end
data/lib/pickle.rb ADDED
@@ -0,0 +1,26 @@
1
+ require 'active_support'
2
+ require 'pickle/version'
3
+ require 'pickle/adapter'
4
+ require 'pickle/config'
5
+ require 'pickle/parser'
6
+ require 'pickle/session'
7
+ require 'pickle/session/parser'
8
+
9
+ # make the parser aware of models in the session (for fields refering to models)
10
+ Pickle::Parser.send :include, Pickle::Session::Parser
11
+
12
+ module Pickle
13
+ class << self
14
+ def config
15
+ @config ||= Config.new
16
+ end
17
+
18
+ def configure(&block)
19
+ config.configure(&block)
20
+ end
21
+
22
+ def parser(options = {})
23
+ @parser ||= Parser.new({:config => config}.merge(options))
24
+ end
25
+ end
26
+ end