rails_best_practices 1.19.3 → 1.19.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.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/CHANGELOG.md +4 -0
- data/Gemfile +0 -4
- data/Gemfile.lock +120 -0
- data/README.md +4 -1
- data/lib/rails_best_practices.rb +2 -0
- data/lib/rails_best_practices/analyzer.rb +5 -4
- data/lib/rails_best_practices/cli.rb +22 -0
- data/lib/rails_best_practices/command.rb +1 -131
- data/lib/rails_best_practices/core/check.rb +24 -23
- data/lib/rails_best_practices/core/checks_loader.rb +17 -18
- data/lib/rails_best_practices/core/methods.rb +9 -8
- data/lib/rails_best_practices/core/model_associations.rb +1 -1
- data/lib/rails_best_practices/core/runner.rb +38 -38
- data/lib/rails_best_practices/option_parser.rb +140 -0
- data/lib/rails_best_practices/prepares/controller_prepare.rb +8 -14
- data/lib/rails_best_practices/prepares/gemfile_prepare.rb +1 -1
- data/lib/rails_best_practices/prepares/initializer_prepare.rb +3 -3
- data/lib/rails_best_practices/prepares/mailer_prepare.rb +1 -1
- data/lib/rails_best_practices/prepares/model_prepare.rb +13 -13
- data/lib/rails_best_practices/prepares/route_prepare.rb +16 -15
- data/lib/rails_best_practices/prepares/schema_prepare.rb +1 -1
- data/lib/rails_best_practices/reviews/add_model_virtual_attribute_review.rb +25 -23
- data/lib/rails_best_practices/reviews/always_add_db_index_review.rb +73 -72
- data/lib/rails_best_practices/reviews/check_destroy_return_value_review.rb +2 -1
- data/lib/rails_best_practices/reviews/check_save_return_value_review.rb +4 -3
- data/lib/rails_best_practices/reviews/default_scope_is_evil_review.rb +1 -1
- data/lib/rails_best_practices/reviews/dry_bundler_in_capistrano_review.rb +1 -1
- data/lib/rails_best_practices/reviews/hash_syntax_review.rb +11 -11
- data/lib/rails_best_practices/reviews/isolate_seed_data_review.rb +8 -8
- data/lib/rails_best_practices/reviews/keep_finders_on_their_own_model_review.rb +5 -5
- data/lib/rails_best_practices/reviews/law_of_demeter_review.rb +20 -19
- data/lib/rails_best_practices/reviews/move_code_into_controller_review.rb +3 -3
- data/lib/rails_best_practices/reviews/move_code_into_helper_review.rb +5 -5
- data/lib/rails_best_practices/reviews/move_finder_to_named_scope_review.rb +5 -5
- data/lib/rails_best_practices/reviews/needless_deep_nesting_review.rb +13 -13
- data/lib/rails_best_practices/reviews/not_rescue_exception_review.rb +1 -1
- data/lib/rails_best_practices/reviews/not_use_default_route_review.rb +2 -2
- data/lib/rails_best_practices/reviews/not_use_time_ago_in_words_review.rb +1 -1
- data/lib/rails_best_practices/reviews/overuse_route_customizations_review.rb +3 -3
- data/lib/rails_best_practices/reviews/protect_mass_assignment_review.rb +32 -32
- data/lib/rails_best_practices/reviews/remove_empty_helpers_review.rb +4 -4
- data/lib/rails_best_practices/reviews/remove_unused_methods_in_controllers_review.rb +14 -14
- data/lib/rails_best_practices/reviews/remove_unused_methods_in_helpers_review.rb +6 -6
- data/lib/rails_best_practices/reviews/remove_unused_methods_in_models_review.rb +15 -15
- data/lib/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review.rb +8 -8
- data/lib/rails_best_practices/reviews/restrict_auto_generated_routes_review.rb +71 -70
- data/lib/rails_best_practices/reviews/review.rb +2 -1
- data/lib/rails_best_practices/reviews/simplify_render_in_controllers_review.rb +1 -1
- data/lib/rails_best_practices/reviews/simplify_render_in_views_review.rb +11 -11
- data/lib/rails_best_practices/reviews/use_before_filter_review.rb +12 -9
- data/lib/rails_best_practices/reviews/use_model_association_review.rb +10 -10
- data/lib/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review.rb +14 -13
- data/lib/rails_best_practices/reviews/use_observer_review.rb +20 -20
- data/lib/rails_best_practices/reviews/use_parentheses_in_method_def_review.rb +6 -6
- data/lib/rails_best_practices/reviews/use_query_attribute_review.rb +44 -41
- data/lib/rails_best_practices/reviews/use_say_with_time_in_migrations_review.rb +7 -7
- data/lib/rails_best_practices/reviews/use_scope_access_review.rb +14 -14
- data/lib/rails_best_practices/reviews/use_turbo_sprockets_rails3_review.rb +1 -1
- data/lib/rails_best_practices/version.rb +1 -1
- data/rails_best_practices.gemspec +8 -8
- data/spec/rails_best_practices/analyzer_spec.rb +4 -4
- data/spec/rails_best_practices/core/error_spec.rb +6 -3
- data/spec/rails_best_practices/lexicals/long_line_check_spec.rb +21 -21
- data/spec/rails_best_practices/prepares/gemfile_prepare_spec.rb +15 -15
- data/spec/rails_best_practices/prepares/route_prepare_spec.rb +17 -15
- data/spec/rails_best_practices/reviews/hash_syntax_review_spec.rb +4 -4
- data/spec/rails_best_practices/reviews/law_of_demeter_review_spec.rb +8 -8
- data/spec/rails_best_practices/reviews/move_code_into_model_review_spec.rb +6 -6
- data/spec/rails_best_practices/reviews/protect_mass_assignment_review_spec.rb +4 -2
- data/spec/rails_best_practices/reviews/remove_unused_methods_in_controllers_review_spec.rb +6 -4
- data/spec/rails_best_practices/reviews/remove_unused_methods_in_helpers_review_spec.rb +8 -6
- data/spec/rails_best_practices/reviews/remove_unused_methods_in_models_review_spec.rb +16 -14
- data/spec/rails_best_practices/reviews/replace_instance_variable_with_local_variable_review_spec.rb +4 -4
- data/spec/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review_spec.rb +14 -14
- data/spec/rails_best_practices/reviews/use_parentheses_in_method_def_review_spec.rb +1 -1
- data/spec/rails_best_practices/reviews/use_turbo_sprockets_rails3_review_spec.rb +51 -51
- metadata +5 -2
@@ -27,21 +27,21 @@ module RailsBestPractices
|
|
27
27
|
first_argument = node.arguments.all.first
|
28
28
|
second_argument = node.arguments.all[1]
|
29
29
|
if @controller_names.last
|
30
|
-
if
|
30
|
+
if first_argument.sexp_type == :bare_assoc_hash
|
31
31
|
action_names = [first_argument.hash_values.first.to_s]
|
32
|
-
elsif
|
32
|
+
elsif first_argument.sexp_type == :array
|
33
33
|
action_names = first_argument.array_values.map(&:to_s)
|
34
|
-
elsif
|
35
|
-
if
|
34
|
+
elsif second_argument.try(:sexp_type) == :bare_assoc_hash && second_argument.hash_value('to').present?
|
35
|
+
if second_argument.hash_value('to').sexp_type == :string_literal
|
36
36
|
controller_name, action_name = second_argument.hash_value('to').to_s.split('#')
|
37
37
|
action_names = [action_name]
|
38
38
|
else
|
39
39
|
action_names = [second_argument.hash_value('to').to_s]
|
40
40
|
end
|
41
|
-
elsif
|
42
|
-
|
41
|
+
elsif first_argument.sexp_type == :symbol_literal && second_argument.try(:sexp_type) && \
|
42
|
+
second_argument.sexp_type == :symbol_literal
|
43
43
|
action_names = node.arguments.all.select \
|
44
|
-
{ |arg|
|
44
|
+
{ |arg| arg.sexp_type == :symbol_literal }.map(&:to_s)
|
45
45
|
else
|
46
46
|
action_names = [first_argument.to_s]
|
47
47
|
end
|
@@ -49,18 +49,18 @@ module RailsBestPractices
|
|
49
49
|
@routes.add_route(current_namespaces, current_controller_name, action_name)
|
50
50
|
end
|
51
51
|
else
|
52
|
-
if
|
52
|
+
if first_argument.sexp_type == :bare_assoc_hash
|
53
53
|
route_node = first_argument.hash_values.first
|
54
54
|
# do not parse redirect block
|
55
|
-
if
|
55
|
+
if route_node.sexp_type != :method_add_arg
|
56
56
|
controller_name, action_name = route_node.to_s.split('#')
|
57
57
|
@routes.add_route(current_namespaces, controller_name.underscore, action_name)
|
58
58
|
end
|
59
|
-
elsif
|
59
|
+
elsif first_argument.sexp_type == :array
|
60
60
|
first_argument.array_values.map(&:to_s).each do |action_node|
|
61
61
|
@routes.add_route(current_namespaces, controller_name, action_node.to_s)
|
62
62
|
end
|
63
|
-
elsif
|
63
|
+
elsif second_argument.try(:sexp_type) == :bare_assoc_hash
|
64
64
|
if second_argument.hash_value('to').present?
|
65
65
|
controller_name, action_name = second_argument.hash_value('to').to_s.split('#')
|
66
66
|
else
|
@@ -78,12 +78,13 @@ module RailsBestPractices
|
|
78
78
|
case options.sexp_type
|
79
79
|
when :bare_assoc_hash
|
80
80
|
if options.hash_value('controller').present?
|
81
|
-
return if
|
81
|
+
return if options.hash_value('controller').sexp_type == :regexp_literal
|
82
|
+
|
82
83
|
controller_name = options.hash_value('controller').to_s
|
83
84
|
action_name = options.hash_value('action').present? ? options.hash_value('action').to_s : '*'
|
84
85
|
@routes.add_route(current_namespaces, controller_name, action_name)
|
85
86
|
else
|
86
|
-
route_node = options.hash_values.find { |value_node|
|
87
|
+
route_node = options.hash_values.find { |value_node| value_node.sexp_type == :string_literal && value_node.to_s.include?('#') }
|
87
88
|
if route_node.present?
|
88
89
|
controller_name, action_name = route_node.to_s.split('#')
|
89
90
|
@routes.add_route(current_namespaces, controller_name.underscore, action_name)
|
@@ -100,7 +101,7 @@ module RailsBestPractices
|
|
100
101
|
options = node.arguments.all.last
|
101
102
|
case options.sexp_type
|
102
103
|
when :bare_assoc_hash
|
103
|
-
route_node = options.hash_values.find { |value_node|
|
104
|
+
route_node = options.hash_values.find { |value_node| value_node.sexp_type == :string_literal && value_node.to_s.include?('#') }
|
104
105
|
if route_node.present?
|
105
106
|
controller_name, action_name = route_node.to_s.split('#')
|
106
107
|
@routes.add_route(current_namespaces, controller_name.underscore, action_name)
|
@@ -151,7 +152,7 @@ module RailsBestPractices
|
|
151
152
|
end
|
152
153
|
when 'with_options'
|
153
154
|
argument = node.arguments.all.last
|
154
|
-
if
|
155
|
+
if argument.sexp_type == :bare_assoc_hash && argument.hash_value('controller').present?
|
155
156
|
@controller_name = [:with_option, argument.hash_value('controller').to_s]
|
156
157
|
end
|
157
158
|
else
|
@@ -48,44 +48,46 @@ module RailsBestPractices
|
|
48
48
|
|
49
49
|
# check an attribute assignment node, if there is a array reference node in the right value of assignment node,
|
50
50
|
# then remember this attribute assignment.
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
51
|
+
def assign(node)
|
52
|
+
left_value = node.left_value
|
53
|
+
right_value = node.right_value
|
54
|
+
return unless left_value.sexp_type == :field && right_value.sexp_type == :call
|
55
|
+
|
56
|
+
aref_node = right_value.grep_node(sexp_type: :aref)
|
57
|
+
if aref_node
|
58
|
+
assignments(left_value.receiver.to_s) << { message: left_value.message.to_s, arguments: aref_node.to_s }
|
59
59
|
end
|
60
|
+
end
|
60
61
|
|
61
62
|
# check a call node with message "save" or "save!",
|
62
63
|
# if there exists an attribute assignment for the receiver of this call node,
|
63
64
|
# and if the arguments of this attribute assignments has duplicated entries (different message and same arguments),
|
64
65
|
# then this node needs to add a virtual attribute.
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
66
|
+
def call_assignment(node)
|
67
|
+
if ['save', 'save!'].include? node.message.to_s
|
68
|
+
receiver = node.receiver.to_s
|
69
|
+
add_error "add model virtual attribute (for #{receiver})" if params_dup?(assignments(receiver).collect { |h| h[:arguments] })
|
70
70
|
end
|
71
|
+
end
|
71
72
|
|
72
73
|
# if the nodes are duplicated.
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
74
|
+
def params_dup?(nodes)
|
75
|
+
return false if nodes.nil?
|
76
|
+
|
77
|
+
!dups(nodes).empty?
|
78
|
+
end
|
77
79
|
|
78
80
|
# get the assignments of receiver.
|
79
|
-
|
80
|
-
|
81
|
-
|
81
|
+
def assignments(receiver)
|
82
|
+
@assignments[receiver] ||= []
|
83
|
+
end
|
82
84
|
|
83
85
|
# Get the duplicate entries from an Enumerable.
|
84
86
|
#
|
85
87
|
# @return [Enumerable] the duplicate entries.
|
86
|
-
|
87
|
-
|
88
|
-
|
88
|
+
def dups(nodes)
|
89
|
+
nodes.each_with_object({}) { |v, h| h[v] = h[v].to_i + 1; }.reject { |_k, v| v == 1 }.keys
|
90
|
+
end
|
89
91
|
end
|
90
92
|
end
|
91
93
|
end
|
@@ -42,7 +42,7 @@ module RailsBestPractices
|
|
42
42
|
add_callback :start_command_call do |node|
|
43
43
|
if %w[integer string].include? node.message.to_s
|
44
44
|
remember_foreign_key_columns(node)
|
45
|
-
elsif
|
45
|
+
elsif node.message.to_s == 'index'
|
46
46
|
remember_index_columns_inside_table(node)
|
47
47
|
end
|
48
48
|
end
|
@@ -87,107 +87,108 @@ module RailsBestPractices
|
|
87
87
|
# remember the node as index columns, when used outside a table
|
88
88
|
# block, i.e.
|
89
89
|
# add_index :table_name, :column_name
|
90
|
-
|
91
|
-
|
92
|
-
|
90
|
+
def remember_index_columns_outside_table(node)
|
91
|
+
table_name = node.arguments.all.first.to_s
|
92
|
+
index_column = node.arguments.all[1].to_object
|
93
93
|
|
94
|
-
|
95
|
-
|
96
|
-
|
94
|
+
@index_columns[table_name] ||= []
|
95
|
+
@index_columns[table_name] << index_column
|
96
|
+
end
|
97
97
|
|
98
98
|
# remember the node as index columns, when used inside a table
|
99
99
|
# block, i.e.
|
100
100
|
# t.index [:column_name, ...]
|
101
|
-
|
102
|
-
|
103
|
-
|
101
|
+
def remember_index_columns_inside_table(node)
|
102
|
+
table_name = @table_name
|
103
|
+
index_column = node.arguments.all.first.to_object
|
104
104
|
|
105
|
-
|
106
|
-
|
107
|
-
|
105
|
+
@index_columns[table_name] ||= []
|
106
|
+
@index_columns[table_name] << index_column
|
107
|
+
end
|
108
108
|
|
109
109
|
# remember table nodes
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
110
|
+
def remember_table_nodes(node)
|
111
|
+
@table_name = node.arguments.all.first.to_s
|
112
|
+
@table_nodes[@table_name] = node
|
113
|
+
end
|
114
114
|
|
115
115
|
# remember foreign key columns
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
end
|
133
|
-
foreign_id_column = "#{$1}_id"
|
116
|
+
def remember_foreign_key_columns(node)
|
117
|
+
table_name = @table_name
|
118
|
+
foreign_key_column = node.arguments.all.first.to_s
|
119
|
+
@foreign_keys[table_name] ||= []
|
120
|
+
if foreign_key_column =~ /(.*?)_id$/
|
121
|
+
if @foreign_keys[table_name].delete("#{$1}_type")
|
122
|
+
@foreign_keys[table_name] << ["#{$1}_id", "#{$1}_type"]
|
123
|
+
else
|
124
|
+
@foreign_keys[table_name] << foreign_key_column
|
125
|
+
end
|
126
|
+
foreign_id_column = foreign_key_column
|
127
|
+
elsif foreign_key_column =~ /(.*?)_type$/
|
128
|
+
if @foreign_keys[table_name].delete("#{$1}_id")
|
129
|
+
@foreign_keys[table_name] << ["#{$1}_id", "#{$1}_type"]
|
130
|
+
else
|
131
|
+
@foreign_keys[table_name] << foreign_key_column
|
134
132
|
end
|
133
|
+
foreign_id_column = "#{$1}_id"
|
134
|
+
end
|
135
135
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
end
|
136
|
+
if foreign_id_column
|
137
|
+
index_node = node.arguments.all.last.hash_value('index')
|
138
|
+
if index_node.present? && (index_node.to_s != 'false')
|
139
|
+
@index_columns[table_name] ||= []
|
140
|
+
@index_columns[table_name] << foreign_id_column
|
142
141
|
end
|
143
142
|
end
|
143
|
+
end
|
144
144
|
|
145
145
|
# remove the non foreign keys without corresponding tables.
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
end
|
146
|
+
def remove_table_not_exist_foreign_keys
|
147
|
+
@foreign_keys.each do |table, foreign_keys|
|
148
|
+
foreign_keys.delete_if do |key|
|
149
|
+
if key =~ /_id$/
|
150
|
+
class_name = Prepares.model_associations.get_association_class_name(table, key[0..-4])
|
151
|
+
class_name ? !@table_nodes[class_name.gsub('::', '').tableize] : !@table_nodes[key[0..-4].pluralize]
|
153
152
|
end
|
154
153
|
end
|
155
154
|
end
|
155
|
+
end
|
156
156
|
|
157
157
|
# remove the non foreign keys with only _type column.
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
}
|
158
|
+
def remove_only_type_foreign_keys
|
159
|
+
@foreign_keys.each do |_table, foreign_keys|
|
160
|
+
foreign_keys.delete_if { |key| key =~ /_type$/ }
|
162
161
|
end
|
162
|
+
end
|
163
163
|
|
164
164
|
# combine polymorphic foreign keys, e.g.
|
165
165
|
# [tagger_id], [tagger_type] => [tagger_id, tagger_type]
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
166
|
+
def combine_polymorphic_foreign_keys
|
167
|
+
@index_columns.each do |_table, foreign_keys|
|
168
|
+
foreign_id_keys = foreign_keys.select { |key| key.size == 1 && key.first =~ /_id/ }
|
169
|
+
foreign_type_keys = foreign_keys.select { |key| key.size == 1 && key.first =~ /_type/ }
|
170
|
+
foreign_id_keys.each do |id_key|
|
171
|
+
next unless type_key = foreign_type_keys.detect { |type_key| type_key.first == id_key.first.sub(/_id/, '') + '_type' }
|
172
|
+
|
173
|
+
foreign_keys.delete(id_key)
|
174
|
+
foreign_keys.delete(type_key)
|
175
|
+
foreign_keys << id_key + type_key
|
176
|
+
end
|
177
177
|
end
|
178
|
+
end
|
178
179
|
|
179
180
|
# check if the table's column is indexed.
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
181
|
+
def not_indexed?(table, column)
|
182
|
+
index_columns = @index_columns[table]
|
183
|
+
!index_columns || index_columns.none? { |e| greater_than_or_equal(Array(e), Array(column)) }
|
184
|
+
end
|
184
185
|
|
185
186
|
# check if more_array is greater than less_array or equal to less_array.
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
187
|
+
def greater_than_or_equal(more_array, less_array)
|
188
|
+
more_size = more_array.size
|
189
|
+
less_size = less_array.size
|
190
|
+
(more_array - less_array).size == more_size - less_size
|
191
|
+
end
|
191
192
|
end
|
192
193
|
end
|
193
194
|
end
|
@@ -28,7 +28,7 @@ module RailsBestPractices
|
|
28
28
|
# if our current binary is a subset of the @used_return_value_of
|
29
29
|
# then don't overwrite it
|
30
30
|
already_included = @used_return_value_of &&
|
31
|
-
|
31
|
+
(all_conditions - @used_return_value_of).empty?
|
32
32
|
|
33
33
|
@used_return_value_of = node.all_conditions unless already_included
|
34
34
|
end
|
@@ -36,6 +36,7 @@ module RailsBestPractices
|
|
36
36
|
|
37
37
|
def return_value_is_used?(node)
|
38
38
|
return false unless @used_return_value_of
|
39
|
+
|
39
40
|
node == @used_return_value_of or @used_return_value_of.include?(node)
|
40
41
|
end
|
41
42
|
|
@@ -33,7 +33,7 @@ module RailsBestPractices
|
|
33
33
|
# if our current binary is a subset of the @used_return_value_of
|
34
34
|
# then don't overwrite it
|
35
35
|
already_included = @used_return_value_of &&
|
36
|
-
|
36
|
+
(all_conditions - @used_return_value_of).empty?
|
37
37
|
|
38
38
|
@used_return_value_of = node.all_conditions unless already_included
|
39
39
|
end
|
@@ -41,6 +41,7 @@ module RailsBestPractices
|
|
41
41
|
|
42
42
|
def return_value_is_used?(node)
|
43
43
|
return false unless @used_return_value_of
|
44
|
+
|
44
45
|
node == @used_return_value_of or @used_return_value_of.include?(node)
|
45
46
|
end
|
46
47
|
|
@@ -58,8 +59,8 @@ module RailsBestPractices
|
|
58
59
|
elsif message == 'create'
|
59
60
|
# We're only interested in 'create' calls on model classes:
|
60
61
|
possible_receiver_classes = [node.receiver.to_s] + classable_modules.map do |mod|
|
61
|
-
|
62
|
-
|
62
|
+
"#{mod}::#{node.receiver}"
|
63
|
+
end
|
63
64
|
unless (possible_receiver_classes & model_classnames).empty?
|
64
65
|
add_error "use 'create!' instead of 'create' as the latter may not always save"
|
65
66
|
end
|
@@ -20,7 +20,7 @@ module RailsBestPractices
|
|
20
20
|
|
21
21
|
# check call node to see if it is with message "namespace" and argument "bundler".
|
22
22
|
add_callback :start_command do |node|
|
23
|
-
if
|
23
|
+
if node.message.to_s == 'namespace' && node.arguments.all[0].to_s == 'bundler'
|
24
24
|
add_error 'dry bundler in capistrano'
|
25
25
|
end
|
26
26
|
end
|
@@ -24,23 +24,23 @@ module RailsBestPractices
|
|
24
24
|
protected
|
25
25
|
|
26
26
|
# check if hash node is empty.
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
def empty_hash?(node)
|
28
|
+
s(:hash, nil) == node || s(:bare_assoc_hash, nil) == node
|
29
|
+
end
|
30
30
|
|
31
31
|
# check if hash key/value pairs are ruby 1.8 style.
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
def hash_is_18?(node)
|
33
|
+
pair_nodes = node.sexp_type == :hash ? node[1][1] : node[1]
|
34
|
+
return false if pair_nodes.blank?
|
35
35
|
|
36
|
-
|
37
|
-
|
36
|
+
pair_nodes.any? { |pair_node| pair_node[1].sexp_type == :symbol_literal }
|
37
|
+
end
|
38
38
|
|
39
39
|
# check if the hash keys are valid to be converted to ruby 1.9
|
40
40
|
# syntax.
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
def valid_keys?(node)
|
42
|
+
node.hash_keys.all? { |key| key =~ VALID_SYMBOL_KEY }
|
43
|
+
end
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|