Skip to content

Commit

Permalink
Improving documentation...
Browse files Browse the repository at this point in the history
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@191 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information
dhh committed Dec 16, 2004
1 parent 6860db6 commit f033833
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 202 deletions.
4 changes: 0 additions & 4 deletions activerecord/CHANGELOG
Expand Up @@ -166,12 +166,8 @@


* Added option to establish_connection where you'll be able to leave out the parameter to have it use the RAILS_ENV environment variable * Added option to establish_connection where you'll be able to leave out the parameter to have it use the RAILS_ENV environment variable


* Added ADO-based SQLServerAdapter (only works on Windows) [Joey Gibson]

* Fixed problems with primary keys and postgresql sequences (#230) [Tim Bates] * Fixed problems with primary keys and postgresql sequences (#230) [Tim Bates]


* Fixed problems with nested transactions (#231) [Tim Bates]

* Added reloading for associations under cached environments like FastCGI and mod_ruby. This makes it possible to use those environments for development. * Added reloading for associations under cached environments like FastCGI and mod_ruby. This makes it possible to use those environments for development.
This is turned on by default, but can be turned off with ActiveRecord::Base.reload_dependencies = false in production environments. This is turned on by default, but can be turned off with ActiveRecord::Base.reload_dependencies = false in production environments.


Expand Down
256 changes: 124 additions & 132 deletions activerecord/lib/active_record/acts/list.rb
@@ -1,46 +1,43 @@
module ActiveRecord module ActiveRecord
# Mixins are a way of decorating existing Active Record models with additional behavior. If you for example module Acts #:nodoc:
# want to keep a number of Documents in order, you can include Mixins::List, and all of the sudden be able to module List #:nodoc:
# call <tt>document.move_to_bottom</tt>.
module Acts
# 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> if you want
# 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 ActiveRecord::Mixins::List
# 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) def self.append_features(base)
super super
base.extend(ClassMethods) base.extend(ClassMethods)
end end


# This act provides the capabilities for sorting and reordering a number of objects in list.
# The class that has this specified needs to have a "position" column defined as an integer on
# the mapped database table.
#
# Todo list example:
#
# class TodoList < ActiveRecord::Base
# has_many :todo_items, :order => "position"
# end
#
# class TodoItem < ActiveRecord::Base
# belongs_to :todo_list
# acts_as_list :scope => :todo_list
# end
#
# todo_list.first.move_to_bottom
# todo_list.last.move_higher
module ClassMethods module ClassMethods
# Configuration options are:
#
# * +column+ - specifies the column name to use for keeping the position integer (default: position)
# * +scope+ - restricts what is to be considered a list. Given a symbol, it'll attach "_id" (if that hasn't been already) and use that
# as the foreign key restriction. It's also possible to give it an entire string that is interpolated if you need a tighter scope than
# just a foreign key. Example: <tt>acts_as_list :scope => 'todo_list_id = #{todo_list_id} AND completed = 0'</tt>
def acts_as_list(options = {}) def acts_as_list(options = {})
configuration = { :column => "position", :scope => "1" } configuration = { :column => "position", :scope => "1" }
configuration.update(options) if options.is_a?(Hash) configuration.update(options) if options.is_a?(Hash)


configuration[:scope] = "#{configuration[:scope]}_id".intern if configuration[:scope].is_a?(Symbol) && configuration[:scope].to_s !~ /_id$/ configuration[:scope] = "#{configuration[:scope]}_id".intern if configuration[:scope].is_a?(Symbol) && configuration[:scope].to_s !~ /_id$/


class_eval <<-EOV class_eval <<-EOV
include InstanceMethods include ActiveRecord::Acts::List::InstanceMethods
def position_column def position_column
'#{configuration[:column]}' '#{configuration[:column]}'
Expand All @@ -54,132 +51,127 @@ def scope_condition
after_create :add_to_list_bottom after_create :add_to_list_bottom
EOV EOV
end end
end


module InstanceMethods # All the methods available to a record that has had <tt>acts_as_list</tt> specified.
def move_lower module InstanceMethods
return unless lower_item def move_lower

return unless lower_item
self.class.transaction do
lower_item.decrement_position self.class.transaction do
increment_position lower_item.decrement_position
end increment_position
end end
end


def move_higher def move_higher
return unless higher_item return unless higher_item


self.class.transaction do self.class.transaction do
higher_item.increment_position higher_item.increment_position
decrement_position decrement_position
end
end end

end
def move_to_bottom
self.class.transaction do def move_to_bottom
decrement_positions_on_lower_items self.class.transaction do
assume_bottom_position decrement_positions_on_lower_items
end assume_bottom_position
end end
end


def move_to_top def move_to_top
self.class.transaction do self.class.transaction do
increment_positions_on_higher_items increment_positions_on_higher_items
assume_top_position assume_top_position
end
end end

end



# Entering or existing the list def add_to_list_top

increment_positions_on_all_items
def add_to_list_top end
increment_positions_on_all_items
end


def add_to_list_bottom def add_to_list_bottom
assume_bottom_position assume_bottom_position
end end


def remove_from_list def remove_from_list
decrement_positions_on_lower_items decrement_positions_on_lower_items
end end




# Changing the position def increment_position
update_attribute position_column, self.send(position_column).to_i + 1
end

def decrement_position
update_attribute position_column, self.send(position_column).to_i - 1
end


def first?
self.send(position_column) == 1
end

def last?
self.send(position_column) == bottom_position_in_list
end


def increment_position private
update_attribute position_column, self.send(position_column).to_i + 1 # Overwrite this method to define the scope of the list changes
def scope_condition() "1" end

def higher_item
self.class.find_first(
"#{scope_condition} AND #{position_column} = #{(send(position_column).to_i - 1).to_s}"
)
end end


def decrement_position def lower_item
update_attribute position_column, self.send(position_column).to_i - 1 self.class.find_first(
"#{scope_condition} AND #{position_column} = #{(send(position_column).to_i + 1).to_s}"
)
end end



def bottom_position_in_list
# Querying the position item = bottom_item

item ? item.send(position_column) : 0
def first?
self.send(position_column) == 1
end end


def last? def bottom_item
self.send(position_column) == bottom_position_in_list self.class.find_first(
"#{scope_condition} ",
"#{position_column} DESC"
)
end end


private def assume_bottom_position
# Overwrite this method to define the scope of the list changes update_attribute position_column, bottom_position_in_list.to_i + 1
def scope_condition() "1" end end

def higher_item
self.class.find_first(
"#{scope_condition} AND #{position_column} = #{(send(position_column).to_i - 1).to_s}"
)
end


def lower_item def assume_top_position
self.class.find_first( update_attribute position_column, 1
"#{scope_condition} AND #{position_column} = #{(send(position_column).to_i + 1).to_s}" end
)
end


def bottom_position_in_list def decrement_positions_on_lower_items
item = bottom_item self.class.update_all(
item ? item.send(position_column) : 0 "#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} > #{send(position_column).to_i}"
end )
end


def bottom_item def increment_positions_on_higher_items
self.class.find_first( self.class.update_all(
"#{scope_condition} ", "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} < #{send(position_column)}"
"#{position_column} DESC" )
) end
end

def assume_bottom_position
update_attribute position_column, bottom_position_in_list.to_i + 1
end

def assume_top_position
update_attribute position_column, 1
end

def decrement_positions_on_lower_items
self.class.update_all(
"#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} > #{send(position_column).to_i}"
)
end

def increment_positions_on_higher_items
self.class.update_all(
"#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} < #{send(position_column)}"
)
end


def increment_positions_on_all_items def increment_positions_on_all_items
self.class.update_all( self.class.update_all(
"#{position_column} = (#{position_column} + 1)", "#{scope_condition}" "#{position_column} = (#{position_column} + 1)", "#{scope_condition}"
) )
end end
end end
end
end end
end end
end end
34 changes: 0 additions & 34 deletions activerecord/lib/active_record/acts/mixins/touch.rb

This file was deleted.

0 comments on commit f033833

Please sign in to comment.