rails_best_practices 0.2.0 → 0.2.6

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.
Files changed (28) hide show
  1. data/README.textile +11 -6
  2. data/VERSION +1 -1
  3. data/lib/rails_best_practices/checks/always_add_db_index_check.rb +83 -0
  4. data/lib/rails_best_practices/checks/check.rb +1 -1
  5. data/lib/rails_best_practices/checks/isolate_seed_data_check.rb +46 -0
  6. data/lib/rails_best_practices/checks/keep_finders_on_their_own_model_check.rb +29 -0
  7. data/lib/rails_best_practices/checks/law_of_demeter_check.rb +47 -0
  8. data/lib/rails_best_practices/checks/use_observer_check.rb +49 -0
  9. data/lib/rails_best_practices/checks/use_scope_access_check.rb +2 -2
  10. data/lib/rails_best_practices/checks.rb +6 -1
  11. data/lib/rails_best_practices/command.rb +24 -4
  12. data/lib/rails_best_practices/core/core_ext.rb +12 -1
  13. data/lib/rails_best_practices/core/runner.rb +5 -1
  14. data/lib/rails_best_practices/core/visitable_sexp.rb +14 -5
  15. data/rails_best_practices.gemspec +17 -2
  16. data/rails_best_practices.yml +5 -0
  17. data/spec/rails_best_practices/checks/add_model_virtual_attribute_check_spec.rb +22 -4
  18. data/spec/rails_best_practices/checks/always_add_db_index_check_spec.rb +153 -0
  19. data/spec/rails_best_practices/checks/isolate_seed_data_check_spec.rb +75 -0
  20. data/spec/rails_best_practices/checks/keep_finders_on_their_own_model_check_spec.rb +71 -0
  21. data/spec/rails_best_practices/checks/law_of_demeter_check_spec.rb +37 -0
  22. data/spec/rails_best_practices/checks/move_finder_to_named_scope_check_spec.rb +6 -6
  23. data/spec/rails_best_practices/checks/move_model_logic_into_model_check_spec.rb +4 -4
  24. data/spec/rails_best_practices/checks/replace_complex_creation_with_factory_method_check_spec.rb +5 -5
  25. data/spec/rails_best_practices/checks/use_model_association_check_spec.rb +6 -6
  26. data/spec/rails_best_practices/checks/use_observer_check_spec.rb +67 -0
  27. data/spec/rails_best_practices/checks/use_scope_access_check_spec.rb +17 -17
  28. metadata +17 -2
data/README.textile CHANGED
@@ -41,6 +41,11 @@ MoveModelLogicIntoModelCheck: { called_count: 4 }
41
41
  OveruseRouteCustomizationsCheck: { customize_count: 3 }
42
42
  NeedlessDeepNestingCheck: { nested_count: 2 }
43
43
  NotUseDefaultRouteCheck: { }
44
+ KeepFindersOnTheirOwnModelCheck: { }
45
+ LawOfDemeterCheck: { }
46
+ UseObserverCheck: { }
47
+ IsolateSeedDataCheck: { }
48
+ AlwaysAddDbIndexCheck: { }
44
49
  </code></pre>
45
50
 
46
51
  *************************************************
@@ -65,17 +70,17 @@ h2. Progress
65
70
  ## [-Not use default route-]
66
71
 
67
72
  * Lesson 3. Model
68
- ## Keep Finders on Their Own Model
69
- ## Love named_scope
70
- ## the Law of Demeter
73
+ ## [-Keep Finders on Their Own Model-]
74
+ ## [-Love named_scope-] # same as Move finder to named_scope
75
+ ## [-the Law of Demeter-]
71
76
  ## DRY: metaprogramming
72
77
  ## Extract into Module
73
78
  ## Extract to composed class
74
- ## Use Observer
79
+ ## [-Use Observer-]
75
80
 
76
81
  * Lesson 4. Migration
77
- ## Isolating Seed Data
78
- ## Always add DB index
82
+ ## [-Isolating Seed Data-]
83
+ ## [-Always add DB index-]
79
84
 
80
85
  * Lesson 5. Controller
81
86
  ## Use before_filter
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.2.6
@@ -0,0 +1,83 @@
1
+ require 'rails_best_practices/checks/check'
2
+
3
+ module RailsBestPractices
4
+ module Checks
5
+ class AlwaysAddDbIndexCheck < Check
6
+
7
+ def interesting_nodes
8
+ [:defs]
9
+ end
10
+
11
+ def interesting_files
12
+ /db\/migrate\/.*rb/
13
+ end
14
+
15
+ def initialize
16
+ super
17
+ @files = []
18
+ @references = {}
19
+ @indexes = {}
20
+ @parse = false
21
+ end
22
+
23
+ def evaluate_start(node)
24
+ if @files.include? node.file
25
+ @parse = true if :up == node.message
26
+ else
27
+ @files << node.file
28
+ end
29
+
30
+ if @parse and :up == node.message
31
+ @references.each do |table_name, column_names|
32
+ differences = column_names - (@indexes[table_name] || [])
33
+ hint = differences.collect {|column_name| "#{table_name} => #{column_name}"}.join(', ')
34
+ add_error "always add db index (#{hint})" unless differences.empty?
35
+ end
36
+ else
37
+ remember_references(node.body)
38
+ remember_indexes(node.body)
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def remember_references(node)
45
+ create_table_node = node.grep_nodes({:node_type => :call, :message => :create_table}).first
46
+ if create_table_node
47
+ table_name = eval(create_table_node.arguments[1].to_ruby).to_s
48
+ node.grep_nodes({:node_type => :call, :message => :integer}).each do |integer_node|
49
+ column_name = eval(integer_node.arguments[1].to_ruby).to_s
50
+ if column_name =~ /_id$/
51
+ @references[table_name] ||= []
52
+ @references[table_name] << column_name
53
+ end
54
+ end
55
+ node.grep_nodes({:node_type => :call, :message => :references}).each do |references_node|
56
+ column_name = eval(references_node.arguments[1].to_ruby).to_s + "_id"
57
+ @references[table_name] ||= []
58
+ @references[table_name] << column_name
59
+ end
60
+ node.grep_nodes({:node_type => :call, :message => :column}).each do |column_node|
61
+ if 'integer' == eval(column_node.arguments[2].to_ruby).to_s
62
+ column_name = eval(column_node.arguments[1].to_ruby).to_s
63
+ if column_name =~ /_id$/
64
+ @references[table_name] ||= []
65
+ @references[table_name] << column_name
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ def remember_indexes(node)
73
+ add_index_nodes = node.grep_nodes({:node_type => :call, :message => :add_index})
74
+ add_index_nodes.each do |add_index_node|
75
+ table_name = eval(add_index_node.arguments[1].to_ruby).to_s
76
+ column_name = eval(add_index_node.arguments[2].to_ruby).to_s
77
+ @indexes[table_name] ||= []
78
+ @indexes[table_name] << column_name
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -3,7 +3,7 @@ require 'rails_best_practices/core/error'
3
3
  module RailsBestPractices
4
4
  module Checks
5
5
  class Check
6
- NODE_TYPES = [:call, :defn, :if, :unless]
6
+ NODE_TYPES = [:call, :defn, :defs, :if, :unless, :class, :lasgn]
7
7
 
8
8
  def initialize
9
9
  @errors = []
@@ -0,0 +1,46 @@
1
+ require 'rails_best_practices/checks/check'
2
+
3
+ module RailsBestPractices
4
+ module Checks
5
+ # Check a migration file to make sure not to insert data in migration, move them to seed file.
6
+ #
7
+ # Implementation: check if there are :create, :create!, and :new with :save or :save! exist, the migration file needs isolate seed data.
8
+ class IsolateSeedDataCheck < Check
9
+
10
+ def interesting_nodes
11
+ [:call, :lasgn]
12
+ end
13
+
14
+ def interesting_files
15
+ /db\/migrate\/.*rb/
16
+ end
17
+
18
+ def initialize
19
+ super
20
+ @new_variables = []
21
+ end
22
+
23
+ def evaluate_start(node)
24
+ if [:create, :create!].include? node.message
25
+ add_error("isolate seed data")
26
+ elsif :lasgn == node.node_type
27
+ remember_new_variable(node)
28
+ elsif [:save, :save!].include? node.message
29
+ add_error("isolate seed data") if new_record?(node)
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def remember_new_variable(node)
36
+ unless node.grep_nodes({:node_type => :call, :message => :new}).empty?
37
+ @new_variables << node.subject.to_s
38
+ end
39
+ end
40
+
41
+ def new_record?(node)
42
+ @new_variables.include? node.subject.to_ruby
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,29 @@
1
+ require 'rails_best_practices/checks/check'
2
+
3
+ module RailsBestPractices
4
+ module Checks
5
+ # Check a model to make sure finders are on their own model.
6
+ #
7
+ # Implementation: check if :find is called by other model.
8
+ class KeepFindersOnTheirOwnModelCheck < Check
9
+
10
+ def interesting_nodes
11
+ [:call]
12
+ end
13
+
14
+ def interesting_files
15
+ /models\/.*rb/
16
+ end
17
+
18
+ def evaluate_start(node)
19
+ add_error "keep finders on their own model" if others_finder?(node)
20
+ end
21
+
22
+ private
23
+
24
+ def others_finder?(node)
25
+ node.message == :find and node.subject.node_type == :call
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,47 @@
1
+ require 'rails_best_practices/checks/check'
2
+
3
+ module RailsBestPractices
4
+ module Checks
5
+ # Check to make sure not avoid the law of demeter.
6
+ #
7
+ # Implementation:
8
+ # 1. check all models to record belongs_to associations
9
+ # 2. check if calling belongs_to association's method or attribute
10
+ class LawOfDemeterCheck < Check
11
+
12
+ def interesting_nodes
13
+ [:call, :class]
14
+ end
15
+
16
+ def initialize
17
+ super
18
+ @associations = {}
19
+ end
20
+
21
+ def evaluate_start(node)
22
+ if node.node_type == :class
23
+ remember_belongs_to(node)
24
+ elsif [:lvar, :ivar].include?(node.subject.node_type) and node.subject != s(:lvar, :_erbout)
25
+ add_error "law of demeter" if need_delegate?(node)
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def remember_belongs_to(node)
32
+ node.body.grep_nodes(:message => :belongs_to).collect do |body_node|
33
+ class_name = node.subject.to_s.underscore
34
+ @associations[class_name] ||= []
35
+ @associations[class_name] << eval(body_node.arguments[1].to_ruby).to_s
36
+ end
37
+ end
38
+
39
+ def need_delegate?(node)
40
+ @associations.each do |class_name, associations|
41
+ return true if node.subject.to_ruby =~ /#{class_name}$/ and associations.include? node.message.to_s
42
+ end
43
+ false
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,49 @@
1
+ require 'rails_best_practices/checks/check'
2
+
3
+ module RailsBestPractices
4
+ module Checks
5
+ # Check a model file to make sure mail deliver method is in observer not callback.
6
+ #
7
+ # Implementation:
8
+ # Record :after_create callback
9
+ # Check method define, if it is a callback and call deliver_xxx message in method body, then it should use observer.
10
+ class UseObserverCheck < Check
11
+
12
+ def interesting_nodes
13
+ [:defn, :call]
14
+ end
15
+
16
+ def interesting_files
17
+ /models\/.*rb/
18
+ end
19
+
20
+ def initialize
21
+ super
22
+ @callbacks = []
23
+ end
24
+
25
+ def evaluate_start(node)
26
+ if :after_create == node.message
27
+ remember_callbacks(node)
28
+ elsif :defn == node.node_type and @callbacks.include?(node.message_name.to_s)
29
+ add_error "use observer" if use_observer?(node)
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def remember_callbacks(node)
36
+ node.arguments[1..-1].each do |argument|
37
+ @callbacks << eval(argument.to_ruby).to_s
38
+ end
39
+ end
40
+
41
+ def use_observer?(node)
42
+ node.recursive_children do |child|
43
+ return true if :call == child.node_type and :const == child.subject.node_type and child.message.to_s =~ /^deliver_/
44
+ end
45
+ false
46
+ end
47
+ end
48
+ end
49
+ end
@@ -26,7 +26,7 @@ module RailsBestPractices
26
26
 
27
27
  condition_node.message == :== and
28
28
  (current_user?(condition_node.arguments.call) or current_user?(condition_node.subject)) and
29
- (node.false_node.method_body.any? {|n| n.message == :redirect_to} or node.true_node.method_body.any? {|n| n.message == :redirect_to})
29
+ (node.false_node.body.any? {|n| n.message == :redirect_to} or node.true_node.method_body.any? {|n| n.message == :redirect_to})
30
30
  end
31
31
 
32
32
  def current_user?(call_node)
@@ -35,4 +35,4 @@ module RailsBestPractices
35
35
 
36
36
  end
37
37
  end
38
- end
38
+ end
@@ -9,4 +9,9 @@ require 'rails_best_practices/checks/many_to_many_collection_check'
9
9
  require 'rails_best_practices/checks/nested_model_forms_check'
10
10
  require 'rails_best_practices/checks/overuse_route_customizations_check'
11
11
  require 'rails_best_practices/checks/needless_deep_nesting_check'
12
- require 'rails_best_practices/checks/not_use_default_route_check'
12
+ require 'rails_best_practices/checks/not_use_default_route_check'
13
+ require 'rails_best_practices/checks/keep_finders_on_their_own_model_check'
14
+ require 'rails_best_practices/checks/law_of_demeter_check'
15
+ require 'rails_best_practices/checks/use_observer_check'
16
+ require 'rails_best_practices/checks/isolate_seed_data_check'
17
+ require 'rails_best_practices/checks/always_add_db_index_check'
@@ -1,7 +1,8 @@
1
1
  require 'optparse'
2
2
 
3
3
  def expand_dirs_to_files *dirs
4
- extensions = ['rb']
4
+ # extensions = ['rb', 'erb', 'builder']
5
+ extensions = ['rb', 'builder']
5
6
 
6
7
  dirs.flatten.map { |p|
7
8
  if File.directory? p
@@ -9,7 +10,26 @@ def expand_dirs_to_files *dirs
9
10
  else
10
11
  p
11
12
  end
12
- }.flatten.sort
13
+ }.flatten.sort { |a, b|
14
+ # for law_of_demeter_check
15
+ if a =~ /models\/.*rb/
16
+ -1
17
+ elsif b =~ /models\/.*rb/
18
+ 1
19
+ else
20
+ a <=> b
21
+ end
22
+ }
23
+ end
24
+
25
+ # for always_add_db_index_check
26
+ def add_duplicate_migration_files files
27
+ migration_files = files.select { |file| file.index("db/migrate") }
28
+ (files << migration_files).flatten
29
+ end
30
+
31
+ def ignore_vendor_directories files
32
+ files.reject { |file| file.index("vendor/") }
13
33
  end
14
34
 
15
35
  options = {}
@@ -25,8 +45,8 @@ OptionParser.new do |opts|
25
45
  end
26
46
 
27
47
  runner = RailsBestPractices::Core::Runner.new
28
- expand_dirs_to_files(ARGV).each.each { |file| runner.check_file(file) }
48
+ ignore_vendor_directories(add_duplicate_migration_files(expand_dirs_to_files(ARGV))).each { |file| runner.check_file(file) }
29
49
  runner.errors.each {|error| puts error}
30
50
  puts "\nFound #{runner.errors.size} errors."
31
51
 
32
- exit runner.errors.size
52
+ exit runner.errors.size
@@ -4,8 +4,19 @@ module Enumerable
4
4
  end
5
5
  end
6
6
 
7
+ class String
8
+ # copy from rails
9
+ def underscore
10
+ self.gsub(/::/, '/').
11
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
12
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
13
+ tr("-", "_").
14
+ downcase
15
+ end
16
+ end
17
+
7
18
  class NilClass
8
19
  def method_missing(method_sym, *arguments, &block)
9
20
  return nil
10
21
  end
11
- end
22
+ end
@@ -1,5 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'ruby_parser'
3
+ require 'erb'
3
4
  require 'yaml'
4
5
 
5
6
  module RailsBestPractices
@@ -21,6 +22,9 @@ module RailsBestPractices
21
22
  end
22
23
 
23
24
  def check(filename, content)
25
+ if filename =~ /.*erb/
26
+ content = ERB.new(content).src
27
+ end
24
28
  node = parse(filename, content)
25
29
  node.accept(@checker) if node
26
30
  end
@@ -45,7 +49,7 @@ module RailsBestPractices
45
49
  begin
46
50
  @parser.parse(content, filename)
47
51
  rescue Exception => e
48
- puts "#{filename} looks like it's not a valid Ruby file. Skipping..." if ENV["ROODI_DEBUG"]
52
+ puts "#{filename} looks like it's not a valid Ruby file. Skipping..."
49
53
  nil
50
54
  end
51
55
  end
@@ -47,13 +47,13 @@ class Sexp
47
47
  end
48
48
 
49
49
  def subject
50
- if [:attrasgn, :call, :iasgn, :lasgn].include? node_type
50
+ if [:attrasgn, :call, :iasgn, :lasgn, :class].include? node_type
51
51
  self[1]
52
52
  end
53
53
  end
54
54
 
55
55
  def message
56
- if [:attrasgn, :call].include? node_type
56
+ if [:attrasgn, :call, :defs].include? node_type
57
57
  self[2]
58
58
  end
59
59
  end
@@ -81,15 +81,24 @@ class Sexp
81
81
  self[3]
82
82
  end
83
83
  end
84
+
85
+ def message_name
86
+ if :defn == node_type
87
+ self[1]
88
+ end
89
+ end
84
90
 
85
- def method_body
91
+ def body
86
92
  if :block == node_type
87
93
  self[1..-1]
88
- else
94
+ elsif :class == node_type
95
+ self[3]
96
+ elsif :defs == node_type
97
+ self[4]
89
98
  end
90
99
  end
91
100
 
92
101
  def to_ruby
93
- Ruby2Ruby.new.process(self)
102
+ Ruby2Ruby.new.process(self) unless self.empty?
94
103
  end
95
104
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rails_best_practices}
8
- s.version = "0.2.0"
8
+ s.version = "0.2.6"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Richard Huang"]
12
- s.date = %q{2009-11-06}
12
+ s.date = %q{2009-11-08}
13
13
  s.default_executable = %q{rails_best_practices}
14
14
  s.description = %q{check rails files according to ihower's presentation 'rails best practices'}
15
15
  s.email = %q{flyerhzm@gmail.com}
@@ -28,7 +28,11 @@ Gem::Specification.new do |s|
28
28
  "lib/rails_best_practices.rb",
29
29
  "lib/rails_best_practices/checks.rb",
30
30
  "lib/rails_best_practices/checks/add_model_virtual_attribute_check.rb",
31
+ "lib/rails_best_practices/checks/always_add_db_index_check.rb",
31
32
  "lib/rails_best_practices/checks/check.rb",
33
+ "lib/rails_best_practices/checks/isolate_seed_data_check.rb",
34
+ "lib/rails_best_practices/checks/keep_finders_on_their_own_model_check.rb",
35
+ "lib/rails_best_practices/checks/law_of_demeter_check.rb",
32
36
  "lib/rails_best_practices/checks/many_to_many_collection_check.rb",
33
37
  "lib/rails_best_practices/checks/move_finder_to_named_scope_check.rb",
34
38
  "lib/rails_best_practices/checks/move_model_logic_into_model_check.rb",
@@ -39,6 +43,7 @@ Gem::Specification.new do |s|
39
43
  "lib/rails_best_practices/checks/replace_complex_creation_with_factory_method_check.rb",
40
44
  "lib/rails_best_practices/checks/use_model_association_check.rb",
41
45
  "lib/rails_best_practices/checks/use_model_callback_check.rb",
46
+ "lib/rails_best_practices/checks/use_observer_check.rb",
42
47
  "lib/rails_best_practices/checks/use_scope_access_check.rb",
43
48
  "lib/rails_best_practices/command.rb",
44
49
  "lib/rails_best_practices/core.rb",
@@ -50,6 +55,10 @@ Gem::Specification.new do |s|
50
55
  "rails_best_practices.gemspec",
51
56
  "rails_best_practices.yml",
52
57
  "spec/rails_best_practices/checks/add_model_virtual_attribute_check_spec.rb",
58
+ "spec/rails_best_practices/checks/always_add_db_index_check_spec.rb",
59
+ "spec/rails_best_practices/checks/isolate_seed_data_check_spec.rb",
60
+ "spec/rails_best_practices/checks/keep_finders_on_their_own_model_check_spec.rb",
61
+ "spec/rails_best_practices/checks/law_of_demeter_check_spec.rb",
53
62
  "spec/rails_best_practices/checks/many_to_many_collection_check_spec.rb",
54
63
  "spec/rails_best_practices/checks/move_finder_to_named_scope_check_spec.rb",
55
64
  "spec/rails_best_practices/checks/move_model_logic_into_model_check_spec.rb",
@@ -60,6 +69,7 @@ Gem::Specification.new do |s|
60
69
  "spec/rails_best_practices/checks/replace_complex_creation_with_factory_method_check_spec.rb",
61
70
  "spec/rails_best_practices/checks/use_model_association_check_spec.rb",
62
71
  "spec/rails_best_practices/checks/use_model_callback_check_spec.rb",
72
+ "spec/rails_best_practices/checks/use_observer_check_spec.rb",
63
73
  "spec/rails_best_practices/checks/use_scope_access_check_spec.rb",
64
74
  "spec/spec.opts",
65
75
  "spec/spec_helper.rb"
@@ -73,15 +83,20 @@ Gem::Specification.new do |s|
73
83
  "spec/rails_best_practices/checks/use_scope_access_check_spec.rb",
74
84
  "spec/rails_best_practices/checks/not_use_default_route_check_spec.rb",
75
85
  "spec/rails_best_practices/checks/add_model_virtual_attribute_check_spec.rb",
86
+ "spec/rails_best_practices/checks/keep_finders_on_their_own_model_check_spec.rb",
76
87
  "spec/rails_best_practices/checks/use_model_callback_check_spec.rb",
88
+ "spec/rails_best_practices/checks/isolate_seed_data_check_spec.rb",
77
89
  "spec/rails_best_practices/checks/many_to_many_collection_check_spec.rb",
78
90
  "spec/rails_best_practices/checks/use_model_association_check_spec.rb",
79
91
  "spec/rails_best_practices/checks/move_model_logic_into_model_check_spec.rb",
92
+ "spec/rails_best_practices/checks/law_of_demeter_check_spec.rb",
80
93
  "spec/rails_best_practices/checks/replace_complex_creation_with_factory_method_check_spec.rb",
81
94
  "spec/rails_best_practices/checks/nested_model_forms_check_spec.rb",
95
+ "spec/rails_best_practices/checks/use_observer_check_spec.rb",
82
96
  "spec/rails_best_practices/checks/move_finder_to_named_scope_check_spec.rb",
83
97
  "spec/rails_best_practices/checks/needless_deep_nesting_check_spec.rb",
84
98
  "spec/rails_best_practices/checks/overuse_route_customizations_check_spec.rb",
99
+ "spec/rails_best_practices/checks/always_add_db_index_check_spec.rb",
85
100
  "spec/spec_helper.rb"
86
101
  ]
87
102
 
@@ -10,3 +10,8 @@ MoveModelLogicIntoModelCheck: { called_count: 4 }
10
10
  OveruseRouteCustomizationsCheck: { customize_count: 3 }
11
11
  NeedlessDeepNestingCheck: { nested_count: 2 }
12
12
  NotUseDefaultRouteCheck: { }
13
+ KeepFindersOnTheirOwnModelCheck: { }
14
+ LawOfDemeterCheck: { }
15
+ UseObserverCheck: { }
16
+ IsolateSeedDataCheck: { }
17
+ AlwaysAddDbIndexCheck: { }
@@ -17,10 +17,28 @@ describe RailsBestPractices::Checks::AddModelVirtualAttributeCheck do
17
17
  end
18
18
  end
19
19
  EOF
20
- @runner.check('app/controller/users_controller.rb', content)
20
+ @runner.check('app/controllers/users_controller.rb', content)
21
21
  errors = @runner.errors
22
22
  errors.should_not be_empty
23
- errors[0].to_s.should == "app/controller/users_controller.rb:3 - add model virtual attribute (for @user)"
23
+ errors[0].to_s.should == "app/controllers/users_controller.rb:3 - add model virtual attribute (for @user)"
24
+ end
25
+
26
+ it "should add model virtual attribute with local assignment" do
27
+ content = <<-EOF
28
+ class UsersController < ApplicationController
29
+
30
+ def create
31
+ user = User.new(params[:user])
32
+ user.first_name = params[:full_name].split(' ', 2).first
33
+ user.last_name = params[:full_name].split(' ', 2).last
34
+ user.save
35
+ end
36
+ end
37
+ EOF
38
+ @runner.check('app/controllers/users_controller.rb', content)
39
+ errors = @runner.errors
40
+ errors.should_not be_empty
41
+ errors[0].to_s.should == "app/controllers/users_controller.rb:3 - add model virtual attribute (for user)"
24
42
  end
25
43
 
26
44
  it "should not add model virtual attribute with differen param" do
@@ -35,7 +53,7 @@ describe RailsBestPractices::Checks::AddModelVirtualAttributeCheck do
35
53
  end
36
54
  end
37
55
  EOF
38
- @runner.check('app/controller/users_controller.rb', content)
56
+ @runner.check('app/controllers/users_controller.rb', content)
39
57
  errors = @runner.errors
40
58
  errors.should be_empty
41
59
  end
@@ -53,7 +71,7 @@ describe RailsBestPractices::Checks::AddModelVirtualAttributeCheck do
53
71
  end
54
72
  end
55
73
  EOF
56
- @runner.check('app/controller/users_controller.rb', content)
74
+ @runner.check('app/controllers/users_controller.rb', content)
57
75
  errors = @runner.errors
58
76
  errors.should be_empty
59
77
  end