rails_best_practices 0.5.3 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
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 stories directories. If you need, see the command options:
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
- --stories include stories files
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. Helpful links
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
@@ -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
- unless @foreign_keys[table_name].find { |foreign_key| foreign_key.include? foreign_key_column }
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
- @foreign_keys[table_name] << ["#{$1}_id", foreign_key_column]
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 evaluate_start(node)
31
- case node.node_type
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
- private
38
+ def prepare_start_call(node)
39
+ remember_association(node) if ASSOCIATION_METHODS.include? node.message
40
+ end
45
41
 
46
- def remember_klazz(class_node)
47
- if class_node.file =~ MODLE_FILES
48
- @klazzes << class_node.subject
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
- def remember_association(association_node)
53
- @associations[@klazzes.last] ||= []
54
- @associations[@klazzes.last] << association_node.arguments[1].to_s
55
- end
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
- def query_attribute_node(conditional_statement_node)
58
- case conditional_statement_node.node_type
59
- when :and, :or
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
- def query_method?(node)
70
- return false unless :call == node.subject.node_type
71
- subject = node.subject.subject
72
- message = node.subject.message
73
- subject_ruby = subject.to_s
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
- subject_ruby && @klazzes.find { |klazz| subject_ruby =~ %r|#{klazz.to_s.underscore}| and !@associations[klazz].find { |association| equal?(association, message) } } &&
76
- message && message.to_s.pluralize != message.to_s &&
77
- QUERY_METHODS.include?(node.message)
78
- end
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
- def compare_with_empty_string?(node)
81
- :== == node.message and [:arglist, [:str, ""]] == node.arguments
82
- end
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', 'stories'].each do |pattern|
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
- if filename =~ /.*\.erb$/
31
- content = Erubis::Eruby.new(content).src
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 check_content(content)
47
- check("dummy-file.rb", content)
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 parse(filename, content)
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
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
  module RailsBestPractices
3
- VERSION = "0.5.3"
3
+ VERSION = "0.5.5"
4
4
  end
5
5
 
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
- - 3
9
- version: 0.5.3
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-04 00:00:00 +08:00
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
- name: ruby_parser
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
- type: :runtime
33
+ requirement: *id001
34
+ name: ruby_parser
33
35
  prerelease: false
34
- version_requirements: *id001
36
+ type: :runtime
35
37
  - !ruby/object:Gem::Dependency
36
- name: progressbar
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
- type: :runtime
49
+ requirement: *id002
50
+ name: progressbar
48
51
  prerelease: false
49
- version_requirements: *id002
52
+ type: :runtime
50
53
  - !ruby/object:Gem::Dependency
51
- name: colored
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
- type: :runtime
64
+ requirement: *id003
65
+ name: colored
62
66
  prerelease: false
63
- version_requirements: *id003
67
+ type: :runtime
64
68
  - !ruby/object:Gem::Dependency
65
- name: erubis
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
- type: :runtime
80
+ requirement: *id004
81
+ name: erubis
77
82
  prerelease: false
78
- version_requirements: *id004
83
+ type: :runtime
79
84
  - !ruby/object:Gem::Dependency
80
- name: i18n
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
- type: :runtime
94
+ requirement: *id005
95
+ name: i18n
90
96
  prerelease: false
91
- version_requirements: *id005
97
+ type: :runtime
92
98
  - !ruby/object:Gem::Dependency
93
- name: activesupport
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
- type: :runtime
108
+ requirement: *id006
109
+ name: activesupport
103
110
  prerelease: false
104
- version_requirements: *id006
111
+ type: :runtime
105
112
  - !ruby/object:Gem::Dependency
106
- name: rspec
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
- type: :development
124
+ requirement: *id007
125
+ name: rspec
118
126
  prerelease: false
119
- version_requirements: *id007
127
+ type: :development
120
128
  - !ruby/object:Gem::Dependency
121
- name: haml
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
- type: :development
140
+ requirement: *id008
141
+ name: haml
133
142
  prerelease: false
134
- version_requirements: *id008
143
+ type: :development
135
144
  - !ruby/object:Gem::Dependency
136
- name: watchr
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
- type: :development
155
+ requirement: *id009
156
+ name: watchr
147
157
  prerelease: false
148
- version_requirements: *id009
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: -3421555404989740069
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