Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

continued extracting SortedHierarchy (class and instance methods upda…

…ted)
  • Loading branch information...
commit 005fc477d8f1e061871cfb4dc807ff6902ae1ba7 1 parent 7f5d6fe
authored January 11, 2010
4  app/controllers/taxonomy/taxa_controller.rb
@@ -98,12 +98,12 @@ def find_taxon
98 98
 
99 99
   def find_taxon_with_children
100 100
     find_taxon
101  
-    @bunch = @taxon.subtaxa if @taxon.respond_to?(:subtaxa)
  101
+    @bunch = @taxon.children if @taxon.respond_to?(:children)
102 102
   end
103 103
 
104 104
   def find_all_taxa
105 105
     @proceed_methods = []
106  
-    @taxa = (!@taxon.nil? && @taxon.respond_to?(:supertaxon)) ? @taxon.supertaxon.subtaxa : model_class.all(:order => "sort")
  106
+    @taxa = (!@taxon.nil? && @taxon.respond_to?(:parent)) ? @taxon.parent.children : model_class.all(:order => "sort")
107 107
   end
108 108
 
109 109
   def prepare_hierarchy
59  app/models/taxonomy/taxon.rb
@@ -14,10 +14,10 @@ def self.prepare_hierarchy
14 14
     initial_model = self
15 15
     eager_load = nil
16 16
 
17  
-    while initial_model.reflect_on_association(:supertaxon) do
18  
-      proceed_methods.push( {:subtaxa => :parent_row} )
19  
-      eager_load = eager_load.nil? ? :subtaxa : { :subtaxa => eager_load }
20  
-      initial_model = initial_model.reflect_on_association(:supertaxon).klass
  17
+    while initial_model.reflect_on_association(:parent) do
  18
+      proceed_methods.push( {:children => :parent_row} )
  19
+      eager_load = eager_load.nil? ? :children : { :children => eager_load }
  20
+      initial_model = initial_model.reflect_on_association(:parent).klass
21 21
     end
22 22
 
23 23
     [initial_model.all(:include => eager_load, :order => "sort"),
@@ -34,55 +34,4 @@ def name
34 34
     send("name_#{I18n.locale}")
35 35
   end
36 36
 
37  
-  def insert_mind_sorting
38  
-    latest = (self.respond_to?(:supertaxon) ? self.supertaxon.subtaxa.count : self.class.count) + 1
39  
-    self.sort = latest if self.sort > latest || self.sort == 0
40  
-    conditions = ["sort >= #{self.sort}"]
41  
-    if self.respond_to?(:supertaxon)
42  
-      fk = self.supertaxon.class.to_s.foreign_key
43  
-      conditions.push("#{fk} = #{self[fk]}")
44  
-    end
45  
-    self.class.transaction do
46  
-      self.class.update_all("sort = sort + 1", conditions.join(" AND "))
47  
-      save!
48  
-    end
49  
-  end
50  
-
51  
-  def update_mind_sorting(attributes)
52  
-    latest = self.respond_to?(:supertaxon) ? self.supertaxon.subtaxa.count : self.class.count
53  
-    current = attributes[:sort].to_i
54  
-    new_sort = attributes[:sort] =
55  
-            current > latest || current == 0 ?
56  
-                    latest :
57  
-                    current
58  
-    old_sort = self[:sort].to_i
59  
-
60  
-    self.class.transaction do
61  
-      if new_sort != old_sort
62  
-        diff = (old_sort - new_sort) / (old_sort - new_sort).abs
63  
-        max_sort = [old_sort, new_sort - diff].max
64  
-        min_sort = [old_sort, new_sort - diff].min
65  
-        conditions = ["sort > #{min_sort}", "sort < #{max_sort}"]
66  
-        if self.respond_to?(:supertaxon)
67  
-          fk = self.supertaxon.class.to_s.foreign_key
68  
-          conditions.push("#{fk} = #{self[fk]}")
69  
-        end
70  
-        self.class.update_all("sort = sort + (#{diff})", conditions.join(" AND "))
71  
-      end
72  
-      update_attributes!(attributes)
73  
-    end
74  
-  end
75  
-
76  
-  def destroy_mind_sorting
77  
-    conditions = ["sort > #{self[:sort]}"]
78  
-    if self.respond_to?(:supertaxon)
79  
-      fk = self.supertaxon.class.to_s.foreign_key
80  
-      conditions.push("#{fk} = #{self[fk]}")
81  
-    end
82  
-    self.class.transaction do
83  
-      destroy
84  
-      self.class.update_all("sort = sort - 1", conditions.join(" AND "))
85  
-    end
86  
-  end
87  
-
88 37
 end
4  lib/legacy/legacy_task.rb
@@ -65,7 +65,7 @@ def import
65 65
       fam_num = 0
66 66
       order.families.each do |family|
67 67
       puts "   - Saving family #{family[:fam_la]}"
68  
-        familia = ordo.subtaxa.create!(
  68
+        familia = ordo.familiae.create!(
69 69
                 :name_la => family[:fam_la],
70 70
                 :name_en => family[:fam_en],
71 71
                 :name_ru => Utils.enconv(family[:fam_ru]),
@@ -77,7 +77,7 @@ def import
77 77
           sp_num = 0
78 78
           family.species.each do |sp|
79 79
           puts "     - Saving species #{sp[:sp_la]}"
80  
-            species = familia.subtaxa.create!(
  80
+            species = familia.species.create!(
81 81
                     :code => sp[:sp_id],
82 82
                     :name_la => sp[:sp_la],
83 83
                     :authority => sp[:sp_prim], 
77  lib/rails_ext/sorted_hierarchy/sorted_hierarchy.rb
@@ -8,22 +8,87 @@ def self.included(klass)
8 8
     module ClassMethods
9 9
       def parent_for(association_id, options = {}, &extension)
10 10
         has_many(association_id, options, &extension)
11  
-        write_inheritable_attribute(:children_assoc, association_id)
  11
+        write_inheritable_hash :reflections, :children => read_inheritable_attribute(:reflections)[association_id]
  12
+        instance_methods.select{|m| m.include?(association_id.to_s)}.each do |method|
  13
+          alias_method method.sub(/#{association_id}/, "children"), method
  14
+        end
12 15
       end
13 16
 
14 17
       def child_of(association_id, options = {})
15 18
         belongs_to(association_id, options)
16  
-        write_inheritable_attribute(:parent_assoc, association_id)
  19
+        write_inheritable_hash :reflections, :parent => read_inheritable_attribute(:reflections)[association_id]
  20
+        instance_methods.select{|m| m.include?(association_id.to_s)}.each do |method|
  21
+          alias_method method.sub(/#{association_id}/, "parent"), method
  22
+        end
17 23
       end
18 24
 
19  
-      def children_assoc
20  
-        read_inheritable_attribute(:children_assoc)
  25
+      def top_level?
  26
+        !read_inheritable_attribute(:reflections).has_key?(:parent)
21 27
       end
22 28
 
23  
-      def parent_assoc
24  
-        read_inheritable_attribute(:parent_assoc)
  29
+      def bottom_level?
  30
+        !read_inheritable_attribute(:reflections).has_key?(:children)
25 31
       end
26 32
 
  33
+      def parent_key
  34
+        unless top_level?
  35
+          assoc = read_inheritable_attribute(:reflections)[:parent]
  36
+          assoc.options[:foreign_key] || assoc.name.to_s.foreign_key 
  37
+        else
  38
+          nil
  39
+        end
  40
+      end
  41
+    end
  42
+
  43
+    def insert_mind_sorting
  44
+      latest = (self.class.top_level? ? self.class.count : self.parent.children.size) + 1
  45
+      self.sort = latest if self.sort > latest || self.sort == 0
  46
+      conditions = ["sort >= #{self.sort}"]
  47
+      unless self.class.top_level?
  48
+        fk = self.class.parent_key
  49
+        conditions.push("#{fk} = #{self[fk]}")
  50
+      end
  51
+      self.class.transaction do
  52
+        self.class.update_all("sort = sort + 1", conditions.join(" AND "))
  53
+        save!
  54
+      end
  55
+    end
  56
+
  57
+    def update_mind_sorting(attributes)
  58
+      latest = self.class.top_level? ? self.class.count : self.parent.children.size
  59
+      current = attributes[:sort].to_i
  60
+      new_sort = attributes[:sort] =
  61
+              current > latest || current == 0 ?
  62
+                      latest :
  63
+                      current
  64
+      old_sort = self[:sort].to_i
  65
+
  66
+      self.class.transaction do
  67
+        if new_sort != old_sort
  68
+          diff = (old_sort - new_sort) / (old_sort - new_sort).abs
  69
+          max_sort = [old_sort, new_sort - diff].max
  70
+          min_sort = [old_sort, new_sort - diff].min
  71
+          conditions = ["sort > #{min_sort}", "sort < #{max_sort}"]
  72
+          unless self.class.top_level?
  73
+            fk = self.class.parent_key
  74
+            conditions.push("#{fk} = #{self[fk]}")
  75
+          end
  76
+          self.class.update_all("sort = sort + (#{diff})", conditions.join(" AND "))
  77
+        end
  78
+        update_attributes!(attributes)
  79
+      end
  80
+    end
  81
+
  82
+    def destroy_mind_sorting
  83
+      conditions = ["sort > #{self[:sort]}"]
  84
+      unless self.class.top_level?
  85
+        fk = self.class.parent_key
  86
+        conditions.push("#{fk} = #{self[fk]}")
  87
+      end
  88
+      self.class.transaction do
  89
+        destroy
  90
+        self.class.update_all("sort = sort - 1", conditions.join(" AND "))
  91
+      end
27 92
     end
28 93
 
29 94
   end
7  test/test_helper.rb
@@ -37,12 +37,11 @@ class ActiveSupport::TestCase
37 37
   # Add more helper methods to be used by all tests here...
38 38
 
39 39
   def assert_sorting_preserved(klass)
40  
-    if klass.reflect_on_association(klass.parent_assoc).nil?
  40
+    if klass.top_level?
41 41
       assert_equal( (1..klass.count).to_a, klass.all(:order => :sort).map {|item| item[:sort] }, "Sorting invalid" )
42 42
     else
43  
-      parent_class = klass.reflect_on_association(klass.parent_assoc).klass
44  
-      parent_class.all(:order => :sort, :include => parent_class.children_assoc).each do |parent|
45  
-        assert_equal( (1..parent.send(parent_class.children_assoc).count).to_a, parent.send(parent_class.children_assoc).map {|item| item[:sort] }, "Sorting invalid" )
  43
+      klass.reflect_on_association(:parent).klass.all(:order => :sort, :include => :children).each do |parent|
  44
+        assert_equal( (1..parent.children.size).to_a, parent.children.map {|item| item[:sort] }, "Sorting invalid" )
46 45
       end
47 46
     end
48 47
   end
40  test/unit/taxonomy/familia_test.rb
@@ -4,8 +4,8 @@ class FamiliaTest < ActiveSupport::TestCase
4 4
 
5 5
   test "insert should preserve sorting" do
6 6
     parent = ordines(:ordines_011)
7  
-    new_sort = parent.subtaxa.count / 2
8  
-    assert_difference("parent.subtaxa.count", 1) do
  7
+    new_sort = parent.children.size / 2
  8
+    assert_difference("parent.children.size", 1) do
9 9
       Familia.new(:name_la => "Mididae", :name_ru => "Средневые", :name_uk => "Середневі", :description => '', :ordo_id => ordines(:ordines_011).id, :sort => new_sort).insert_mind_sorting
10 10
     end
11 11
     assert_equal new_sort, Familia.find_by_name_la("Mididae")[:sort], "Badly inserted"
@@ -14,7 +14,7 @@ class FamiliaTest < ActiveSupport::TestCase
14 14
 
15 15
   test "destroy should preserve sorting" do
16 16
     parent = ordines(:ordines_011)
17  
-    assert_difference("parent.subtaxa.count", -1) do
  17
+    assert_difference("parent.children.size", -1) do
18 18
       familiae(:familiae_013).destroy_mind_sorting
19 19
     end
20 20
     assert_sorting_preserved(Familia)
@@ -22,7 +22,7 @@ class FamiliaTest < ActiveSupport::TestCase
22 22
 
23 23
   test "move down should preserve sorting" do
24 24
     parent = ordines(:ordines_011)
25  
-    new_sort = parent.subtaxa.count * 2 / 3
  25
+    new_sort = parent.children.size * 2 / 3
26 26
     for_update = familiae(:familiae_013)
27 27
     for_update.update_mind_sorting(:sort => new_sort)
28 28
 
@@ -32,7 +32,7 @@ class FamiliaTest < ActiveSupport::TestCase
32 32
 
33 33
   test "move up should preserve sorting" do
34 34
     parent = ordines(:ordines_011)
35  
-    new_sort = parent.subtaxa.count / 3
  35
+    new_sort = parent.children.size / 3
36 36
     for_update = familiae(:familiae_013)
37 37
     for_update.update_mind_sorting(:sort => new_sort)
38 38
 
@@ -43,8 +43,8 @@ class FamiliaTest < ActiveSupport::TestCase
43 43
   test "invalid add should preserve sorting" do
44 44
     parent = ordines(:ordines_011)
45 45
     assert_raise(ActiveRecord::RecordInvalid) do
46  
-      assert_difference("parent.subtaxa.count", 0) do
47  
-        Familia.new(:name_la => "Scolopaci", :ordo_id => ordines(:ordines_011).id, :sort => parent.subtaxa.count / 2).insert_mind_sorting
  46
+      assert_difference("parent.children.size", 0) do
  47
+        Familia.new(:name_la => "Scolopaci", :ordo_id => ordines(:ordines_011).id, :sort => parent.children.size / 2).insert_mind_sorting
48 48
       end
49 49
     end
50 50
     assert_nil Familia.find_by_name_la("Scolopaci")
@@ -54,9 +54,9 @@ class FamiliaTest < ActiveSupport::TestCase
54 54
   test "invalid edit should preserve sorting" do
55 55
     parent = ordines(:ordines_011)
56 56
     assert_raise(ActiveRecord::RecordInvalid) do
57  
-      assert_difference("parent.subtaxa.count", 0) do
  57
+      assert_difference("parent.children.size", 0) do
58 58
         for_update = familiae(:familiae_013)
59  
-        for_update.update_mind_sorting(:name_la => "Scolopaci", :sort => parent.subtaxa.count / 3)
  59
+        for_update.update_mind_sorting(:name_la => "Scolopaci", :sort => parent.children.size / 3)
60 60
       end
61 61
     end
62 62
     assert_nil Familia.find_by_name_la("Scolopaci")
@@ -65,22 +65,22 @@ class FamiliaTest < ActiveSupport::TestCase
65 65
 
66 66
   test "insert with illegal or 0 sort value should append to the end" do
67 67
     parent = ordines(:ordines_011)
68  
-    assert_difference("parent.subtaxa.count", 1) do
69  
-      Familia.new(:name_la => "Zerodae", :name_ru => "Нулебразные", :name_uk => "Нульові", :description => '', :ordo_id => ordines(:ordines_011).id, :sort => 0).insert_mind_sorting
  68
+    assert_difference("parent.children.size", 1) do
  69
+      Familia.new(:name_la => "Zerodae", :name_ru => "Нулевые", :name_uk => "Нульові", :description => '', :ordo_id => ordines(:ordines_011).id, :sort => 0).insert_mind_sorting
70 70
     end
71  
-    assert_equal parent.subtaxa.count, Familia.find_by_name_la("Zerodae")[:sort], "Badly inserted"
  71
+    assert_equal parent.children.size, Familia.find_by_name_la("Zerodae")[:sort], "Badly inserted"
72 72
     assert_sorting_preserved(Familia)
73 73
 
74  
-    assert_difference("parent.subtaxa.count", 1) do
75  
-      Familia.new(:name_la => "Superidae", :name_ru => "Сверхвые", :name_uk => "Наднові", :description => '', :ordo_id => ordines(:ordines_011).id, :sort => 1000).insert_mind_sorting
  74
+    assert_difference("parent.children.size", 1) do
  75
+      Familia.new(:name_la => "Superidae", :name_ru => "Сверховые", :name_uk => "Наднові", :description => '', :ordo_id => ordines(:ordines_011).id, :sort => 1000).insert_mind_sorting
76 76
     end
77  
-    assert_equal parent.subtaxa.count, Familia.find_by_name_la("Superidae")[:sort], "Badly inserted"
  77
+    assert_equal parent.children.size, Familia.find_by_name_la("Superidae")[:sort], "Badly inserted"
78 78
     assert_sorting_preserved(Familia)
79 79
 
80  
-    assert_difference("parent.subtaxa.count", 1) do
  80
+    assert_difference("parent.children.size", 1) do
81 81
       Familia.new(:name_la => "Xxxdae", :name_ru => "Хххвые", :name_uk => "Хххві", :description => '', :ordo_id => ordines(:ordines_011).id, :sort => "xxx").insert_mind_sorting
82 82
     end
83  
-    assert_equal parent.subtaxa.count, Familia.find_by_name_la("Xxxdae")[:sort], "Badly inserted"
  83
+    assert_equal parent.children.size, Familia.find_by_name_la("Xxxdae")[:sort], "Badly inserted"
84 84
     assert_sorting_preserved(Familia)
85 85
   end
86 86
 
@@ -88,17 +88,17 @@ class FamiliaTest < ActiveSupport::TestCase
88 88
     parent = ordines(:ordines_011)
89 89
     for_update = familiae(:familiae_013)
90 90
     for_update.update_mind_sorting(:sort => 0)
91  
-    assert_equal parent.subtaxa.count, Familia.find_by_name_la(for_update[:name_la])[:sort], "Badly inserted"
  91
+    assert_equal parent.children.size, Familia.find_by_name_la(for_update[:name_la])[:sort], "Badly inserted"
92 92
     assert_sorting_preserved(Familia)
93 93
 
94 94
     for_update = familiae(:familiae_013)
95 95
     for_update.update_mind_sorting(:sort => 1000)
96  
-    assert_equal parent.subtaxa.count, Familia.find_by_name_la(for_update[:name_la])[:sort], "Badly inserted"
  96
+    assert_equal parent.children.size, Familia.find_by_name_la(for_update[:name_la])[:sort], "Badly inserted"
97 97
     assert_sorting_preserved(Familia)
98 98
 
99 99
     for_update = familiae(:familiae_013)
100 100
     for_update.update_mind_sorting(:sort => "xxxx")
101  
-    assert_equal parent.subtaxa.count, Familia.find_by_name_la(for_update[:name_la])[:sort], "Badly inserted"
  101
+    assert_equal parent.children.size, Familia.find_by_name_la(for_update[:name_la])[:sort], "Badly inserted"
102 102
     assert_sorting_preserved(Familia)
103 103
   end
104 104
 end

0 notes on commit 005fc47

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