Permalink
Browse files

continued extracting SortedHierarchy (class and instance methods upda…

…ted)
  • Loading branch information...
1 parent 7f5d6fe commit 005fc477d8f1e061871cfb4dc807ff6902ae1ba7 @khustochka committed Jan 10, 2010
@@ -98,12 +98,12 @@ def find_taxon
def find_taxon_with_children
find_taxon
- @bunch = @taxon.subtaxa if @taxon.respond_to?(:subtaxa)
+ @bunch = @taxon.children if @taxon.respond_to?(:children)
end
def find_all_taxa
@proceed_methods = []
- @taxa = (!@taxon.nil? && @taxon.respond_to?(:supertaxon)) ? @taxon.supertaxon.subtaxa : model_class.all(:order => "sort")
+ @taxa = (!@taxon.nil? && @taxon.respond_to?(:parent)) ? @taxon.parent.children : model_class.all(:order => "sort")
end
def prepare_hierarchy
@@ -14,10 +14,10 @@ def self.prepare_hierarchy
initial_model = self
eager_load = nil
- while initial_model.reflect_on_association(:supertaxon) do
- proceed_methods.push( {:subtaxa => :parent_row} )
- eager_load = eager_load.nil? ? :subtaxa : { :subtaxa => eager_load }
- initial_model = initial_model.reflect_on_association(:supertaxon).klass
+ while initial_model.reflect_on_association(:parent) do
+ proceed_methods.push( {:children => :parent_row} )
+ eager_load = eager_load.nil? ? :children : { :children => eager_load }
+ initial_model = initial_model.reflect_on_association(:parent).klass
end
[initial_model.all(:include => eager_load, :order => "sort"),
@@ -34,55 +34,4 @@ def name
send("name_#{I18n.locale}")
end
- def insert_mind_sorting
- latest = (self.respond_to?(:supertaxon) ? self.supertaxon.subtaxa.count : self.class.count) + 1
- self.sort = latest if self.sort > latest || self.sort == 0
- conditions = ["sort >= #{self.sort}"]
- if self.respond_to?(:supertaxon)
- fk = self.supertaxon.class.to_s.foreign_key
- conditions.push("#{fk} = #{self[fk]}")
- end
- self.class.transaction do
- self.class.update_all("sort = sort + 1", conditions.join(" AND "))
- save!
- end
- end
-
- def update_mind_sorting(attributes)
- latest = self.respond_to?(:supertaxon) ? self.supertaxon.subtaxa.count : self.class.count
- current = attributes[:sort].to_i
- new_sort = attributes[:sort] =
- current > latest || current == 0 ?
- latest :
- current
- old_sort = self[:sort].to_i
-
- self.class.transaction do
- if new_sort != old_sort
- diff = (old_sort - new_sort) / (old_sort - new_sort).abs
- max_sort = [old_sort, new_sort - diff].max
- min_sort = [old_sort, new_sort - diff].min
- conditions = ["sort > #{min_sort}", "sort < #{max_sort}"]
- if self.respond_to?(:supertaxon)
- fk = self.supertaxon.class.to_s.foreign_key
- conditions.push("#{fk} = #{self[fk]}")
- end
- self.class.update_all("sort = sort + (#{diff})", conditions.join(" AND "))
- end
- update_attributes!(attributes)
- end
- end
-
- def destroy_mind_sorting
- conditions = ["sort > #{self[:sort]}"]
- if self.respond_to?(:supertaxon)
- fk = self.supertaxon.class.to_s.foreign_key
- conditions.push("#{fk} = #{self[fk]}")
- end
- self.class.transaction do
- destroy
- self.class.update_all("sort = sort - 1", conditions.join(" AND "))
- end
- end
-
end
@@ -65,7 +65,7 @@ def import
fam_num = 0
order.families.each do |family|
puts " - Saving family #{family[:fam_la]}"
- familia = ordo.subtaxa.create!(
+ familia = ordo.familiae.create!(
:name_la => family[:fam_la],
:name_en => family[:fam_en],
:name_ru => Utils.enconv(family[:fam_ru]),
@@ -77,7 +77,7 @@ def import
sp_num = 0
family.species.each do |sp|
puts " - Saving species #{sp[:sp_la]}"
- species = familia.subtaxa.create!(
+ species = familia.species.create!(
:code => sp[:sp_id],
:name_la => sp[:sp_la],
:authority => sp[:sp_prim],
@@ -8,22 +8,87 @@ def self.included(klass)
module ClassMethods
def parent_for(association_id, options = {}, &extension)
has_many(association_id, options, &extension)
- write_inheritable_attribute(:children_assoc, association_id)
+ write_inheritable_hash :reflections, :children => read_inheritable_attribute(:reflections)[association_id]
+ instance_methods.select{|m| m.include?(association_id.to_s)}.each do |method|
+ alias_method method.sub(/#{association_id}/, "children"), method
+ end
end
def child_of(association_id, options = {})
belongs_to(association_id, options)
- write_inheritable_attribute(:parent_assoc, association_id)
+ write_inheritable_hash :reflections, :parent => read_inheritable_attribute(:reflections)[association_id]
+ instance_methods.select{|m| m.include?(association_id.to_s)}.each do |method|
+ alias_method method.sub(/#{association_id}/, "parent"), method
+ end
end
- def children_assoc
- read_inheritable_attribute(:children_assoc)
+ def top_level?
+ !read_inheritable_attribute(:reflections).has_key?(:parent)
end
- def parent_assoc
- read_inheritable_attribute(:parent_assoc)
+ def bottom_level?
+ !read_inheritable_attribute(:reflections).has_key?(:children)
end
+ def parent_key
+ unless top_level?
+ assoc = read_inheritable_attribute(:reflections)[:parent]
+ assoc.options[:foreign_key] || assoc.name.to_s.foreign_key
+ else
+ nil
+ end
+ end
+ end
+
+ def insert_mind_sorting
+ latest = (self.class.top_level? ? self.class.count : self.parent.children.size) + 1
+ self.sort = latest if self.sort > latest || self.sort == 0
+ conditions = ["sort >= #{self.sort}"]
+ unless self.class.top_level?
+ fk = self.class.parent_key
+ conditions.push("#{fk} = #{self[fk]}")
+ end
+ self.class.transaction do
+ self.class.update_all("sort = sort + 1", conditions.join(" AND "))
+ save!
+ end
+ end
+
+ def update_mind_sorting(attributes)
+ latest = self.class.top_level? ? self.class.count : self.parent.children.size
+ current = attributes[:sort].to_i
+ new_sort = attributes[:sort] =
+ current > latest || current == 0 ?
+ latest :
+ current
+ old_sort = self[:sort].to_i
+
+ self.class.transaction do
+ if new_sort != old_sort
+ diff = (old_sort - new_sort) / (old_sort - new_sort).abs
+ max_sort = [old_sort, new_sort - diff].max
+ min_sort = [old_sort, new_sort - diff].min
+ conditions = ["sort > #{min_sort}", "sort < #{max_sort}"]
+ unless self.class.top_level?
+ fk = self.class.parent_key
+ conditions.push("#{fk} = #{self[fk]}")
+ end
+ self.class.update_all("sort = sort + (#{diff})", conditions.join(" AND "))
+ end
+ update_attributes!(attributes)
+ end
+ end
+
+ def destroy_mind_sorting
+ conditions = ["sort > #{self[:sort]}"]
+ unless self.class.top_level?
+ fk = self.class.parent_key
+ conditions.push("#{fk} = #{self[fk]}")
+ end
+ self.class.transaction do
+ destroy
+ self.class.update_all("sort = sort - 1", conditions.join(" AND "))
+ end
end
end
View
@@ -37,12 +37,11 @@ class ActiveSupport::TestCase
# Add more helper methods to be used by all tests here...
def assert_sorting_preserved(klass)
- if klass.reflect_on_association(klass.parent_assoc).nil?
+ if klass.top_level?
assert_equal( (1..klass.count).to_a, klass.all(:order => :sort).map {|item| item[:sort] }, "Sorting invalid" )
else
- parent_class = klass.reflect_on_association(klass.parent_assoc).klass
- parent_class.all(:order => :sort, :include => parent_class.children_assoc).each do |parent|
- assert_equal( (1..parent.send(parent_class.children_assoc).count).to_a, parent.send(parent_class.children_assoc).map {|item| item[:sort] }, "Sorting invalid" )
+ klass.reflect_on_association(:parent).klass.all(:order => :sort, :include => :children).each do |parent|
+ assert_equal( (1..parent.children.size).to_a, parent.children.map {|item| item[:sort] }, "Sorting invalid" )
end
end
end
@@ -4,8 +4,8 @@ class FamiliaTest < ActiveSupport::TestCase
test "insert should preserve sorting" do
parent = ordines(:ordines_011)
- new_sort = parent.subtaxa.count / 2
- assert_difference("parent.subtaxa.count", 1) do
+ new_sort = parent.children.size / 2
+ assert_difference("parent.children.size", 1) do
Familia.new(:name_la => "Mididae", :name_ru => "Средневые", :name_uk => "Середневі", :description => '', :ordo_id => ordines(:ordines_011).id, :sort => new_sort).insert_mind_sorting
end
assert_equal new_sort, Familia.find_by_name_la("Mididae")[:sort], "Badly inserted"
@@ -14,15 +14,15 @@ class FamiliaTest < ActiveSupport::TestCase
test "destroy should preserve sorting" do
parent = ordines(:ordines_011)
- assert_difference("parent.subtaxa.count", -1) do
+ assert_difference("parent.children.size", -1) do
familiae(:familiae_013).destroy_mind_sorting
end
assert_sorting_preserved(Familia)
end
test "move down should preserve sorting" do
parent = ordines(:ordines_011)
- new_sort = parent.subtaxa.count * 2 / 3
+ new_sort = parent.children.size * 2 / 3
for_update = familiae(:familiae_013)
for_update.update_mind_sorting(:sort => new_sort)
@@ -32,7 +32,7 @@ class FamiliaTest < ActiveSupport::TestCase
test "move up should preserve sorting" do
parent = ordines(:ordines_011)
- new_sort = parent.subtaxa.count / 3
+ new_sort = parent.children.size / 3
for_update = familiae(:familiae_013)
for_update.update_mind_sorting(:sort => new_sort)
@@ -43,8 +43,8 @@ class FamiliaTest < ActiveSupport::TestCase
test "invalid add should preserve sorting" do
parent = ordines(:ordines_011)
assert_raise(ActiveRecord::RecordInvalid) do
- assert_difference("parent.subtaxa.count", 0) do
- Familia.new(:name_la => "Scolopaci", :ordo_id => ordines(:ordines_011).id, :sort => parent.subtaxa.count / 2).insert_mind_sorting
+ assert_difference("parent.children.size", 0) do
+ Familia.new(:name_la => "Scolopaci", :ordo_id => ordines(:ordines_011).id, :sort => parent.children.size / 2).insert_mind_sorting
end
end
assert_nil Familia.find_by_name_la("Scolopaci")
@@ -54,9 +54,9 @@ class FamiliaTest < ActiveSupport::TestCase
test "invalid edit should preserve sorting" do
parent = ordines(:ordines_011)
assert_raise(ActiveRecord::RecordInvalid) do
- assert_difference("parent.subtaxa.count", 0) do
+ assert_difference("parent.children.size", 0) do
for_update = familiae(:familiae_013)
- for_update.update_mind_sorting(:name_la => "Scolopaci", :sort => parent.subtaxa.count / 3)
+ for_update.update_mind_sorting(:name_la => "Scolopaci", :sort => parent.children.size / 3)
end
end
assert_nil Familia.find_by_name_la("Scolopaci")
@@ -65,40 +65,40 @@ class FamiliaTest < ActiveSupport::TestCase
test "insert with illegal or 0 sort value should append to the end" do
parent = ordines(:ordines_011)
- assert_difference("parent.subtaxa.count", 1) do
- Familia.new(:name_la => "Zerodae", :name_ru => "Нулебразные", :name_uk => "Нульові", :description => '', :ordo_id => ordines(:ordines_011).id, :sort => 0).insert_mind_sorting
+ assert_difference("parent.children.size", 1) do
+ Familia.new(:name_la => "Zerodae", :name_ru => "Нулевые", :name_uk => "Нульові", :description => '', :ordo_id => ordines(:ordines_011).id, :sort => 0).insert_mind_sorting
end
- assert_equal parent.subtaxa.count, Familia.find_by_name_la("Zerodae")[:sort], "Badly inserted"
+ assert_equal parent.children.size, Familia.find_by_name_la("Zerodae")[:sort], "Badly inserted"
assert_sorting_preserved(Familia)
- assert_difference("parent.subtaxa.count", 1) do
- Familia.new(:name_la => "Superidae", :name_ru => "Сверхвые", :name_uk => "Наднові", :description => '', :ordo_id => ordines(:ordines_011).id, :sort => 1000).insert_mind_sorting
+ assert_difference("parent.children.size", 1) do
+ Familia.new(:name_la => "Superidae", :name_ru => "Сверховые", :name_uk => "Наднові", :description => '', :ordo_id => ordines(:ordines_011).id, :sort => 1000).insert_mind_sorting
end
- assert_equal parent.subtaxa.count, Familia.find_by_name_la("Superidae")[:sort], "Badly inserted"
+ assert_equal parent.children.size, Familia.find_by_name_la("Superidae")[:sort], "Badly inserted"
assert_sorting_preserved(Familia)
- assert_difference("parent.subtaxa.count", 1) do
+ assert_difference("parent.children.size", 1) do
Familia.new(:name_la => "Xxxdae", :name_ru => "Хххвые", :name_uk => "Хххві", :description => '', :ordo_id => ordines(:ordines_011).id, :sort => "xxx").insert_mind_sorting
end
- assert_equal parent.subtaxa.count, Familia.find_by_name_la("Xxxdae")[:sort], "Badly inserted"
+ assert_equal parent.children.size, Familia.find_by_name_la("Xxxdae")[:sort], "Badly inserted"
assert_sorting_preserved(Familia)
end
test "update with illegal or 0 sort value should move to the end" do
parent = ordines(:ordines_011)
for_update = familiae(:familiae_013)
for_update.update_mind_sorting(:sort => 0)
- assert_equal parent.subtaxa.count, Familia.find_by_name_la(for_update[:name_la])[:sort], "Badly inserted"
+ assert_equal parent.children.size, Familia.find_by_name_la(for_update[:name_la])[:sort], "Badly inserted"
assert_sorting_preserved(Familia)
for_update = familiae(:familiae_013)
for_update.update_mind_sorting(:sort => 1000)
- assert_equal parent.subtaxa.count, Familia.find_by_name_la(for_update[:name_la])[:sort], "Badly inserted"
+ assert_equal parent.children.size, Familia.find_by_name_la(for_update[:name_la])[:sort], "Badly inserted"
assert_sorting_preserved(Familia)
for_update = familiae(:familiae_013)
for_update.update_mind_sorting(:sort => "xxxx")
- assert_equal parent.subtaxa.count, Familia.find_by_name_la(for_update[:name_la])[:sort], "Badly inserted"
+ assert_equal parent.children.size, Familia.find_by_name_la(for_update[:name_la])[:sort], "Badly inserted"
assert_sorting_preserved(Familia)
end
end

0 comments on commit 005fc47

Please sign in to comment.