mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Unofficially added ListMixin
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@82 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
ffd93a84ff
commit
2d483af0d7
1 changed files with 154 additions and 0 deletions
154
activerecord/lib/active_record/mixins/list_mixin.rb
Normal file
154
activerecord/lib/active_record/mixins/list_mixin.rb
Normal file
|
@ -0,0 +1,154 @@
|
|||
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
|
Loading…
Reference in a new issue