factory_girl_upgrader 0.1.0

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/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,49 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ factory_girl_upgrader (0.1.0)
5
+ activesupport (~> 3.0.10)
6
+ factory_girl (~> 2.0)
7
+ i18n (~> 0.6.0)
8
+ ruby_parser (~> 2.3.1)
9
+ ruby_scribe (~> 0.1.0)
10
+ ruby_transform (~> 0.1.0)
11
+ thor (~> 0.13)
12
+
13
+ GEM
14
+ remote: http://rubygems.org/
15
+ specs:
16
+ activesupport (3.0.10)
17
+ diff-lcs (1.1.3)
18
+ factory_girl (2.1.0)
19
+ i18n (0.6.0)
20
+ rspec (2.6.0)
21
+ rspec-core (~> 2.6.0)
22
+ rspec-expectations (~> 2.6.0)
23
+ rspec-mocks (~> 2.6.0)
24
+ rspec-core (2.6.4)
25
+ rspec-expectations (2.6.0)
26
+ diff-lcs (~> 1.1.2)
27
+ rspec-mocks (2.6.0)
28
+ ruby_parser (2.3.1)
29
+ sexp_processor (~> 3.0)
30
+ ruby_scribe (0.1.2)
31
+ activesupport (~> 3.0.10)
32
+ i18n (~> 0.6.0)
33
+ ruby_parser (~> 2.3.1)
34
+ thor (~> 0.13)
35
+ ruby_transform (0.1.1)
36
+ activesupport (~> 3.0.10)
37
+ i18n (~> 0.6.0)
38
+ ruby_parser (~> 2.3.1)
39
+ ruby_scribe (~> 0.1.0)
40
+ thor (~> 0.13)
41
+ sexp_processor (3.0.7)
42
+ thor (0.14.6)
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ factory_girl_upgrader!
49
+ rspec (~> 2.0)
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Ben Hughes
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,62 @@
1
+ = Factory Girl Upgrader
2
+
3
+ Uses ruby_parser and ruby_scribe to dynamically convert factory_girl factories in the V1 DSL into the V2 DSL.
4
+
5
+ == In-Progress
6
+
7
+ NOTE: This gem is not essentially unusable and is being continually worked on - more of a proof of concept for now.
8
+
9
+ == Command-Line Usage
10
+
11
+ The gem comes with a thor task that you can use to print out a converted version of any Ruby file containing factory_girl V1 code:
12
+
13
+ $ factory_girl_upgrader cat test_project.rb
14
+
15
+ == API Usage
16
+
17
+ This is built on the tree-walking base class RubyTransform::Transformer from the +ruby_transform+ project.
18
+ The principal transform, which is a composite of other more granular transforms, is +RSpecify::Transformer+.
19
+ Here's how it can be used in conjunction with +ruby_parser+:
20
+
21
+ sexp = RubyParser.new.parse(File.read(path))
22
+ sexp = FactoryGirl::Upgrader::Transformer.new.transform(sexp)
23
+
24
+ emitter = RubyScribe::Emitter.new
25
+ emitter.methods_without_parenthesis += ["factory"]
26
+ emitter.emit(sexp)
27
+
28
+ == Supported factory_girl V1 features:
29
+
30
+ * Simple attribute setting
31
+ * Sequences with a block
32
+ * Associations (without options)
33
+
34
+ NOTE: Indeed, this is only the basics. This will be expanded in the future to be a more comprehensive set of transformations.
35
+
36
+ == Limitations
37
+
38
+ To make this more DSL-friendly without parentheses requires expansion of the emitter configuration on ruby_scribe
39
+ (we need to be able to give ruby_scribe AST node hints on parentheses and block style).
40
+
41
+ == Example:
42
+
43
+ === Original (factory_girl V1):
44
+
45
+ Factory.define(:product) do |f|
46
+ f.association :category
47
+ f.sequence(:name) {|n| "Product #{n}" }
48
+ f.price 19.95
49
+ end
50
+
51
+
52
+ === Transformed (factory_girl V2):
53
+
54
+ FactoryGirl.define do
55
+ factory :product do
56
+ category
57
+ price(19.95)
58
+ sequence(:name) do |n|
59
+ "Product #{n}"
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,26 @@
1
+ require "thor"
2
+ require "factory_girl/upgrader"
3
+
4
+ module FactoryGirl
5
+ module Upgrader
6
+ class Runner < Thor
7
+ desc :cat, "Takes a single ruby file, parses it, and outputs the scribed version."
8
+ def cat(path)
9
+ sexp = RubyParser.new.parse(File.read(path))
10
+ sexp = FactoryGirl::Upgrader::Transformer.new.transform(sexp)
11
+ RubyScribe::Emitter.new.tap do |emitter|
12
+ emitter.methods_without_parenthesis += ["factory"]
13
+ puts emitter.emit(sexp)
14
+ end
15
+ end
16
+
17
+ protected
18
+
19
+ def expand_paths(paths = [])
20
+ paths.map do |path|
21
+ [path] + Dir[path + "**/*.rb"]
22
+ end.flatten.uniq.reject {|f| File.directory?(f) }
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,88 @@
1
+ module FactoryGirl
2
+ module Upgrader
3
+ class Transformer < RubyTransform::Transformer
4
+ def transform(e)
5
+ super(transform_factories(e))
6
+ end
7
+
8
+ def transform_factories(e)
9
+ if matches_define_factory?(e)
10
+ transform_factory_definition(e)
11
+ else
12
+ e
13
+ end
14
+ end
15
+
16
+ def matches_define_factory?(e)
17
+ e.is_a?(Sexp) && e.kind == :iter && # We're in a block
18
+ e.body.first.is_a?(Sexp) && e.body.first.kind == :call && # What's calling
19
+ e.body.first.body.first == s(:const, :Factory) && e.body.first.body.second == :define && # Factory.define
20
+ e.body.second.try(:kind) == :lasgn && # and we're passing a block variable for the factory
21
+ e.body.third.try(:kind) == :block # and we have a block
22
+ end
23
+
24
+ def transform_factory_definition(e)
25
+ factory_name = e.body.first.body.third.body.first.body.first # Yeah... we really need an OO AST model.
26
+ local_variable = e.body.second.body.first
27
+ block = e.body.third
28
+
29
+ s(:iter,
30
+ s(:call, s(:const, :FactoryGirl), :define, s(:arglist)), nil,
31
+ s(:iter,
32
+ s(:call, nil, :factory, s(:arglist, s(:lit, factory_name.to_sym))), nil,
33
+ transform_factory_definition_block(block, local_variable)
34
+ )
35
+ )
36
+ end
37
+
38
+ def transform_factory_definition_block(block, local_variable)
39
+ Sexp.new(*([:block] + block.body.map {|e|
40
+ case
41
+ when matches_factory_association?(e, local_variable)
42
+ transform_factory_association(e)
43
+ when matches_factory_sequence?(e, local_variable)
44
+ transform_factory_sequence(e)
45
+ when matches_factory_attribute?(e, local_variable)
46
+ transform_factory_attribute(e)
47
+ else
48
+ e
49
+ end
50
+ }))
51
+ end
52
+
53
+ # Factory Attributes:
54
+ def matches_factory_attribute?(e, local_variable)
55
+ e.is_a?(Sexp) && e.kind == :call && e.body.first.kind == :lvar && e.body.first.body.first == local_variable.to_sym
56
+ end
57
+
58
+ def transform_factory_attribute(e)
59
+ e.dup.tap do |sexp|
60
+ sexp[1] = nil
61
+ end
62
+ end
63
+
64
+ # Factory Sequences:
65
+ def matches_factory_sequence?(e, local_variable)
66
+ e.is_a?(Sexp) && e.kind == :iter && matches_factory_attribute?(e.body.first, local_variable)
67
+ end
68
+
69
+ def transform_factory_sequence(e)
70
+ e.dup.tap do |sexp|
71
+ sexp[1] = transform_factory_attribute(sexp[1])
72
+ end
73
+ end
74
+
75
+ # Factory Associations:
76
+ def matches_factory_association?(e, local_variable)
77
+ e.is_a?(Sexp) && e.kind == :call && e.body.first.kind == :lvar && e.body.first.body.first == local_variable.to_sym &&
78
+ e.body.second == :association
79
+ end
80
+
81
+ def transform_factory_association(e)
82
+ association_name = e.body.third.body.first.body.first
83
+
84
+ s(:call, nil, association_name, s(:arglist))
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,5 @@
1
+ module FactoryGirl
2
+ module Upgrader
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ require "rubygems"
2
+ require "factory_girl"
3
+ require "ruby_parser"
4
+ require "ruby_scribe"
5
+ require "ruby_transform"
6
+
7
+ require "factory_girl/upgrader/transformer"
8
+
9
+ Dir[File.join(File.dirname(__FILE__), "upgrader/transformers/**/*.rb")].each do |file|
10
+ require file
11
+ end
@@ -0,0 +1,28 @@
1
+ require "spec_helper"
2
+
3
+ describe FactoryGirl::Upgrader::Transformer do
4
+
5
+ describe "old factory_girl V1 factory" do
6
+ subject { '
7
+ Factory.define(:product) do |f|
8
+ f.association :category
9
+ f.price 19.95
10
+ f.sequence(:name) {|n| "Product #{n}" }
11
+ end
12
+ ' }
13
+
14
+ it { should transform_to("new factory_girl V2 factory", '
15
+ FactoryGirl.define do
16
+ factory(:product) do
17
+ category
18
+ price(19.95)
19
+
20
+ sequence(:name) do |n|
21
+ "Product #{n}"
22
+ end
23
+ end
24
+ end
25
+ ') }
26
+ end
27
+
28
+ end
@@ -0,0 +1,26 @@
1
+ RSpec::Matchers.define :transform_to do |desc, expected|
2
+ match do |actual|
3
+ actual_as_sexp = actual.is_a?(String) ? RubyParser.new.parse(actual) : actual
4
+ expected_as_sexp = expected.is_a?(String) ? RubyParser.new.parse(expected) : expected
5
+
6
+ transformer = described_class.is_a?(Class) ? described_class.new : described_class
7
+ @transformed = transformer.transform(actual_as_sexp)
8
+ @transformed == expected_as_sexp
9
+ end
10
+
11
+ failure_message_for_should do |actual|
12
+ "expected that:\n\n#{RubyParser.new.parse(actual)}\n\nwould transform to:\n\n#{RubyParser.new.parse(expected)}\n\nbut instead was:\n\n#{@transformed}\n\n#{transformed_as_ruby}"
13
+ end
14
+
15
+ failure_message_for_should_not do |actual|
16
+ "expected that:\n\n#{RubyParser.new.parse(actual)}\n\nwould not transform to:\n\n#{RubyParser.new.parse(expected)}\n\nbut instead was:\n\n#{@transformed}\n\n#{transformed_as_ruby}"
17
+ end
18
+
19
+ description do
20
+ "transform with to #{desc}"
21
+ end
22
+
23
+ def transformed_as_ruby
24
+ RubyScribe::Emitter.new.emit(@transformed) rescue nil
25
+ end
26
+ end
@@ -0,0 +1,10 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), "../lib"))
2
+
3
+ require "rubygems"
4
+ require "rspec"
5
+ require "factory_girl/upgrader"
6
+
7
+ # Requires supporting files with custom matchers and macros, etc,
8
+ # in ./support/ and its subdirectories.
9
+ Dir["#{File.dirname(__FILE__)}/matchers/**/*.rb"].each {|f| require f}
10
+
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: factory_girl_upgrader
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ben Hughes
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-11 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: &70286276079920 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '0.13'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70286276079920
25
+ - !ruby/object:Gem::Dependency
26
+ name: activesupport
27
+ requirement: &70286276078840 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 3.0.10
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70286276078840
36
+ - !ruby/object:Gem::Dependency
37
+ name: i18n
38
+ requirement: &70286276078100 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 0.6.0
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70286276078100
47
+ - !ruby/object:Gem::Dependency
48
+ name: factory_girl
49
+ requirement: &70286276077420 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70286276077420
58
+ - !ruby/object:Gem::Dependency
59
+ name: ruby_parser
60
+ requirement: &70286276076940 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 2.3.1
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *70286276076940
69
+ - !ruby/object:Gem::Dependency
70
+ name: ruby_scribe
71
+ requirement: &70286276076340 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 0.1.0
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: *70286276076340
80
+ - !ruby/object:Gem::Dependency
81
+ name: ruby_transform
82
+ requirement: &70286276075560 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ version: 0.1.0
88
+ type: :runtime
89
+ prerelease: false
90
+ version_requirements: *70286276075560
91
+ - !ruby/object:Gem::Dependency
92
+ name: rspec
93
+ requirement: &70286276074860 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ~>
97
+ - !ruby/object:Gem::Version
98
+ version: '2.0'
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *70286276074860
102
+ description: Uses ruby_parser and ruby_scribe to dynamically convert factory_girl
103
+ factories in the V1 DSL into the V2 DSL.
104
+ email: ben@railsgarden.com
105
+ executables: []
106
+ extensions: []
107
+ extra_rdoc_files: []
108
+ files:
109
+ - lib/factory_girl/upgrader/runner.rb
110
+ - lib/factory_girl/upgrader/transformer.rb
111
+ - lib/factory_girl/upgrader/version.rb
112
+ - lib/factory_girl/upgrader.rb
113
+ - spec/factory_girl/upgrader/transformer_spec.rb
114
+ - spec/matchers/should_transform_to.rb
115
+ - spec/spec_helper.rb
116
+ - Gemfile
117
+ - Gemfile.lock
118
+ - LICENSE
119
+ - README.rdoc
120
+ homepage: http://github.com/rubiety/factory_girl_upgrader
121
+ licenses: []
122
+ post_install_message:
123
+ rdoc_options: []
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ! '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
+ none: false
134
+ requirements:
135
+ - - ! '>='
136
+ - !ruby/object:Gem::Version
137
+ version: 1.3.4
138
+ requirements: []
139
+ rubyforge_project: factory_girl_upgrader
140
+ rubygems_version: 1.8.10
141
+ signing_key:
142
+ specification_version: 3
143
+ summary: Converts factory_girl V1 DSL factories to factory_girl V2 DSL.
144
+ test_files: []