diff options
Diffstat (limited to 'activerecord/lib')
-rwxr-xr-x | activerecord/lib/active_record.rb | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/mixins/list.rb | 155 | ||||
-rw-r--r-- | activerecord/lib/active_record/mixins/list_mixin.rb | 154 |
3 files changed, 157 insertions, 154 deletions
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index 0d02dde13a..3e080ae810 100755 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -45,6 +45,8 @@ ActiveRecord::Base.class_eval do include ActiveRecord::Reflection end +require 'active_record/mixins/list' + require 'active_record/connection_adapters/mysql_adapter' require 'active_record/connection_adapters/postgresql_adapter' require 'active_record/connection_adapters/sqlite_adapter' diff --git a/activerecord/lib/active_record/mixins/list.rb b/activerecord/lib/active_record/mixins/list.rb new file mode 100644 index 0000000000..1965c46be6 --- /dev/null +++ b/activerecord/lib/active_record/mixins/list.rb @@ -0,0 +1,155 @@ +module ActiveRecord + module Mixins + # This mixin provides the capabilities for sorting and reordering a number of objects in list. + # The class that has this mixin included needs to have a "position" column defined as an integer on + # the mapped database table. Further more, you need to implement the <tt>scope_condition</tt> that + # defines how to separate one list from another. + # + # Todo list example: + # + # class TodoList < ActiveRecord::Base + # has_many :todo_items, :order => "position" + # end + # + # class TodoItem < ActiveRecord::Base + # include ListMixin + # belongs_to :todo_list + # + # private + # def scope_condition + # "todo_list_id = #{todo_list_id}" + # end + # end + # + # todo_list.first.move_to_bottom + # todo_list.last.move_higher + module List + def self.append_features(base) + super + base.class_eval do + before_destroy :remove_from_list + after_create :add_to_list_bottom + end + end + + # Moving around on the list + + def move_lower + return unless lower_item + lower_item.decrement_position + increment_position + end + + def move_higher + return unless higher_item + higher_item.increment_position + decrement_position + end + + def move_to_bottom + decrement_positions_on_lower_items + assume_bottom_position + end + + def move_to_top + increment_positions_on_higher_items + assume_top_position + end + + + # Entering or existing the list + + def add_to_list_top + increment_positions_on_all_items + end + + def add_to_list_bottom + assume_bottom_position + end + + def remove_from_list + decrement_positions_on_lower_items + end + + + # Changing the position + + def increment_position + self.position = position.to_i + 1 + save + end + + def decrement_position + self.position = position.to_i - 1 + save + end + + + # Querying the position + + def first? + self.position == 1 + end + + def last? + self.position == bottom_position_in_list + end + + private + # Overwrite this method to define the scope of the list changes + def scope_condition; end + + def higher_item + self.class.find_first( + "#{scope_condition} AND position = #{(position.to_i - 1).to_s}" + ) + end + + def lower_item + self.class.find_first( + "#{scope_condition} AND position = #{(position.to_i + 1).to_s}" + ) + end + + def bottom_position_in_list + item = bottom_item + item ? item.position : 0 + end + + def bottom_item + self.class.find_first( + "#{scope_condition} ", + "position DESC" + ) + end + + def assume_bottom_position + self.position = bottom_position_in_list.to_i + 1 + save + end + + def assume_top_position + self.position = 1 + save + end + + def decrement_positions_on_lower_items + self.class.update_all( + "position = (position - 1)", "#{scope_condition} AND position > #{position.to_i}" + ) + end + + def increment_positions_on_higher_items + self.class.update_all( + "position = (position + 1)", "#{scope_condition} AND position < #{position.to_i}" + ) + end + + def increment_positions_on_all_items + self.class.update_all( + "position = (position + 1)", "#{scope_condition}" + ) + end + end + end +end
\ No newline at end of file diff --git a/activerecord/lib/active_record/mixins/list_mixin.rb b/activerecord/lib/active_record/mixins/list_mixin.rb deleted file mode 100644 index 9f964f11af..0000000000 --- a/activerecord/lib/active_record/mixins/list_mixin.rb +++ /dev/null @@ -1,154 +0,0 @@ -module ActiveRecord - # This mixin provides the capabilities for sorting and reordering a number of objects in list. - # The class that has this mixin included needs to have a "position" column defined as an integer on - # the mapped database table. Further more, you need to implement the <tt>scope_condition</tt> that - # defines how to separate one list from another. - # - # Todo list example: - # - # class TodoList < ActiveRecord::Base - # has_many :todo_items, :order => "position" - # end - # - # class TodoItem < ActiveRecord::Base - # include ListMixin - # belongs_to :todo_list - # - # private - # def scope_condition - # "todo_list_id = #{todo_list_id}" - # end - # end - # - # todo_list.first.move_to_bottom - # todo_list.last.move_higher - # - module ListMixin - def self.append_features(base) - super - base.class_eval do - before_destroy :remove_from_list - after_create :add_to_list_bottom - end - end - - # Moving around on the list - - def move_lower - return unless lower_item - lower_item.decrement_position - increment_position - end - - def move_higher - return unless higher_item - higher_item.increment_position - decrement_position - end - - def move_to_bottom - decrement_positions_on_lower_items - assume_bottom_position - end - - def move_to_top - increment_positions_on_higher_items - assume_top_position - end - - - # Entering or existing the list - - def add_to_list_top - increment_positions_on_all_items - end - - def add_to_list_bottom - assume_bottom_position - end - - def remove_from_list - decrement_positions_on_lower_items - end - - - # Changing the position - - def increment_position - self.position = position.to_i + 1 - save - end - - def decrement_position - self.position = position.to_i - 1 - save - end - - - # Querying the position - - def first? - self.position == 1 - end - - def last? - self.position == bottom_position_in_list - end - - private - # Overwrite this method to define the scope of the list changes - def scope_condition; end - - def higher_item - self.class.find_first( - "#{scope_condition} AND position = #{(position.to_i - 1).to_s}" - ) - end - - def lower_item - self.class.find_first( - "#{scope_condition} AND position = #{(position.to_i + 1).to_s}" - ) - end - - def bottom_position_in_list - item = bottom_item - item ? item.position : 0 - end - - def bottom_item - self.class.find_first( - "#{scope_condition} ", - "position DESC" - ) - end - - def assume_bottom_position - self.position = bottom_position_in_list.to_i + 1 - save - end - - def assume_top_position - self.position = 1 - save - end - - def decrement_positions_on_lower_items - self.class.update_all( - "position = (position - 1)", "#{scope_condition} AND position > #{position.to_i}" - ) - end - - def increment_positions_on_higher_items - self.class.update_all( - "position = (position + 1)", "#{scope_condition} AND position < #{position.to_i}" - ) - end - - def increment_positions_on_all_items - self.class.update_all( - "position = (position + 1)", "#{scope_condition}" - ) - end - end -end
\ No newline at end of file |