Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

92 lines (77 sloc) 3.062 kb
# Copyright (c) 2008 Michael Hartl, released under the MIT license
# http://github.com/mhartl/find_mass_assignment
require 'active_support'
# Find potential mass assignment problems.
# The method is to scan the controllers for likely mass assignment,
# and then find the corresponding models that *don't* have
# attr_accessible defined. Any time that happens, it's a potential problem.
class String
@@cache = {}
# A regex to match likely cases of mass assignment
# Examples of matching strings:
# "Foo.new( { :bar => 'baz' } )"
# "Foo.update_attributes!(params[:foo])"
MASS_ASSIGNMENT = /(\w+)\.(new|create|update_attributes|build)!*\(/
# Return the strings that represent potential mass assignment problems.
# The MASS_ASSIGNMENT regex returns, e.g., ['Post', 'new'] because of
# the grouping methods; we want the first of the two for each match.
# For example, the call to scan might return
# [['Post', 'new'], ['Person', 'create']]
# We then select the first element of each subarray, returning
# ['Post', 'Person']
def mass_assignment_models
scan(MASS_ASSIGNMENT).map { |problem| problem.first.classify }
end
# Return true if the string has potential mass assignment code.
def mass_assignment?
self =~ MASS_ASSIGNMENT
end
# Return true if the model defines attr_accessible.
# Note that 'attr_accessible' must be preceded by nothing other than
# whitespace; this catches cases where attr_accessible is commented out.
def attr_accessible?
model = "#{Rails.root.to_s}/app/models/#{self.classify}.rb"
if File.exist?(model)
return @@cache[model] unless @@cache[model].nil?
@@cache[model] = File.open(model).read =~ /^\s*attr_accessible/
else
# If the model file doesn't exist, ignore it by returning true.
# This way, problem? is false and the item won't be flagged.
true
end
end
# Returnt true if a model does not define attr_accessible.
def problem?
not attr_accessible?
end
# Return true if a line has a problem model (no attr_accessible).
def problem_model?
mass_assignment_models.find { |model| model.problem? }
end
# Return true if a controller string has a (likely) mass assignment problem.
# This is true if at least one of the controller's lines
# (1) Has a likely mass assignment
# (2) The corresponding model doesn't define attr_accessible
def mass_assignment_problem?
File.open(self).find { |l| l.mass_assignment? and l.problem_model? }
end
end
module MassAssignment
def self.print_mass_assignment_problems(controller)
lines = File.open(controller)
lines.each_with_index do |line, number|
if line.mass_assignment? and line.problem_model?
puts " #{number} #{line}"
end
end
end
def self.find
controllers = Dir.glob("#{Rails.root.to_s}/app/controllers/*_controller.rb")
controllers.each do |controller|
if controller.mass_assignment_problem?
puts "\n#{controller}"
print_mass_assignment_problems(controller)
end
end
end
end
Jump to Line
Something went wrong with that request. Please try again.