synvert 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,19 +2,35 @@
2
2
 
3
3
  module Synvert
4
4
  class Rewriter::Scope
5
- def initialize(options)
5
+ def initialize(instance, options, &block)
6
+ @instance = instance
6
7
  @options = options
8
+ @block = block
7
9
  end
8
10
 
9
- def matching_nodes(nodes)
10
- matching_nodes = []
11
- while node = nodes.shift
12
- matching_nodes << node if node.match?(@options)
13
- node.recursive_children do |child_node|
14
- matching_nodes << child_node if child_node.match?(@options)
11
+ def process
12
+ current_node = @instance.current_node
13
+ return unless current_node
14
+ process_with_node current_node do
15
+ matching_nodes = []
16
+ matching_nodes << current_node if current_node.match? @instance, @options
17
+ current_node.recursive_children do |child_node|
18
+ matching_nodes << child_node if child_node.match? @instance, @options
19
+ end
20
+ matching_nodes.each do |matching_node|
21
+ process_with_node matching_node do
22
+ @instance.instance_eval &@block
23
+ end
15
24
  end
16
25
  end
17
- matching_nodes
26
+ end
27
+
28
+ private
29
+
30
+ def process_with_node(node)
31
+ @instance.current_node = node
32
+ yield
33
+ @instance.current_node = node
18
34
  end
19
35
  end
20
36
  end
@@ -1,35 +1,46 @@
1
1
  Synvert::Rewriter.new "FactoryGirl uses short syntax" do
2
2
  gem_spec 'factory_girl', '2.0.0'
3
3
 
4
+ # insert include FactoryGirl::Syntax::Methods
4
5
  within_file 'spec/spec_helper.rb' do
5
6
  within_node type: 'block', caller: {receiver: 'RSpec', message: 'configure'} do
6
- unless_exist_node type: 'send', message: 'include', arguments: {first: {to_s: 'FactoryGirl::Syntax::Methods'}} do
7
- insert "{{self.arguments.first}}.include FactoryGirl::Syntax::Methods"
7
+ unless_exist_node type: 'send', message: 'include', arguments: ['FactoryGirl::Syntax::Methods'] do
8
+ insert "{{arguments.first}}.include FactoryGirl::Syntax::Methods"
8
9
  end
9
10
  end
10
11
  end
11
12
 
12
- %w(Test::Unit::TestCase ActiveSupport::TestCase MiniTest::Unit::TestCase MiniTest::Spec MiniTest::Rails::ActiveSupport::TestCase).each do |class_name|
13
- within_file 'test/test_helper.rb' do
13
+ # insert include FactoryGirl::Syntax::Methods
14
+ within_file 'test/test_helper.rb' do
15
+ %w(Test::Unit::TestCase ActiveSupport::TestCase MiniTest::Unit::TestCase MiniTest::Spec MiniTest::Rails::ActiveSupport::TestCase).each do |class_name|
14
16
  within_node type: 'class', name: class_name do
15
- unless_exist_node type: 'send', message: 'include', arguments: {first: {to_s: 'FactoryGirl::Syntax::Methods'}} do
17
+ unless_exist_node type: 'send', message: 'include', arguments: ['FactoryGirl::Syntax::Methods'] do
16
18
  insert "include FactoryGirl::Syntax::Methods"
17
19
  end
18
20
  end
19
21
  end
20
22
  end
21
23
 
24
+ # insert World(FactoryGirl::Syntax::Methods)
22
25
  within_file 'features/support/env.rb' do
23
- unless_exist_node type: 'send', message: 'World', arguments: {first: {to_s: 'FactoryGirl::Syntax::Methods'}} do
26
+ unless_exist_node type: 'send', message: 'World', arguments: ['FactoryGirl::Syntax::Methods'] do
24
27
  insert "World(FactoryGirl::Syntax::Methods)"
25
28
  end
26
29
  end
27
30
 
31
+ # FactoryGirl.create(...) => create(...)
32
+ # FactoryGirl.build(...) => build(...)
33
+ # FactoryGirl.attributes_for(...) => attributes_for(...)
34
+ # FactoryGirl.build_stubbed(...) => build_stubbed(...)
35
+ # FactoryGirl.create_list(...) => create_list(...)
36
+ # FactoryGirl.build_list(...) => build_list(...)
37
+ # FactoryGirl.create_pair(...) => create_pair(...)
38
+ # FactoryGirl.build_pair(...) => build_pair(...)
28
39
  %w(test/**/*.rb spec/**/*.rb features/**/*.rb).each do |file_pattern|
29
- %w(create build attributes_for build_stubbed create_list build_list ccreate_pair build_pair).each do |message|
30
- within_files file_pattern do
40
+ within_files file_pattern do
41
+ %w(create build attributes_for build_stubbed create_list build_list create_pair build_pair).each do |message|
31
42
  with_node type: 'send', receiver: 'FactoryGirl', message: message do
32
- replace_with "#{message}({{self.arguments}})"
43
+ replace_with "#{message}({{arguments}})"
33
44
  end
34
45
  end
35
46
  end
@@ -1,13 +1,15 @@
1
1
  require 'securerandom'
2
2
 
3
- def dynamic_finder_to_hash(node, prefix)
4
- fields = node.message.to_s[prefix.length..-1].split("_and_")
5
- fields.length.times.map { |i|
6
- fields[i] + ": " + node.arguments[i].to_s
7
- }.join(", ")
3
+ class Synvert::Rewriter::Instance
4
+ def dynamic_finder_to_hash(node, prefix)
5
+ fields = node.message.to_s[prefix.length..-1].split("_and_")
6
+ fields.length.times.map { |i|
7
+ fields[i] + ": " + node.arguments[i].source(self)
8
+ }.join(", ")
9
+ end
8
10
  end
9
11
 
10
- Synvert::Rewriter.new "Upgrade from rails 3.2 to rails 4.0" do
12
+ Synvert::Rewriter.new "Upgrade rails from 3.2 to 4.0" do
11
13
  gem_spec 'rails', '3.2.0'
12
14
 
13
15
  within_file 'config/application.rb' do
@@ -15,128 +17,166 @@ Synvert::Rewriter.new "Upgrade from rails 3.2 to rails 4.0" do
15
17
  # Bundler.require(*Rails.groups(:assets => %w(development test)))
16
18
  # end
17
19
  # => Bundler.require(:default, Rails.env)
18
- with_node type: 'if', condition: {type: 'defined?', arguments: {first: 'Bundler'}} do
20
+ with_node type: 'if', condition: {type: 'defined?', arguments: ['Bundler']} do
19
21
  replace_with 'Bundler.require(:default, Rails.env)'
20
22
  end
21
23
  end
22
24
 
23
- within_file 'config/environments/production.rb' do
25
+ within_file 'config/**/*.rb' do
24
26
  # remove config.active_record.identity_map = true
25
27
  with_node type: 'send', receiver: {type: 'send', receiver: {type: 'send', message: 'config'}, message: 'active_record'}, message: 'identity_map=' do
26
28
  remove
27
29
  end
28
30
  end
29
31
 
30
- within_file 'app/models/**/*.rb' do
31
- # self.serialized_attributes => self.class.serialized_attributes
32
- with_node type: 'send', receiver: 'self', message: 'serialized_attributes' do
33
- replace_with 'self.class.serialized_attributes'
34
- end
35
- end
36
-
37
- within_file 'app/models/**/*.rb' do
38
- # scope :active, where(active: true) => scope :active, -> { where(active: true) }
39
- with_node type: 'send', receiver: nil, message: 'scope' do
40
- replace_with 'scope {{self.arguments.first}}, -> { {{self.arguments.last}} }'
41
- end
42
- end
43
-
44
- within_file 'test/unit/**/*.rb' do
45
- # ActiveRecord::TestCase => ActiveSupport::TestCase
46
- with_node type: 'const', to_s: 'ActiveRecord::TestCase' do
47
- replace_with 'ActiveSupport::TestCase'
32
+ within_file 'config/initializers/wrap_parameters.rb' do
33
+ # remove self.include_root_in_json = false
34
+ with_node type: 'block', caller: {receiver: 'ActiveSupport', message: 'on_load', arguments: [':active_record']} do
35
+ if_only_exist_node to_ast: Parser::CurrentRuby.parse('self.include_root_in_json = false') do
36
+ remove
37
+ end
48
38
  end
49
39
  end
50
40
 
51
- within_file 'app/**/*.rb' do
52
- # find_all_by_... => where(...)
53
- with_node type: 'send', message: /find_all_by_(.*)/ do
54
- hash_params = '{{find_all_by(self, "find_last_by_")}}'
55
- replace_with "{{self.receiver}}.where(#{hash_params})"
41
+ within_file 'config/initializers/secret_token.rb' do
42
+ # insert Application.config.secret_key_base = '...'
43
+ unless_exist_node type: 'send', message: 'secret_key_base=' do
44
+ with_node type: 'send', message: 'secret_token=' do
45
+ secret = SecureRandom.hex(64)
46
+ insert_after "{{receiver}}.secret_key_base = \"#{secret}\""
47
+ end
56
48
  end
57
49
  end
58
50
 
59
- within_file 'app/**/*.rb' do
60
- # find_last_by_... => where(...).last
61
- with_node type: 'send', message: /find_last_by_(.*)/ do
62
- hash_params = '{{dynamic_finder_to_hash(self, "find_last_by_")}}'
63
- replace_with "{{self.receiver}}.where(#{hash_params}).last"
51
+ within_files 'config/**/*.rb' do
52
+ # remove config.action_dispatch.best_standards_support = ...
53
+ with_node type: 'send', receiver: {type: 'send', receiver: {type: 'send', message: 'config'}, message: 'action_dispatch'}, message: 'best_standards_support=' do
54
+ remove
64
55
  end
65
56
  end
66
57
 
67
- within_file 'app/**/*.rb' do
68
- # scoped_by_... => where(...)
69
- with_node type: 'send', message: /scoped_by_(.*)/ do
70
- hash_params = '{{dynamic_finder_to_hash(self, "scoped_by_")}}'
71
- replace_with "{{self.receiver}}.where(#{hash_params})"
58
+ within_files 'config/**/*.rb' do
59
+ # remove config.active_record.whitelist_attributes = ...
60
+ with_node type: 'send', receiver: {type: 'send', receiver: {type: 'send', message: 'config'}, message: 'active_record'}, message: 'whitelist_attributes=' do
61
+ remove
72
62
  end
73
63
  end
74
64
 
75
- within_file 'app/**/*.rb' do
76
- # find_or_initialize_by_... => find_or_initialize_by(...)
77
- with_node type: 'send', message: /find_or_initialize_by_(.*)/ do
78
- hash_params = '{{dynamic_finder_to_hash(self, "find_or_initialize_by_")}}'
79
- replace_with "{{self.receiver}}.find_or_initialize_by(#{hash_params})"
65
+ within_file 'config/environments/production.rb' do
66
+ # insert config.eager_load = true
67
+ unless_exist_node type: 'send', message: 'eager_load=' do
68
+ insert 'config.eager_load = true'
80
69
  end
81
70
  end
82
71
 
83
- within_file 'app/**/*.rb' do
84
- # find_or_create_by_... => find_or_create_by(...)
85
- with_node type: 'send', message: /find_or_create_by_(.*)/ do
86
- hash_params = '{{dynamic_finder_to_hash(self, "find_or_create_by_")}}'
87
- replace_with "{{self.receiver}}.find_or_create_by(#{hash_params})"
72
+ within_file 'config/environments/development.rb' do
73
+ # insert config.eager_load = false
74
+ unless_exist_node type: 'send', message: 'eager_load=' do
75
+ insert 'config.eager_load = false'
88
76
  end
89
77
  end
90
78
 
91
- within_file 'config/initializers/wrap_parameters.rb' do
92
- # remove self.include_root_in_json = false
93
- with_node type: 'block', caller: {receiver: 'ActiveSupport', message: 'on_load', arguments: {first: ':active_record'}} do
94
- if_only_exist_node to_ast: Parser::CurrentRuby.parse('self.include_root_in_json = false') do
95
- remove
96
- end
79
+ within_file 'config/environments/test.rb' do
80
+ # insert config.eager_load = false
81
+ unless_exist_node type: 'send', message: 'eager_load=' do
82
+ insert 'config.eager_load = false'
97
83
  end
98
84
  end
99
85
 
100
- within_file 'config/initializers/secret_token.rb' do
101
- # insert Application.config.secret_key_base = '...'
102
- unless_exist_node type: 'send', message: 'secret_key_base=' do
103
- with_node type: 'send', message: 'secret_token=' do
104
- secret = SecureRandom.hex(64)
105
- insert_after "{{self.receiver}}.secret_key_base = '#{secret}'"
106
- end
86
+ within_files 'config/**/*.rb' do
87
+ # remove config.middleware.xxx(..., ActionDispatch::BestStandardsSupport)
88
+ with_node type: 'send', arguments: {any: 'ActionDispatch::BestStandardsSupport'} do
89
+ remove
107
90
  end
108
91
  end
109
92
 
110
- within_file 'config/**/*.rb' do
111
- # remove ActionController::Base.page_cache_extension => ActionController::Base.default_static_extension
93
+ within_files 'config/**/*.rb' do
94
+ # remove ActionController::Base.page_cache_extension = ... => ActionController::Base.default_static_extension = ...
112
95
  with_node type: 'send', message: 'page_cache_extension=' do
113
- replace_with 'ActionController::Base.default_static_extension = {{self.arguments}}'
96
+ replace_with 'ActionController::Base.default_static_extension = {{arguments}}'
114
97
  end
115
98
  end
116
99
 
117
100
  within_file 'config/routes.rb' do
118
101
  # Rack::Utils.escape('こんにちは') => 'こんにちは'
119
102
  with_node type: 'send', receiver: 'Rack::Utils', message: 'escape' do
120
- replace_with '{{self.arguments}}'
103
+ replace_with '{{arguments}}'
121
104
  end
122
105
  end
123
106
 
124
107
  within_file 'config/routes.rb' do
125
108
  # match "/" => "root#index" => get "/" => "root#index"
126
109
  with_node type: 'send', message: 'match' do
127
- replace_with 'get {{self.arguments}}'
110
+ replace_with 'get {{arguments}}'
128
111
  end
129
112
  end
130
113
 
131
- within_file 'config/**/*.rb' do
132
- with_node type: 'send', arguments: {any: 'ActionDispatch::BestStandardsSupport'} do
133
- remove
114
+ within_files 'app/models/**/*.rb' do
115
+ # self.serialized_attributes => self.class.serialized_attributes
116
+ with_node type: 'send', receiver: 'self', message: 'serialized_attributes' do
117
+ replace_with 'self.class.serialized_attributes'
134
118
  end
135
119
  end
136
120
 
137
- within_file 'config/**/*.rb' do
138
- with_node type: 'send', message: 'best_standards_support=' do
139
- remove
121
+ within_files 'app/models/**/*.rb' do
122
+ # scope :active, where(active: true) => scope :active, -> { where(active: true) }
123
+ with_node type: 'send', receiver: nil, message: 'scope' do
124
+ replace_with 'scope {{arguments.first}}, -> { {{arguments.last}} }'
125
+ end
126
+ end
127
+
128
+ within_files 'test/unit/**/*.rb' do
129
+ # ActiveRecord::TestCase => ActiveSupport::TestCase
130
+ with_node source: 'ActiveRecord::TestCase' do
131
+ replace_with 'ActiveSupport::TestCase'
132
+ end
133
+ end
134
+
135
+ within_files 'app/**/*.rb' do
136
+ # find_all_by_... => where(...)
137
+ with_node type: 'send', message: /find_all_by_(.*)/ do
138
+ hash_params = dynamic_finder_to_hash(node, "find_all_by_")
139
+ replace_with "{{receiver}}.where(#{hash_params})"
140
+ end
141
+ end
142
+
143
+ within_files 'app/**/*.rb' do
144
+ # find_by_... => where(...).first
145
+ with_node type: 'send', message: /find_by_(.*)/ do
146
+ hash_params = dynamic_finder_to_hash(node, "find_by_")
147
+ replace_with "{{receiver}}.where(#{hash_params}).first"
148
+ end
149
+ end
150
+
151
+ within_files 'app/**/*.rb' do
152
+ # find_last_by_... => where(...).last
153
+ with_node type: 'send', message: /find_last_by_(.*)/ do
154
+ hash_params = dynamic_finder_to_hash(node, "find_last_by_")
155
+ replace_with "{{receiver}}.where(#{hash_params}).last"
156
+ end
157
+ end
158
+
159
+ within_files 'app/**/*.rb' do
160
+ # scoped_by_... => where(...)
161
+ with_node type: 'send', message: /scoped_by_(.*)/ do
162
+ hash_params = dynamic_finder_to_hash(node, "scoped_by_")
163
+ replace_with "{{receiver}}.where(#{hash_params})"
164
+ end
165
+ end
166
+
167
+ within_files 'app/**/*.rb' do
168
+ # find_or_initialize_by_... => find_or_initialize_by(...)
169
+ with_node type: 'send', message: /find_or_initialize_by_(.*)/ do
170
+ hash_params = dynamic_finder_to_hash(node, "find_or_initialize_by_")
171
+ replace_with "{{receiver}}.find_or_initialize_by(#{hash_params})"
172
+ end
173
+ end
174
+
175
+ within_files 'app/**/*.rb' do
176
+ # find_or_create_by_... => find_or_create_by(...)
177
+ with_node type: 'send', message: /find_or_create_by_(.*)/ do
178
+ hash_params = dynamic_finder_to_hash(node, "find_or_create_by_")
179
+ replace_with "{{receiver}}.find_or_create_by(#{hash_params})"
140
180
  end
141
181
  end
142
182
 
@@ -148,10 +188,46 @@ Synvert::Rewriter.new "Upgrade from rails 3.2 to rails 4.0" do
148
188
  'ActionController::AbstractResponse' => 'ActionDispatch::Response',
149
189
  'ActionController::Response' => 'ActionDispatch::Response',
150
190
  'ActionController::Routing' => 'ActionDispatch::Routing'}.each do |deprecated, favor|
151
- within_file '**/*.rb' do
152
- with_node to_s: deprecated do
191
+ within_files '**/*.rb' do
192
+ with_node source: deprecated do
153
193
  replace_with favor
154
194
  end
155
195
  end
156
196
  end
197
+
198
+ #####################
199
+ # strong_parameters #
200
+ #####################
201
+ within_files 'app/models/**/*.rb' do
202
+ # assign and remove attr_accessible ...
203
+ within_node type: 'class' do
204
+ class_node = node
205
+ with_node type: 'send', message: 'attr_accessible' do
206
+ assign 'parameters', class_node.name.source(self).underscore, node.arguments.map { |key| key.source(self) }.join(', ')
207
+ remove
208
+ end
209
+ end
210
+ end
211
+
212
+ within_file 'app/controllers/**/*.rb' do
213
+ within_node type: 'class' do
214
+ # insert def xxx_params; ...; end
215
+ object_name = node.name.source(self).sub('Controller', '').singularize.underscore
216
+ if fetch('parameters', object_name)
217
+ unless_exist_node type: 'def', name: "#{object_name}_params" do
218
+ append """def #{object_name}_params
219
+ params.require(:#{object_name}).permit(#{fetch 'parameters', object_name})
220
+ end"""
221
+ end
222
+
223
+ # params[:xxx] => xxx_params
224
+ with_node type: 'send', receiver: 'params', message: '[]' do
225
+ object_name = eval(node.arguments.first.source(self)).to_s
226
+ if fetch('parameters', object_name)
227
+ replace_with "#{object_name}_params"
228
+ end
229
+ end
230
+ end
231
+ end
232
+ end
157
233
  end
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
2
 
3
3
  module Synvert
4
- VERSION = "0.0.3"
4
+ VERSION = "0.0.4"
5
5
  end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
2
2
 
3
3
  require 'synvert'
4
+ require 'fakefs/spec_helpers'
4
5
 
5
6
  Dir[File.join(File.dirname(__FILE__), 'support', '*')].each do |path|
6
7
  require path
@@ -8,6 +9,7 @@ end
8
9
 
9
10
  RSpec.configure do |config|
10
11
  config.include ParserHelper
12
+ config.include FakeFS::SpecHelpers, fakefs: true
11
13
 
12
14
  config.treat_symbols_as_metadata_keys_with_true_values = true
13
15
  config.run_all_when_everything_filtered = true
@@ -9,6 +9,11 @@ describe Parser::AST::Node do
9
9
  node = parse('class Synvert::Rewriter::Instance; end')
10
10
  expect(node.name).to eq parse('Synvert::Rewriter::Instance')
11
11
  end
12
+
13
+ it 'gets for def node' do
14
+ node = parse('def current_node; end')
15
+ expect(node.name).to eq :current_node
16
+ end
12
17
  end
13
18
 
14
19
  describe '#receiver' do
@@ -32,8 +37,10 @@ describe Parser::AST::Node do
32
37
  end
33
38
 
34
39
  it 'gets for block node' do
35
- node = parse('RSpec.configure do |config|; end')
36
- expect(node.arguments.map(&:to_s)).to eq ['config']
40
+ source = 'RSpec.configure do |config|; end'
41
+ node = parse(source)
42
+ instance = double(current_source: source)
43
+ expect(node.arguments.map { |argument| argument.source(instance) }).to eq ['config']
37
44
  end
38
45
 
39
46
  it 'gets for defined? node' do
@@ -63,48 +70,12 @@ describe Parser::AST::Node do
63
70
  end
64
71
  end
65
72
 
66
- describe '#to_s' do
67
- it 'gets for const node' do
68
- node = parse('Synvert')
69
- expect(node.to_s).to eq 'Synvert'
70
-
71
- node = parse('Synvert::Rewriter::Instance')
72
- expect(node.to_s).to eq 'Synvert::Rewriter::Instance'
73
- end
74
-
75
- it 'gets for sym node' do
76
- node = parse(':synvert')
77
- expect(node.to_s).to eq ':synvert'
78
- end
79
-
80
- it 'gets for str node' do
81
- node = parse("'synvert'")
82
- expect(node.to_s).to eq "'synvert'"
83
- end
84
-
85
- it 'gets for lvar node' do
86
- node = parse("user = User.find 1; user.valid?").grep_node(type: 'lvar')
87
- expect(node.to_s).to eq 'user'
88
- end
89
-
90
- it 'gets for ivar node' do
91
- node = parse('@user')
92
- expect(node.to_s).to eq '@user'
93
- end
94
-
95
- it 'gets for arg node' do
96
- node = parse("RSpec.configure do |config|; end").grep_node(type: 'arg')
97
- expect(node.to_s).to eq 'config'
98
- end
99
-
100
- it 'gets for self node' do
101
- node = parse('self')
102
- expect(node.to_s).to eq 'self'
103
- end
104
-
105
- it 'gets for send node' do
106
- node = parse('email')
107
- expect(node.to_s).to eq 'email'
73
+ describe '#source' do
74
+ it 'gets for node' do
75
+ source = 'params[:user][:email]'
76
+ instance = double(current_source: source)
77
+ node = parse(source)
78
+ expect(node.source(instance)).to eq 'params[:user][:email]'
108
79
  end
109
80
  end
110
81