Skip to content
This repository
Browse code

disallow mutating a relation once loaded

  • Loading branch information...
commit 70d3625760aac9994790bd023f1b5060fe1d06c5 1 parent bacfa9d
Jon Leighton authored June 22, 2012
3  activerecord/lib/active_record/errors.rb
@@ -196,4 +196,7 @@ def message
196 196
       "Unknown primary key for table #{model.table_name} in model #{model}."
197 197
     end
198 198
   end
  199
+
  200
+  class ImmutableRelation < ActiveRecordError
  201
+  end
199 202
 end
38  activerecord/lib/active_record/relation/query_methods.rb
@@ -7,34 +7,36 @@ module QueryMethods
7 7
 
8 8
     Relation::MULTI_VALUE_METHODS.each do |name|
9 9
       class_eval <<-CODE, __FILE__, __LINE__ + 1
10  
-        def #{name}_values            # def select_values
11  
-          @values[:#{name}] || []     #   @values[:select] || []
12  
-        end                           # end
13  
-                                      #
14  
-        def #{name}_values=(values)   # def select_values=(values)
15  
-          @values[:#{name}] = values  #   @values[:select] = values
16  
-        end                           # end
  10
+        def #{name}_values                   # def select_values
  11
+          @values[:#{name}] || []            #   @values[:select] || []
  12
+        end                                  # end
  13
+                                             #
  14
+        def #{name}_values=(values)          # def select_values=(values)
  15
+          raise ImmutableRelation if @loaded #   raise ImmutableRelation if @loaded
  16
+          @values[:#{name}] = values         #   @values[:select] = values
  17
+        end                                  # end
17 18
       CODE
18 19
     end
19 20
 
20 21
     (Relation::SINGLE_VALUE_METHODS - [:create_with]).each do |name|
21 22
       class_eval <<-CODE, __FILE__, __LINE__ + 1
22  
-        def #{name}_value             # def readonly_value
23  
-          @values[:#{name}]           #   @values[:readonly]
24  
-        end                           # end
25  
-                                      #
26  
-        def #{name}_value=(value)     # def readonly_value=(value)
27  
-          @values[:#{name}] = value   #   @values[:readonly] = value
28  
-        end                           # end
  23
+        def #{name}_value                    # def readonly_value
  24
+          @values[:#{name}]                  #   @values[:readonly]
  25
+        end                                  # end
29 26
       CODE
30 27
     end
31 28
 
32  
-    def create_with_value
33  
-      @values[:create_with] || {}
  29
+    Relation::SINGLE_VALUE_METHODS.each do |name|
  30
+      class_eval <<-CODE, __FILE__, __LINE__ + 1
  31
+        def #{name}_value=(value)            # def readonly_value=(value)
  32
+          raise ImmutableRelation if @loaded #   raise ImmutableRelation if @loaded
  33
+          @values[:#{name}] = value          #   @values[:readonly] = value
  34
+        end                                  # end
  35
+      CODE
34 36
     end
35 37
 
36  
-    def create_with_value=(value)
37  
-      @values[:create_with] = value
  38
+    def create_with_value
  39
+      @values[:create_with] || {}
38 40
     end
39 41
 
40 42
     alias extensions extending_values
27  activerecord/test/cases/relations_test.rb
@@ -1284,4 +1284,31 @@ def test_presence
1284 1284
       Post.scoped.find_by!("1 = 0")
1285 1285
     end
1286 1286
   end
  1287
+
  1288
+  test "loaded relations cannot be mutated by multi value methods" do
  1289
+    relation = Post.scoped
  1290
+    relation.to_a
  1291
+
  1292
+    assert_raises(ActiveRecord::ImmutableRelation) do
  1293
+      relation.where! 'foo'
  1294
+    end
  1295
+  end
  1296
+
  1297
+  test "loaded relations cannot be mutated by single value methods" do
  1298
+    relation = Post.scoped
  1299
+    relation.to_a
  1300
+
  1301
+    assert_raises(ActiveRecord::ImmutableRelation) do
  1302
+      relation.limit! 5
  1303
+    end
  1304
+  end
  1305
+
  1306
+  test "loaded relations cannot be mutated by merge!" do
  1307
+    relation = Post.scoped
  1308
+    relation.to_a
  1309
+
  1310
+    assert_raises(ActiveRecord::ImmutableRelation) do
  1311
+      relation.merge! where: 'foo'
  1312
+    end
  1313
+  end
1287 1314
 end

0 notes on commit 70d3625

Please sign in to comment.
Something went wrong with that request. Please try again.