mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Improving documentation...
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@191 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
6860db61f5
commit
f033833fb9
6 changed files with 167 additions and 206 deletions
|
@ -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 ADO-based SQLServerAdapter (only works on Windows) [Joey Gibson]
|
||||
|
||||
* 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.
|
||||
This is turned on by default, but can be turned off with ActiveRecord::Base.reload_dependencies = false in production environments.
|
||||
|
||||
|
|
|
@ -1,38 +1,35 @@
|
|||
module ActiveRecord
|
||||
# Mixins are a way of decorating existing Active Record models with additional behavior. If you for example
|
||||
# want to keep a number of Documents in order, you can include Mixins::List, and all of the sudden be able to
|
||||
# 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
|
||||
module Acts #:nodoc:
|
||||
module List #:nodoc:
|
||||
def self.append_features(base)
|
||||
super
|
||||
base.extend(ClassMethods)
|
||||
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
|
||||
# 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 = {})
|
||||
configuration = { :column => "position", :scope => "1" }
|
||||
configuration.update(options) if options.is_a?(Hash)
|
||||
|
@ -40,7 +37,7 @@ module ActiveRecord
|
|||
configuration[:scope] = "#{configuration[:scope]}_id".intern if configuration[:scope].is_a?(Symbol) && configuration[:scope].to_s !~ /_id$/
|
||||
|
||||
class_eval <<-EOV
|
||||
include InstanceMethods
|
||||
include ActiveRecord::Acts::List::InstanceMethods
|
||||
|
||||
def position_column
|
||||
'#{configuration[:column]}'
|
||||
|
@ -54,132 +51,127 @@ module ActiveRecord
|
|||
after_create :add_to_list_bottom
|
||||
EOV
|
||||
end
|
||||
end
|
||||
|
||||
module InstanceMethods
|
||||
def move_lower
|
||||
return unless lower_item
|
||||
# All the methods available to a record that has had <tt>acts_as_list</tt> specified.
|
||||
module InstanceMethods
|
||||
def move_lower
|
||||
return unless lower_item
|
||||
|
||||
self.class.transaction do
|
||||
lower_item.decrement_position
|
||||
increment_position
|
||||
end
|
||||
self.class.transaction do
|
||||
lower_item.decrement_position
|
||||
increment_position
|
||||
end
|
||||
end
|
||||
|
||||
def move_higher
|
||||
return unless higher_item
|
||||
def move_higher
|
||||
return unless higher_item
|
||||
|
||||
self.class.transaction do
|
||||
higher_item.increment_position
|
||||
decrement_position
|
||||
end
|
||||
self.class.transaction do
|
||||
higher_item.increment_position
|
||||
decrement_position
|
||||
end
|
||||
|
||||
def move_to_bottom
|
||||
self.class.transaction do
|
||||
decrement_positions_on_lower_items
|
||||
assume_bottom_position
|
||||
end
|
||||
end
|
||||
|
||||
def move_to_top
|
||||
self.class.transaction do
|
||||
increment_positions_on_higher_items
|
||||
assume_top_position
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Entering or existing the list
|
||||
|
||||
def add_to_list_top
|
||||
increment_positions_on_all_items
|
||||
end
|
||||
|
||||
def add_to_list_bottom
|
||||
end
|
||||
|
||||
def move_to_bottom
|
||||
self.class.transaction do
|
||||
decrement_positions_on_lower_items
|
||||
assume_bottom_position
|
||||
end
|
||||
end
|
||||
|
||||
def remove_from_list
|
||||
decrement_positions_on_lower_items
|
||||
def move_to_top
|
||||
self.class.transaction do
|
||||
increment_positions_on_higher_items
|
||||
assume_top_position
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
|
||||
private
|
||||
# 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
|
||||
|
||||
def lower_item
|
||||
self.class.find_first(
|
||||
"#{scope_condition} AND #{position_column} = #{(send(position_column).to_i + 1).to_s}"
|
||||
)
|
||||
end
|
||||
|
||||
def bottom_position_in_list
|
||||
item = bottom_item
|
||||
item ? item.send(position_column) : 0
|
||||
end
|
||||
|
||||
def bottom_item
|
||||
self.class.find_first(
|
||||
"#{scope_condition} ",
|
||||
"#{position_column} DESC"
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
# Changing the position
|
||||
|
||||
def increment_position
|
||||
update_attribute position_column, self.send(position_column).to_i + 1
|
||||
def assume_bottom_position
|
||||
update_attribute position_column, bottom_position_in_list.to_i + 1
|
||||
end
|
||||
|
||||
def decrement_position
|
||||
update_attribute position_column, self.send(position_column).to_i - 1
|
||||
def assume_top_position
|
||||
update_attribute position_column, 1
|
||||
end
|
||||
|
||||
|
||||
# Querying the position
|
||||
|
||||
def first?
|
||||
self.send(position_column) == 1
|
||||
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 last?
|
||||
self.send(position_column) == bottom_position_in_list
|
||||
def increment_positions_on_higher_items
|
||||
self.class.update_all(
|
||||
"#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} < #{send(position_column)}"
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
# 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
|
||||
|
||||
def lower_item
|
||||
self.class.find_first(
|
||||
"#{scope_condition} AND #{position_column} = #{(send(position_column).to_i + 1).to_s}"
|
||||
)
|
||||
end
|
||||
|
||||
def bottom_position_in_list
|
||||
item = bottom_item
|
||||
item ? item.send(position_column) : 0
|
||||
end
|
||||
|
||||
def bottom_item
|
||||
self.class.find_first(
|
||||
"#{scope_condition} ",
|
||||
"#{position_column} DESC"
|
||||
)
|
||||
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
|
||||
self.class.update_all(
|
||||
"#{position_column} = (#{position_column} + 1)", "#{scope_condition}"
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
def increment_positions_on_all_items
|
||||
self.class.update_all(
|
||||
"#{position_column} = (#{position_column} + 1)", "#{scope_condition}"
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,34 +0,0 @@
|
|||
module ActiveRecord
|
||||
module Mixins
|
||||
# Including this mixins will record when objects of the class are created in a datetime column called "created_at"
|
||||
# and when its updated in another datetime column called "updated_at".
|
||||
#
|
||||
# class Bill < ActiveRecord::Base
|
||||
# include ActiveRecord::Mixins::Touch
|
||||
# end
|
||||
#
|
||||
# bill = Bill.create("amount" => 100)
|
||||
# bill.created_at # => Time.now at the moment of Bill.create
|
||||
# bill.updated_at # => Time.now at the moment of Bill.create
|
||||
#
|
||||
# bill.update_attribute("amount", 150)
|
||||
# bill.created_at # => Time.now at the moment of Bill.create
|
||||
# bill.updated_at # => Time.now at the moment of bill.update_attribute
|
||||
module Touch
|
||||
def self.append_features(base)
|
||||
super
|
||||
|
||||
base.before_create :touch_on_create
|
||||
base.before_update :touch_on_update
|
||||
end
|
||||
|
||||
def touch_on_create
|
||||
self.updated_at = (self.created_at ||= Time.now)
|
||||
end
|
||||
|
||||
def touch_on_update
|
||||
self.updated_at = Time.now
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,39 +1,43 @@
|
|||
module ActiveRecord
|
||||
module Acts
|
||||
# Including this mixin if you want to model a tree structure by providing a parent association and an children
|
||||
# association. This mixin assumes that you have a column called parent_id
|
||||
#
|
||||
# class Category < ActiveRecord::Base
|
||||
# include ActiveRecord::Mixins::Tree
|
||||
# end
|
||||
#
|
||||
# Example :
|
||||
# root
|
||||
# \_ child1
|
||||
# \_ sub-child1
|
||||
#
|
||||
# root = Category.create("name" => "root")
|
||||
# child1 = root.children.create("name" => "child1")
|
||||
# subchild1 = child1.children.create("name" => "subchild1")
|
||||
#
|
||||
# root.parent # => nil
|
||||
# child1.parent # => root
|
||||
# root.children # => [child1]
|
||||
# root.children.first.children.first # => subchild1
|
||||
module Tree
|
||||
module Acts #:nodoc:
|
||||
module Tree #:nodoc:
|
||||
def self.append_features(base)
|
||||
super
|
||||
base.extend(ClassMethods)
|
||||
end
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def acts_as_tree(options = {})
|
||||
configuration = { :foreign_key => "parent_id", :order => nil }
|
||||
configuration.update(options) if options.is_a?(Hash)
|
||||
|
||||
belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key]
|
||||
has_many :children, :class_name => name, :foreign_key => configuration[:foreign_key], :order => configuration[:order], :dependent => true
|
||||
|
||||
# Specify this act if you want to model a tree structure by providing a parent association and an children
|
||||
# association. This act assumes that requires that you have a foreign key column, which by default is called parent_id.
|
||||
#
|
||||
# class Category < ActiveRecord::Base
|
||||
# acts_as_tree :order => "name"
|
||||
# end
|
||||
#
|
||||
# Example :
|
||||
# root
|
||||
# \_ child1
|
||||
# \_ sub-child1
|
||||
#
|
||||
# root = Category.create("name" => "root")
|
||||
# child1 = root.children.create("name" => "child1")
|
||||
# subchild1 = child1.children.create("name" => "subchild1")
|
||||
#
|
||||
# root.parent # => nil
|
||||
# child1.parent # => root
|
||||
# root.children # => [child1]
|
||||
# root.children.first.children.first # => subchild1
|
||||
module ClassMethods
|
||||
# Configuration options are:
|
||||
#
|
||||
# * <tt>foreign_key</tt> - specifies the column name to use for track of the tree (default: parent_id)
|
||||
# * <tt>order</tt> - makes it possible to sort the children according to this SQL snippet.
|
||||
def acts_as_tree(options = {})
|
||||
configuration = { :foreign_key => "parent_id", :order => nil }
|
||||
configuration.update(options) if options.is_a?(Hash)
|
||||
|
||||
belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key]
|
||||
has_many :children, :class_name => name, :foreign_key => configuration[:foreign_key], :order => configuration[:order], :dependent => true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -130,6 +130,9 @@ module ActiveRecord #:nodoc:
|
|||
# When you do Firm.create("name" => "37signals"), this record with be saved in the companies table with type = "Firm". You can then
|
||||
# fetch this row again using Company.find_first "name = '37signals'" and it will return a Firm object.
|
||||
#
|
||||
# If you don't have a type column defined in your table, single-table inheritance won't be triggered. In that case, it'll work just
|
||||
# like normal subclasses with no special magic for differentiating between them or reloading the right type with find.
|
||||
#
|
||||
# Note, all the attributes for all the cases are kept in the same table. Read more:
|
||||
# http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
|
||||
#
|
||||
|
|
|
@ -92,7 +92,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
module ConnectionAdapters
|
||||
class ColumnWithIdentity < Column
|
||||
class ColumnWithIdentity < Column# :nodoc:
|
||||
attr_reader :identity
|
||||
|
||||
def initialize(name, default, sql_type = nil, is_identity = false)
|
||||
|
|
Loading…
Reference in a new issue