synvert 0.0.17 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -1
  3. data/CHANGELOG.md +4 -0
  4. data/README.md +7 -26
  5. data/bin/synvert +0 -1
  6. data/lib/synvert/cli.rb +26 -14
  7. data/lib/synvert/snippet.rb +17 -0
  8. data/lib/synvert/version.rb +1 -1
  9. data/lib/synvert.rb +3 -11
  10. data/synvert.gemspec +2 -3
  11. metadata +6 -85
  12. data/lib/synvert/configuration.rb +0 -25
  13. data/lib/synvert/exceptions.rb +0 -13
  14. data/lib/synvert/node_ext.rb +0 -319
  15. data/lib/synvert/rewriter/action.rb +0 -224
  16. data/lib/synvert/rewriter/condition.rb +0 -56
  17. data/lib/synvert/rewriter/gem_spec.rb +0 -42
  18. data/lib/synvert/rewriter/instance.rb +0 -185
  19. data/lib/synvert/rewriter/scope.rb +0 -46
  20. data/lib/synvert/rewriter.rb +0 -200
  21. data/lib/synvert/snippets/check_syntax.rb +0 -5
  22. data/lib/synvert/snippets/factory_girl/syntax_methods.rb +0 -98
  23. data/lib/synvert/snippets/rails/convert_dynamic_finders.rb +0 -93
  24. data/lib/synvert/snippets/rails/strong_parameters.rb +0 -93
  25. data/lib/synvert/snippets/rails/upgrade_3_0_to_3_1.rb +0 -135
  26. data/lib/synvert/snippets/rails/upgrade_3_1_to_3_2.rb +0 -42
  27. data/lib/synvert/snippets/rails/upgrade_3_2_to_4_0.rb +0 -230
  28. data/lib/synvert/snippets/rspec/be_close_to_be_within.rb +0 -18
  29. data/lib/synvert/snippets/rspec/block_to_expect.rb +0 -22
  30. data/lib/synvert/snippets/rspec/boolean_matcher.rb +0 -20
  31. data/lib/synvert/snippets/rspec/collection_matcher.rb +0 -34
  32. data/lib/synvert/snippets/rspec/its_to_it.rb +0 -89
  33. data/lib/synvert/snippets/rspec/message_expectation.rb +0 -41
  34. data/lib/synvert/snippets/rspec/method_stub.rb +0 -84
  35. data/lib/synvert/snippets/rspec/negative_error_expectation.rb +0 -21
  36. data/lib/synvert/snippets/rspec/new_syntax.rb +0 -18
  37. data/lib/synvert/snippets/rspec/one_liner_expectation.rb +0 -71
  38. data/lib/synvert/snippets/rspec/should_to_expect.rb +0 -50
  39. data/lib/synvert/snippets/rspec/stub_and_mock_to_double.rb +0 -22
  40. data/lib/synvert/snippets/ruby/new_hash_syntax.rb +0 -21
  41. data/lib/synvert/snippets/ruby/new_lambda_syntax.rb +0 -20
  42. data/spec/spec_helper.rb +0 -26
  43. data/spec/support/parser_helper.rb +0 -5
  44. data/spec/synvert/node_ext_spec.rb +0 -201
  45. data/spec/synvert/rewriter/action_spec.rb +0 -225
  46. data/spec/synvert/rewriter/condition_spec.rb +0 -106
  47. data/spec/synvert/rewriter/gem_spec_spec.rb +0 -52
  48. data/spec/synvert/rewriter/instance_spec.rb +0 -163
  49. data/spec/synvert/rewriter/scope_spec.rb +0 -42
  50. data/spec/synvert/rewriter_spec.rb +0 -153
  51. data/spec/synvert/snippets/factory_girl/syntax_methods_spec.rb +0 -154
  52. data/spec/synvert/snippets/rails/convert_dynamic_finders_spec.rb +0 -83
  53. data/spec/synvert/snippets/rails/strong_parameters_spec.rb +0 -132
  54. data/spec/synvert/snippets/rails/upgrade_3_0_to_3_1_spec.rb +0 -88
  55. data/spec/synvert/snippets/rails/upgrade_3_1_to_3_2_spec.rb +0 -41
  56. data/spec/synvert/snippets/rails/upgrade_3_2_to_4_0_spec.rb +0 -299
  57. data/spec/synvert/snippets/rspec/new_syntax_spec.rb +0 -183
  58. data/spec/synvert/snippets/ruby/new_hash_syntax_spec.rb +0 -27
  59. data/spec/synvert/snippets/ruby/new_lambda_syntax_spec.rb +0 -27
@@ -1,185 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Synvert
4
- # Instance is an execution unit, it finds specified ast nodes,
5
- # checks if the nodes match some conditions, then add, replace or remove code.
6
- #
7
- # One instance can contains one or many [Synvert::Rewriter::Scope] and [Synvert::Rewriter::Condition].
8
- class Rewriter::Instance
9
- # @!attribute [rw] current_node
10
- # @return current parsing node
11
- # @!attribute [rw] current_source
12
- # @return current source code of file
13
- # @!attribute [rw] current_file
14
- # @return current filename
15
- attr_accessor :current_node, :current_source, :current_file
16
-
17
- # Initialize an instance.
18
- #
19
- # @param file_pattern [String] pattern to find files, e.g. spec/**/*_spec.rb
20
- # @param block [Block] block code to find nodes, match conditions and rewrite code.
21
- # @return [Synvert::Rewriter::Instance]
22
- def initialize(file_pattern, &block)
23
- @actions = []
24
- @file_pattern = file_pattern
25
- @block = block
26
- end
27
-
28
- # Process the instance.
29
- # It finds all files, for each file, it executes the block code, gets all rewrite actions,
30
- # and rewrite source code back to original file.
31
- def process
32
- parser = Parser::CurrentRuby.new
33
- file_pattern = File.join(Configuration.instance.get(:path), @file_pattern)
34
- Dir.glob(file_pattern).each do |file_path|
35
- unless Configuration.instance.get(:skip_files).include? file_path
36
- begin
37
- source = File.read(file_path)
38
- buffer = Parser::Source::Buffer.new file_path
39
- buffer.source = source
40
-
41
- parser.reset
42
- ast = parser.parse buffer
43
-
44
- @current_file = file_path
45
- @current_source = source
46
- @current_node = ast
47
- instance_eval &@block
48
- @current_node = ast
49
-
50
- @actions.sort!
51
- check_conflict_actions
52
- @actions.reverse.each do |action|
53
- source[action.begin_pos...action.end_pos] = action.rewritten_code
54
- source = remove_code_or_whole_line(source, action.line)
55
- end
56
- @actions = []
57
-
58
- File.write file_path, source
59
- end while !@conflict_actions.empty?
60
- end
61
- end
62
- end
63
-
64
- # Gets current node, it allows to get current node in block code.
65
- #
66
- # @return [Parser::AST::Node]
67
- def node
68
- @current_node
69
- end
70
-
71
- #######
72
- # DSL #
73
- #######
74
-
75
- # Parse within_node dsl, it creates a [Synvert::Rewriter::Scope] to find matching ast nodes,
76
- # then continue operating on each matching ast node.
77
- #
78
- # @param rules [Hash] rules to find mathing ast nodes.
79
- # @param block [Block] block code to continue operating on the matching nodes.
80
- def within_node(rules, &block)
81
- Rewriter::Scope.new(self, rules, &block).process
82
- end
83
-
84
- alias with_node within_node
85
-
86
- # Parse if_exist_node dsl, it creates a [Synvert::Rewriter::IfExistCondition] to check
87
- # if matching nodes exist in the child nodes, if so, then continue operating on each matching ast node.
88
- #
89
- # @param rules [Hash] rules to check mathing ast nodes.
90
- # @param block [Block] block code to continue operating on the matching nodes.
91
- def if_exist_node(rules, &block)
92
- Rewriter::IfExistCondition.new(self, rules, &block).process
93
- end
94
-
95
- # Parse unless_exist_node dsl, it creates a [Synvert::Rewriter::UnlessExistCondition] to check
96
- # if matching nodes doesn't exist in the child nodes, if so, then continue operating on each matching ast node.
97
- #
98
- # @param rules [Hash] rules to check mathing ast nodes.
99
- # @param block [Block] block code to continue operating on the matching nodes.
100
- def unless_exist_node(rules, &block)
101
- Rewriter::UnlessExistCondition.new(self, rules, &block).process
102
- end
103
-
104
- # Parse if_only_exist_node dsl, it creates a [Synvert::Rewriter::IfOnlyExistCondition] to check
105
- # if current node has only one child node and the child node matches rules,
106
- # if so, then continue operating on each matching ast node.
107
- #
108
- # @param rules [Hash] rules to check mathing ast nodes.
109
- # @param block [Block] block code to continue operating on the matching nodes.
110
- def if_only_exist_node(rules, &block)
111
- Rewriter::IfOnlyExistCondition.new(self, rules, &block).process
112
- end
113
-
114
- # Parse append dsl, it creates a [Synvert::Rewriter::AppendAction] to
115
- # append the code to the bottom of current node body.
116
- #
117
- # @param code [String] code need to be appended.
118
- def append(code)
119
- @actions << Rewriter::AppendAction.new(self, code)
120
- end
121
-
122
- # Parse insert dsl, it creates a [Synvert::Rewriter::InsertAction] to
123
- # insert the code to the top of current node body.
124
- #
125
- # @param code [String] code need to be inserted.
126
- def insert(code)
127
- @actions << Rewriter::InsertAction.new(self, code)
128
- end
129
-
130
- # Parse insert_after dsl, it creates a [Synvert::Rewriter::InsertAfterAction] to
131
- # insert the code next to the current node.
132
- #
133
- # @param code [String] code need to be inserted.
134
- def insert_after(node)
135
- @actions << Rewriter::InsertAfterAction.new(self, node)
136
- end
137
-
138
- # Parse replace_with dsl, it creates a [Synvert::Rewriter::ReplaceWithAction] to
139
- # replace current node with code.
140
- #
141
- # @param code [String] code need to be replaced with.
142
- def replace_with(code)
143
- @actions << Rewriter::ReplaceWithAction.new(self, code)
144
- end
145
-
146
- # Parse remove dsl, it creates a [Synvert::Rewriter::RemoveAction] to current node.
147
- def remove
148
- @actions << Rewriter::RemoveAction.new(self)
149
- end
150
-
151
- private
152
-
153
- # It changes source code from bottom to top, and it can change source code twice at the same time.
154
- # So if there is an overlap between two actions, it removes the conflict actions and operate them in the next loop.
155
- def check_conflict_actions
156
- i = @actions.length - 1
157
- @conflict_actions = []
158
- while i > 0
159
- if @actions[i].begin_pos <= @actions[i - 1].end_pos
160
- @conflict_actions << @actions.delete_at(i)
161
- end
162
- i -= 1
163
- end
164
- @conflict_actions
165
- end
166
-
167
- # It checks if code is removed and that line is empty.
168
- #
169
- # @param source [String] source code of file
170
- # @param line [String] the line number
171
- def remove_code_or_whole_line(source, line)
172
- newline_at_end_of_line = source[-1] == "\n"
173
- source_arr = source.split("\n")
174
- if source_arr[line - 1] && source_arr[line - 1].strip.empty?
175
- source_arr.delete_at(line - 1)
176
- if source_arr[line - 2] && source_arr[line - 2].strip.empty? && source_arr[line - 1] && source_arr[line - 1].strip.empty?
177
- source_arr.delete_at(line - 1)
178
- end
179
- source_arr.join("\n") + (newline_at_end_of_line ? "\n" : '')
180
- else
181
- source
182
- end
183
- end
184
- end
185
- end
@@ -1,46 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Synvert
4
- # Scope finds the child nodes which match rules.
5
- class Rewriter::Scope
6
- # Initialize a scope
7
- #
8
- # @param instance [Synvert::Rewriter::Instance]
9
- # @param rules [Hash]
10
- # @param block [Block]
11
- def initialize(instance, rules, &block)
12
- @instance = instance
13
- @rules = rules
14
- @block = block
15
- end
16
-
17
- # Find the matching nodes. It checks the current node and iterates all child nodes,
18
- # then run the block code for each matching node.
19
- def process
20
- current_node = @instance.current_node
21
- return unless current_node
22
- process_with_node current_node do
23
- matching_nodes = []
24
- matching_nodes << current_node if current_node.match? @instance, @rules
25
- current_node.recursive_children do |child_node|
26
- matching_nodes << child_node if child_node.match? @instance, @rules
27
- end
28
- matching_nodes.each do |matching_node|
29
- process_with_node matching_node do
30
- @instance.instance_eval &@block
31
- end
32
- end
33
- end
34
- end
35
-
36
- private
37
-
38
- # Set instance current node properly and process.
39
- # @param node [Parser::AST::Node]
40
- def process_with_node(node)
41
- @instance.current_node = node
42
- yield
43
- @instance.current_node = node
44
- end
45
- end
46
- end
@@ -1,200 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Synvert
4
- # Rewriter is the top level namespace in a snippet.
5
- #
6
- # One Rewriter can contain one or many [Synvert::Rewriter::Instance],
7
- # which define the behavior what files and what codes to detect and rewrite to what code.
8
- #
9
- # Synvert::Rewriter.new 'factory_girl_short_syntax', 'use FactoryGirl short syntax' do
10
- # if_gem 'factory_girl', {gte: '2.0.0'}
11
- #
12
- # within_files 'spec/**/*.rb' do
13
- # with_node type: 'send', receiver: 'FactoryGirl', message: 'create' do
14
- # replace_with "create({{arguments}})"
15
- # end
16
- # end
17
- # end
18
- class Rewriter
19
- autoload :Action, 'synvert/rewriter/action'
20
- autoload :AppendAction, 'synvert/rewriter/action'
21
- autoload :InsertAction, 'synvert/rewriter/action'
22
- autoload :InsertAfterAction, 'synvert/rewriter/action'
23
- autoload :ReplaceWithAction, 'synvert/rewriter/action'
24
- autoload :RemoveAction, 'synvert/rewriter/action'
25
-
26
- autoload :Instance, 'synvert/rewriter/instance'
27
-
28
- autoload :Scope, 'synvert/rewriter/scope'
29
-
30
- autoload :Condition, 'synvert/rewriter/condition'
31
- autoload :IfExistCondition, 'synvert/rewriter/condition'
32
- autoload :UnlessExistCondition, 'synvert/rewriter/condition'
33
- autoload :IfOnlyExistCondition, 'synvert/rewriter/condition'
34
-
35
- autoload :GemSpec, 'synvert/rewriter/gem_spec'
36
-
37
- class <<self
38
- # Register a rewriter with its name.
39
- #
40
- # @param name [String] the unique rewriter name.
41
- # @param rewriter [Synvert::Rewriter] the rewriter to register.
42
- def register(name, rewriter)
43
- @rewriters ||= {}
44
- @rewriters[name] = rewriter
45
- end
46
-
47
- # Fetch a rewriter by name.
48
- #
49
- # @param name [String] rewrtier name.
50
- # @return [Synvert::Rewriter] the matching rewriter.
51
- def fetch(name)
52
- @rewriters[name]
53
- end
54
-
55
- # Get a registered rewriter by name and process that rewriter.
56
- #
57
- # @param name [String] the rewriter name.
58
- # @return [Synvert::Rewriter] the registered rewriter.
59
- # @raise [Synvert::RewriterNotFound] if the registered rewriter is not found.
60
- def call(name)
61
- if (rewriter = @rewriters[name])
62
- rewriter.process
63
- rewriter
64
- else
65
- raise RewriterNotFound.new "Rewriter #{name} not found"
66
- end
67
- end
68
-
69
- # Get all available rewriters
70
- #
71
- # @return [Array<Synvert::Rewriter>]
72
- def availables
73
- @rewriters.values
74
- end
75
-
76
- # Clear all registered rewriters.
77
- def clear
78
- @rewriters.clear
79
- end
80
- end
81
-
82
- # @!attribute [r] name
83
- # @return [String] the unique name of rewriter
84
- # @!attribute [r] sub_snippets
85
- # @return [Array<Synvert::Rewriter>] all rewriters this rewiter calls.
86
- attr_reader :name, :sub_snippets
87
-
88
- # Initialize a rewriter.
89
- # When a rewriter is initialized, it is also registered.
90
- #
91
- # @param name [String] name of the rewriter.
92
- # @param block [Block] a block defines the behaviors of the rewriter, block code won't be called when initialization.
93
- # @return [Synvert::Rewriter]
94
- def initialize(name, &block)
95
- @name = name.to_s
96
- @block = block
97
- @helpers = []
98
- @sub_snippets = []
99
- self.class.register(@name, self)
100
- end
101
-
102
- # Process the rewriter.
103
- # It will call the block.
104
- def process
105
- self.instance_eval &@block
106
- end
107
-
108
- # Process rewriter with sandbox mode.
109
- # It will call the block but doesn't change any file.
110
- def process_with_sandbox
111
- @sandbox = true
112
- self.process
113
- @sandbox = false
114
- end
115
-
116
- #######
117
- # DSL #
118
- #######
119
-
120
- # Parse description dsl, it sets description of the rewrite.
121
- # Or get description.
122
- #
123
- # @param description [String] rewriter description.
124
- # @return rewriter description.
125
- def description(description=nil)
126
- if description
127
- @description = description
128
- else
129
- @description
130
- end
131
- end
132
-
133
- # Parse if_gem dsl, it compares version of the specified gem.
134
- #
135
- # @param name [String] gem name.
136
- # @param comparator [Hash] equal, less than or greater than specified version, e.g. {gte: '2.0.0'},
137
- # key can be eq, lt, gt, lte, gte or ne.
138
- def if_gem(name, comparator)
139
- @gem_spec = Rewriter::GemSpec.new(name, comparator)
140
- end
141
-
142
- # Parse within_files dsl, it finds specified files.
143
- # It creates a [Synvert::Rewriter::Instance] to rewrite code.
144
- #
145
- # @param file_pattern [String] pattern to find files, e.g. spec/**/*_spec.rb
146
- # @param block [Block] the block to rewrite code in the matching files.
147
- def within_files(file_pattern, &block)
148
- return if @sandbox
149
-
150
- if !@gem_spec || @gem_spec.match?
151
- instance = Rewriter::Instance.new(file_pattern, &block)
152
- @helpers.each { |helper| instance.singleton_class.send(:define_method, helper[:name], &helper[:block]) }
153
- instance.process
154
- end
155
- end
156
-
157
- # Parse within_file dsl, it finds a specifiled file.
158
- alias within_file within_files
159
-
160
- # Parses add_file dsl, it adds a new file.
161
- #
162
- # @param filename [String] file name of newly created file.
163
- # @param content [String] file body of newly created file.
164
- def add_file(filename, content)
165
- return if @sandbox
166
-
167
- File.open filename, 'w' do |file|
168
- file.write content
169
- end
170
- end
171
-
172
- # Parse add_snippet dsl, it calls anther rewriter.
173
- #
174
- # @param name [String] name of another rewriter.
175
- def add_snippet(name)
176
- @sub_snippets << self.class.call(name.to_s)
177
- end
178
-
179
- # Parse helper_method dsl, it defines helper method for [Synvert::Rewriter::Instance].
180
- #
181
- # @param name [String] helper method name.
182
- # @param block [Block] helper method block.
183
- def helper_method(name, &block)
184
- @helpers << {name: name, block: block}
185
- end
186
-
187
- # Parse todo dsl, it sets todo of the rewriter.
188
- # Or get todo.
189
- #
190
- # @param todo_list [String] rewriter todo.
191
- # @return [String] rewriter todo.
192
- def todo(todo=nil)
193
- if todo
194
- @todo = todo
195
- else
196
- @todo
197
- end
198
- end
199
- end
200
- end
@@ -1,5 +0,0 @@
1
- Synvert::Rewriter.new :check_syntax do
2
- description "just used to check if there are syntax errors."
3
-
4
- within_files "**/*.rb" do; end
5
- end
@@ -1,98 +0,0 @@
1
- Synvert::Rewriter.new "factory_girl_short_syntax" do
2
- description <<-EOF
3
- Uses FactoryGirl short syntax.
4
-
5
- 1. it adds FactoryGirl::Syntax::methods module to RSpec, Test::Unit, Cucumber, Spainach, MiniTest, MiniTest::Spec, minitest-rails.
6
-
7
- # rspec
8
- RSpec.configure do |config|
9
- config.include FactoryGirl::Syntax::Methods
10
- end
11
-
12
- # Test::Unit
13
- class Test::Unit::TestCase
14
- include FactoryGirl::Syntax::Methods
15
- end
16
-
17
- # Cucumber
18
- World(FactoryGirl::Syntax::Methods)
19
-
20
- # Spinach
21
- class Spinach::FeatureSteps
22
- include FactoryGirl::Syntax::Methods
23
- end
24
-
25
- # MiniTest
26
- class MiniTest::Unit::TestCase
27
- include FactoryGirl::Syntax::Methods
28
- end
29
-
30
- # MiniTest::Spec
31
- class MiniTest::Spec
32
- include FactoryGirl::Syntax::Methods
33
- end
34
-
35
- # minitest-rails
36
- class MiniTest::Rails::ActiveSupport::TestCase
37
- include FactoryGirl::Syntax::Methods
38
- end
39
-
40
- 2. it converts to short syntax.
41
-
42
- FactoryGirl.create(...) => create(...)
43
- FactoryGirl.build(...) => build(...)
44
- FactoryGirl.attributes_for(...) => attributes_for(...)
45
- FactoryGirl.build_stubbed(...) => build_stubbed(...)
46
- FactoryGirl.create_list(...) => create_list(...)
47
- FactoryGirl.build_list(...) => build_list(...)
48
- FactoryGirl.create_pair(...) => create_pair(...)
49
- FactoryGirl.build_pair(...) => build_pair(...)
50
- EOF
51
-
52
- if_gem 'factory_girl', {gte: '2.0.0'}
53
-
54
- # insert include FactoryGirl::Syntax::Methods
55
- within_file 'spec/spec_helper.rb' do
56
- within_node type: 'block', caller: {receiver: 'RSpec', message: 'configure'} do
57
- unless_exist_node type: 'send', message: 'include', arguments: ['FactoryGirl::Syntax::Methods'] do
58
- insert "{{arguments.first}}.include FactoryGirl::Syntax::Methods"
59
- end
60
- end
61
- end
62
-
63
- # insert include FactoryGirl::Syntax::Methods
64
- within_file 'test/test_helper.rb' do
65
- %w(Test::Unit::TestCase ActiveSupport::TestCase MiniTest::Unit::TestCase MiniTest::Spec MiniTest::Rails::ActiveSupport::TestCase).each do |class_name|
66
- within_node type: 'class', name: class_name do
67
- unless_exist_node type: 'send', message: 'include', arguments: ['FactoryGirl::Syntax::Methods'] do
68
- insert "include FactoryGirl::Syntax::Methods"
69
- end
70
- end
71
- end
72
- end
73
-
74
- # insert World(FactoryGirl::Syntax::Methods)
75
- within_file 'features/support/env.rb' do
76
- unless_exist_node type: 'send', message: 'World', arguments: ['FactoryGirl::Syntax::Methods'] do
77
- insert "World(FactoryGirl::Syntax::Methods)"
78
- end
79
- end
80
-
81
- # FactoryGirl.create(...) => create(...)
82
- # FactoryGirl.build(...) => build(...)
83
- # FactoryGirl.attributes_for(...) => attributes_for(...)
84
- # FactoryGirl.build_stubbed(...) => build_stubbed(...)
85
- # FactoryGirl.create_list(...) => create_list(...)
86
- # FactoryGirl.build_list(...) => build_list(...)
87
- # FactoryGirl.create_pair(...) => create_pair(...)
88
- # FactoryGirl.build_pair(...) => build_pair(...)
89
- %w(test/**/*.rb spec/**/*.rb features/**/*.rb).each do |file_pattern|
90
- within_files file_pattern do
91
- %w(create build attributes_for build_stubbed create_list build_list create_pair build_pair).each do |message|
92
- with_node type: 'send', receiver: 'FactoryGirl', message: message do
93
- replace_with "#{message}({{arguments}})"
94
- end
95
- end
96
- end
97
- end
98
- end
@@ -1,93 +0,0 @@
1
- Synvert::Rewriter.new "convert_rails_dynamic_finders" do
2
- description <<-EOF
3
- It converts rails dynamic finders to arel syntax.
4
-
5
- find_all_by_... => where(...)
6
- find_by_... => where(...).first
7
- find_last_by_... => where(...).last
8
- scoped_by_... => where(...)
9
- find_or_initialize_by_... => find_or_initialize_by(...)
10
- find_or_create_by_... => find_or_create_by(...)
11
- EOF
12
-
13
- helper_method 'dynamic_finder_to_hash' do |prefix|
14
- fields = node.message.to_s[prefix.length..-1].split("_and_")
15
- if fields.length == node.arguments.length && :hash != node.arguments.first.type
16
- fields.length.times.map { |i|
17
- fields[i] + ": " + node.arguments[i].source(self)
18
- }.join(", ")
19
- else
20
- "{{arguments}}"
21
- end
22
- end
23
-
24
- within_files '**/*.rb' do
25
- # find_all_by_... => where(...)
26
- with_node type: 'send', message: /^find_all_by_/ do
27
- hash_params = dynamic_finder_to_hash("find_all_by_")
28
- if node.receiver
29
- replace_with "{{receiver}}.where(#{hash_params})"
30
- else
31
- replace_with "where(#{hash_params})"
32
- end
33
- end
34
-
35
- # find_by_... => where(...).first
36
- with_node type: 'send', message: /^find_by_/ do
37
- if :find_by_id == node.message
38
- if node.receiver
39
- replace_with "{{receiver}}.find({{arguments}})"
40
- else
41
- replace_with "find({{arguments}}"
42
- end
43
- elsif :find_by_sql != node.message
44
- hash_params = dynamic_finder_to_hash("find_by_")
45
- if node.receiver
46
- replace_with "{{receiver}}.where(#{hash_params}).first"
47
- else
48
- replace_with "where(#{hash_params}).first"
49
- end
50
- end
51
- end
52
-
53
- # find_last_by_... => where(...).last
54
- with_node type: 'send', message: /^find_last_by_/ do
55
- hash_params = dynamic_finder_to_hash("find_last_by_")
56
- if node.receiver
57
- replace_with "{{receiver}}.where(#{hash_params}).last"
58
- else
59
- replace_with "where(#{hash_params}).last"
60
- end
61
- end
62
-
63
- # scoped_by_... => where(...)
64
- with_node type: 'send', message: /^scoped_by_/ do
65
- hash_params = dynamic_finder_to_hash("scoped_by_")
66
- if node.receiver
67
- replace_with "{{receiver}}.where(#{hash_params})"
68
- else
69
- replace_with "where(#{hash_params})"
70
- end
71
- end
72
-
73
- # find_or_initialize_by_... => find_or_initialize_by(...)
74
- with_node type: 'send', message: /^find_or_initialize_by_/ do
75
- hash_params = dynamic_finder_to_hash("find_or_initialize_by_")
76
- if node.receiver
77
- replace_with "{{receiver}}.find_or_initialize_by(#{hash_params})"
78
- else
79
- replace_with "find_or_initialize_by(#{hash_params})"
80
- end
81
- end
82
-
83
- # find_or_create_by_... => find_or_create_by(...)
84
- with_node type: 'send', message: /^find_or_create_by_/ do
85
- hash_params = dynamic_finder_to_hash("find_or_create_by_")
86
- if node.receiver
87
- replace_with "{{receiver}}.find_or_create_by(#{hash_params})"
88
- else
89
- replace_with "find_or_create_by(#{hash_params})"
90
- end
91
- end
92
- end
93
- end