synvert 0.0.3 → 0.0.4

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.
@@ -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