spbtv_pickle 0.5.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 (80) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +10 -0
  5. data/Gemfile +3 -0
  6. data/Gemfile.lock.development +158 -0
  7. data/History.txt +499 -0
  8. data/License.txt +20 -0
  9. data/README.md +566 -0
  10. data/Rakefile +20 -0
  11. data/Rakefile.d/cucumber.rake +27 -0
  12. data/Rakefile.d/release.rake +44 -0
  13. data/Rakefile.d/rspec.rake +3 -0
  14. data/Rakefile.d/yard.rake +5 -0
  15. data/Todo.txt +3 -0
  16. data/autotest/discover.rb +9 -0
  17. data/features/app/app.rb +128 -0
  18. data/features/app/blueprints.rb +6 -0
  19. data/features/app/fabricators.rb +6 -0
  20. data/features/app/factories.rb +25 -0
  21. data/features/app/views/notifier/email.erb +1 -0
  22. data/features/app/views/notifier/user_email.erb +6 -0
  23. data/features/email/email.feature +64 -0
  24. data/features/generator/generators.feature +59 -0
  25. data/features/path/models_page.feature +44 -0
  26. data/features/path/named_route_page.feature +10 -0
  27. data/features/pickle/create_from_active_record.feature +83 -0
  28. data/features/pickle/create_from_fabrication.feature +46 -0
  29. data/features/pickle/create_from_factory_girl.feature +66 -0
  30. data/features/pickle/create_from_machinist.feature +46 -0
  31. data/features/step_definitions/email_steps.rb +1 -0
  32. data/features/step_definitions/extra_email_steps.rb +12 -0
  33. data/features/step_definitions/fork_steps.rb +4 -0
  34. data/features/step_definitions/generator_steps.rb +52 -0
  35. data/features/step_definitions/path_steps.rb +14 -0
  36. data/features/step_definitions/pickle_steps.rb +1 -0
  37. data/features/step_definitions/raise_error_steps.rb +7 -0
  38. data/features/support/email.rb +1 -0
  39. data/features/support/env.rb +14 -0
  40. data/features/support/paths.rb +47 -0
  41. data/features/support/pickle.rb +27 -0
  42. data/features/support/pickle_app.rb +4 -0
  43. data/init.rb +0 -0
  44. data/lib/generators/pickle_generator.rb +44 -0
  45. data/lib/pickle.rb +26 -0
  46. data/lib/pickle/adapter.rb +183 -0
  47. data/lib/pickle/adapters/active_record.rb +67 -0
  48. data/lib/pickle/adapters/data_mapper.rb +42 -0
  49. data/lib/pickle/adapters/mongoid.rb +54 -0
  50. data/lib/pickle/config.rb +49 -0
  51. data/lib/pickle/email.rb +87 -0
  52. data/lib/pickle/email/parser.rb +18 -0
  53. data/lib/pickle/email/world.rb +13 -0
  54. data/lib/pickle/parser.rb +65 -0
  55. data/lib/pickle/parser/matchers.rb +87 -0
  56. data/lib/pickle/path.rb +45 -0
  57. data/lib/pickle/path/world.rb +5 -0
  58. data/lib/pickle/session.rb +244 -0
  59. data/lib/pickle/session/parser.rb +34 -0
  60. data/lib/pickle/version.rb +3 -0
  61. data/lib/pickle/world.rb +14 -0
  62. data/lib/spbtv_pickle.rb +1 -0
  63. data/rails_generators/pickle/pickle_generator.rb +31 -0
  64. data/rails_generators/pickle/templates/email.rb +21 -0
  65. data/rails_generators/pickle/templates/email_steps.rb +65 -0
  66. data/rails_generators/pickle/templates/paths.rb +47 -0
  67. data/rails_generators/pickle/templates/pickle.rb +29 -0
  68. data/rails_generators/pickle/templates/pickle_steps.rb +105 -0
  69. data/spbtv_pickle.gemspec +38 -0
  70. data/spec/pickle/adapter_spec.rb +203 -0
  71. data/spec/pickle/config_spec.rb +112 -0
  72. data/spec/pickle/email/parser_spec.rb +51 -0
  73. data/spec/pickle/email_spec.rb +187 -0
  74. data/spec/pickle/parser/matchers_spec.rb +70 -0
  75. data/spec/pickle/parser_spec.rb +165 -0
  76. data/spec/pickle/path_spec.rb +120 -0
  77. data/spec/pickle/session_spec.rb +448 -0
  78. data/spec/pickle_spec.rb +24 -0
  79. data/spec/spec_helper.rb +78 -0
  80. metadata +370 -0
@@ -0,0 +1,4 @@
1
+ Pickle.configure do |c|
2
+ c.map 'I', :to => 'user: "me"'
3
+ c.map 'killah fork', :to => 'fancy fork: "of cornwood"'
4
+ end
data/init.rb ADDED
File without changes
@@ -0,0 +1,44 @@
1
+ require 'rails/generators'
2
+
3
+ class PickleGenerator < Rails::Generators::Base
4
+ desc "Generates Pickle step files."
5
+
6
+ # Use the same templates as Rails 2 generator
7
+ source_root File.expand_path("../../../rails_generators/pickle/templates", __FILE__)
8
+
9
+ class_option :paths, :desc => "Generate features/support/paths.rb file.", :type => :boolean
10
+ class_option :email, :desc => "Generate features/step_definitions/email_steps.rb file", :type => :boolean
11
+
12
+ def create_directories
13
+ empty_directory "features/step_definitions"
14
+ empty_directory "features/support"
15
+ end
16
+
17
+ def copy_pickle_steps_file
18
+ template "pickle_steps.rb", "features/step_definitions/pickle_steps.rb"
19
+ template "pickle.rb", "features/support/pickle.rb"
20
+ end
21
+
22
+ def copy_paths_file
23
+ return unless options.paths?
24
+ template "paths.rb", "features/support/paths.rb"
25
+ end
26
+
27
+ def copy_email_steps_file
28
+ return unless options.email?
29
+ template "email_steps.rb", "features/step_definitions/email_steps.rb"
30
+ template "email.rb", "features/support/email.rb"
31
+ end
32
+
33
+
34
+ private
35
+
36
+ # Compatibility methods for Rails 2 templates
37
+ def pickle_path
38
+ options.paths?
39
+ end
40
+
41
+ def pickle_email
42
+ options.email?
43
+ end
44
+ end
@@ -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
@@ -0,0 +1,183 @@
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 ORM 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
+ # @see pickle/adapters/mongoid
37
+ module Base
38
+ def self.included(base)
39
+ adapters << base
40
+ end
41
+
42
+ # A collection of registered adapters
43
+ def self.adapters
44
+ @@adapters ||= []
45
+ end
46
+ end
47
+
48
+ class << self
49
+ def factories
50
+ raise NotImplementedError, "return an array of factory adapter objects"
51
+ end
52
+
53
+ def model_classes
54
+ @@model_classes ||= self::Base.adapters.map{ |a| a.model_classes }.flatten
55
+ end
56
+
57
+ # Returns the column names for the given ORM model class.
58
+ def column_names(klass)
59
+ klass.const_get(:PickleAdapter).column_names(klass)
60
+ end
61
+
62
+ def get_model(klass, id)
63
+ klass.const_get(:PickleAdapter).get_model(klass, id)
64
+ end
65
+
66
+ def find_first_model(klass, conditions)
67
+ klass.const_get(:PickleAdapter).find_first_model(klass, conditions)
68
+ end
69
+
70
+ def find_all_models(klass, conditions)
71
+ klass.const_get(:PickleAdapter).find_all_models(klass, conditions)
72
+ end
73
+
74
+ def create_model(klass, attributes)
75
+ klass.const_get(:PickleAdapter).create_model(klass, attributes)
76
+ end
77
+ end
78
+
79
+ # machinist adapter
80
+ class Machinist < Adapter
81
+ def self.factories
82
+ factories = []
83
+ model_classes.each do |klass|
84
+ if blueprints = klass.instance_variable_get('@blueprints')
85
+ blueprints.keys.each {|blueprint| factories << new(klass, blueprint)}
86
+ end
87
+ end
88
+ factories
89
+ end
90
+
91
+ def initialize(klass, blueprint)
92
+ @klass, @blueprint = klass, blueprint
93
+ @name = @klass.name.underscore.gsub('/','_')
94
+ @name = "#{@blueprint}_#{@name}" unless @blueprint == :master
95
+ end
96
+
97
+ def create(attrs = {})
98
+ @klass.send(:make!, @blueprint, attrs)
99
+ end
100
+ end
101
+
102
+ # factory-girl adapter
103
+ class FactoryGirl < Adapter
104
+ def self.factories
105
+ if defined? ::FactoryGirl
106
+ factories = []
107
+ ::FactoryGirl.factories.each do |factory|
108
+ factory.names.each do |name|
109
+ factories << new(factory, name)
110
+ end
111
+ end
112
+ factories
113
+ else
114
+ (::Factory.factories.values rescue []).map {|factory| new(factory)}
115
+ end
116
+ end
117
+
118
+ def initialize(factory, factory_name)
119
+ if defined? ::FactoryGirl
120
+ @klass, @name = factory.build_class, factory_name.to_s
121
+ else
122
+ @klass, @name = factory.build_class, factory.factory_name.to_s
123
+ end
124
+ end
125
+
126
+ def create(attrs = {})
127
+ if defined? ::FactoryGirl
128
+ ::FactoryGirl.create(@name, attrs)
129
+ else
130
+ Factory(@name, attrs)
131
+ end
132
+ end
133
+
134
+ def build(attrs = {})
135
+ if defined? ::FactoryGirl
136
+ ::FactoryGirl.build(@name, attrs)
137
+ else
138
+ Factory.build(@name, attrs)
139
+ end
140
+ end
141
+ end
142
+
143
+ # fabrication adapter
144
+ class Fabrication < Adapter
145
+ def self.factories
146
+ if defined? ::Fabrication
147
+ ::Fabrication.manager.load_definitions if ::Fabrication.manager.schematics.empty?
148
+ ::Fabrication.manager.schematics.map { |name, klass| new([name, klass]) }
149
+ else
150
+ []
151
+ end
152
+ end
153
+
154
+ def initialize(factory)
155
+ if defined? ::Fabrication
156
+ @klass, @name = factory[1].klass, factory[0].to_s
157
+ end
158
+ end
159
+
160
+ def create(attrs = {})
161
+ if defined? ::Fabrication
162
+ Fabricate(@name.to_sym, attrs)
163
+ end
164
+ end
165
+ end
166
+
167
+ # ORM adapter. If you have no factory adapter, you can use this adapter to
168
+ # use your orm as 'factory' - ie create objects
169
+ class Orm < Adapter
170
+ def self.factories
171
+ model_classes.map{|k| new(k)}
172
+ end
173
+
174
+ def initialize(klass)
175
+ @klass, @name = klass, klass.name.underscore.gsub('/','_')
176
+ end
177
+
178
+ def create(attrs = {})
179
+ Pickle::Adapter.create_model(@klass, attrs)
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,67 @@
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
+ if ::ActiveRecord::Base.respond_to?(:descendants)
22
+ klasses = ::ActiveRecord::Base.descendants # Rails 3, 4
23
+ else
24
+ klasses = ::ActiveRecord::Base.subclasses # Rails 2
25
+ end
26
+
27
+ klasses.select do |klass|
28
+ !klass.abstract_class? && klass.table_exists? && !except_classes.include?(klass.name)
29
+ end
30
+ end
31
+
32
+ # get a list of column names for a given class
33
+ def self.column_names(klass)
34
+ klass.column_names
35
+ end
36
+
37
+ # Get an instance by id of the model
38
+ def self.get_model(klass, id)
39
+ klass.find(id)
40
+ end
41
+
42
+ # Find the first instance matching conditions
43
+ def self.find_first_model(klass, conditions)
44
+ if defined? ::ActiveRecord::Relation
45
+ klass.where(conditions).first # Rails 3, 4
46
+ else
47
+ klass.find(:first,
48
+ :conditions => conditions) # Rails 2
49
+ end
50
+ end
51
+
52
+ # Find all models matching conditions
53
+ def self.find_all_models(klass, conditions)
54
+ if defined? ::ActiveRecord::Relation
55
+ klass.where(conditions) # Rails 3, 4
56
+ else
57
+ klass.find(:all,
58
+ :conditions => conditions) # Rails 2
59
+ end
60
+ end
61
+
62
+ # Create a model using attributes
63
+ def self.create_model(klass, attributes)
64
+ klass.create!(attributes)
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,42 @@
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
+
37
+ # Create a model using attributes
38
+ def self.create_model(klass, attributes)
39
+ klass.create(attributes)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,54 @@
1
+ require 'mongoid'
2
+
3
+ module Mongoid
4
+ module Document
5
+ module PickleAdapter
6
+ include Pickle::Adapter::Base
7
+
8
+ # Do not consider these to be part of the class list
9
+ def self.except_classes
10
+ @@except_classes ||= []
11
+ end
12
+
13
+ # Gets a list of the available models for this adapter
14
+ def self.model_classes
15
+ ObjectSpace.each_object(Class).to_a.select do |klass|
16
+ klass.name && klass.ancestors.include?(Mongoid::Document)
17
+ end
18
+ end
19
+
20
+ # get a list of column names for a given class
21
+ def self.column_names(klass)
22
+ klass.try(:fields).try(:keys) || []
23
+ end
24
+
25
+ # Get an instance by id of the model
26
+ def self.get_model(klass, id)
27
+ klass.find(id)
28
+ end
29
+
30
+ # Find the first instance matching conditions
31
+ def self.find_first_model(klass, conditions)
32
+ if defined? ::Mongoid::Criteria
33
+ klass.where(conditions).first
34
+ else
35
+ klass.first(:conditions => conditions)
36
+ end
37
+ end
38
+
39
+ # Find all models matching conditions
40
+ def self.find_all_models(klass, conditions)
41
+ if defined? ::Mongoid::Criteria
42
+ klass.where(conditions).to_a
43
+ else
44
+ klass.all(:conditions => conditions)
45
+ end
46
+ end
47
+
48
+ # Create a model with given attributes
49
+ def self.create_model(klass, attributes)
50
+ klass.create!(attributes)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,49 @@
1
+ module Pickle
2
+ class Config
3
+ attr_writer :adapters, :factories, :mappings, :predicates
4
+
5
+ def initialize(&block)
6
+ configure(&block) if block_given?
7
+ end
8
+
9
+ def configure(&block)
10
+ yield(self)
11
+ end
12
+
13
+ def adapters
14
+ @adapters ||= [:machinist, :factory_girl, :fabrication, :orm]
15
+ end
16
+
17
+ def adapter_classes
18
+ adapters.map {|a| a.is_a?(Class) ? a : "pickle/adapter/#{a}".classify.constantize}
19
+ end
20
+
21
+ def factories
22
+ @factories ||= adapter_classes.reverse.inject({}) do |factories, adapter|
23
+ factories.merge(adapter.factories.inject({}){|h, f| h.merge(f.name => f)})
24
+ end
25
+ end
26
+
27
+ def predicates
28
+ @predicates ||= Pickle::Adapter.model_classes.map do |k|
29
+ k.public_instance_methods.select {|m| m =~ /\?$/} + Pickle::Adapter.column_names(k)
30
+ end.flatten.uniq
31
+ end
32
+
33
+ class Mapping < Struct.new(:search, :replacement)
34
+ end
35
+
36
+ def mappings
37
+ @mappings ||= []
38
+ end
39
+
40
+ # Usage: map 'me', 'myself', 'I', :to => 'user: "me"'
41
+ def map(*args)
42
+ options = args.extract_options!
43
+ raise ArgumentError, "Usage: map 'search' [, 'search2', ...] :to => 'replace'" unless args.any? && options[:to].is_a?(String)
44
+ args.each do |search|
45
+ self.mappings << Mapping.new(search, options[:to])
46
+ end
47
+ end
48
+ end
49
+ end