rails_best_practices 0.5.3 → 0.5.5
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.textile +3 -3
- data/lib/rails_best_practices.rb +8 -4
- data/lib/rails_best_practices/checks/always_add_db_index_check.rb +16 -4
- data/lib/rails_best_practices/checks/check.rb +39 -8
- data/lib/rails_best_practices/checks/use_query_attribute_check.rb +47 -42
- data/lib/rails_best_practices/command.rb +9 -2
- data/lib/rails_best_practices/core/checking_visitor.rb +7 -2
- data/lib/rails_best_practices/core/runner.rb +27 -16
- data/lib/rails_best_practices/core/visitable_sexp.rb +21 -15
- data/lib/rails_best_practices/version.rb +1 -1
- metadata +51 -40
data/README.textile
CHANGED
@@ -14,7 +14,7 @@ rails_best_practices .
|
|
14
14
|
|
15
15
|
notice the period at the end, it can be the relative or absolute path of your rails app.
|
16
16
|
|
17
|
-
And default rails_best_practices will do parse codes in vendor, spec, test and
|
17
|
+
And default rails_best_practices will do parse codes in vendor, spec, test and features directories. If you need, see the command options:
|
18
18
|
|
19
19
|
<pre><code>
|
20
20
|
$ rails_best_practices -h
|
@@ -23,7 +23,7 @@ Usage: rails_best_practices [options]
|
|
23
23
|
--vendor include vendor files
|
24
24
|
--spec include spec files
|
25
25
|
--test include test files
|
26
|
-
--
|
26
|
+
--features include features files
|
27
27
|
-x, --exclude PATTERNS Don't analyze files matching a pattern
|
28
28
|
(comma-separated regexp list)
|
29
29
|
-v, --version Show this version
|
@@ -32,7 +32,7 @@ Usage: rails_best_practices [options]
|
|
32
32
|
|
33
33
|
*************************************************
|
34
34
|
|
35
|
-
h2.
|
35
|
+
h2. Resources
|
36
36
|
|
37
37
|
Homepage: "http://rails-bestpractices.com":http://rails-bestpractices.com
|
38
38
|
Repository: "http://github.com/flyerhzm/rails_best_practices":http://github.com/flyerhzm/rails_best_practices
|
data/lib/rails_best_practices.rb
CHANGED
@@ -3,23 +3,27 @@ require 'rails_best_practices/checks'
|
|
3
3
|
require 'rails_best_practices/core'
|
4
4
|
|
5
5
|
module RailsBestPractices
|
6
|
-
|
6
|
+
|
7
7
|
class <<self
|
8
|
+
def prepare_files
|
9
|
+
expand_dirs_to_files 'app/models'
|
10
|
+
end
|
11
|
+
|
8
12
|
def analyze_files(dir = '.', options = {})
|
9
13
|
files = expand_dirs_to_files(dir)
|
10
14
|
files = model_first_sort(files)
|
11
15
|
['vendor', 'spec', 'test', 'stories', 'features'].each do |pattern|
|
12
16
|
files = ignore_files(files, "#{pattern}/") unless options[pattern]
|
13
17
|
end
|
14
|
-
|
18
|
+
|
15
19
|
# Exclude files based on exclude regexes if the option is set.
|
16
20
|
for pattern in options[:exclude]
|
17
21
|
files = ignore_files(files, pattern)
|
18
22
|
end
|
19
|
-
|
23
|
+
|
20
24
|
files
|
21
25
|
end
|
22
|
-
|
26
|
+
|
23
27
|
def expand_dirs_to_files *dirs
|
24
28
|
extensions = ['rb', 'erb', 'haml', 'builder']
|
25
29
|
|
@@ -40,6 +40,7 @@ module RailsBestPractices
|
|
40
40
|
|
41
41
|
def evaluate_end(node)
|
42
42
|
if :iter == node.node_type && :call == node.subject.node_type && s(:colon2, s(:const, :ActiveRecord), :Schema) == node.subject.subject
|
43
|
+
remove_only_type_foreign_keys
|
43
44
|
@foreign_keys.each do |table, foreign_key|
|
44
45
|
table_node = @table_nodes[table]
|
45
46
|
foreign_key.each do |column|
|
@@ -67,16 +68,27 @@ module RailsBestPractices
|
|
67
68
|
|
68
69
|
def add_foreign_key_column(table_name, foreign_key_column)
|
69
70
|
@foreign_keys[table_name] ||= []
|
70
|
-
if foreign_key_column =~ /_id$/
|
71
|
-
|
71
|
+
if foreign_key_column =~ /(.*?)_id$/
|
72
|
+
if @foreign_keys[table_name].delete("#{$1}_type")
|
73
|
+
@foreign_keys[table_name] << ["#{$1}_id", "#{$1}_type"]
|
74
|
+
else
|
72
75
|
@foreign_keys[table_name] << foreign_key_column
|
73
76
|
end
|
74
77
|
elsif foreign_key_column =~ /(.*?)_type$/
|
75
|
-
@foreign_keys[table_name].delete("#{$1}_id")
|
76
|
-
|
78
|
+
if @foreign_keys[table_name].delete("#{$1}_id")
|
79
|
+
@foreign_keys[table_name] << ["#{$1}_id", "#{$1}_type"]
|
80
|
+
else
|
81
|
+
@foreign_keys[table_name] << foreign_key_column
|
82
|
+
end
|
77
83
|
end
|
78
84
|
end
|
79
85
|
|
86
|
+
def remove_only_type_foreign_keys
|
87
|
+
@foreign_keys.delete_if { |table, foreign_key|
|
88
|
+
foreign_key.size == 1 && foreign_key[0] =~ /_type$/
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
80
92
|
def indexed?(table, column)
|
81
93
|
index_columns = @index_columns[table]
|
82
94
|
!index_columns || !index_columns.any? { |e| greater_than(Array(e), Array(column)) }
|
@@ -4,8 +4,8 @@ require 'rails_best_practices/core/error'
|
|
4
4
|
module RailsBestPractices
|
5
5
|
module Checks
|
6
6
|
class Check
|
7
|
-
NODE_TYPES = [:call, :defn, :defs, :if, :unless, :class, :lasgn, :iasgn, :ivar, :lvar, :block, :iter]
|
8
|
-
|
7
|
+
NODE_TYPES = [:call, :defn, :defs, :if, :unless, :class, :lasgn, :iasgn, :ivar, :lvar, :block, :iter, :const]
|
8
|
+
|
9
9
|
CONTROLLER_FILES = /_controller\.rb$/
|
10
10
|
MIGRATION_FILES = /db\/migrate\/.*\.rb$/
|
11
11
|
MODLE_FILES = /models\/.*\.rb$/
|
@@ -17,50 +17,81 @@ module RailsBestPractices
|
|
17
17
|
def initialize
|
18
18
|
@errors = []
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def interesting_files
|
22
22
|
/.*/
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
|
+
def interesting_prepare_files
|
26
|
+
/.*/
|
27
|
+
end
|
28
|
+
|
25
29
|
NODE_TYPES.each do |node|
|
26
30
|
start_node_method = "evaluate_start_#{node}"
|
27
31
|
end_node_method = "evaluate_end_#{node}"
|
28
32
|
define_method(start_node_method) { |node| } unless self.respond_to?(start_node_method)
|
29
33
|
define_method(end_node_method) { |node| } unless self.respond_to?(end_node_method)
|
34
|
+
|
35
|
+
prepare_start_node_method = "prepare_start_#{node}"
|
36
|
+
prepare_end_node_method = "prepare_end_#{node}"
|
37
|
+
define_method(prepare_start_node_method) { |node| } unless self.respond_to?(prepare_start_node_method)
|
38
|
+
define_method(prepare_end_node_method) { |node| } unless self.respond_to?(prepare_end_node_method)
|
30
39
|
end
|
31
40
|
|
32
41
|
def position(offset = 0)
|
33
42
|
"#{@line[2]}:#{@line[1] + offset}"
|
34
43
|
end
|
35
|
-
|
44
|
+
|
45
|
+
def prepare_start(node)
|
46
|
+
end
|
47
|
+
|
48
|
+
def prepare_end(node)
|
49
|
+
end
|
50
|
+
|
36
51
|
def evaluate_start(node)
|
37
52
|
end
|
38
53
|
|
39
54
|
def evaluate_end(node)
|
40
55
|
end
|
41
56
|
|
57
|
+
def prepare_node(position, node)
|
58
|
+
@node = node
|
59
|
+
prepare_method = "prepare_#{position}_#{node.node_type}"
|
60
|
+
self.send(prepare_method, node)
|
61
|
+
end
|
62
|
+
|
42
63
|
def evaluate_node(position, node)
|
43
64
|
@node = node
|
44
65
|
eval_method = "evaluate_#{position}_#{node.node_type}"
|
45
66
|
self.send(eval_method, node)
|
46
67
|
end
|
47
68
|
|
69
|
+
def prepare_node_start(node)
|
70
|
+
prepare_node(:start, node)
|
71
|
+
prepare_start(node)
|
72
|
+
end
|
73
|
+
|
74
|
+
def prepare_node_end(node)
|
75
|
+
prepare_node(:end, node)
|
76
|
+
prepare_end(node)
|
77
|
+
end
|
78
|
+
|
48
79
|
def evaluate_node_start(node)
|
49
80
|
evaluate_node(:start, node)
|
50
81
|
evaluate_start(node)
|
51
82
|
end
|
52
|
-
|
83
|
+
|
53
84
|
def evaluate_node_end(node)
|
54
85
|
evaluate_node(:end, node)
|
55
86
|
evaluate_end(node)
|
56
87
|
end
|
57
|
-
|
88
|
+
|
58
89
|
def add_error(error, file = nil, line = nil)
|
59
90
|
file ||= @node.file
|
60
91
|
line ||= @node.line
|
61
92
|
@errors << RailsBestPractices::Core::Error.new("#{file}", "#{line}", error)
|
62
93
|
end
|
63
|
-
|
94
|
+
|
64
95
|
def equal?(node, expected)
|
65
96
|
node.to_s == expected or node.to_s == ':' + expected.to_s
|
66
97
|
end
|
@@ -21,65 +21,70 @@ module RailsBestPractices
|
|
21
21
|
[:if, :class, :call]
|
22
22
|
end
|
23
23
|
|
24
|
+
def interesting_prepare_files
|
25
|
+
MODLE_FILES
|
26
|
+
end
|
27
|
+
|
24
28
|
def initialize
|
25
29
|
super
|
26
30
|
@klazzes = []
|
27
31
|
@associations = {}
|
28
32
|
end
|
29
33
|
|
30
|
-
def
|
31
|
-
|
32
|
-
when :class
|
33
|
-
remember_klazz(node)
|
34
|
-
when :call
|
35
|
-
remember_association(node) if ASSOCIATION_METHODS.include? node.message
|
36
|
-
when :if
|
37
|
-
if node = query_attribute_node(node.conditional_statement)
|
38
|
-
add_error "use query attribute", node.file, node.line
|
39
|
-
end
|
40
|
-
else
|
41
|
-
end
|
34
|
+
def prepare_start_class(node)
|
35
|
+
remember_klazz(node)
|
42
36
|
end
|
43
37
|
|
44
|
-
|
38
|
+
def prepare_start_call(node)
|
39
|
+
remember_association(node) if ASSOCIATION_METHODS.include? node.message
|
40
|
+
end
|
45
41
|
|
46
|
-
def
|
47
|
-
if
|
48
|
-
|
42
|
+
def evaluate_start_if(node)
|
43
|
+
if node = query_attribute_node(node.conditional_statement)
|
44
|
+
subject_node = node.subject
|
45
|
+
add_error "use query attribute (#{subject_node.subject}.#{subject_node.message}?)", node.file, node.line
|
49
46
|
end
|
50
47
|
end
|
51
48
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
49
|
+
private
|
50
|
+
def remember_klazz(class_node)
|
51
|
+
if class_node.file =~ MODLE_FILES
|
52
|
+
@klazzes << class_node.subject
|
53
|
+
end
|
54
|
+
end
|
56
55
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
return query_attribute_node(conditional_statement_node[1]) || query_attribute_node(conditional_statement_node[2])
|
61
|
-
when :not
|
62
|
-
return query_attribute_node(conditional_statement_node[1])
|
63
|
-
when :call
|
64
|
-
return conditional_statement_node if query_method?(conditional_statement_node) or compare_with_empty_string?(conditional_statement_node)
|
56
|
+
def remember_association(association_node)
|
57
|
+
@associations[@klazzes.last] ||= []
|
58
|
+
@associations[@klazzes.last] << association_node.arguments[1].to_s
|
65
59
|
end
|
66
|
-
nil
|
67
|
-
end
|
68
60
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
61
|
+
def query_attribute_node(conditional_statement_node)
|
62
|
+
case conditional_statement_node.node_type
|
63
|
+
when :and, :or
|
64
|
+
return query_attribute_node(conditional_statement_node[1]) || query_attribute_node(conditional_statement_node[2])
|
65
|
+
when :not
|
66
|
+
return query_attribute_node(conditional_statement_node[1])
|
67
|
+
when :call
|
68
|
+
return conditional_statement_node if query_method?(conditional_statement_node) or compare_with_empty_string?(conditional_statement_node)
|
69
|
+
end
|
70
|
+
nil
|
71
|
+
end
|
74
72
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
73
|
+
def query_method?(node)
|
74
|
+
return false unless :call == node.subject.node_type
|
75
|
+
subject = node.subject.subject
|
76
|
+
message = node.subject.message
|
77
|
+
subject_ruby = subject.to_s
|
79
78
|
|
80
|
-
|
81
|
-
|
82
|
-
|
79
|
+
subject_ruby && node.subject.arguments.size == 1 &&
|
80
|
+
@klazzes.find { |klazz| subject_ruby =~ %r|#{klazz.to_s.underscore}| and !@associations[klazz].find { |association| equal?(association, message) } } &&
|
81
|
+
message && message.to_s.pluralize != message.to_s &&
|
82
|
+
QUERY_METHODS.include?(node.message)
|
83
|
+
end
|
84
|
+
|
85
|
+
def compare_with_empty_string?(node)
|
86
|
+
:== == node.message and [:arglist, [:str, ""]] == node.arguments
|
87
|
+
end
|
83
88
|
end
|
84
89
|
end
|
85
90
|
end
|
@@ -11,7 +11,7 @@ OptionParser.new do |opts|
|
|
11
11
|
options['debug'] = true
|
12
12
|
end
|
13
13
|
|
14
|
-
['vendor', 'spec', 'test', '
|
14
|
+
['vendor', 'spec', 'test', 'features'].each do |pattern|
|
15
15
|
opts.on("--#{pattern}", "include #{pattern} files") do
|
16
16
|
options[pattern] = true
|
17
17
|
end
|
@@ -42,6 +42,7 @@ end
|
|
42
42
|
runner = RailsBestPractices::Core::Runner.new
|
43
43
|
runner.set_debug if options['debug']
|
44
44
|
|
45
|
+
prepare_files = RailsBestPractices::prepare_files
|
45
46
|
files = RailsBestPractices::analyze_files(ARGV, options)
|
46
47
|
|
47
48
|
if runner.checks.find { |check| check.is_a? RailsBestPractices::Checks::AlwaysAddDbIndexCheck } &&
|
@@ -49,7 +50,13 @@ if runner.checks.find { |check| check.is_a? RailsBestPractices::Checks::AlwaysAd
|
|
49
50
|
puts "AlwaysAddDbIndexCheck is disabled as there is no db/schema.rb file in your rails project.".blue
|
50
51
|
end
|
51
52
|
|
52
|
-
bar = ProgressBar.new('Analyzing', files.size)
|
53
|
+
bar = ProgressBar.new('Analyzing', prepare_files.size + files.size)
|
54
|
+
|
55
|
+
prepare_files.each do |file|
|
56
|
+
runner.prepare_file(file)
|
57
|
+
bar.inc unless options['debug']
|
58
|
+
end
|
59
|
+
|
53
60
|
files.each do |file|
|
54
61
|
runner.check_file(file)
|
55
62
|
bar.inc unless options['debug']
|
@@ -14,12 +14,17 @@ module RailsBestPractices
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
def prepare(node)
|
18
|
+
checks = @checks[node.node_type]
|
19
|
+
checks.each {|check| check.prepare_node_start(node) if node.file =~ check.interesting_prepare_files} unless checks.nil?
|
20
|
+
node.visitable_children.each {|sexp| sexp.prepare(self)}
|
21
|
+
checks.each {|check| check.prepare_node_end(node) if node.file =~ check.interesting_prepare_files} unless checks.nil?
|
22
|
+
end
|
23
|
+
|
17
24
|
def visit(node)
|
18
25
|
checks = @checks[node.node_type]
|
19
26
|
checks.each {|check| check.evaluate_node_start(node) if node.file =~ check.interesting_files} unless checks.nil?
|
20
|
-
|
21
27
|
node.visitable_children.each {|sexp| sexp.accept(self)}
|
22
|
-
|
23
28
|
checks.each {|check| check.evaluate_node_end(node) if node.file =~ check.interesting_files} unless checks.nil?
|
24
29
|
end
|
25
30
|
end
|
@@ -27,30 +27,25 @@ module RailsBestPractices
|
|
27
27
|
|
28
28
|
def check(filename, content)
|
29
29
|
puts filename if @debug
|
30
|
-
|
31
|
-
|
32
|
-
end
|
33
|
-
if filename =~ /.*\.haml$/
|
34
|
-
begin
|
35
|
-
require 'haml'
|
36
|
-
content = Haml::Engine.new(content).precompiled
|
37
|
-
# remove \xxx characters
|
38
|
-
content.gsub!(/\\\d{3}/, '')
|
39
|
-
rescue Haml::SyntaxError
|
40
|
-
end
|
41
|
-
end
|
42
|
-
node = parse(filename, content)
|
30
|
+
content = parse_erb_or_haml(filename, content)
|
31
|
+
node = parse_ruby(filename, content)
|
43
32
|
node.accept(@checker) if node
|
44
33
|
end
|
45
34
|
|
46
|
-
def
|
47
|
-
|
35
|
+
def prepare(filename, content)
|
36
|
+
puts filename if @debug
|
37
|
+
node = parse_ruby(filename, content)
|
38
|
+
node.prepare(@checker) if node
|
48
39
|
end
|
49
40
|
|
50
41
|
def check_file(filename)
|
51
42
|
check(filename, File.read(filename))
|
52
43
|
end
|
53
44
|
|
45
|
+
def prepare_file(filename)
|
46
|
+
prepare(filename, File.read(filename))
|
47
|
+
end
|
48
|
+
|
54
49
|
def errors
|
55
50
|
@checks ||= []
|
56
51
|
all_errors = @checks.collect {|check| check.errors}
|
@@ -59,7 +54,7 @@ module RailsBestPractices
|
|
59
54
|
|
60
55
|
private
|
61
56
|
|
62
|
-
def
|
57
|
+
def parse_ruby(filename, content)
|
63
58
|
begin
|
64
59
|
RubyParser.new.parse(content, filename)
|
65
60
|
rescue Exception => e
|
@@ -68,6 +63,22 @@ module RailsBestPractices
|
|
68
63
|
end
|
69
64
|
end
|
70
65
|
|
66
|
+
def parse_erb_or_haml(filename, content)
|
67
|
+
if filename =~ /.*\.erb$/
|
68
|
+
content = Erubis::Eruby.new(content).src
|
69
|
+
end
|
70
|
+
if filename =~ /.*\.haml$/
|
71
|
+
begin
|
72
|
+
require 'haml'
|
73
|
+
content = Haml::Engine.new(content).precompiled
|
74
|
+
# remove \xxx characters
|
75
|
+
content.gsub!(/\\\d{3}/, '')
|
76
|
+
rescue Haml::SyntaxError
|
77
|
+
end
|
78
|
+
end
|
79
|
+
content
|
80
|
+
end
|
81
|
+
|
71
82
|
def load_checks
|
72
83
|
check_objects = []
|
73
84
|
checks = YAML.load_file @config
|
@@ -3,6 +3,10 @@ require 'rubygems'
|
|
3
3
|
require 'sexp'
|
4
4
|
|
5
5
|
class Sexp
|
6
|
+
def prepare(visitor)
|
7
|
+
visitor.prepare(self)
|
8
|
+
end
|
9
|
+
|
6
10
|
def accept(visitor)
|
7
11
|
visitor.visit(self)
|
8
12
|
end
|
@@ -14,23 +18,23 @@ class Sexp
|
|
14
18
|
def children
|
15
19
|
find_all { | sexp | Sexp === sexp }
|
16
20
|
end
|
17
|
-
|
21
|
+
|
18
22
|
def is_language_node?
|
19
23
|
first.class == Symbol
|
20
24
|
end
|
21
|
-
|
25
|
+
|
22
26
|
def visitable_children
|
23
27
|
parent = is_language_node? ? sexp_body : self
|
24
28
|
parent.children
|
25
29
|
end
|
26
|
-
|
30
|
+
|
27
31
|
def recursive_children(&handler)
|
28
32
|
visitable_children.each do |child|
|
29
33
|
handler.call child
|
30
34
|
child.recursive_children(&handler)
|
31
35
|
end
|
32
36
|
end
|
33
|
-
|
37
|
+
|
34
38
|
def grep_nodes(options)
|
35
39
|
return self if options.empty?
|
36
40
|
node_type = options[:node_type]
|
@@ -45,7 +49,7 @@ class Sexp
|
|
45
49
|
end
|
46
50
|
nodes
|
47
51
|
end
|
48
|
-
|
52
|
+
|
49
53
|
def subject
|
50
54
|
if [:attrasgn, :call, :class, :iter].include? node_type
|
51
55
|
self[1]
|
@@ -57,37 +61,37 @@ class Sexp
|
|
57
61
|
self[1]
|
58
62
|
end
|
59
63
|
end
|
60
|
-
|
64
|
+
|
61
65
|
def message
|
62
66
|
if [:attrasgn, :call, :defs, :iter].include? node_type
|
63
67
|
self[2]
|
64
68
|
end
|
65
69
|
end
|
66
|
-
|
70
|
+
|
67
71
|
def arguments
|
68
72
|
if [:attrasgn, :call].include? node_type
|
69
73
|
self[3]
|
70
74
|
end
|
71
75
|
end
|
72
|
-
|
76
|
+
|
73
77
|
def call
|
74
78
|
if [:if, :arglist].include? node_type
|
75
79
|
self[1]
|
76
80
|
end
|
77
81
|
end
|
78
|
-
|
82
|
+
|
79
83
|
def conditional_statement
|
80
84
|
if node_type == :if
|
81
85
|
self[1]
|
82
86
|
end
|
83
87
|
end
|
84
|
-
|
88
|
+
|
85
89
|
def true_node
|
86
90
|
if :if == node_type
|
87
91
|
self[2]
|
88
92
|
end
|
89
93
|
end
|
90
|
-
|
94
|
+
|
91
95
|
def false_node
|
92
96
|
if :if == node_type
|
93
97
|
self[3]
|
@@ -99,7 +103,7 @@ class Sexp
|
|
99
103
|
self[1]
|
100
104
|
end
|
101
105
|
end
|
102
|
-
|
106
|
+
|
103
107
|
def body
|
104
108
|
if :block == node_type
|
105
109
|
self[1..-1]
|
@@ -111,7 +115,7 @@ class Sexp
|
|
111
115
|
self[4][1]
|
112
116
|
end
|
113
117
|
end
|
114
|
-
|
118
|
+
|
115
119
|
def to_s
|
116
120
|
if [:lvar, :ivar].include? node_type
|
117
121
|
self[1].to_s
|
@@ -119,6 +123,8 @@ class Sexp
|
|
119
123
|
self[1]
|
120
124
|
elsif :lit == node_type
|
121
125
|
":#{self[1]}"
|
126
|
+
elsif :const == node_type
|
127
|
+
self[1]
|
122
128
|
elsif :array == node_type
|
123
129
|
"[\"#{self.children.collect(&:to_s).join('", "')}\"]"
|
124
130
|
elsif :hash == node_type
|
@@ -132,11 +138,11 @@ class Sexp
|
|
132
138
|
result += "}"
|
133
139
|
end
|
134
140
|
end
|
135
|
-
|
141
|
+
|
136
142
|
#def to_ruby
|
137
143
|
#Ruby2Ruby.new.process(self) unless self.empty?
|
138
144
|
#end
|
139
|
-
|
145
|
+
|
140
146
|
#def to_ruby_string
|
141
147
|
#return nil if self.empty?
|
142
148
|
#eval(Ruby2Ruby.new.process(self)).to_s
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_best_practices
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 1
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 5
|
8
|
-
-
|
9
|
-
version: 0.5.
|
9
|
+
- 5
|
10
|
+
version: 0.5.5
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Richard Huang
|
@@ -14,138 +15,147 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2010-12-
|
18
|
+
date: 2010-12-13 00:00:00 +08:00
|
18
19
|
default_executable: rails_best_practices
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
|
-
|
22
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
22
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
23
23
|
none: false
|
24
24
|
requirements:
|
25
25
|
- - ~>
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
+
hash: 7
|
27
28
|
segments:
|
28
29
|
- 2
|
29
30
|
- 0
|
30
31
|
- 4
|
31
32
|
version: 2.0.4
|
32
|
-
|
33
|
+
requirement: *id001
|
34
|
+
name: ruby_parser
|
33
35
|
prerelease: false
|
34
|
-
|
36
|
+
type: :runtime
|
35
37
|
- !ruby/object:Gem::Dependency
|
36
|
-
|
37
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
38
39
|
none: false
|
39
40
|
requirements:
|
40
41
|
- - ~>
|
41
42
|
- !ruby/object:Gem::Version
|
43
|
+
hash: 59
|
42
44
|
segments:
|
43
45
|
- 0
|
44
46
|
- 9
|
45
47
|
- 0
|
46
48
|
version: 0.9.0
|
47
|
-
|
49
|
+
requirement: *id002
|
50
|
+
name: progressbar
|
48
51
|
prerelease: false
|
49
|
-
|
52
|
+
type: :runtime
|
50
53
|
- !ruby/object:Gem::Dependency
|
51
|
-
|
52
|
-
requirement: &id003 !ruby/object:Gem::Requirement
|
54
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
53
55
|
none: false
|
54
56
|
requirements:
|
55
57
|
- - ~>
|
56
58
|
- !ruby/object:Gem::Version
|
59
|
+
hash: 11
|
57
60
|
segments:
|
58
61
|
- 1
|
59
62
|
- 2
|
60
63
|
version: "1.2"
|
61
|
-
|
64
|
+
requirement: *id003
|
65
|
+
name: colored
|
62
66
|
prerelease: false
|
63
|
-
|
67
|
+
type: :runtime
|
64
68
|
- !ruby/object:Gem::Dependency
|
65
|
-
|
66
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
69
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
67
70
|
none: false
|
68
71
|
requirements:
|
69
72
|
- - ~>
|
70
73
|
- !ruby/object:Gem::Version
|
74
|
+
hash: 27
|
71
75
|
segments:
|
72
76
|
- 2
|
73
77
|
- 6
|
74
78
|
- 6
|
75
79
|
version: 2.6.6
|
76
|
-
|
80
|
+
requirement: *id004
|
81
|
+
name: erubis
|
77
82
|
prerelease: false
|
78
|
-
|
83
|
+
type: :runtime
|
79
84
|
- !ruby/object:Gem::Dependency
|
80
|
-
|
81
|
-
requirement: &id005 !ruby/object:Gem::Requirement
|
85
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
82
86
|
none: false
|
83
87
|
requirements:
|
84
88
|
- - ">="
|
85
89
|
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
86
91
|
segments:
|
87
92
|
- 0
|
88
93
|
version: "0"
|
89
|
-
|
94
|
+
requirement: *id005
|
95
|
+
name: i18n
|
90
96
|
prerelease: false
|
91
|
-
|
97
|
+
type: :runtime
|
92
98
|
- !ruby/object:Gem::Dependency
|
93
|
-
|
94
|
-
requirement: &id006 !ruby/object:Gem::Requirement
|
99
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
95
100
|
none: false
|
96
101
|
requirements:
|
97
102
|
- - ">="
|
98
103
|
- !ruby/object:Gem::Version
|
104
|
+
hash: 3
|
99
105
|
segments:
|
100
106
|
- 0
|
101
107
|
version: "0"
|
102
|
-
|
108
|
+
requirement: *id006
|
109
|
+
name: activesupport
|
103
110
|
prerelease: false
|
104
|
-
|
111
|
+
type: :runtime
|
105
112
|
- !ruby/object:Gem::Dependency
|
106
|
-
|
107
|
-
requirement: &id007 !ruby/object:Gem::Requirement
|
113
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
108
114
|
none: false
|
109
115
|
requirements:
|
110
116
|
- - ~>
|
111
117
|
- !ruby/object:Gem::Version
|
118
|
+
hash: 13
|
112
119
|
segments:
|
113
120
|
- 2
|
114
121
|
- 0
|
115
122
|
- 1
|
116
123
|
version: 2.0.1
|
117
|
-
|
124
|
+
requirement: *id007
|
125
|
+
name: rspec
|
118
126
|
prerelease: false
|
119
|
-
|
127
|
+
type: :development
|
120
128
|
- !ruby/object:Gem::Dependency
|
121
|
-
|
122
|
-
requirement: &id008 !ruby/object:Gem::Requirement
|
129
|
+
version_requirements: &id008 !ruby/object:Gem::Requirement
|
123
130
|
none: false
|
124
131
|
requirements:
|
125
132
|
- - ~>
|
126
133
|
- !ruby/object:Gem::Version
|
134
|
+
hash: 35
|
127
135
|
segments:
|
128
136
|
- 3
|
129
137
|
- 0
|
130
138
|
- 18
|
131
139
|
version: 3.0.18
|
132
|
-
|
140
|
+
requirement: *id008
|
141
|
+
name: haml
|
133
142
|
prerelease: false
|
134
|
-
|
143
|
+
type: :development
|
135
144
|
- !ruby/object:Gem::Dependency
|
136
|
-
|
137
|
-
requirement: &id009 !ruby/object:Gem::Requirement
|
145
|
+
version_requirements: &id009 !ruby/object:Gem::Requirement
|
138
146
|
none: false
|
139
147
|
requirements:
|
140
148
|
- - ~>
|
141
149
|
- !ruby/object:Gem::Version
|
150
|
+
hash: 7
|
142
151
|
segments:
|
143
152
|
- 0
|
144
153
|
- 6
|
145
154
|
version: "0.6"
|
146
|
-
|
155
|
+
requirement: *id009
|
156
|
+
name: watchr
|
147
157
|
prerelease: false
|
148
|
-
|
158
|
+
type: :development
|
149
159
|
description: a code metric tool for rails codes, written in Ruby.
|
150
160
|
email:
|
151
161
|
- flyerhzm@gmail.com
|
@@ -208,7 +218,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
208
218
|
requirements:
|
209
219
|
- - ">="
|
210
220
|
- !ruby/object:Gem::Version
|
211
|
-
hash:
|
221
|
+
hash: 3
|
212
222
|
segments:
|
213
223
|
- 0
|
214
224
|
version: "0"
|
@@ -217,6 +227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
217
227
|
requirements:
|
218
228
|
- - ">="
|
219
229
|
- !ruby/object:Gem::Version
|
230
|
+
hash: 23
|
220
231
|
segments:
|
221
232
|
- 1
|
222
233
|
- 3
|