rails_best_practices 0.10.1 → 1.0.0
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.
- data/README.md +20 -0
- data/assets/result.html.haml +1 -1
- data/lib/rails_best_practices.rb +5 -3
- data/lib/rails_best_practices/core.rb +1 -1
- data/lib/rails_best_practices/core/check.rb +9 -12
- data/lib/rails_best_practices/core/checking_visitor.rb +9 -6
- data/lib/rails_best_practices/core/model_associations.rb +1 -1
- data/lib/rails_best_practices/core/nil.rb +5 -1
- data/lib/rails_best_practices/core/runner.rb +5 -5
- data/lib/rails_best_practices/core_ext/sexp.rb +688 -0
- data/lib/rails_best_practices/prepares/mailer_prepare.rb +4 -5
- data/lib/rails_best_practices/prepares/model_prepare.rb +16 -26
- data/lib/rails_best_practices/prepares/schema_prepare.rb +11 -17
- data/lib/rails_best_practices/reviews/add_model_virtual_attribute_review.rb +24 -75
- data/lib/rails_best_practices/reviews/always_add_db_index_review.rb +39 -113
- data/lib/rails_best_practices/reviews/dry_bundler_in_capistrano_review.rb +6 -16
- data/lib/rails_best_practices/reviews/isolate_seed_data_review.rb +16 -32
- data/lib/rails_best_practices/reviews/keep_finders_on_their_own_model_review.rb +11 -20
- data/lib/rails_best_practices/reviews/law_of_demeter_review.rb +7 -28
- data/lib/rails_best_practices/reviews/move_code_into_controller_review.rb +16 -14
- data/lib/rails_best_practices/reviews/move_code_into_helper_review.rb +10 -28
- data/lib/rails_best_practices/reviews/move_code_into_model_review.rb +12 -11
- data/lib/rails_best_practices/reviews/move_finder_to_named_scope_review.rb +13 -24
- data/lib/rails_best_practices/reviews/move_model_logic_into_model_review.rb +9 -9
- data/lib/rails_best_practices/reviews/needless_deep_nesting_review.rb +24 -68
- data/lib/rails_best_practices/reviews/not_use_default_route_review.rb +15 -22
- data/lib/rails_best_practices/reviews/overuse_route_customizations_review.rb +31 -91
- data/lib/rails_best_practices/reviews/remove_empty_helpers_review.rb +4 -2
- data/lib/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review.rb +20 -18
- data/lib/rails_best_practices/reviews/replace_instance_variable_with_local_variable_review.rb +5 -3
- data/lib/rails_best_practices/reviews/review.rb +8 -37
- data/lib/rails_best_practices/reviews/simplify_render_in_controllers_review.rb +10 -6
- data/lib/rails_best_practices/reviews/simplify_render_in_views_review.rb +9 -6
- data/lib/rails_best_practices/reviews/use_before_filter_review.rb +14 -72
- data/lib/rails_best_practices/reviews/use_model_association_review.rb +19 -31
- data/lib/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review.rb +5 -5
- data/lib/rails_best_practices/reviews/use_observer_review.rb +22 -40
- data/lib/rails_best_practices/reviews/use_query_attribute_review.rb +34 -39
- data/lib/rails_best_practices/reviews/use_say_with_time_in_migrations_review.rb +14 -38
- data/lib/rails_best_practices/reviews/use_scope_access_review.rb +13 -44
- data/lib/rails_best_practices/version.rb +1 -1
- data/spec/rails_best_practices/core/check_spec.rb +5 -5
- data/spec/rails_best_practices/core/checking_visitor_spec.rb +4 -4
- data/spec/rails_best_practices/core/model_associations_spec.rb +4 -4
- data/spec/rails_best_practices/core/nil_spec.rb +7 -1
- data/spec/rails_best_practices/core_ext/sexp_spec.rb +430 -0
- data/spec/rails_best_practices/prepares/model_prepare_spec.rb +12 -12
- data/spec/rails_best_practices/prepares/schema_prepare_spec.rb +6 -6
- data/spec/rails_best_practices/reviews/move_code_into_controller_review_spec.rb +14 -2
- data/spec/rails_best_practices/reviews/move_code_into_helper_review_spec.rb +1 -1
- data/spec/rails_best_practices/reviews/needless_deep_nesting_review_spec.rb +3 -3
- data/spec/rails_best_practices/reviews/not_use_default_route_review_spec.rb +1 -1
- data/spec/rails_best_practices/reviews/overuse_route_customizations_review_spec.rb +15 -1
- data/spec/rails_best_practices/reviews/simplify_render_in_controllers_review_spec.rb +3 -3
- data/spec/rails_best_practices/reviews/use_query_attribute_review_spec.rb +1 -1
- data/spec/rails_best_practices/reviews/use_say_with_time_in_migrations_review_spec.rb +1 -1
- data/spec/rails_best_practices/reviews/use_scope_access_review_spec.rb +4 -4
- data/spec/rails_best_practices_spec.rb +1 -3
- data/spec/spec_helper.rb +4 -0
- metadata +6 -8
- data/lib/rails_best_practices/core/visitable_sexp.rb +0 -444
- data/spec/rails_best_practices/core/visitable_sexp_spec.rb +0 -272
- data/spec/rails_best_practices/reviews/review_spec.rb +0 -11
@@ -15,17 +15,16 @@ module RailsBestPractices
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def initialize
|
18
|
-
@mailers =
|
18
|
+
@mailers = Prepares.mailers
|
19
19
|
end
|
20
20
|
|
21
21
|
# check class node.
|
22
22
|
#
|
23
23
|
# if it is a subclass of ActionMailer::Base,
|
24
24
|
# then remember its class name.
|
25
|
-
def start_class(
|
26
|
-
if
|
27
|
-
@mailers <<
|
28
|
-
Prepares.mailers = @mailers
|
25
|
+
def start_class(node)
|
26
|
+
if "ActionMailer::Base" == node.base_class.to_s
|
27
|
+
@mailers << node.class_name.to_s
|
29
28
|
end
|
30
29
|
end
|
31
30
|
end
|
@@ -5,9 +5,10 @@ module RailsBestPractices
|
|
5
5
|
module Prepares
|
6
6
|
# Remember the model associations.
|
7
7
|
class ModelPrepare < Core::Check
|
8
|
+
ASSOCIATION_METHODS = %w(belongs_to has_one has_many has_and_belongs_to_many)
|
8
9
|
|
9
10
|
def interesting_nodes
|
10
|
-
[:class, :
|
11
|
+
[:class, :command]
|
11
12
|
end
|
12
13
|
|
13
14
|
def interesting_files
|
@@ -15,23 +16,17 @@ module RailsBestPractices
|
|
15
16
|
end
|
16
17
|
|
17
18
|
def initialize
|
18
|
-
@models =
|
19
|
-
@model_associations =
|
19
|
+
@models = Prepares.models
|
20
|
+
@model_associations = Prepares.model_associations
|
20
21
|
end
|
21
22
|
|
22
23
|
# check class node to remember the last class name.
|
23
|
-
def start_class(
|
24
|
-
@last_klazz
|
24
|
+
def start_class(node)
|
25
|
+
@last_klazz= node.class_name.to_s
|
25
26
|
@models << @last_klazz
|
26
27
|
end
|
27
28
|
|
28
|
-
#
|
29
|
-
def end_class(class_node)
|
30
|
-
Prepares.models = @models
|
31
|
-
Prepares.model_associations = @model_associations
|
32
|
-
end
|
33
|
-
|
34
|
-
# check call node to remember all assoications.
|
29
|
+
# check command node to remember all assoications.
|
35
30
|
#
|
36
31
|
# the remembered association names (@associations) are like
|
37
32
|
# {
|
@@ -42,26 +37,21 @@ module RailsBestPractices
|
|
42
37
|
# "milestones => {:has_many" => "Milestone"}
|
43
38
|
# }
|
44
39
|
# }
|
45
|
-
def
|
46
|
-
remember_association(node) if
|
40
|
+
def start_command(node)
|
41
|
+
remember_association(node) if ASSOCIATION_METHODS.include? node.message.to_s
|
47
42
|
end
|
48
43
|
|
49
44
|
# remember associations, with class to association names.
|
50
|
-
def remember_association(
|
51
|
-
association_meta =
|
52
|
-
association_name =
|
53
|
-
arguments_node =
|
54
|
-
if arguments_node && :
|
55
|
-
|
56
|
-
association_class = arguments_node[index + 1].to_s if index
|
45
|
+
def remember_association(node)
|
46
|
+
association_meta = node.message.to_s
|
47
|
+
association_name = node.arguments.all[0].to_s
|
48
|
+
arguments_node = node.arguments.all[1]
|
49
|
+
if arguments_node && :bare_assoc_hash == arguments_node.sexp_type
|
50
|
+
association_class = arguments_node.hash_value("class_name").to_s
|
57
51
|
end
|
52
|
+
association_class ||= association_name.classify
|
58
53
|
@model_associations.add_association(@last_klazz, association_name, association_meta, association_class)
|
59
54
|
end
|
60
|
-
|
61
|
-
# default rails association methods.
|
62
|
-
def association_methods
|
63
|
-
[:belongs_to, :has_one, :has_many, :has_and_belongs_to_many]
|
64
|
-
end
|
65
55
|
end
|
66
56
|
end
|
67
57
|
end
|
@@ -6,10 +6,10 @@ module RailsBestPractices
|
|
6
6
|
# Remember the model attributes.
|
7
7
|
class SchemaPrepare < Core::Check
|
8
8
|
# all attribute types
|
9
|
-
ATTRIBUTE_TYPES =
|
9
|
+
ATTRIBUTE_TYPES = %w(integer float boolean string text date time datetime binary)
|
10
10
|
|
11
11
|
def interesting_nodes
|
12
|
-
[:
|
12
|
+
[:command, :command_call]
|
13
13
|
end
|
14
14
|
|
15
15
|
def interesting_files
|
@@ -17,26 +17,20 @@ module RailsBestPractices
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def initialize
|
20
|
-
@model_attributes =
|
20
|
+
@model_attributes = Prepares.model_attributes
|
21
21
|
end
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
when :create_table
|
27
|
-
@last_klazz = call_node.arguments[1].to_s.classify
|
28
|
-
when *ATTRIBUTE_TYPES
|
29
|
-
attribute_name = call_node.arguments[1].to_s
|
30
|
-
@model_attributes.add_attribute(@last_klazz, attribute_name, call_node.message)
|
31
|
-
else
|
32
|
-
# nothing to do
|
23
|
+
def start_command(node)
|
24
|
+
if "create_table" == node.message.to_s
|
25
|
+
@last_klazz = node.arguments.all[0].to_s.classify
|
33
26
|
end
|
34
27
|
end
|
35
28
|
|
36
|
-
#
|
37
|
-
def
|
38
|
-
if
|
39
|
-
|
29
|
+
# check command_call node to remember the model attributes.
|
30
|
+
def start_command_call(node)
|
31
|
+
if ATTRIBUTE_TYPES.include? node.message.to_s
|
32
|
+
attribute_name = node.arguments.all[0].to_s
|
33
|
+
@model_attributes.add_attribute(@last_klazz, attribute_name, node.message.to_s)
|
40
34
|
end
|
41
35
|
end
|
42
36
|
end
|
@@ -13,15 +13,7 @@ module RailsBestPractices
|
|
13
13
|
# check method define nodes in all controller files,
|
14
14
|
# if there are more than one [] method calls with the same subject and arguments,
|
15
15
|
# but assigned to one model's different attribute.
|
16
|
-
# and after these method calls, there is a save method call for that model,
|
17
|
-
#
|
18
|
-
# def create
|
19
|
-
# @user = User.new(params[:user])
|
20
|
-
# @user.first_name = params[:full_name].split(' ', 2).first
|
21
|
-
# @user.last_name = params[:full_name].split(' ', 2).last
|
22
|
-
# @user.save
|
23
|
-
# end
|
24
|
-
#
|
16
|
+
# and after these method calls, there is a save method call for that model,
|
25
17
|
# then the model needs to add a virtual attribute.
|
26
18
|
class AddModelVirtualAttributeReview < Review
|
27
19
|
def url
|
@@ -29,7 +21,7 @@ module RailsBestPractices
|
|
29
21
|
end
|
30
22
|
|
31
23
|
def interesting_nodes
|
32
|
-
[:
|
24
|
+
[:def]
|
33
25
|
end
|
34
26
|
|
35
27
|
def interesting_files
|
@@ -40,89 +32,46 @@ module RailsBestPractices
|
|
40
32
|
#
|
41
33
|
# it will check every attribute assignment nodes and call node of message :save or :save!, if
|
42
34
|
#
|
43
|
-
# 1. there are more than one arguments who contain
|
44
|
-
# @user.first_name = params[:full_name].split(' ').first
|
45
|
-
# @user.last_name = params[:full_name].split(' ').last
|
35
|
+
# 1. there are more than one arguments who contain array reference node in the right value of assignment nodes,
|
46
36
|
# 2. the messages of attribute assignment nodes housld be different (:first_name= , :last_name=)
|
47
37
|
# 3. the argument of call nodes with message :[] should be same (:full_name)
|
48
38
|
# 4. there should be a call node with message :save or :save! after attribute assignment nodes
|
49
|
-
# @user.save
|
50
39
|
# 5. and the subject of save or save! call node should be the same with the subject of attribute assignment nodes
|
51
40
|
#
|
52
41
|
# then the attribute assignment nodes can add model virtual attribute instead.
|
53
|
-
def
|
54
|
-
@
|
42
|
+
def start_def(node)
|
43
|
+
@assignments = {}
|
55
44
|
node.recursive_children do |child|
|
56
|
-
case child.
|
57
|
-
when :
|
58
|
-
|
45
|
+
case child.sexp_type
|
46
|
+
when :assign
|
47
|
+
assign(child)
|
59
48
|
when :call
|
60
49
|
call_assignment(child)
|
61
|
-
else
|
62
50
|
end
|
63
51
|
end
|
64
52
|
end
|
65
53
|
|
66
54
|
private
|
67
|
-
# check an attribute assignment node, if there is a
|
55
|
+
# check an attribute assignment node, if there is a array reference node in the right value of assignment node,
|
68
56
|
# then remember this attribute assignment.
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
# ),
|
78
|
-
# :first,
|
79
|
-
# s(:arglist)
|
80
|
-
# )
|
81
|
-
# )
|
82
|
-
# )
|
83
|
-
#
|
84
|
-
# The remember attribute assignments (@attrasgns) are as follows
|
85
|
-
#
|
86
|
-
# {
|
87
|
-
# s(:ivar, :@user) =>
|
88
|
-
# [{
|
89
|
-
# :message=>:first_name=,
|
90
|
-
# :arguments=>s(:call, s(:call, nil, :params, s(:arglist)), :[], s(:arglist, s(:lit, :full_name)))
|
91
|
-
# }]
|
92
|
-
# }
|
93
|
-
def attribute_assignment(node)
|
94
|
-
subject = node.subject
|
95
|
-
arguments_node = node.arguments.grep_node(:message => :[])
|
96
|
-
return if subject.nil? or arguments_node.nil?
|
97
|
-
attrasgns(subject) << {:message => node.message, :arguments => arguments_node}
|
57
|
+
def assign(node)
|
58
|
+
left_value = node.left_value
|
59
|
+
right_value = node.right_value
|
60
|
+
return unless :field == left_value.sexp_type && :call == right_value.sexp_type
|
61
|
+
aref_node = right_value.grep_node(:sexp_type => :aref)
|
62
|
+
if aref_node
|
63
|
+
assignments(left_value.subject.to_s) << {:message => left_value.message.to_s, :arguments => aref_node.to_s}
|
64
|
+
end
|
98
65
|
end
|
99
66
|
|
100
|
-
# check a call node with message
|
67
|
+
# check a call node with message "save" or "save!",
|
101
68
|
# if there exists an attribute assignment for the subject of this call node,
|
102
69
|
# and if the arguments of this attribute assignments has duplicated entries (different message and same arguments),
|
103
70
|
# then this node needs to add a virtual attribute.
|
104
|
-
#
|
105
|
-
# e.g. this is @attrasgns
|
106
|
-
# {
|
107
|
-
# s(:ivar, :@user)=>
|
108
|
-
# [{
|
109
|
-
# :message=>:first_name=,
|
110
|
-
# :arguments=>s(:call, s(:call, nil, :params, s(:arglist)), :[], s(:arglist, s(:lit, :full_name)))
|
111
|
-
# }, {
|
112
|
-
# :message=>:last_name=,
|
113
|
-
# :arguments=>s(:call, s(:call, nil, :params, s(:arglist)), :[], s(:arglist, s(:lit, :full_name)))
|
114
|
-
# }]
|
115
|
-
# }
|
116
|
-
# and this is the call node
|
117
|
-
# s(:call, s(:ivar, :@user), :save, s(:arglist))
|
118
|
-
#
|
119
|
-
# The message of call node is :save,
|
120
|
-
# and the key of @attrasgns is the same as the subject of call node,
|
121
|
-
# and the value of @aatrasgns has different message and same arguments.
|
122
71
|
def call_assignment(node)
|
123
|
-
if [
|
124
|
-
subject = node.subject
|
125
|
-
add_error "add model virtual attribute (for #{subject})" if params_dup?(
|
72
|
+
if ["save", "save!"].include? node.message.to_s
|
73
|
+
subject = node.subject.to_s
|
74
|
+
add_error "add model virtual attribute (for #{subject})" if params_dup?(assignments(subject).collect {|h| h[:arguments]})
|
126
75
|
end
|
127
76
|
end
|
128
77
|
|
@@ -132,9 +81,9 @@ module RailsBestPractices
|
|
132
81
|
!nodes.dups.empty?
|
133
82
|
end
|
134
83
|
|
135
|
-
# get the
|
136
|
-
def
|
137
|
-
@
|
84
|
+
# get the assignments of subject.
|
85
|
+
def assignments(subject)
|
86
|
+
@assignments[subject] ||= []
|
138
87
|
end
|
139
88
|
end
|
140
89
|
end
|
@@ -10,12 +10,12 @@ module RailsBestPractices
|
|
10
10
|
# Implementation:
|
11
11
|
#
|
12
12
|
# Review process:
|
13
|
-
# only check the
|
14
|
-
# if the subject of
|
15
|
-
# if the subject of
|
16
|
-
# if the sujbect of
|
17
|
-
# if the subject of
|
18
|
-
# after all of these, at the end of
|
13
|
+
# only check the command and command_calls nodes and at the end of program node in db/schema file,
|
14
|
+
# if the subject of command node is "create_table", then remember the table names
|
15
|
+
# if the subject of command_call node is "integer" and suffix with id, then remember it as foreign key
|
16
|
+
# if the sujbect of command_call node is "string", the name of it is _type suffixed and there is an integer column _id suffixed, then remember it as polymorphic foreign key
|
17
|
+
# if the subject of command node is "add_index", then remember the index columns
|
18
|
+
# after all of these, at the end of program node
|
19
19
|
#
|
20
20
|
# ActiveRecord::Schema.define(:version => 20101201111111) do
|
21
21
|
# ......
|
@@ -29,7 +29,7 @@ module RailsBestPractices
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def interesting_nodes
|
32
|
-
[:
|
32
|
+
[:command, :command_call, :program]
|
33
33
|
end
|
34
34
|
|
35
35
|
def interesting_files
|
@@ -43,83 +43,46 @@ module RailsBestPractices
|
|
43
43
|
@table_nodes = {}
|
44
44
|
end
|
45
45
|
|
46
|
-
# check
|
46
|
+
# check command_call node.
|
47
47
|
#
|
48
|
-
# if the message of
|
49
|
-
# then remember
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
48
|
+
# if the message of command_call node is "create_table", then remember the table name.
|
49
|
+
# if the message of command_call node is "add_index", then remember it as index columns.
|
50
|
+
def start_command_call(node)
|
51
|
+
case node.message.to_s
|
52
|
+
when "integer", "string"
|
53
|
+
remember_foreign_key_columns(node)
|
54
|
+
else
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# check command node.
|
54
59
|
#
|
55
|
-
# if the message of
|
60
|
+
# if the message of command node is "integer",
|
56
61
|
# then remember it as a foreign key of last create table name.
|
57
62
|
#
|
58
|
-
# if the message of
|
63
|
+
# if the message of command node is "type" and the name of argument is _type suffixed,
|
59
64
|
# then remember it with _id suffixed column as polymorphic foreign key.
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
# {
|
64
|
-
# "taggings" =>
|
65
|
-
# ["tag_id", ["taggable_id", "taggable_type"]]
|
66
|
-
# }
|
67
|
-
#
|
68
|
-
# if the message of call node is :add_index,
|
69
|
-
# then remember it as index columns (@index_columns) like
|
70
|
-
#
|
71
|
-
# {
|
72
|
-
# "comments" =>
|
73
|
-
# ["post_id", "user_id"]
|
74
|
-
# }
|
75
|
-
def start_call(node)
|
76
|
-
case node.message
|
77
|
-
when :create_table
|
65
|
+
def start_command(node)
|
66
|
+
case node.message.to_s
|
67
|
+
when "create_table"
|
78
68
|
remember_table_nodes(node)
|
79
|
-
when
|
80
|
-
remember_foreign_key_columns(node)
|
81
|
-
when :add_index
|
69
|
+
when "add_index"
|
82
70
|
remember_index_columns(node)
|
83
|
-
else
|
84
71
|
end
|
85
72
|
end
|
86
73
|
|
87
|
-
# check at the end of
|
88
|
-
#
|
89
|
-
# s(:iter,
|
90
|
-
# s(:call,
|
91
|
-
# s(:colon2, s(:const, :ActiveRecord), :Schema),
|
92
|
-
# :define,
|
93
|
-
# s(:arglist, s(:hash, s(:lit, :version), s(:lit, 20100603080629)))
|
94
|
-
# ),
|
95
|
-
# nil,
|
96
|
-
# s(:iter,
|
97
|
-
# s(:call, nil, :create_table,
|
98
|
-
# s(:arglist, s(:str, "comments"), s(:hash, s(:lit, :force), s(:true)))
|
99
|
-
# ),
|
100
|
-
# s(:lasgn, :t),
|
101
|
-
# s(:block,
|
102
|
-
# s(:call, s(:lvar, :t), :string, s(:arglist, s(:str, "content")))
|
103
|
-
# )
|
104
|
-
# )
|
105
|
-
# )
|
106
|
-
#
|
107
|
-
# if the subject of iter node is with subject ActiveRecord::Schema,
|
108
|
-
# it means we have completed the foreign keys and index columns parsing,
|
109
|
-
# then we compare foreign keys and index columns.
|
74
|
+
# check at the end of program node.
|
110
75
|
#
|
76
|
+
# compare foreign keys and index columns,
|
111
77
|
# if there are any foreign keys not existed in index columns,
|
112
78
|
# then we should add db index for that foreign keys.
|
113
|
-
def
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
if indexed?(table, column)
|
121
|
-
add_error "always add db index (#{table} => [#{Array(column).join(', ')}])", table_node.file, table_node.line
|
122
|
-
end
|
79
|
+
def end_program(node)
|
80
|
+
remove_only_type_foreign_keys
|
81
|
+
@foreign_keys.each do |table, foreign_key|
|
82
|
+
table_node = @table_nodes[table]
|
83
|
+
foreign_key.each do |column|
|
84
|
+
if indexed?(table, column)
|
85
|
+
add_error "always add db index (#{table} => [#{Array(column).join(', ')}])", table_node.file, table_node.line
|
123
86
|
end
|
124
87
|
end
|
125
88
|
end
|
@@ -127,62 +90,25 @@ module RailsBestPractices
|
|
127
90
|
|
128
91
|
private
|
129
92
|
# remember the node as index columns
|
130
|
-
#
|
131
|
-
# s(:call, nil, :add_index,
|
132
|
-
# s(:arglist,
|
133
|
-
# s(:str, "comments"),
|
134
|
-
# s(:array, s(:str, "post_id")),
|
135
|
-
# s(:hash, s(:lit, :name), s(:str, "index_comments_on_post_id"))
|
136
|
-
# )
|
137
|
-
# )
|
138
|
-
#
|
139
|
-
# the remember index columns are like
|
140
|
-
# {
|
141
|
-
# "comments" =>
|
142
|
-
# ["post_id", "user_id"]
|
143
|
-
# }
|
144
93
|
def remember_index_columns(node)
|
145
|
-
table_name = node.arguments[
|
146
|
-
index_column =
|
94
|
+
table_name = node.arguments.all[0].to_s
|
95
|
+
index_column = node.arguments.all[1].to_object
|
147
96
|
|
148
97
|
@index_columns[table_name] ||= []
|
149
|
-
@index_columns[table_name] <<
|
98
|
+
@index_columns[table_name] << index_column
|
150
99
|
end
|
151
100
|
|
152
101
|
# remember table nodes
|
153
|
-
#
|
154
|
-
# if the node is
|
155
|
-
#
|
156
|
-
# s(:call, nil, :create_table,
|
157
|
-
# s(:arglist, s(:str, "comments"), s(:hash, s(:lit, :force), s(:true))))
|
158
|
-
#
|
159
|
-
# then the table nodes will be
|
160
|
-
#
|
161
|
-
# {
|
162
|
-
# "comments" =>
|
163
|
-
# s(:call, nil, :create_table, s(:arglist, s(:str, "comments"), s(:hash, s(:lit, :force), s(:true))))
|
164
|
-
# }
|
165
102
|
def remember_table_nodes(node)
|
166
|
-
@table_name = node.arguments[
|
103
|
+
@table_name = node.arguments.all[0].to_s
|
167
104
|
@table_nodes[@table_name] = node
|
168
105
|
end
|
169
106
|
|
170
107
|
|
171
108
|
# remember foreign key columns
|
172
|
-
#
|
173
|
-
# if the message of node is :integer,
|
174
|
-
# then it is a foreign key, like
|
175
|
-
#
|
176
|
-
# s(:call, s(:lvar, :t), :integer, s(:arglist, s(:str, "post_id")))
|
177
|
-
#
|
178
|
-
# if the message of node is :string, with _type suffixed and there is a _id suffixed column,
|
179
|
-
# then they are polymorphic foreign key
|
180
|
-
#
|
181
|
-
# s(:call, s(:lvar, :t), :integer, s(:arglist, s(:str, "taggable_id")))
|
182
|
-
# s(:call, s(:lvar, :t), :string, s(:arglist, s(:str, "taggable_type")))
|
183
109
|
def remember_foreign_key_columns(node)
|
184
110
|
table_name = @table_name
|
185
|
-
foreign_key_column = node.arguments[
|
111
|
+
foreign_key_column = node.arguments.all[0].to_s
|
186
112
|
@foreign_keys[table_name] ||= []
|
187
113
|
if foreign_key_column =~ /(.*?)_id$/
|
188
114
|
if @foreign_keys[table_name].delete("#{$1}_type")
|