rails_best_practices 0.6.6 → 0.6.7
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/Gemfile +0 -1
- data/README.md +28 -24
- data/Rakefile +0 -8
- data/install_supported_rubies.sh +2 -3
- data/lib/rails_best_practices.rb +8 -7
- data/lib/rails_best_practices/core.rb +1 -0
- data/lib/rails_best_practices/core/check.rb +68 -0
- data/lib/rails_best_practices/core/checking_visitor.rb +18 -15
- data/lib/rails_best_practices/core/runner.rb +22 -12
- data/lib/rails_best_practices/core/visitable_sexp.rb +6 -2
- data/lib/rails_best_practices/prepares.rb +11 -0
- data/lib/rails_best_practices/prepares/mailer_prepare.rb +33 -0
- data/lib/rails_best_practices/prepares/model_prepare.rb +60 -0
- data/lib/rails_best_practices/reviews.rb +23 -0
- data/lib/rails_best_practices/{checks/add_model_virtual_attribute_check.rb → reviews/add_model_virtual_attribute_review.rb} +6 -9
- data/lib/rails_best_practices/{checks/always_add_db_index_check.rb → reviews/always_add_db_index_review.rb} +9 -12
- data/lib/rails_best_practices/{checks/dry_bundler_in_capistrano_check.rb → reviews/dry_bundler_in_capistrano_review.rb} +8 -11
- data/lib/rails_best_practices/{checks/isolate_seed_data_check.rb → reviews/isolate_seed_data_review.rb} +11 -14
- data/lib/rails_best_practices/{checks/keep_finders_on_their_own_model_check.rb → reviews/keep_finders_on_their_own_model_review.rb} +7 -10
- data/lib/rails_best_practices/{checks/law_of_demeter_check.rb → reviews/law_of_demeter_review.rb} +10 -14
- data/lib/rails_best_practices/{checks/move_code_into_controller_check.rb → reviews/move_code_into_controller_review.rb} +8 -11
- data/lib/rails_best_practices/{checks/move_code_into_helper_check.rb → reviews/move_code_into_helper_review.rb} +7 -10
- data/lib/rails_best_practices/{checks/move_code_into_model_check.rb → reviews/move_code_into_model_review.rb} +7 -10
- data/lib/rails_best_practices/{checks/move_finder_to_named_scope_check.rb → reviews/move_finder_to_named_scope_review.rb} +7 -10
- data/lib/rails_best_practices/{checks/move_model_logic_into_model_check.rb → reviews/move_model_logic_into_model_review.rb} +8 -11
- data/lib/rails_best_practices/{checks/needless_deep_nesting_check.rb → reviews/needless_deep_nesting_review.rb} +8 -11
- data/lib/rails_best_practices/{checks/not_use_default_route_check.rb → reviews/not_use_default_route_review.rb} +7 -10
- data/lib/rails_best_practices/{checks/overuse_route_customizations_check.rb → reviews/overuse_route_customizations_review.rb} +10 -13
- data/lib/rails_best_practices/{checks/replace_complex_creation_with_factory_method_check.rb → reviews/replace_complex_creation_with_factory_method_review.rb} +8 -11
- data/lib/rails_best_practices/{checks/replace_instance_variable_with_local_variable_check.rb → reviews/replace_instance_variable_with_local_variable_review.rb} +7 -10
- data/lib/rails_best_practices/reviews/review.rb +92 -0
- data/lib/rails_best_practices/{checks/use_before_filter_check.rb → reviews/use_before_filter_review.rb} +8 -11
- data/lib/rails_best_practices/{checks/use_model_association_check.rb → reviews/use_model_association_review.rb} +8 -11
- data/lib/rails_best_practices/{checks/use_observer_check.rb → reviews/use_observer_review.rb} +14 -41
- data/lib/rails_best_practices/{checks/use_query_attribute_check.rb → reviews/use_query_attribute_review.rb} +20 -16
- data/lib/rails_best_practices/{checks/use_say_with_time_in_migrations_check.rb → reviews/use_say_with_time_in_migrations_review.rb} +8 -11
- data/lib/rails_best_practices/{checks/use_scope_access_check.rb → reviews/use_scope_access_review.rb} +8 -11
- data/lib/rails_best_practices/version.rb +1 -1
- data/rails_best_practices.gemspec +3 -2
- data/rails_best_practices.yml +22 -22
- data/rake_rubies.sh +3 -2
- data/spec/rails_best_practices/core/check_spec.rb +41 -0
- data/spec/rails_best_practices/core/checking_visitor_spec.rb +78 -0
- data/spec/rails_best_practices/core/visitable_sexp_spec.rb +39 -36
- data/spec/rails_best_practices/prepares/mailer_prepare_spec.rb +14 -0
- data/spec/rails_best_practices/prepares/model_prepare_spec.rb +22 -0
- data/spec/rails_best_practices/{checks/add_model_virtual_attribute_check_spec.rb → reviews/add_model_virtual_attribute_review_spec.rb} +17 -25
- data/spec/rails_best_practices/{checks/always_add_db_index_check_spec.rb → reviews/always_add_db_index_review_spec.rb} +28 -41
- data/spec/rails_best_practices/{checks/dry_bundler_in_capistrano_check_spec.rb → reviews/dry_bundler_in_capistrano_review_spec.rb} +7 -11
- data/spec/rails_best_practices/{checks/isolate_seed_data_check_spec.rb → reviews/isolate_seed_data_review_spec.rb} +13 -20
- data/spec/rails_best_practices/{checks/keep_finders_on_their_own_model_check_spec.rb → reviews/keep_finders_on_their_own_model_review_spec.rb} +16 -24
- data/spec/rails_best_practices/{checks/law_of_demeter_check_spec.rb → reviews/law_of_demeter_review_spec.rb} +24 -26
- data/spec/rails_best_practices/reviews/move_code_into_controller_review_spec.rb +29 -0
- data/spec/rails_best_practices/reviews/move_code_into_helper_review_spec.rb +24 -0
- data/spec/rails_best_practices/{checks/move_code_into_model_check_spec.rb → reviews/move_code_into_model_review_spec.rb} +12 -18
- data/spec/rails_best_practices/{checks/move_finder_to_named_scope_check_spec.rb → reviews/move_finder_to_named_scope_review_spec.rb} +12 -16
- data/spec/rails_best_practices/{checks/move_model_logic_into_model_check_spec.rb → reviews/move_model_logic_into_model_review_spec.rb} +7 -11
- data/spec/rails_best_practices/{checks/needless_deep_nesting_check_spec.rb → reviews/needless_deep_nesting_review_spec.rb} +26 -37
- data/spec/rails_best_practices/{checks/not_use_default_route_check_spec.rb → reviews/not_use_default_route_review_spec.rb} +13 -19
- data/spec/rails_best_practices/{checks/overuse_route_customizations_check_spec.rb → reviews/overuse_route_customizations_review_spec.rb} +27 -39
- data/spec/rails_best_practices/{checks/replace_complex_creation_with_factory_method_check_spec.rb → reviews/replace_complex_creation_with_factory_method_review_spec.rb} +10 -15
- data/spec/rails_best_practices/reviews/replace_instance_variable_with_local_variable_review_spec.rb +31 -0
- data/spec/rails_best_practices/reviews/review_spec.rb +11 -0
- data/spec/rails_best_practices/{checks/use_before_filter_check_spec.rb → reviews/use_before_filter_review_spec.rb} +11 -17
- data/spec/rails_best_practices/{checks/use_model_association_check_spec.rb → reviews/use_model_association_review_spec.rb} +12 -18
- data/spec/rails_best_practices/{checks/use_observer_check_spec.rb → reviews/use_observer_review_spec.rb} +28 -29
- data/spec/rails_best_practices/reviews/use_query_attribute_review_spec.rb +190 -0
- data/spec/rails_best_practices/{checks/use_say_with_time_in_migrations_check_spec.rb → reviews/use_say_with_time_in_migrations_review_spec.rb} +14 -23
- data/spec/rails_best_practices/{checks/use_scope_access_check_spec.rb → reviews/use_scope_access_review_spec.rb} +28 -37
- data/spec/rails_best_practices_spec.rb +4 -4
- data/spec/spec_helper.rb +1 -0
- metadata +128 -102
- data/lib/rails_best_practices/checks.rb +0 -23
- data/lib/rails_best_practices/checks/check.rb +0 -203
- data/spec/rails_best_practices/checks/check_spec.rb +0 -57
- data/spec/rails_best_practices/checks/move_code_into_controller_check_spec.rb +0 -33
- data/spec/rails_best_practices/checks/move_code_into_helper_check_spec.rb +0 -28
- data/spec/rails_best_practices/checks/replace_instance_variable_with_local_variable_check_spec.rb +0 -36
- data/spec/rails_best_practices/checks/use_query_attribute_check_spec.rb +0 -192
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -62,6 +62,10 @@ Install
|
|
62
62
|
Issue
|
63
63
|
-----
|
64
64
|
|
65
|
+
If you install the rails_best_practices with bundler-installed github-sourced gem, please use the following command instead.
|
66
|
+
|
67
|
+
bundle exec rails_best_practices .
|
68
|
+
|
65
69
|
If you got NoMethodError or any syntax error, you should use debug mode to detect which file rails_best_practices is parsing and getting the error.
|
66
70
|
|
67
71
|
rails_best_practices -d .
|
@@ -79,30 +83,30 @@ to generate `rails_best_practices.yml` file.
|
|
79
83
|
|
80
84
|
Now you can customize this configuration file, the default configuration is as follows:
|
81
85
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
You can remove or comment one
|
86
|
+
MoveFinderToNamedScopeReview: { }
|
87
|
+
UseModelAssociationReview: { }
|
88
|
+
UseScopeAccessReview: { }
|
89
|
+
AddModelVirtualAttributeReview: { }
|
90
|
+
ReplaceComplexCreationWithFactoryMethodReview: { attribute_assignment_count: 2 }
|
91
|
+
MoveModelLogicIntoModelReview: { use_count: 4 }
|
92
|
+
OveruseRouteCustomizationsReview: { customize_count: 3 }
|
93
|
+
NeedlessDeepNestingReview: { nested_count: 2 }
|
94
|
+
NotUseDefaultRouteReview: { }
|
95
|
+
KeepFindersOnTheirOwnModelReview: { }
|
96
|
+
LawOfDemeterReview: { }
|
97
|
+
UseObserverReview: { }
|
98
|
+
IsolateSeedDataReview: { }
|
99
|
+
AlwaysAddDbIndexReview: { }
|
100
|
+
UseBeforeFilterReview: { }
|
101
|
+
MoveCodeIntoControllerReview: { }
|
102
|
+
MoveCodeIntoModelReview: { use_count: 2 }
|
103
|
+
MoveCodeIntoHelperReview: { array_count: 3 }
|
104
|
+
ReplaceInstanceVariableWithLocalVariableReview: { }
|
105
|
+
DryBundlerInCapistranoReview: { }
|
106
|
+
UseSayWithTimeInMigrationsReview: { }
|
107
|
+
UseQueryAttributeReview: { }
|
108
|
+
|
109
|
+
You can remove or comment one review to disable it, and you can change the options.
|
106
110
|
|
107
111
|
Implementation
|
108
112
|
--------------
|
data/Rakefile
CHANGED
@@ -2,7 +2,6 @@ require "bundler"
|
|
2
2
|
Bundler.setup
|
3
3
|
|
4
4
|
require "rake"
|
5
|
-
require "rake/rdoctask"
|
6
5
|
require "rspec"
|
7
6
|
require "rspec/core/rake_task"
|
8
7
|
|
@@ -35,11 +34,4 @@ Rspec::Core::RakeTask.new('spec:progress') do |spec|
|
|
35
34
|
spec.pattern = "spec/**/*_spec.rb"
|
36
35
|
end
|
37
36
|
|
38
|
-
Rake::RDocTask.new do |rdoc|
|
39
|
-
rdoc.rdoc_dir = "rdoc"
|
40
|
-
rdoc.title = "rails_best_practices #{RailsBestPractices::VERSION}"
|
41
|
-
rdoc.rdoc_files.include("README*")
|
42
|
-
rdoc.rdoc_files.include("lib/**/*.rb")
|
43
|
-
end
|
44
|
-
|
45
37
|
task :default => :spec
|
data/install_supported_rubies.sh
CHANGED
data/lib/rails_best_practices.rb
CHANGED
@@ -26,7 +26,8 @@ require 'rubygems'
|
|
26
26
|
require 'progressbar'
|
27
27
|
require 'colored'
|
28
28
|
require 'haml'
|
29
|
-
require 'rails_best_practices/
|
29
|
+
require 'rails_best_practices/prepares'
|
30
|
+
require 'rails_best_practices/reviews'
|
30
31
|
require 'rails_best_practices/core'
|
31
32
|
require 'fileutils'
|
32
33
|
|
@@ -73,9 +74,9 @@ module RailsBestPractices
|
|
73
74
|
@runner.debug = true if @options['debug']
|
74
75
|
@runner.color = !options['without-color']
|
75
76
|
|
76
|
-
if @runner.checks.find { |check| check.is_a?
|
77
|
+
if @runner.checks.find { |check| check.is_a? Reviews::AlwaysAddDbIndexReview } &&
|
77
78
|
!review_files.find { |file| file.index "db\/schema.rb" }
|
78
|
-
plain_output("
|
79
|
+
plain_output("AlwaysAddDbIndexReview is disabled as there is no db/schema.rb file in your rails project.", 'blue')
|
79
80
|
end
|
80
81
|
|
81
82
|
@bar = ProgressBar.new('Analyzing', prepare_files.size + review_files.size)
|
@@ -162,13 +163,13 @@ module RailsBestPractices
|
|
162
163
|
# @return [Array] sorted files
|
163
164
|
def file_sort files
|
164
165
|
files.sort { |a, b|
|
165
|
-
if a =~
|
166
|
+
if a =~ Core::Check::MODEL_FILES
|
166
167
|
-1
|
167
|
-
elsif b =~
|
168
|
+
elsif b =~ Core::Check::MODEL_FILES
|
168
169
|
1
|
169
|
-
elsif a =~
|
170
|
+
elsif a =~ Core::Check::MAILER_FILES
|
170
171
|
-1
|
171
|
-
elsif b =~
|
172
|
+
elsif b =~ Core::Check::MAILER_FILES
|
172
173
|
1
|
173
174
|
else
|
174
175
|
a <=> b
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module RailsBestPractices
|
3
|
+
module Core
|
4
|
+
# A Check class that takes charge of checking the sexp.
|
5
|
+
class Check
|
6
|
+
# only nodes whose node_type is in NODE_TYPE will be reviewed.
|
7
|
+
NODE_TYPES = [:call, :defn, :defs, :if, :class, :lasgn, :iasgn, :ivar, :lvar, :block, :iter, :const]
|
8
|
+
|
9
|
+
CONTROLLER_FILES = /_controller\.rb$/
|
10
|
+
MIGRATION_FILES = /db\/migrate\/.*\.rb$/
|
11
|
+
MODEL_FILES = /models\/.*\.rb$/
|
12
|
+
MAILER_FILES = /models\/.*\.rb$|mailers\/.*\.rb/
|
13
|
+
VIEW_FILES = /views\/.*\.(erb|haml)$/
|
14
|
+
PARTIAL_VIEW_FILES = /views\/.*\/_.*\.(erb|haml)$/
|
15
|
+
ROUTE_FILE = /config\/routes.rb/
|
16
|
+
|
17
|
+
# default interesting nodes.
|
18
|
+
def interesting_nodes
|
19
|
+
[]
|
20
|
+
end
|
21
|
+
|
22
|
+
# default interesting files.
|
23
|
+
def interesting_files
|
24
|
+
/.*/
|
25
|
+
end
|
26
|
+
|
27
|
+
# delegate to start_### according to the node_type, like
|
28
|
+
#
|
29
|
+
# start_call
|
30
|
+
# start_defn
|
31
|
+
#
|
32
|
+
# @param [Sexp] node
|
33
|
+
def node_start(node)
|
34
|
+
@node = node
|
35
|
+
self.send("start_#{node.node_type}", node)
|
36
|
+
end
|
37
|
+
|
38
|
+
# delegate to end_### according to the node_type, like
|
39
|
+
#
|
40
|
+
# end_call
|
41
|
+
# end_defn
|
42
|
+
#
|
43
|
+
# @param [Sexp] node
|
44
|
+
def node_end(node)
|
45
|
+
@node = node
|
46
|
+
self.send("end_#{node.node_type}", node)
|
47
|
+
end
|
48
|
+
|
49
|
+
# method_missing to catch all start and end process for each node type, like
|
50
|
+
#
|
51
|
+
# start_defn
|
52
|
+
# end_defn
|
53
|
+
# start_call
|
54
|
+
# end_call
|
55
|
+
#
|
56
|
+
# if there is a "debug" method defined in check, each node will be output.
|
57
|
+
def method_missing(method_name, *args)
|
58
|
+
if method_name.to_s =~ /^start_/
|
59
|
+
p args if respond_to?(:debug)
|
60
|
+
elsif method_name.to_s =~ /^end_/
|
61
|
+
# nothing to do
|
62
|
+
else
|
63
|
+
super
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -14,26 +14,29 @@ module RailsBestPractices
|
|
14
14
|
# if the node_type and the node filename match the interesting_review_nodes and interesting_review_files,
|
15
15
|
# then run the reivew for that node.
|
16
16
|
class CheckingVisitor
|
17
|
-
# remember all the checks for prepare and review processes according to
|
18
|
-
|
17
|
+
# remember all the checks for prepare and review processes according to interesting_nodes.
|
18
|
+
#
|
19
|
+
# @param [Array] prepares
|
20
|
+
# @param [Array] reviews
|
21
|
+
def initialize(prepares, reviews)
|
19
22
|
[:prepare, :review].each do |process|
|
20
23
|
instance_variable_set("@#{process}_checks", {}) # @review_checks = {}
|
21
|
-
|
22
|
-
check.send("
|
23
|
-
instance_variable_get("@#{process}_checks")[node] ||= [] #
|
24
|
-
instance_variable_get("@#{process}_checks")[node] << check #
|
25
|
-
instance_variable_get("@#{process}_checks")[node].uniq! #
|
26
|
-
end #
|
27
|
-
end
|
24
|
+
eval("#{process}s").each do |check| # reviews.each do |check|
|
25
|
+
check.send("interesting_nodes").each do |node| # check.interesting_nodes.each do |node|
|
26
|
+
instance_variable_get("@#{process}_checks")[node] ||= [] # @review_checks[node] ||= []
|
27
|
+
instance_variable_get("@#{process}_checks")[node] << check # @review_checks[node] << check
|
28
|
+
instance_variable_get("@#{process}_checks")[node].uniq! # @review_checks[node].uniq!
|
29
|
+
end # end
|
30
|
+
end # end
|
28
31
|
end
|
29
32
|
end
|
30
33
|
|
31
34
|
# for prepare process
|
32
|
-
# if the node_type and the node filename match the
|
35
|
+
# if the node_type and the node filename match the interesting_nodes and interesting_files,
|
33
36
|
# then run the prepare for that node.
|
34
37
|
#
|
35
38
|
# for review process
|
36
|
-
# if the node_type and the node filename match the
|
39
|
+
# if the node_type and the node filename match the interesting_nodes and interesting_files,
|
37
40
|
# then run the reivew for that node.
|
38
41
|
[:prepare, :review].each do |process|
|
39
42
|
class_eval <<-EOS
|
@@ -41,16 +44,16 @@ module RailsBestPractices
|
|
41
44
|
checks = @#{process}_checks[node.node_type] # checks = @review_checks[node.node_type]
|
42
45
|
if checks # if checks
|
43
46
|
checks.each { |check| # checks.each { |check|
|
44
|
-
if node.file =~ check.
|
45
|
-
check
|
47
|
+
if node.file =~ check.interesting_files # if node.file =~ check.interesting_files
|
48
|
+
check.node_start(node) # check.node_start(node)
|
46
49
|
end # end
|
47
50
|
} # }
|
48
51
|
end # end
|
49
52
|
node.children.each {|sexp| sexp.#{process}(self)} # node.children.each {|sexp| sexp.review(self)}
|
50
53
|
if checks # if checks
|
51
54
|
checks.each { |check| # checks.each { |check|
|
52
|
-
if node.file =~ check.
|
53
|
-
check
|
55
|
+
if node.file =~ check.interesting_files # if node.file =~ check.interesting_files
|
56
|
+
check.node_end(node) # check.node_end(node)
|
54
57
|
end # end
|
55
58
|
} # }
|
56
59
|
end # end
|
@@ -31,12 +31,19 @@ module RailsBestPractices
|
|
31
31
|
@base_path || "."
|
32
32
|
end
|
33
33
|
|
34
|
-
|
34
|
+
# initialize the runner.
|
35
|
+
#
|
36
|
+
# @param [Hash] options pass the prepares and reviews.
|
37
|
+
def initialize(options={})
|
35
38
|
custom_config = File.join(Runner.base_path, 'config/rails_best_practices.yml')
|
36
39
|
@config = File.exists?(custom_config) ? custom_config : RailsBestPractices::DEFAULT_CONFIG
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
+
|
41
|
+
prepares = Array(options[:prepares])
|
42
|
+
reviews = Array(options[:reviews])
|
43
|
+
@prepares = prepares.empty? ? load_prepares : prepares
|
44
|
+
@reviews = reviews.empty? ? load_reviews : reviews
|
45
|
+
|
46
|
+
@checker ||= CheckingVisitor.new(@prepares, @reviews)
|
40
47
|
@debug = false
|
41
48
|
end
|
42
49
|
|
@@ -60,13 +67,11 @@ module RailsBestPractices
|
|
60
67
|
EOS
|
61
68
|
end
|
62
69
|
|
63
|
-
# get all errors from
|
70
|
+
# get all errors from reviews.
|
64
71
|
#
|
65
|
-
# @return [Array] all errors from
|
72
|
+
# @return [Array] all errors from reviews
|
66
73
|
def errors
|
67
|
-
@
|
68
|
-
all_errors = @checks.collect {|check| check.errors}
|
69
|
-
all_errors.flatten
|
74
|
+
@reviews.collect {|review| review.errors}.flatten
|
70
75
|
end
|
71
76
|
|
72
77
|
private
|
@@ -106,12 +111,17 @@ module RailsBestPractices
|
|
106
111
|
content
|
107
112
|
end
|
108
113
|
|
109
|
-
# load all
|
110
|
-
def
|
114
|
+
# load all prepares.
|
115
|
+
def load_prepares
|
116
|
+
[RailsBestPractices::Prepares::ModelPrepare.new, RailsBestPractices::Prepares::MailerPrepare.new]
|
117
|
+
end
|
118
|
+
|
119
|
+
# load all reviews according to configuration.
|
120
|
+
def load_reviews
|
111
121
|
check_objects = []
|
112
122
|
checks = YAML.load_file @config
|
113
123
|
checks.each do |check|
|
114
|
-
klass = RailsBestPractices::
|
124
|
+
klass = RailsBestPractices::Reviews.const_get(check[0].gsub(/Check/, 'Review'))
|
115
125
|
check_objects << (check[1].empty? ? klass.new : klass.new(check[1]))
|
116
126
|
end
|
117
127
|
check_objects
|
@@ -395,10 +395,14 @@ class Sexp
|
|
395
395
|
|
396
396
|
# to_s for lvar, ivar, lit, const, array, hash, and colon2 node.
|
397
397
|
#
|
398
|
+
# @param [Hash] options
|
399
|
+
# :remove_at remove the @ symbol for ivar.
|
398
400
|
# @return [String] to_s
|
399
|
-
def to_s
|
401
|
+
def to_s(options={})
|
400
402
|
case node_type
|
401
|
-
when :
|
403
|
+
when :ivar
|
404
|
+
options[:remove_at] ? self[1].to_s[1..-1] : self[1].to_s
|
405
|
+
when :lvar, :str, :lit, :const
|
402
406
|
self[1].to_s
|
403
407
|
when :array
|
404
408
|
"[\"#{self.children.collect(&:to_s).join('", "')}\"]"
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'rails_best_practices/prepares/model_prepare'
|
3
|
+
require 'rails_best_practices/prepares/mailer_prepare'
|
4
|
+
|
5
|
+
module RailsBestPractices
|
6
|
+
module Prepares
|
7
|
+
class <<self
|
8
|
+
attr_accessor :model_associations, :mailer_names
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'rails_best_practices/core/check'
|
3
|
+
|
4
|
+
module RailsBestPractices
|
5
|
+
module Prepares
|
6
|
+
# Remember the mailer names.
|
7
|
+
class MailerPrepare < Core::Check
|
8
|
+
|
9
|
+
def interesting_nodes
|
10
|
+
[:class]
|
11
|
+
end
|
12
|
+
|
13
|
+
def interesting_files
|
14
|
+
/#{MAILER_FILES}|#{MODEL_FILES}/
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@mailer_names = []
|
19
|
+
end
|
20
|
+
|
21
|
+
# check class node.
|
22
|
+
#
|
23
|
+
# if it is a subclass of ActionMailer::Base,
|
24
|
+
# then remember its class name.
|
25
|
+
def start_class(class_node)
|
26
|
+
if s(:colon2, s(:const, :ActionMailer), :Base) == class_node.base_class
|
27
|
+
@mailer_names << class_node.class_name
|
28
|
+
Prepares.mailer_names = @mailer_names
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'rails_best_practices/core/check'
|
3
|
+
|
4
|
+
module RailsBestPractices
|
5
|
+
module Prepares
|
6
|
+
# Remember the model associations.
|
7
|
+
class ModelPrepare < Core::Check
|
8
|
+
|
9
|
+
def interesting_nodes
|
10
|
+
[:class, :call]
|
11
|
+
end
|
12
|
+
|
13
|
+
def interesting_files
|
14
|
+
MODEL_FILES
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@associations = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
# check class node to remember the last class name.
|
22
|
+
def start_class(class_node)
|
23
|
+
@last_klazz = class_node.class_name.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
# assign @associations to Prepare.model_associations.
|
27
|
+
def end_class(class_node)
|
28
|
+
Prepares.model_associations = @associations
|
29
|
+
end
|
30
|
+
|
31
|
+
# check call node to remember all assoications.
|
32
|
+
#
|
33
|
+
# the remembered association names (@associations) are like
|
34
|
+
# {
|
35
|
+
# :Project=>{
|
36
|
+
# "categories"=>:has_and_belongs_to_many,
|
37
|
+
# "project_manager"=>:has_one,
|
38
|
+
# "portfolio"=>:belongs_to,
|
39
|
+
# "milestones=>:has_many"
|
40
|
+
# }
|
41
|
+
# }
|
42
|
+
def start_call(node)
|
43
|
+
remember_association(node) if association_methods.include? node.message
|
44
|
+
end
|
45
|
+
|
46
|
+
# remember associations, with class to association names.
|
47
|
+
def remember_association(association_node)
|
48
|
+
association_meta = association_node.message
|
49
|
+
association_name = association_node.arguments[1].to_s
|
50
|
+
@associations[@last_klazz] ||= {}
|
51
|
+
@associations[@last_klazz][association_name] = association_meta
|
52
|
+
end
|
53
|
+
|
54
|
+
# default rails association methods.
|
55
|
+
def association_methods
|
56
|
+
[:belongs_to, :has_one, :has_many, :has_and_belongs_to_many]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|