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.
- data/.gitignore +5 -0
- data/History.txt +331 -0
- data/License.txt +20 -0
- data/README.rdoc +299 -0
- data/Rakefile +20 -0
- data/Rakefile.d/cucumber.rake +24 -0
- data/Rakefile.d/jeweller.rake +19 -0
- data/Rakefile.d/rcov.rake +18 -0
- data/Rakefile.d/rspec.rake +7 -0
- data/Rakefile.d/yard.rake +5 -0
- data/Todo.txt +3 -0
- data/VERSION +1 -0
- data/features/app/app.rb +122 -0
- data/features/app/blueprints.rb +11 -0
- data/features/app/factories.rb +23 -0
- data/features/app/views/notifier/email.erb +1 -0
- data/features/app/views/notifier/user_email.erb +6 -0
- data/features/email/email.feature +64 -0
- data/features/generator/generators.feature +59 -0
- data/features/path/models_page.feature +44 -0
- data/features/path/named_route_page.feature +10 -0
- data/features/pickle/create_from_active_record.feature +76 -0
- data/features/pickle/create_from_factory_girl.feature +59 -0
- data/features/pickle/create_from_machinist.feature +39 -0
- data/features/step_definitions/email_steps.rb +63 -0
- data/features/step_definitions/extra_email_steps.rb +7 -0
- data/features/step_definitions/fork_steps.rb +4 -0
- data/features/step_definitions/generator_steps.rb +46 -0
- data/features/step_definitions/path_steps.rb +14 -0
- data/features/step_definitions/pickle_steps.rb +100 -0
- data/features/support/email.rb +21 -0
- data/features/support/env.rb +52 -0
- data/features/support/paths.rb +47 -0
- data/features/support/pickle.rb +26 -0
- data/features/support/pickle_app.rb +4 -0
- data/init.rb +0 -0
- data/lib/pickle/adapter.rb +127 -0
- data/lib/pickle/adapters/active_record.rb +46 -0
- data/lib/pickle/adapters/data_mapper.rb +37 -0
- data/lib/pickle/config.rb +48 -0
- data/lib/pickle/email/parser.rb +18 -0
- data/lib/pickle/email/world.rb +13 -0
- data/lib/pickle/email.rb +79 -0
- data/lib/pickle/parser/matchers.rb +95 -0
- data/lib/pickle/parser.rb +71 -0
- data/lib/pickle/path/world.rb +5 -0
- data/lib/pickle/path.rb +45 -0
- data/lib/pickle/session/parser.rb +34 -0
- data/lib/pickle/session.rb +195 -0
- data/lib/pickle/version.rb +9 -0
- data/lib/pickle/world.rb +13 -0
- data/lib/pickle.rb +26 -0
- data/pickle.gemspec +117 -0
- data/rails_generators/pickle/pickle_generator.rb +33 -0
- data/rails_generators/pickle/templates/email.rb +21 -0
- data/rails_generators/pickle/templates/email_steps.rb +63 -0
- data/rails_generators/pickle/templates/paths.rb +47 -0
- data/rails_generators/pickle/templates/pickle.rb +28 -0
- data/rails_generators/pickle/templates/pickle_steps.rb +100 -0
- data/spec/pickle/adapter_spec.rb +163 -0
- data/spec/pickle/config_spec.rb +105 -0
- data/spec/pickle/email/parser_spec.rb +51 -0
- data/spec/pickle/email_spec.rb +160 -0
- data/spec/pickle/parser/matchers_spec.rb +74 -0
- data/spec/pickle/parser_spec.rb +165 -0
- data/spec/pickle/path_spec.rb +101 -0
- data/spec/pickle/session_spec.rb +451 -0
- data/spec/pickle_spec.rb +24 -0
- data/spec/spec_helper.rb +8 -0
- metadata +144 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
Before('@gen') do
|
2
|
+
`mv #{Rails.root}/features/ #{Rails.root}/features.orig/ > /dev/null 2>&1`
|
3
|
+
end
|
4
|
+
|
5
|
+
After('@gen') do
|
6
|
+
`rm -rf #{Rails.root}/features`
|
7
|
+
`mv #{Rails.root}/features.orig/ #{Rails.root}/features/ > /dev/null 2>&1`
|
8
|
+
end
|
9
|
+
|
10
|
+
Given(/^cucumber has been freshly generated$/) do
|
11
|
+
`cd #{Rails.root}; script/generate cucumber -f --webrat`
|
12
|
+
end
|
13
|
+
|
14
|
+
Given(/^pickle path email has been freshly generated$/) do
|
15
|
+
`cd #{Rails.root}; script/generate -f pickle paths email`
|
16
|
+
end
|
17
|
+
|
18
|
+
Given(/^env\.rb already requires (.+)$/) do |file|
|
19
|
+
File.open("#{Rails.root}/features/support/env.rb", "a") do |env|
|
20
|
+
env << "require '#{file}'\n"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
When(/^I run "(.*)"$/) do |command|
|
25
|
+
@output = `cd #{Rails.root}; #{command}`
|
26
|
+
end
|
27
|
+
|
28
|
+
Then(/^I should see "(.*)"$/) do |text|
|
29
|
+
@output.should include(text)
|
30
|
+
end
|
31
|
+
|
32
|
+
Then(/^the file (.+?) should exist$/) do |file|
|
33
|
+
File.exist?("#{Rails.root}/#{file}").should == true
|
34
|
+
end
|
35
|
+
|
36
|
+
Then(/^the file (.+?) should match \/(.*?)\/$/) do |file, regexp|
|
37
|
+
File.read("#{Rails.root}/#{file}").should match(/#{regexp}/m)
|
38
|
+
end
|
39
|
+
|
40
|
+
Then(/^the file (.+?) should not match \/(.*?)\/$/) do |file, regexp|
|
41
|
+
File.read("#{Rails.root}/#{file}").should_not match(/#{regexp}/m)
|
42
|
+
end
|
43
|
+
|
44
|
+
Then /^the file ([^ ]+) should be identical to the local (.+)$/ do |generated_file, source_file|
|
45
|
+
File.read("#{Rails.root}/#{generated_file}").should == File.read("#{File.dirname(__FILE__)}/../#{source_file}")
|
46
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "paths"))
|
2
|
+
|
3
|
+
Then(/^(.+?) should match route \/(.+?)$/) do |page, route|
|
4
|
+
regexp = route.gsub(/:(\w*?)id/,'\d+')
|
5
|
+
path_to(page).should =~ /#{regexp}/
|
6
|
+
end
|
7
|
+
|
8
|
+
When(/^I go to (.+)$/) do |page|
|
9
|
+
visit path_to(page)
|
10
|
+
end
|
11
|
+
|
12
|
+
Then(/^I should be at (.+)$/) do |page|
|
13
|
+
request.path.should =~ /#{path_to(page)}/
|
14
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# this file generated by script/generate pickle
|
2
|
+
|
3
|
+
# create a model
|
4
|
+
Given(/^#{capture_model} exists?(?: with #{capture_fields})?$/) do |name, fields|
|
5
|
+
create_model(name, fields)
|
6
|
+
end
|
7
|
+
|
8
|
+
# create n models
|
9
|
+
Given(/^(\d+) #{capture_plural_factory} exist(?: with #{capture_fields})?$/) do |count, plural_factory, fields|
|
10
|
+
count.to_i.times { create_model(plural_factory.singularize, fields) }
|
11
|
+
end
|
12
|
+
|
13
|
+
# create models from a table
|
14
|
+
Given(/^the following #{capture_plural_factory} exists?:?$/) do |plural_factory, table|
|
15
|
+
create_models_from_table(plural_factory, table)
|
16
|
+
end
|
17
|
+
|
18
|
+
# find a model
|
19
|
+
Then(/^#{capture_model} should exist(?: with #{capture_fields})?$/) do |name, fields|
|
20
|
+
find_model!(name, fields)
|
21
|
+
end
|
22
|
+
|
23
|
+
# not find a model
|
24
|
+
Then(/^#{capture_model} should not exist(?: with #{capture_fields})?$/) do |name, fields|
|
25
|
+
find_model(name, fields).should be_nil
|
26
|
+
end
|
27
|
+
|
28
|
+
# find models with a table
|
29
|
+
Then(/^the following #{capture_plural_factory} should exists?:?$/) do |plural_factory, table|
|
30
|
+
find_models_from_table(plural_factory, table).should_not be_any(&:nil?)
|
31
|
+
end
|
32
|
+
|
33
|
+
# find exactly n models
|
34
|
+
Then(/^(\d+) #{capture_plural_factory} should exist(?: with #{capture_fields})?$/) do |count, plural_factory, fields|
|
35
|
+
find_models(plural_factory.singularize, fields).size.should == count.to_i
|
36
|
+
end
|
37
|
+
|
38
|
+
# assert equality of models
|
39
|
+
Then(/^#{capture_model} should be #{capture_model}$/) do |a, b|
|
40
|
+
model!(a).should == model!(b)
|
41
|
+
end
|
42
|
+
|
43
|
+
# assert model is in another model's has_many assoc
|
44
|
+
Then(/^#{capture_model} should be (?:in|one of|amongst) #{capture_model}(?:'s)? (\w+)$/) do |target, owner, association|
|
45
|
+
model!(owner).send(association).should include(model!(target))
|
46
|
+
end
|
47
|
+
|
48
|
+
# assert model is not in another model's has_many assoc
|
49
|
+
Then(/^#{capture_model} should not be (?:in|one of|amongst) #{capture_model}(?:'s)? (\w+)$/) do |target, owner, association|
|
50
|
+
model!(owner).send(association).should_not include(model!(target))
|
51
|
+
end
|
52
|
+
|
53
|
+
# assert model is another model's has_one/belongs_to assoc
|
54
|
+
Then(/^#{capture_model} should be #{capture_model}(?:'s)? (\w+)$/) do |target, owner, association|
|
55
|
+
model!(owner).send(association).should == model!(target)
|
56
|
+
end
|
57
|
+
|
58
|
+
# assert model is not another model's has_one/belongs_to assoc
|
59
|
+
Then(/^#{capture_model} should not be #{capture_model}(?:'s)? (\w+)$/) do |target, owner, association|
|
60
|
+
model!(owner).send(association).should_not == model!(target)
|
61
|
+
end
|
62
|
+
|
63
|
+
# assert model.predicate?
|
64
|
+
Then(/^#{capture_model} should (?:be|have) (?:an? )?#{capture_predicate}$/) do |name, predicate|
|
65
|
+
if model!(name).respond_to?("has_#{predicate.gsub(' ', '_')}")
|
66
|
+
model!(name).should send("have_#{predicate.gsub(' ', '_')}")
|
67
|
+
else
|
68
|
+
model!(name).should send("be_#{predicate.gsub(' ', '_')}")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# assert not model.predicate?
|
73
|
+
Then(/^#{capture_model} should not (?:be|have) (?:an? )?#{capture_predicate}$/) do |name, predicate|
|
74
|
+
if model!(name).respond_to?("has_#{predicate.gsub(' ', '_')}")
|
75
|
+
model!(name).should_not send("have_#{predicate.gsub(' ', '_')}")
|
76
|
+
else
|
77
|
+
model!(name).should_not send("be_#{predicate.gsub(' ', '_')}")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# model.attribute.should eql(value)
|
82
|
+
# model.attribute.should_not eql(value)
|
83
|
+
Then(/^#{capture_model}'s (\w+) (should(?: not)?) be #{capture_value}$/) do |name, attribute, expectation, expected|
|
84
|
+
actual_value = model(name).send(attribute)
|
85
|
+
expectation = expectation.gsub(' ', '_')
|
86
|
+
|
87
|
+
case expected
|
88
|
+
when 'nil', 'true', 'false'
|
89
|
+
actual_value.send(expectation, send("be_#{expected}"))
|
90
|
+
when /^[+-]?[0-9_]+(\.\d+)?$/
|
91
|
+
actual_value.send(expectation, eql(expected.to_f))
|
92
|
+
else
|
93
|
+
actual_value.to_s.send(expectation, eql(eval(expected)))
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# assert size of association
|
98
|
+
Then /^#{capture_model} should have (\d+) (\w+)$/ do |name, size, association|
|
99
|
+
model!(name).send(association).size.should == size.to_i
|
100
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module EmailHelpers
|
2
|
+
# Maps a name to an email address. Used by email_steps
|
3
|
+
|
4
|
+
def email_for(to)
|
5
|
+
case to
|
6
|
+
|
7
|
+
# add your own name => email address mappings here
|
8
|
+
|
9
|
+
when /^#{capture_model}$/
|
10
|
+
model($1).email
|
11
|
+
|
12
|
+
when /^"(.*)"$/
|
13
|
+
$1
|
14
|
+
|
15
|
+
else
|
16
|
+
to
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
World(EmailHelpers)
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril.
|
2
|
+
# It is recommended to regenerate this file in the future when you upgrade to a
|
3
|
+
# newer version of cucumber-rails. Consider adding your own code to a new file
|
4
|
+
# instead of editing this one. Cucumber will automatically load all features/**/*.rb
|
5
|
+
# files.
|
6
|
+
|
7
|
+
ENV["RAILS_ENV"] ||= "cucumber"
|
8
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../cucumber_test_app/config/environment')
|
9
|
+
|
10
|
+
require 'cucumber/formatter/unicode' # Remove this line if you don't want Cucumber Unicode support
|
11
|
+
require 'cucumber/rails/world'
|
12
|
+
require 'cucumber/rails/active_record'
|
13
|
+
require 'cucumber/web/tableish'
|
14
|
+
|
15
|
+
require 'webrat'
|
16
|
+
require 'webrat/core/matchers'
|
17
|
+
|
18
|
+
Webrat.configure do |config|
|
19
|
+
config.mode = :rails
|
20
|
+
config.open_error_files = false # Set to true if you want error pages to pop up in the browser
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
# If you set this to false, any error raised from within your app will bubble
|
25
|
+
# up to your step definition and out to cucumber unless you catch it somewhere
|
26
|
+
# on the way. You can make Rails rescue errors and render error pages on a
|
27
|
+
# per-scenario basis by tagging a scenario or feature with the @allow-rescue tag.
|
28
|
+
#
|
29
|
+
# If you set this to true, Rails will rescue all errors and render error
|
30
|
+
# pages, more or less in the same way your application would behave in the
|
31
|
+
# default production environment. It's not recommended to do this for all
|
32
|
+
# of your scenarios, as this makes it hard to discover errors in your application.
|
33
|
+
ActionController::Base.allow_rescue = false
|
34
|
+
|
35
|
+
# If you set this to true, each scenario will run in a database transaction.
|
36
|
+
# You can still turn off transactions on a per-scenario basis, simply tagging
|
37
|
+
# a feature or scenario with the @no-txn tag. If you are using Capybara,
|
38
|
+
# tagging with @culerity or @javascript will also turn transactions off.
|
39
|
+
#
|
40
|
+
# If you set this to false, transactions will be off for all scenarios,
|
41
|
+
# regardless of whether you use @no-txn or not.
|
42
|
+
#
|
43
|
+
# Beware that turning transactions off will leave data in your database
|
44
|
+
# after each scenario, which can lead to hard-to-debug failures in
|
45
|
+
# subsequent scenarios. If you do this, we recommend you create a Before
|
46
|
+
# block that will explicitly put your database in a known state.
|
47
|
+
Cucumber::Rails::World.use_transactional_fixtures = true
|
48
|
+
|
49
|
+
# How to clean your database when transactions are turned off. See
|
50
|
+
# http://github.com/bmabey/database_cleaner for more info.
|
51
|
+
require 'database_cleaner'
|
52
|
+
DatabaseCleaner.strategy = :truncation
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module NavigationHelpers
|
2
|
+
# Maps a name to a path. Used by the
|
3
|
+
#
|
4
|
+
# When /^I go to (.+)$/ do |page_name|
|
5
|
+
#
|
6
|
+
# step definition in web_steps.rb
|
7
|
+
#
|
8
|
+
def path_to(page_name)
|
9
|
+
case page_name
|
10
|
+
|
11
|
+
when /the home\s?page/
|
12
|
+
'/'
|
13
|
+
|
14
|
+
# the following are examples using path_to_pickle
|
15
|
+
|
16
|
+
when /^#{capture_model}(?:'s)? page$/ # eg. the forum's page
|
17
|
+
path_to_pickle $1
|
18
|
+
|
19
|
+
when /^#{capture_model}(?:'s)? #{capture_model}(?:'s)? page$/ # eg. the forum's post's page
|
20
|
+
path_to_pickle $1, $2
|
21
|
+
|
22
|
+
when /^#{capture_model}(?:'s)? #{capture_model}'s (.+?) page$/ # eg. the forum's post's comments page
|
23
|
+
path_to_pickle $1, $2, :extra => $3 # or the forum's post's edit page
|
24
|
+
|
25
|
+
when /^#{capture_model}(?:'s)? (.+?) page$/ # eg. the forum's posts page
|
26
|
+
path_to_pickle $1, :extra => $2 # or the forum's edit page
|
27
|
+
|
28
|
+
# Add more mappings here.
|
29
|
+
# Here is an example that pulls values out of the Regexp:
|
30
|
+
#
|
31
|
+
# when /^(.*)'s profile page$/i
|
32
|
+
# user_profile_path(User.find_by_login($1))
|
33
|
+
|
34
|
+
else
|
35
|
+
begin
|
36
|
+
page_name =~ /the (.*) page/
|
37
|
+
path_components = $1.split(/\s+/)
|
38
|
+
self.send(path_components.push('path').join('_').to_sym)
|
39
|
+
rescue Object => e
|
40
|
+
raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
|
41
|
+
"Now, go and add a mapping in #{__FILE__}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
World(NavigationHelpers)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# this file generated by script/generate pickle [paths] [email]
|
2
|
+
#
|
3
|
+
# Make sure that you are loading your factory of choice in your cucumber environment
|
4
|
+
#
|
5
|
+
# For machinist add: features/support/machinist.rb
|
6
|
+
#
|
7
|
+
# require 'machinist/active_record' # or your chosen adaptor
|
8
|
+
# require File.dirname(__FILE__) + '/../../spec/blueprints' # or wherever your blueprints are
|
9
|
+
# Before { Sham.reset } # to reset Sham's seed between scenarios so each run has same random sequences
|
10
|
+
#
|
11
|
+
# For FactoryGirl add: features/support/factory_girl.rb
|
12
|
+
#
|
13
|
+
# require 'factory_girl'
|
14
|
+
# require File.dirname(__FILE__) + '/../../spec/factories' # or wherever your factories are
|
15
|
+
#
|
16
|
+
# You may also need to add gem dependencies on your factory of choice in <tt>config/environments/cucumber.rb</tt>
|
17
|
+
|
18
|
+
require 'pickle/world'
|
19
|
+
# Example of configuring pickle:
|
20
|
+
#
|
21
|
+
# Pickle.configure do |config|
|
22
|
+
# config.adapters = [:machinist]
|
23
|
+
# config.map 'I', 'myself', 'me', 'my', :to => 'user: "me"'
|
24
|
+
# end
|
25
|
+
require 'pickle/path/world'
|
26
|
+
require 'pickle/email/world'
|
data/init.rb
ADDED
File without changes
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'active_support/core_ext'
|
2
|
+
|
3
|
+
module Pickle
|
4
|
+
# Abstract Factory adapter class, if you have a factory type setup, you
|
5
|
+
# can easily create an adaptor to make it work with Pickle.
|
6
|
+
#
|
7
|
+
# The factory adaptor must have a #factories class method that returns
|
8
|
+
# its instances, and each instance must respond to:
|
9
|
+
#
|
10
|
+
# #name : identifies the factory by name (default is attr_reader)
|
11
|
+
# #klass : returns the associated model class for this factory (default is attr_reader)
|
12
|
+
# #create(attrs = {}) : returns a newly created object
|
13
|
+
class Adapter
|
14
|
+
attr_reader :name, :klass
|
15
|
+
|
16
|
+
def create(attrs = {})
|
17
|
+
raise NotImplementedError, "create and return an object with the given attributes"
|
18
|
+
end
|
19
|
+
|
20
|
+
if respond_to?(:class_attribute)
|
21
|
+
class_attribute :model_classes
|
22
|
+
else
|
23
|
+
cattr_writer :model_classes
|
24
|
+
end
|
25
|
+
|
26
|
+
self.model_classes = nil
|
27
|
+
|
28
|
+
# Include this module into your adapter
|
29
|
+
# this will register the adapter with pickle and it will be picked up for you
|
30
|
+
# To create an adapter you should create an inner constant "PickleAdapter"
|
31
|
+
#
|
32
|
+
# e.g. ActiveRecord::Base::PickleAdapter
|
33
|
+
#
|
34
|
+
# @see pickle/adapters/active_record
|
35
|
+
# @see pickle/adapters/datamapper
|
36
|
+
module Base
|
37
|
+
def self.included(base)
|
38
|
+
adapters << base
|
39
|
+
end
|
40
|
+
|
41
|
+
# A collection of registered adapters
|
42
|
+
def self.adapters
|
43
|
+
@@adapters ||= []
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class << self
|
48
|
+
def factories
|
49
|
+
raise NotImplementedError, "return an array of factory adapter objects"
|
50
|
+
end
|
51
|
+
|
52
|
+
def model_classes
|
53
|
+
@@model_classes ||= self::Base.adapters.map{ |a| a.model_classes }.flatten
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns the column names for the given ORM model class.
|
57
|
+
def column_names(klass)
|
58
|
+
klass.const_get(:PickleAdapter).column_names(klass)
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_model(klass, id)
|
62
|
+
klass.const_get(:PickleAdapter).get_model(klass, id)
|
63
|
+
end
|
64
|
+
|
65
|
+
def find_first_model(klass, conditions)
|
66
|
+
klass.const_get(:PickleAdapter).find_first_model(klass, conditions)
|
67
|
+
end
|
68
|
+
|
69
|
+
def find_all_models(klass, conditions)
|
70
|
+
klass.const_get(:PickleAdapter).find_all_models(klass, conditions)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# machinist adapter
|
75
|
+
class Machinist < Adapter
|
76
|
+
def self.factories
|
77
|
+
factories = []
|
78
|
+
model_classes.each do |klass|
|
79
|
+
if blueprints = klass.instance_variable_get('@blueprints')
|
80
|
+
blueprints.keys.each {|blueprint| factories << new(klass, blueprint)}
|
81
|
+
end
|
82
|
+
end
|
83
|
+
factories
|
84
|
+
end
|
85
|
+
|
86
|
+
def initialize(klass, blueprint)
|
87
|
+
@klass, @blueprint = klass, blueprint
|
88
|
+
@name = @klass.name.underscore.gsub('/','_')
|
89
|
+
@name = "#{@blueprint}_#{@name}" unless @blueprint == :master
|
90
|
+
end
|
91
|
+
|
92
|
+
def create(attrs = {})
|
93
|
+
@klass.send(:make, @blueprint, attrs)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# factory-girl adapter
|
98
|
+
class FactoryGirl < Adapter
|
99
|
+
def self.factories
|
100
|
+
(::Factory.factories.values rescue []).map {|factory| new(factory)}
|
101
|
+
end
|
102
|
+
|
103
|
+
def initialize(factory)
|
104
|
+
@klass, @name = factory.build_class, factory.factory_name.to_s
|
105
|
+
end
|
106
|
+
|
107
|
+
def create(attrs = {})
|
108
|
+
Factory.create(@name, attrs)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# fallback active record adapter
|
113
|
+
class ActiveRecord < Adapter
|
114
|
+
def self.factories
|
115
|
+
::ActiveRecord::Base::PickleAdapter.model_classes.map{|k| new(k)}
|
116
|
+
end
|
117
|
+
|
118
|
+
def initialize(klass)
|
119
|
+
@klass, @name = klass, klass.name.underscore.gsub('/','_')
|
120
|
+
end
|
121
|
+
|
122
|
+
def create(attrs = {})
|
123
|
+
@klass.send(:create!, attrs)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
begin
|
2
|
+
require 'activerecord'
|
3
|
+
rescue LoadError
|
4
|
+
require 'active_record'
|
5
|
+
end
|
6
|
+
|
7
|
+
class ActiveRecord::Base
|
8
|
+
module PickleAdapter
|
9
|
+
include Pickle::Adapter::Base
|
10
|
+
|
11
|
+
# Do not consider these to be part of the class list
|
12
|
+
def self.except_classes
|
13
|
+
@@except_classes ||= [
|
14
|
+
"CGI::Session::ActiveRecordStore::Session",
|
15
|
+
"ActiveRecord::SessionStore::Session"
|
16
|
+
]
|
17
|
+
end
|
18
|
+
|
19
|
+
# Gets a list of the available models for this adapter
|
20
|
+
def self.model_classes
|
21
|
+
::ActiveRecord::Base.__send__(:subclasses).select do |klass|
|
22
|
+
!klass.abstract_class? && klass.table_exists? && !except_classes.include?(klass.name)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# get a list of column names for a given class
|
27
|
+
def self.column_names(klass)
|
28
|
+
klass.column_names
|
29
|
+
end
|
30
|
+
|
31
|
+
# Get an instance by id of the model
|
32
|
+
def self.get_model(klass, id)
|
33
|
+
klass.find(id)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Find the first instance matching conditions
|
37
|
+
def self.find_first_model(klass, conditions)
|
38
|
+
klass.find(:first, :conditions => conditions)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Find all models matching conditions
|
42
|
+
def self.find_all_models(klass, conditions)
|
43
|
+
klass.find(:all, :conditions => conditions)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
|
3
|
+
module DataMapper::Resource
|
4
|
+
module PickleAdapter
|
5
|
+
include Pickle::Adapter::Base
|
6
|
+
|
7
|
+
# Do not consider these to be part of the class list
|
8
|
+
def self.except_classes
|
9
|
+
@@except_classes ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
# Gets a list of the available models for this adapter
|
13
|
+
def self.model_classes
|
14
|
+
::DataMapper::Model.descendants.to_a.select{|k| !except_classes.include?(k.name)}
|
15
|
+
end
|
16
|
+
|
17
|
+
# get a list of column names for a given class
|
18
|
+
def self.column_names(klass)
|
19
|
+
klass.properties.map(&:name)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Get an instance by id of the model
|
23
|
+
def self.get_model(klass, id)
|
24
|
+
klass.get(id)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Find the first instance matching conditions
|
28
|
+
def self.find_first_model(klass, conditions)
|
29
|
+
klass.first(conditions)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Find all models matching conditions
|
33
|
+
def self.find_all_models(klass, conditions)
|
34
|
+
klass.all(conditions)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Pickle
|
4
|
+
class Config
|
5
|
+
attr_writer :adapters, :factories, :mappings, :predicates
|
6
|
+
|
7
|
+
def initialize(&block)
|
8
|
+
configure(&block) if block_given?
|
9
|
+
end
|
10
|
+
|
11
|
+
def configure(&block)
|
12
|
+
yield(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def adapters
|
16
|
+
@adapters ||= [:machinist, :factory_girl, :active_record]
|
17
|
+
end
|
18
|
+
|
19
|
+
def adapter_classes
|
20
|
+
adapters.map {|a| a.is_a?(Class) ? a : "pickle/adapter/#{a}".classify.constantize}
|
21
|
+
end
|
22
|
+
|
23
|
+
def factories
|
24
|
+
@factories ||= adapter_classes.reverse.inject({}) do |factories, adapter|
|
25
|
+
factories.merge(adapter.factories.inject({}){|h, f| h.merge(f.name => f)})
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def predicates
|
30
|
+
@predicates ||= Pickle::Adapter.model_classes.map do |k|
|
31
|
+
k.public_instance_methods.select {|m| m =~ /\?$/} + Pickle::Adapter.column_names(k)
|
32
|
+
end.flatten.uniq
|
33
|
+
end
|
34
|
+
|
35
|
+
def mappings
|
36
|
+
@mappings ||= []
|
37
|
+
end
|
38
|
+
|
39
|
+
# Usage: map 'me', 'myself', 'I', :to => 'user: "me"'
|
40
|
+
def map(*args)
|
41
|
+
options = args.extract_options!
|
42
|
+
raise ArgumentError, "Usage: map 'search' [, 'search2', ...] :to => 'replace'" unless args.any? && options[:to].is_a?(String)
|
43
|
+
args.each do |search|
|
44
|
+
self.mappings << OpenStruct.new(:search => search, :replacement => options[:to])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Pickle
|
2
|
+
module Email
|
3
|
+
# add ability to parse emails
|
4
|
+
module Parser
|
5
|
+
def match_email
|
6
|
+
"(?:#{match_prefix}?(?:#{match_index} )?email)"
|
7
|
+
end
|
8
|
+
|
9
|
+
def capture_email
|
10
|
+
"(#{match_email})"
|
11
|
+
end
|
12
|
+
|
13
|
+
def capture_index_in_email
|
14
|
+
"(?:#{match_prefix}?(?:#{capture_index} )?email)"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'pickle'
|
2
|
+
require 'pickle/email'
|
3
|
+
require 'pickle/email/parser'
|
4
|
+
|
5
|
+
# add email parser expressions
|
6
|
+
Pickle::Parser.send :include, Pickle::Email::Parser
|
7
|
+
|
8
|
+
World(Pickle::Email)
|
9
|
+
|
10
|
+
# shortcuts for use in step regexps
|
11
|
+
class << self
|
12
|
+
delegate :capture_email, :to => 'Pickle.parser'
|
13
|
+
end
|