Permalink
Browse files

Follow up to bbe7fe4 to fix enum leakage across classes.

The original attempt didn't really fix the problem and wasn't testing the
problematic area. This commit corrected those issues in the original commit.

Also removed the private `enum_mapping_for` method. As `defined_enums` is now a
method, this method doesn't provide much value anymore.
  • Loading branch information...
1 parent 3f5eb59 commit a5664fe27b1797983537c0764003e618bd3d2801 @chancancode chancancode committed Apr 8, 2014
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/object/deep_dup'
+
module ActiveRecord
# Declare an enum attribute where the values map to integers in the database,
# but can be queried by name. Example:
@@ -70,8 +72,9 @@ def self.extended(base)
base.defined_enums = {}
end
- def enum_mapping_for(attr_name) # :nodoc:
- defined_enums[attr_name.to_s]
+ def inherited(base)
+ base.defined_enums = defined_enums.deep_dup
@rafaelfranca
rafaelfranca Apr 8, 2014 Ruby on Rails member

Why do we have an inherited and an extended callbacks?

@chancancode
chancancode via email Apr 8, 2014 Ruby on Rails member
+ super
end
def enum(definitions)
@@ -136,7 +139,7 @@ def _enum_methods_module
mod = Module.new do
private
def save_changed_attribute(attr_name, value)
- if (mapping = self.class.enum_mapping_for(attr_name))
+ if (mapping = self.class.defined_enums[attr_name])
if attribute_changed?(attr_name)
old = changed_attributes[attr_name]
@@ -93,7 +93,7 @@ def deserialize_attribute(record, attribute, value)
end
def map_enum_attribute(klass, attribute, value)
- mapping = klass.enum_mapping_for(attribute.to_s)
+ mapping = klass.defined_enums[attribute.to_s]
value = mapping[value] if value && mapping
value
end
@@ -252,17 +252,38 @@ def self.name; 'Book'; end
end
test "enums are distinct per class" do
- Plane = Class.new(ActiveRecord::Base) do
- enum status: [:grounded, :operational]
+ klass1 = Class.new(ActiveRecord::Base) do
+ self.table_name = "books"
+ enum status: [:proposed, :written]
+ end
+
+ klass2 = Class.new(ActiveRecord::Base) do
+ self.table_name = "books"
+ enum status: [:drafted, :uploaded]
end
- assert_equal({ "proposed" => 0, "written" => 1, "published" => 2 }, Book.statuses)
- assert_equal({ "grounded" => 0, "operational" => 1 }, Plane.statuses)
+
+ book1 = klass1.proposed.create!
+ book1.status = :written
+ assert_equal ['proposed', 'written'], book1.status_change
+
+ book2 = klass2.drafted.create!
+ book2.status = :uploaded
+ assert_equal ['drafted', 'uploaded'], book2.status_change
end
test "enums are inheritable" do
- Encyclopedia = Class.new(Book) do
- enum status: [:published, :reprinted]
+ subklass1 = Class.new(Book)
+
+ subklass2 = Class.new(Book) do
+ enum status: [:drafted, :uploaded]
end
- assert_equal({ "published" => 0, "reprinted" => 1 }, Encyclopedia.statuses)
+
+ book1 = subklass1.proposed.create!
+ book1.status = :written
+ assert_equal ['proposed', 'written'], book1.status_change
+
+ book2 = subklass2.drafted.create!
+ book2.status = :uploaded
+ assert_equal ['drafted', 'uploaded'], book2.status_change
end
end

1 comment on commit a5664fe

@chancancode
Member
Please sign in to comment.