Skip to content
This repository

AM::MassAssingmentSecurity: improve performance #5431

Merged
merged 1 commit into from about 2 years ago

2 participants

Bogdan Gusiev José Valim
Bogdan Gusiev

According to this article:
http://merbist.com/2012/02/23/quick-dive-into-ruby-orm-object-initialization/

Current implementation of mass assignment security takes a lot of processor time because spawning to many redundant objects in MassAssignmentSecuritySanitizer#debug_protected_attribute_removal

We can get rid of this method.

Benchmark: https://gist.github.com/2036114

----------when something sanitized----------
New:   0.010000   0.000000   0.010000 (  0.006924)
Old:   0.010000   0.000000   0.010000 (  0.009284)
----------when nothing sanitized----------
New:   0.010000   0.000000   0.010000 (  0.003906)
Old:   0.000000   0.000000   0.000000 (  0.005500) 

A little side effect of this patch attributes are processed one by one. Instead of:

      def process_removed_attributes(attrs)

We get:

      def process_removed_attribute(attr)

The only one place where this could cause side effect is when someone wants to create it's own sanitizer(other than built-in Strict and Logger).

We can make a backward compatibility for this but decided that it doesn't make that much sense.

José Valim josevalim merged commit cc1c4ac into from March 14, 2012
José Valim josevalim closed this March 14, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Mar 14, 2012
Bogdan Gusiev AM::MassAssingmentSecurity: improve performance 7d1379f
This page is out of date. Refresh to see the latest.
34  activemodel/lib/active_model/mass_assignment_security/sanitizer.rb
@@ -3,20 +3,18 @@ module MassAssignmentSecurity
3 3
     class Sanitizer
4 4
       # Returns all attributes not denied by the authorizer.
5 5
       def sanitize(attributes, authorizer)
6  
-        sanitized_attributes = attributes.reject { |key, value| authorizer.deny?(key) }
7  
-        debug_protected_attribute_removal(attributes, sanitized_attributes)
8  
-        sanitized_attributes
  6
+        attributes.reject do |attr, value|
  7
+          if authorizer.deny?(attr)
  8
+            process_removed_attribute(attr)
  9
+            true
  10
+          end
  11
+        end
9 12
       end
10 13
 
11 14
     protected
12 15
 
13  
-      def debug_protected_attribute_removal(attributes, sanitized_attributes)
14  
-        removed_keys = attributes.keys - sanitized_attributes.keys
15  
-        process_removed_attributes(removed_keys) if removed_keys.any?
16  
-      end
17  
-
18  
-      def process_removed_attributes(attrs)
19  
-        raise NotImplementedError, "#process_removed_attributes(attrs) suppose to be overwritten"
  16
+      def process_removed_attribute(attr)
  17
+        raise NotImplementedError, "#process_removed_attribute(attr) suppose to be overwritten"
20 18
       end
21 19
     end
22 20
 
@@ -34,8 +32,8 @@ def logger?
34 32
         @target.respond_to?(:logger) && @target.logger
35 33
       end
36 34
 
37  
-      def process_removed_attributes(attrs)
38  
-        logger.warn "Can't mass-assign protected attributes: #{attrs.join(', ')}" if logger?
  35
+      def process_removed_attribute(attr)
  36
+        logger.warn "Can't mass-assign protected attribute: #{attr}" if logger?
39 37
       end
40 38
     end
41 39
 
@@ -44,19 +42,19 @@ def initialize(target = nil)
44 42
         super()
45 43
       end
46 44
 
47  
-      def process_removed_attributes(attrs)
48  
-        return if (attrs - insensitive_attributes).empty?
49  
-        raise ActiveModel::MassAssignmentSecurity::Error.new(attrs)
  45
+      def process_removed_attribute(attr)
  46
+        return if insensitive_attributes.include?(attr)
  47
+        raise ActiveModel::MassAssignmentSecurity::Error.new(attr)
50 48
       end
51 49
 
52 50
       def insensitive_attributes
53  
-        ['id']
  51
+        @insensitive_attributes ||= ['id']
54 52
       end
55 53
     end
56 54
 
57 55
     class Error < StandardError
58  
-      def initialize(attrs)
59  
-        super("Can't mass-assign protected attributes: #{attrs.join(', ')}")
  56
+      def initialize(attr)
  57
+        super("Can't mass-assign protected attribute: #{attr}")
60 58
       end
61 59
     end
62 60
   end
2  activemodel/test/cases/mass_assignment_security_test.rb
@@ -4,7 +4,7 @@
4 4
 
5 5
 class CustomSanitizer < ActiveModel::MassAssignmentSecurity::Sanitizer
6 6
 
7  
-  def process_removed_attributes(attrs)
  7
+  def process_removed_attribute(attr)
8 8
     raise StandardError
9 9
   end
10 10
 
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.