arel_converter 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +124 -0
  7. data/Rakefile +8 -0
  8. data/TODO.md +6 -0
  9. data/arel_converter.gemspec +28 -0
  10. data/bin/arel_convert +7 -0
  11. data/lib/arel_converter.rb +25 -0
  12. data/lib/arel_converter/active_record_finder.rb +19 -0
  13. data/lib/arel_converter/association.rb +21 -0
  14. data/lib/arel_converter/base.rb +76 -0
  15. data/lib/arel_converter/command.rb +50 -0
  16. data/lib/arel_converter/formatter.rb +46 -0
  17. data/lib/arel_converter/replacement.rb +21 -0
  18. data/lib/arel_converter/scope.rb +22 -0
  19. data/lib/arel_converter/translators/association.rb +71 -0
  20. data/lib/arel_converter/translators/base.rb +49 -0
  21. data/lib/arel_converter/translators/finder.rb +28 -0
  22. data/lib/arel_converter/translators/options.rb +172 -0
  23. data/lib/arel_converter/translators/scope.rb +28 -0
  24. data/lib/arel_converter/version.rb +3 -0
  25. data/spec/fixtures/grep_matching.rb +38 -0
  26. data/spec/fixtures/my/base_fixture.rb +0 -0
  27. data/spec/fixtures/my/files/controller.rb +0 -0
  28. data/spec/fixtures/my/files/model.rb +0 -0
  29. data/spec/fixtures/my/files/not_source.txt +0 -0
  30. data/spec/fixtures/my/files/source.rb +0 -0
  31. data/spec/lib/arel_converter/active_record_finder_spec.rb +26 -0
  32. data/spec/lib/arel_converter/association_spec.rb +36 -0
  33. data/spec/lib/arel_converter/base_spec.rb +130 -0
  34. data/spec/lib/arel_converter/command_spec.rb +7 -0
  35. data/spec/lib/arel_converter/replacement_spec.rb +22 -0
  36. data/spec/lib/arel_converter/scope_spec.rb +40 -0
  37. data/spec/lib/arel_converter/translators/association_spec.rb +110 -0
  38. data/spec/lib/arel_converter/translators/finder_spec.rb +88 -0
  39. data/spec/lib/arel_converter/translators/options_spec.rb +104 -0
  40. data/spec/lib/arel_converter/translators/scope_spec.rb +130 -0
  41. data/spec/spec_helper.rb +20 -0
  42. metadata +186 -0
File without changes
File without changes
File without changes
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe ArelConverter::ActiveRecordFinder do
4
+
5
+ let(:converter) { ArelConverter::ActiveRecordFinder.new('spec/fixtures/grep_matching.rb') }
6
+
7
+ let(:valid_lines) { [" Model.find(:all)", " Model.find(:all, :conditions => {:active => true})", " Model.find(:first)", " Model.find(:all, :conditions => {:active => true})", " Model.all(:conditions => {:active => false})", " Model.first(:conditions => {:active => false})"] }
8
+
9
+ it 'should find all the valid lines from a file' do
10
+ expect(converter.grep_matches_in_file('spec/fixtures/grep_matching.rb')).to eq(valid_lines)
11
+ end
12
+
13
+ describe '#process_lines' do
14
+ it 'should pass of translation to the ActiveRecordFinder translator' do
15
+ expect(ArelConverter::Translator::Finder).to receive(:translate).with('MyModel.find(:all)').and_return('scope(:active)')
16
+ converter.process_line('MyModel.find(:all)')
17
+ end
18
+
19
+ it 'should remove surrounding brackets for clarity' do
20
+ allow(ArelConverter::Translator::Finder).to receive(:translate).and_return('translated line')
21
+ expect(converter.process_line('MyModel.find(:all)')).to eq('translated line')
22
+ end
23
+ end
24
+
25
+ end
26
+
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe ArelConverter::Association do
4
+
5
+ let(:converter) { ArelConverter::Association.new('spec/fixtures/grep_matching.rb') }
6
+
7
+ let(:valid_lines) { [" has_many :posts", " has_and_belongs_to_many :articles", " has_one :author", " belongs_to :blog"] }
8
+ let(:invalid_lines) { [" has_many = 'Test cases'"] }
9
+ let(:all_lines) { valid_lines + invalid_lines }
10
+
11
+ it 'should find all the valid lines from a file' do
12
+ expect(converter.grep_matches_in_file('spec/fixtures/grep_matching.rb')).to eq(all_lines)
13
+ end
14
+
15
+ describe 'verify lines' do
16
+ it 'should know of valid lines' do
17
+ valid_lines.each do |l|
18
+ expect(converter.verify_line(l)).to be_true
19
+ end
20
+ end
21
+
22
+ it 'should know of invalid lines' do
23
+ invalid_lines.each do |l|
24
+ expect(converter.verify_line(l)).to be_false
25
+ end
26
+ end
27
+ end
28
+
29
+ describe '#process_lines' do
30
+ it 'should pass of translation to the Association translator' do
31
+ expect(ArelConverter::Translator::Association).to receive(:translate).with('my line')
32
+ converter.process_line('my line')
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,130 @@
1
+ require 'spec_helper'
2
+
3
+ describe ArelConverter::Base do
4
+
5
+
6
+ let(:converter) { ArelConverter::Base.new('.') }
7
+ let(:file_converter) { ArelConverter::Base.new('spec/fixtures/my/files/source.rb') }
8
+ let(:dir_converter) { ArelConverter::Base.new('spec/fixtures/my') }
9
+
10
+ let(:replacement_good) { ArelConverter::Replacement.new('Good Line', 'PROCESSED') }
11
+ let(:replacemetn_bad) { ArelConverter::Replacement.new('Pretty Line', 'PROCESSED') }
12
+ let(:replacement_error) {
13
+ r = ArelConverter::Replacement.new('Invalid Line')
14
+ r.error = "This is no good!"
15
+ r
16
+ }
17
+ let(:replacements) { [replacement_good, replacemetn_bad] }
18
+ let(:replacements_with_errors) { [replacement_good, replacement_error, replacemetn_bad] }
19
+
20
+ describe 'executes against the proper type' do
21
+ it 'should execute against a single file' do
22
+ expect(file_converter).to receive(:parse_file).with('spec/fixtures/my/files/source.rb')
23
+ expect(file_converter).not_to receive(:parse_directory)
24
+ file_converter.run!
25
+ end
26
+
27
+ it 'should execute against a directory' do
28
+ expect(dir_converter).to receive(:parse_directory).with('spec/fixtures/my')
29
+ dir_converter.run!
30
+ end
31
+ end
32
+
33
+ describe 'executing against a directory' do
34
+ let(:files) { Dir['spec/fixtures/my/**/*.rb'].map {|file| file } }
35
+
36
+ it 'should execute against all ruby files in the supplied directory' do
37
+ files.each do |f|
38
+ expect(dir_converter).to receive(:parse_file).with(f)
39
+ end
40
+ dir_converter.run!
41
+ end
42
+ end
43
+
44
+ describe 'parsing a file' do
45
+
46
+ let(:matched_lines) { ['a','b'] }
47
+ let(:results) { ['result 1', 'result 2'] }
48
+
49
+ before do
50
+ file_converter.stub(:update_file)
51
+ allow(file_converter).to receive(:grep_matches_in_file).and_return(matched_lines)
52
+ allow(file_converter).to receive(:process_lines).with(matched_lines).and_return(results)
53
+ allow(ArelConverter::Formatter).to receive(:alert)
54
+ end
55
+
56
+ it "should grep the file for matches and do nothing if there are none" do
57
+ expect(file_converter).to receive(:grep_matches_in_file).and_return([])
58
+ expect(file_converter).to_not receive(:process_lines)
59
+ file_converter.run!
60
+ end
61
+
62
+ it 'should process any lines that are found' do
63
+ expect(file_converter).to receive(:grep_matches_in_file).and_return(matched_lines)
64
+ expect(file_converter).to receive(:process_lines).with(matched_lines).and_return([])
65
+ file_converter.run!
66
+ end
67
+
68
+ it 'should pass to the formatter any results' do
69
+ expect(ArelConverter::Formatter).to receive(:alert).with('spec/fixtures/my/files/source.rb',results)
70
+ file_converter.run!
71
+ end
72
+
73
+ it 'should update the file' do
74
+ allow(file_converter).to receive(:process_lines).with(matched_lines).and_return(results)
75
+ expect(file_converter).to receive(:update_file).with('spec/fixtures/my/files/source.rb',results)
76
+ file_converter.run!
77
+ end
78
+
79
+ it 'should not update the files if configured not to' do
80
+ allow(file_converter).to receive(:process_lines).with(matched_lines).and_return(results)
81
+ expect(ArelConverter::Formatter).to receive(:alert)
82
+ expect(file_converter).to_not receive(:update_file)
83
+ file_converter.options[:dry_run] = true
84
+ file_converter.run!
85
+ end
86
+
87
+ it 'should not output or update if there are no results' do
88
+ allow(file_converter).to receive(:process_lines).and_return([])
89
+ expect(ArelConverter::Formatter).to_not receive(:alert)
90
+ expect(file_converter).to_not receive(:update_file)
91
+ file_converter.run!
92
+ end
93
+
94
+ end
95
+
96
+ describe 'processing lines' do
97
+ let(:lines) { ['Good Line', 'Invalid Line', 'Pretty Line'] }
98
+
99
+ before do
100
+ allow(converter).to receive(:process_line).and_return('PROCESSED')
101
+ end
102
+
103
+ it 'should return only lines that are valid ' do
104
+ allow(converter).to receive(:verify_line).and_return(true, false, true)
105
+ expect(converter.process_lines(lines)).to eq(replacements)
106
+ end
107
+
108
+ it 'should return only lines that do not raise a SyntaxError' do
109
+ allow(converter).to receive(:process_line).with('Invalid Line').and_raise(SyntaxError)
110
+ expect(converter.process_lines(lines)).to eq(replacements_with_errors)
111
+ end
112
+
113
+ it 'should only return lines that do not raise other exceptions' do
114
+ allow(converter).to receive(:process_line).with('Invalid Line').and_raise(RuntimeError)
115
+ expect(converter.process_lines(lines)).to eq(replacements_with_errors)
116
+ end
117
+ end
118
+
119
+ describe 'updating files' do
120
+
121
+ it 'should do replacement on the proper lines' do
122
+ file_handle = double
123
+ allow(File).to receive(:read).and_return("Good Line\n\nNext Line\n\nThird Line\n\nPretty Line")
124
+ expect(File).to receive(:open).and_yield(file_handle)
125
+ expect(file_handle).to receive(:puts).with("PROCESSED\n\nNext Line\n\nThird Line\n\nPROCESSED")
126
+ converter.update_file('my/file.rb', replacements_with_errors)
127
+ end
128
+
129
+ end
130
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe ArelConverter::Command do
4
+
5
+ it 'needs to be tested'
6
+
7
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe ArelConverter::Replacement do
4
+ let(:r) { ArelConverter::Replacement.new('old', 'new') }
5
+
6
+ it 'should initialize correctly' do
7
+ expect(r.old_content).to eq('old')
8
+ expect(r.new_content).to eq('new')
9
+ end
10
+
11
+ it 'should be valid if error is nil' do
12
+ r.error = nil
13
+ expect(r).to be_valid
14
+ end
15
+
16
+ it 'should be invalid if error is set' do
17
+ r.error = 'Some Random Error'
18
+ expect(r).not_to be_valid
19
+ end
20
+ end
21
+
22
+
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe ArelConverter::Scope do
4
+
5
+ let(:converter) { ArelConverter::Scope.new('spec/fixtures/grep_matching.rb') }
6
+
7
+ let(:valid_lines) { [" scope :active, :conditions => ['status NOT IN (?)', ['closed','cancelled']]"] }
8
+ let(:invalid_lines) { [" scope = 'Test cases'"] }
9
+
10
+ it 'should find all the valid lines from a file' do
11
+ expect(converter.grep_matches_in_file('spec/fixtures/grep_matching.rb')).to eq(valid_lines)
12
+ end
13
+
14
+ describe 'verify lines' do
15
+ it 'should know of valid lines' do
16
+ valid_lines.each do |l|
17
+ expect(converter.verify_line(l)).to be_true
18
+ end
19
+ end
20
+
21
+ it 'should know of invalid lines' do
22
+ invalid_lines.each do |l|
23
+ expect(converter.verify_line(l)).to be_false
24
+ end
25
+ end
26
+ end
27
+
28
+ describe '#process_lines' do
29
+ it 'should pass of translation to the Scope translator' do
30
+ expect(ArelConverter::Translator::Scope).to receive(:translate).with('scope :active').and_return('scope(:active)')
31
+ converter.process_line('scope :active')
32
+ end
33
+
34
+ it 'should remove surrounding brackets for clarity' do
35
+ allow(ArelConverter::Translator::Scope).to receive(:translate).and_return('scope(:active)')
36
+ expect(converter.process_line('scope :active')).to eq('scope :active')
37
+ end
38
+ end
39
+
40
+ end
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+
3
+ describe ArelConverter::Translator::Association do
4
+
5
+ context 'parsing belongs_to' do
6
+ it 'should not change if there are no options' do
7
+ assoc = %Q{belongs_to :post}
8
+ expect(ArelConverter::Translator::Association.translate(assoc)).to eq(%Q{belongs_to :post})
9
+ end
10
+
11
+ it 'should translate the options' do
12
+ assoc = %Q{belongs_to :post, :class_name => "Article", :foreign_key => "article_id"}
13
+ expect(ArelConverter::Translator::Association.translate(assoc)).to eq(%Q{belongs_to :post, class_name: "Article", foreign_key: "article_id"})
14
+ end
15
+
16
+ it 'should translate polymorphic correctly' do
17
+ assoc = %Q{belongs_to :post, :polymorphic => true}
18
+ expect(ArelConverter::Translator::Association.translate(assoc)).to eq(%Q{belongs_to :post, polymorphic: true})
19
+ end
20
+ end
21
+
22
+ context 'parsing has_and_belongs_to_many' do
23
+
24
+ it 'should not change if there are no options' do
25
+ finder = %Q{has_and_belongs_to_many :posts}
26
+ expect(ArelConverter::Translator::Association.translate(finder)).to eq(%Q{has_and_belongs_to_many :posts})
27
+ end
28
+
29
+ it 'should translate options' do
30
+ finder = %Q{has_and_belongs_to_many :posts, :uniq => true}
31
+ expect(ArelConverter::Translator::Association.translate(finder)).to eq(%Q{has_and_belongs_to_many :posts, -> { uniq(true) }})
32
+ end
33
+
34
+ end
35
+
36
+
37
+ context 'parsing has_one' do
38
+ it 'should ignore if no options set' do
39
+ finder = %Q{has_one :posts}
40
+ expect(ArelConverter::Translator::Association.translate(finder)).to eq(%Q{has_one :posts})
41
+ end
42
+
43
+ it 'should translate options' do
44
+ finder = %Q{has_one :posts, :conditions => ['posts.active = ?', true]}
45
+ expect(ArelConverter::Translator::Association.translate(finder)).to eq(%Q{has_one :posts, -> { where("posts.active = ?", true) }})
46
+ end
47
+
48
+ context 'with options' do
49
+
50
+ %w[as autosave class_name dependent foreign_key inverse_of
51
+ primary_key source source_type through validate].each do |option|
52
+
53
+ it "should handle the #{option} option" do
54
+ finder = %Q{has_one :posts, :#{option} => 'Sheet'}
55
+ expect(ArelConverter::Translator::Association.translate(finder)).to eq(%Q{has_one :posts, #{option}: "Sheet"})
56
+ end
57
+
58
+ it "such as #{option} with scoping" do
59
+ finder = %Q{has_one :posts, :#{option} => 'Sheet', :conditions => ['posts.active = ?', true]}
60
+ expect(ArelConverter::Translator::Association.translate(finder)).to eq(%Q{has_one :posts, -> { where("posts.active = ?", true) }, #{option}: "Sheet"})
61
+ end
62
+
63
+ end
64
+
65
+ it 'should handle multiple options' do
66
+ finder = %Q{has_one :posts, :as => 'Sheet', :through => :roles}
67
+ expect(ArelConverter::Translator::Association.translate(finder)).to eq(%Q{has_one :posts, as: "Sheet", through: :roles})
68
+ end
69
+ end
70
+ end
71
+
72
+
73
+ context 'parsing has_many' do
74
+ it 'should ignore if no options set' do
75
+ finder = %Q{has_many :posts}
76
+ expect(ArelConverter::Translator::Association.translate(finder)).to eq(%Q{has_many :posts})
77
+ end
78
+
79
+ it 'should translate options' do
80
+ finder = %Q{has_many :posts, :conditions => ['posts.active = ?', true]}
81
+ expect(ArelConverter::Translator::Association.translate(finder)).to eq(%Q{has_many :posts, -> { where("posts.active = ?", true) }})
82
+ end
83
+
84
+ context 'with options' do
85
+
86
+ %w[as autosave class_name dependent foreign_key inverse_of
87
+ primary_key source source_type through validate].each do |option|
88
+
89
+ it "should handle the #{option} option" do
90
+ finder = %Q{has_many :posts, :#{option} => 'Sheet'}
91
+ expect(ArelConverter::Translator::Association.translate(finder)).to eq(%Q{has_many :posts, #{option}: "Sheet"})
92
+ end
93
+
94
+ it "such as #{option} with scoping" do
95
+ finder = %Q{has_many :posts, :#{option} => 'Sheet', :conditions => ['posts.active = ?', true]}
96
+ expect(ArelConverter::Translator::Association.translate(finder)).to eq(%Q{has_many :posts, -> { where("posts.active = ?", true) }, #{option}: "Sheet"})
97
+ end
98
+
99
+ end
100
+
101
+ it 'should handle multiple options' do
102
+ finder = %Q{has_many :posts, :as => 'Sheet', :through => :roles}
103
+ expect(ArelConverter::Translator::Association.translate(finder)).to eq(%Q{has_many :posts, as: "Sheet", through: :roles})
104
+ end
105
+ end
106
+
107
+ end
108
+
109
+ end
110
+
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ describe ArelConverter::Translator::Finder do
4
+
5
+ context 'parsing .all' do
6
+ it 'as a model method with no arguments' do
7
+ finder = %Q{MyModel.all}
8
+ expect(ArelConverter::Translator::Finder.translate(finder)).to eq(%Q{MyModel.all})
9
+ end
10
+
11
+ it 'as a model method' do
12
+ finder = %Q{MyModel.all(:joins => [:payment_method], :conditions => ["payment_methodable_type = 'ChequePaymentMethod' AND amount > 0"])}
13
+ expect(ArelConverter::Translator::Finder.translate(finder)).to eq(%Q{MyModel.joins(:payment_method).where("payment_methodable_type = 'ChequePaymentMethod' AND amount > 0")})
14
+ end
15
+
16
+ it 'as a chained method' do
17
+ finder = %Q{self.payments.all(:joins => [:payment_method], :conditions => ["payment_methodable_type = 'ChequePaymentMethod' AND amount > 0"])}
18
+ expect(ArelConverter::Translator::Finder.translate(finder)).to eq(%Q{self.payments.joins(:payment_method).where("payment_methodable_type = 'ChequePaymentMethod' AND amount > 0")})
19
+ end
20
+ end
21
+
22
+ context 'parsing .first' do
23
+ it 'as a model method with no arguments' do
24
+ finder = %Q{MyModel.first}
25
+ expect(ArelConverter::Translator::Finder.translate(finder)).to eq(%Q{MyModel.first})
26
+ end
27
+
28
+ it 'as a model method' do
29
+ finder = %Q{MyModel.first(:joins => [:payment_method], :conditions => ["payment_methodable_type = 'ChequePaymentMethod' AND amount > 0"])}
30
+ expect(ArelConverter::Translator::Finder.translate(finder)).to eq(%Q{MyModel.joins(:payment_method).where("payment_methodable_type = 'ChequePaymentMethod' AND amount > 0").first})
31
+ end
32
+
33
+ it 'as a chained method' do
34
+ finder = %Q{self.payments.first(:joins => [:payment_method], :conditions => ["payment_methodable_type = 'ChequePaymentMethod' AND amount > 0"])}
35
+ expect(ArelConverter::Translator::Finder.translate(finder)).to eq(%Q{self.payments.joins(:payment_method).where("payment_methodable_type = 'ChequePaymentMethod' AND amount > 0").first})
36
+ end
37
+
38
+ it '' do
39
+ finder = %Q{MyModel.first(:conditions=> conditions_array, :order => "tickets.weight desc, tickets.sort_date asc", :include => INCLUDE, :joins => joins)}
40
+ expect(ArelConverter::Translator::Finder.translate(finder)).to eq(%Q{MyModel.where(conditions_array).order("tickets.weight desc, tickets.sort_date asc").includes(INCLUDE).joins(joins).first})
41
+ end
42
+ end
43
+
44
+
45
+ context 'parsing #find' do
46
+
47
+ context 'with the :first argument' do
48
+
49
+ it 'without conditions in a model' do
50
+ finder = %Q{MyModel.find(:first)}
51
+ expect(ArelConverter::Translator::Finder.translate(finder)).to eq(%Q{MyModel.first})
52
+ end
53
+
54
+ it 'without conditions in a model' do
55
+ finder = %Q{MyModel.find(:first, :order => 'created_at DESC', :conditions => "active = 1")}
56
+ expect(ArelConverter::Translator::Finder.translate(finder)).to eq(%Q{MyModel.order("created_at DESC").where("active = 1").first})
57
+ end
58
+
59
+ it 'without conditions' do
60
+ finder = %Q{self.payment_optimizations.find(:first)}
61
+ expect(ArelConverter::Translator::Finder.translate(finder)).to eq(%Q{self.payment_optimizations.first})
62
+ end
63
+
64
+ it 'with a single condition' do
65
+ finder = %Q{self.payment_optimizations.find(:first, :order => 'created_at DESC')}
66
+ expect(ArelConverter::Translator::Finder.translate(finder)).to eq(%Q{self.payment_optimizations.order("created_at DESC").first})
67
+ end
68
+
69
+ it 'with conditions' do
70
+ finder = %Q{self.payment_optimizations.find(:first, :order => 'created_at DESC', :conditions => "active = 1")}
71
+ expect(ArelConverter::Translator::Finder.translate(finder)).to eq(%Q{self.payment_optimizations.order("created_at DESC").where("active = 1").first})
72
+ end
73
+
74
+ end
75
+
76
+ context 'with the :all argument' do
77
+ it 'should not append .all' do
78
+ finder = %Q{self.find(:all, :select => "DISTINCT(sales_channels.name)").map(&:name)}
79
+ expect(ArelConverter::Translator::Finder.translate(finder)).to eq(%Q{self.select("DISTINCT(sales_channels.name)").map(&:name)})
80
+ end
81
+ end
82
+
83
+ end
84
+
85
+ end
86
+
87
+
88
+