From 25783f4e1e0b9b258252dfc719b3f7f3b15f0ec0 Mon Sep 17 00:00:00 2001 From: gt-sdi Date: Sat, 9 Jun 2012 14:00:53 -0600 Subject: [PATCH 1/2] Sequenced fields for sub-classed Mongoid Documents. --- README.md | 26 ++++++++++ lib/mongoid-sequence.rb | 28 +++++++---- .../models/sub_class_multi_sequenced_model.rb | 8 ++++ test/models/sub_class_self_sequenced_model.rb | 6 +++ .../models/sub_class_super_sequenced_model.rb | 5 ++ test/sub_class_test.rb | 47 +++++++++++++++++++ 6 files changed, 112 insertions(+), 8 deletions(-) create mode 100644 test/models/sub_class_multi_sequenced_model.rb create mode 100644 test/models/sub_class_self_sequenced_model.rb create mode 100644 test/models/sub_class_super_sequenced_model.rb create mode 100644 test/sub_class_test.rb diff --git a/README.md b/README.md index e6d5448..47877fc 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,32 @@ s2 = Sequenced.create s2.id #=> 2 # and so on ``` +Subclasses can share their superclass sequenced field(s) and/or have their own sequenced field(s): +```ruby +class Sequenced + include Mongoid::Document + include Mongoid::Sequence + + field :my_sequence, :type => Integer + sequence :my_sequence +end + +class SubSequenced + use_superclass_sequence + + field :my_sub_sequence, :type => Integer + sequence :my_sub_sequence +end + +s1 = Sequenced.create +s1.my_sequence #=> 1 + +s2 = SubSequenced.create +s2.my_sequence #=> 2 +s2.my_sub_sequence #=> 1 + +``` + ## Consistency Mongoid::Sequence uses the atomic [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) command, so you shouldn't have to worry about the sequence's consistency. diff --git a/lib/mongoid-sequence.rb b/lib/mongoid-sequence.rb index f29f69a..14706fb 100644 --- a/lib/mongoid-sequence.rb +++ b/lib/mongoid-sequence.rb @@ -1,5 +1,6 @@ require "mongoid-sequence/version" require "active_support/concern" +require "set" module Mongoid module Sequence @@ -11,23 +12,34 @@ module Sequence module ClassMethods attr_accessor :sequence_fields + attr_accessor :klazzes def sequence(field) + self.klazzes ||= Set.new + self.klazzes << self self.sequence_fields ||= [] self.sequence_fields << field end + + def use_superclass_sequence + self.klazzes ||= self.superclass.klazzes = Set.new + self.klazzes << self.superclass + end + end def set_sequence sequences = self.db.collection("__sequences") - self.class.sequence_fields.each do |field| - next_sequence = sequences.find_and_modify(:query => {"_id" => "#{self.class.name.underscore}_#{field}"}, - :update => {"$inc" => {"seq" => 1}}, - :new => true, - :upsert => true) - - self[field] = next_sequence["seq"] - end if self.class.sequence_fields + self.class.klazzes.each do |klazz| + klazz.sequence_fields.each do |field| + next_sequence = sequences.find_and_modify(:query => {"_id" => "#{klazz.name.underscore}_#{field}"}, + :update => {"$inc" => {"seq" => 1}}, + :new => true, + :upsert => true) + + self[field] = next_sequence["seq"] + end if klazz.sequence_fields + end end end end diff --git a/test/models/sub_class_multi_sequenced_model.rb b/test/models/sub_class_multi_sequenced_model.rb new file mode 100644 index 0000000..0a586c7 --- /dev/null +++ b/test/models/sub_class_multi_sequenced_model.rb @@ -0,0 +1,8 @@ +class SubClassMultiSequencedModel < FirstSequencedModel + + field :sequence, :type => Integer + sequence :sequence + + use_superclass_sequence + +end diff --git a/test/models/sub_class_self_sequenced_model.rb b/test/models/sub_class_self_sequenced_model.rb new file mode 100644 index 0000000..3c428bd --- /dev/null +++ b/test/models/sub_class_self_sequenced_model.rb @@ -0,0 +1,6 @@ +class SubClassSelfSequencedModel < FirstSequencedModel + + field :sequence, :type => Integer + sequence :sequence + +end diff --git a/test/models/sub_class_super_sequenced_model.rb b/test/models/sub_class_super_sequenced_model.rb new file mode 100644 index 0000000..743b73d --- /dev/null +++ b/test/models/sub_class_super_sequenced_model.rb @@ -0,0 +1,5 @@ +class SubClassSuperSequencedModel < FirstSequencedModel + + use_superclass_sequence + +end diff --git a/test/sub_class_test.rb b/test/sub_class_test.rb new file mode 100644 index 0000000..1d01648 --- /dev/null +++ b/test/sub_class_test.rb @@ -0,0 +1,47 @@ +require "test_helper" + +class SubClassTest < BaseTest + def test_subclass_parent_sequence + parent = FirstSequencedModel.create + child = SubClassSuperSequencedModel.create + + assert_equal parent.auto_increment + 1, child.auto_increment + + parent2 = FirstSequencedModel.create + child2 = SubClassSuperSequencedModel.create + + assert_equal parent2.auto_increment + 1, child2.auto_increment + end + + def test_subclass_self_sequence + parent = FirstSequencedModel.create + child = SubClassSelfSequencedModel.create + + assert_equal parent.auto_increment, 1 + assert_equal child.auto_increment, nil + assert_equal child.sequence, 1 + + parent2 = FirstSequencedModel.create + child2 = SubClassSelfSequencedModel.create + + assert_equal parent2.auto_increment, 2 + assert_equal child2.auto_increment, nil + assert_equal child2.sequence, 2 + end + + def test_subclass_multi_sequence + parent = FirstSequencedModel.create + child = SubClassMultiSequencedModel.create + + assert_equal parent.auto_increment, 1 + assert_equal child.auto_increment, 2 + assert_equal child.sequence, 1 + + parent2 = FirstSequencedModel.create + child2 = SubClassMultiSequencedModel.create + + assert_equal parent2.auto_increment, 3 + assert_equal child2.auto_increment, 4 + assert_equal child2.sequence, 2 + end +end \ No newline at end of file From 6a3b3dd768ab4526a9fb3ec59263948b8cc6cf89 Mon Sep 17 00:00:00 2001 From: gt-sdi Date: Tue, 12 Jun 2012 15:07:05 -0600 Subject: [PATCH 2/2] Now works on embedded documents too. --- lib/mongoid-sequence.rb | 10 +++++++++- test/embedded_test.rb | 11 +++++++++++ test/models/child_sequenced_model.rb | 9 +++++++++ test/models/parent_sequenced_model.rb | 9 +++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 test/embedded_test.rb create mode 100644 test/models/child_sequenced_model.rb create mode 100644 test/models/parent_sequenced_model.rb diff --git a/lib/mongoid-sequence.rb b/lib/mongoid-sequence.rb index 14706fb..c09ef90 100644 --- a/lib/mongoid-sequence.rb +++ b/lib/mongoid-sequence.rb @@ -29,7 +29,7 @@ def use_superclass_sequence end def set_sequence - sequences = self.db.collection("__sequences") + sequences = get_sequence_collection self.class.klazzes.each do |klazz| klazz.sequence_fields.each do |field| next_sequence = sequences.find_and_modify(:query => {"_id" => "#{klazz.name.underscore}_#{field}"}, @@ -41,5 +41,13 @@ def set_sequence end if klazz.sequence_fields end end + + def get_sequence_collection + if self.embedded? + sequences = self._parent.db.collection("__sequences") + else + sequences = self.db.collection("__sequences") + end + end end end diff --git a/test/embedded_test.rb b/test/embedded_test.rb new file mode 100644 index 0000000..e82cca0 --- /dev/null +++ b/test/embedded_test.rb @@ -0,0 +1,11 @@ +require "test_helper" + +class EmbeddedTest < BaseTest + def test_embedded_sequence + parent = ParentSequencedModel.create + child = parent.child_sequenced_models.create + + assert_equal parent.auto_increment, 1 + assert_equal child.child_auto_increment, 1 + end +end diff --git a/test/models/child_sequenced_model.rb b/test/models/child_sequenced_model.rb new file mode 100644 index 0000000..14facbf --- /dev/null +++ b/test/models/child_sequenced_model.rb @@ -0,0 +1,9 @@ +class ChildSequencedModel + include Mongoid::Document + include Mongoid::Sequence + + field :child_auto_increment, :type => Integer + sequence :child_auto_increment + + embedded_in :child_sequenced_models, :inverse_of => :child_sequenced_models +end diff --git a/test/models/parent_sequenced_model.rb b/test/models/parent_sequenced_model.rb new file mode 100644 index 0000000..2e6bef4 --- /dev/null +++ b/test/models/parent_sequenced_model.rb @@ -0,0 +1,9 @@ +class ParentSequencedModel + include Mongoid::Document + include Mongoid::Sequence + + field :auto_increment, :type => Integer + sequence :auto_increment + + embeds_many :child_sequenced_models +end