diff options
Diffstat (limited to 'activerecord/lib/active_record')
11 files changed, 97 insertions, 106 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index b2c30dafb3..381f3e4931 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -403,7 +403,7 @@ module ActiveRecord # # Adds the following methods for retrieval and query. # +collection+ is replaced with the symbol passed as the first argument, so - # <tt>has_and_belongs_to_many :categories</tt> would add among others +categories.empty?+. + # <tt>has_and_belongs_to_many :categories</tt> would add among others <tt>categories.empty?</tt>. # * <tt>collection(force_reload = false)</tt> - returns an array of all the associated objects. # An empty array is returned if none is found. # * <tt>collection<<(object, ...)</tt> - adds one or more objects to the collection by creating associations in the join table diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 0c086183dc..92f5724249 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -97,6 +97,16 @@ module ActiveRecord #:nodoc: # end # end # + # == Accessing attributes before they have been type casted + # + # Some times you want to be able to read the raw attribute data without having the column-determined type cast run its course first. + # That can be done by using the <attribute>_before_type_cast accessors that all attributes have. For example, if your Account model + # has a balance attribute, you can call account.balance_before_type_cast or account.id_before_type_cast. + # + # This is especially useful in validation situations where the user might supply a string for an integer field and you want to display + # the original string back in an error message. Accessing the attribute normally would type cast the string to 0, which isn't what you + # want. + # # == Dynamic attribute-based finders # # Dynamic attribute-based finders are a cleaner way of getting objects by simple queries without turning to SQL. They work by @@ -479,20 +489,8 @@ module ActiveRecord #:nodoc: # Guesses the table name (in forced lower-case) based on the name of the class in the inheritance hierarchy descending # directly from ActiveRecord. So if the hierarchy looks like: Reply < Message < ActiveRecord, then Message is used - # to guess the table name from even when called on Reply. The guessing rules are as follows: - # - # * Class name ends in "x", "ch" or "ss": "es" is appended, so a Search class becomes a searches table. - # * Class name ends in "y" preceded by a consonant or "qu": The "y" is replaced with "ies", so a Category class becomes a categories table. - # * Class name ends in "fe": The "fe" is replaced with "ves", so a Wife class becomes a wives table. - # * Class name ends in "lf" or "rf": The "f" is replaced with "ves", so a Half class becomes a halves table. - # * Class name ends in "person": The "person" is replaced with "people", so a Salesperson class becomes a salespeople table. - # * Class name ends in "man": The "man" is replaced with "men", so a Spokesman class becomes a spokesmen table. - # * Class name ends in "sis": The "i" is replaced with an "e", so a Basis class becomes a bases table. - # * Class name ends in "tum" or "ium": The "um" is replaced with an "a", so a Datum class becomes a data table. - # * Class name ends in "child": The "child" is replaced with "children", so a NodeChild class becomes a node_children table. - # * Class name ends in an "s": No additional characters are added or removed. - # * Class name doesn't end in "s": An "s" is appended, so a Comment class becomes a comments table. - # * Class name with word compositions: Compositions are underscored, so CreditCard class becomes a credit_cards table. + # to guess the table name from even when called on Reply. The rules used to do the guess are handled by the Inflector class + # in Active Support, which knows almost all common English inflections (report a bug if your inflection isn't covered). # # Additionally, the class-level table_name_prefix is prepended to the table_name and the table_name_suffix is appended. # So if you have "myapp_" as a prefix, the table name guess for an Account class becomes "myapp_accounts". @@ -501,7 +499,7 @@ module ActiveRecord #:nodoc: # "mice" table. Example: # # class Mouse < ActiveRecord::Base - # def self.table_name() "mice" end + # table_name "mice" # end def table_name table_name_prefix + undecorated_table_name(class_name_of_active_record_descendant(self)) + table_name_suffix @@ -525,34 +523,8 @@ module ActiveRecord #:nodoc: "type" end - # Defines an "attribute" method (like #inheritance_column or - # #table_name). A new (class) method will be created with the - # given name. If a value is specified, the new method will - # return that value (as a string). Otherwise, the given block - # will be used to compute the value of the method. - # - # The original method will be aliased, with the new name being - # prefixed with "original_". This allows the new method to - # access the original value. - # - # Example: - # - # class A < ActiveRecord::Base - # define_attr_method :primary_key, "sysid" - # define_attr_method( :inheritance_column ) do - # original_inheritance_column + "_id" - # end - # end - def define_attr_method( name, value=nil, &block ) - sing = class << self; self; end - block = proc { value.to_s } if value - sing.send( :alias_method, "original_#{name}", name ) - sing.send( :define_method, name, &block ) - end - # Sets the table name to use to the given value, or (if the value - # is nil or false) to the value returned by the given block. (See - # #define_attr_method). + # is nil or false) to the value returned by the given block. # # Example: # @@ -566,7 +538,7 @@ module ActiveRecord #:nodoc: # Sets the name of the primary key column to use to the given value, # or (if the value is nil or false) to the value returned by the given - # block. (See #define_attr_method). + # block. # # Example: # @@ -580,7 +552,7 @@ module ActiveRecord #:nodoc: # Sets the name of the inheritance column to use to the given value, # or (if the value # is nil or false) to the value returned by the - # given block. (See # #define_attr_method). + # given block. # # Example: # @@ -636,13 +608,14 @@ module ActiveRecord #:nodoc: @columns = @columns_hash = @content_columns = @dynamic_methods_hash = nil end - def reset_column_information_and_inheritable_attributes_for_all_subclasses + def reset_column_information_and_inheritable_attributes_for_all_subclasses#:nodoc: subclasses.each { |klass| klass.reset_inheritable_attributes; klass.reset_column_information } end # Transforms attribute key names into a more humane format, such as "First name" instead of "first_name". Example: # Person.human_attribute_name("first_name") # => "First name" - def human_attribute_name(attribute_key_name) + # Deprecated in favor of just calling "first_name".humanize + def human_attribute_name(attribute_key_name) #:nodoc: attribute_key_name.humanize end @@ -650,12 +623,12 @@ module ActiveRecord #:nodoc: superclass == Base || !columns_hash.has_key?(inheritance_column) end - def quote(object) + def quote(object) #:nodoc: connection.quote(object) end # Used to sanitize objects before they're used in an SELECT SQL-statement. Delegates to <tt>connection.quote</tt>. - def sanitize(object) # :nodoc: + def sanitize(object) #:nodoc: connection.quote(object) end @@ -762,6 +735,31 @@ module ActiveRecord #:nodoc: end end + # Defines an "attribute" method (like #inheritance_column or + # #table_name). A new (class) method will be created with the + # given name. If a value is specified, the new method will + # return that value (as a string). Otherwise, the given block + # will be used to compute the value of the method. + # + # The original method will be aliased, with the new name being + # prefixed with "original_". This allows the new method to + # access the original value. + # + # Example: + # + # class A < ActiveRecord::Base + # define_attr_method :primary_key, "sysid" + # define_attr_method( :inheritance_column ) do + # original_inheritance_column + "_id" + # end + # end + def define_attr_method(name, value=nil, &block) + sing = class << self; self; end + block = proc { value.to_s } if value + sing.send( :alias_method, "original_#{name}", name ) + sing.send( :define_method, name, &block ) + end + protected def subclasses @@subclasses[self] ||= [] @@ -868,11 +866,11 @@ module ActiveRecord #:nodoc: read_attribute(self.class.primary_key) end - def id_before_type_cast + def id_before_type_cast #:nodoc: read_attribute_before_type_cast(self.class.primary_key) end - def quoted_id + def quoted_id #:nodoc: quote(id, self.class.columns_hash[self.class.primary_key]) end @@ -1123,7 +1121,7 @@ module ActiveRecord #:nodoc: # Returns the value of attribute identified by <tt>attr_name</tt> after it has been type cast (for example, # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). - def read_attribute(attr_name) #:doc: + def read_attribute(attr_name) if @attributes.keys.include? attr_name if column = column_for_attribute(attr_name) unserializable_attribute?(attr_name, column) ? @@ -1162,7 +1160,7 @@ module ActiveRecord #:nodoc: # Updates the attribute identified by <tt>attr_name</tt> with the specified +value+. Empty strings for fixnum and float # columns are turned into nil. - def write_attribute(attr_name, value) #:doc: + def write_attribute(attr_name, value) @attributes[attr_name] = empty_string_for_number_column?(attr_name, value) ? nil : value end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 5d2c764afe..605a82bf74 100755 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -63,18 +63,6 @@ module ActiveRecord # # The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError # may be returned on an error. - # - # == Connecting to another database for a single model - # - # To support different connections for different classes, you can - # simply call establish_connection with the classes you wish to have - # different connections for: - # - # class Courses < ActiveRecord::Base - # ... - # end - # - # Courses.establish_connection( ... ) def self.establish_connection(spec = nil) case spec when nil @@ -151,7 +139,7 @@ module ActiveRecord end # Converts all strings in a hash to symbols. - def self.symbolize_strings_in_hash(hash) + def self.symbolize_strings_in_hash(hash) #:nodoc: hash.symbolize_keys end end diff --git a/activerecord/lib/active_record/connection_adapters/oci_adapter.rb b/activerecord/lib/active_record/connection_adapters/oci_adapter.rb index 8b9b5627e0..8fb57f9c39 100644 --- a/activerecord/lib/active_record/connection_adapters/oci_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/oci_adapter.rb @@ -215,7 +215,7 @@ begin ConnectionAdapters::OCIAdapter.new conn, logger end - alias :attributes_with_quotes_pre_oci :attributes_with_quotes + alias :attributes_with_quotes_pre_oci :attributes_with_quotes #:nodoc: # Enable the id column to be bound into the sql later, by the adapter's insert method. # This is preferable to inserting the hard-coded value here, because the insert method # needs to know the id value explicitly. diff --git a/activerecord/lib/active_record/connection_adapters/sqlserver_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlserver_adapter.rb index d221f99be3..f6325d845c 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlserver_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlserver_adapter.rb @@ -10,7 +10,7 @@ require 'active_record/connection_adapters/abstract_adapter' # module ActiveRecord class Base - def self.sqlserver_connection(config) + def self.sqlserver_connection(config) #:nodoc: require_library_or_gem 'dbi' unless self.class.const_defined?(:DBI) symbolize_strings_in_hash(config) @@ -25,10 +25,6 @@ module ActiveRecord raise ArgumentError, "No database specified. Missing argument: database." end - def adapter_name() - 'SqlServer' - end - conn = DBI.connect("DBI:ADO:Provider=SQLOLEDB;Data Source=#{host};Initial Catalog=#{database};User Id=#{username};Password=#{password};") conn["AutoCommit"] = true @@ -295,6 +291,10 @@ EOL end end + def adapter_name() + 'SqlServer' + end + private def select(sql, name = nil) rows = [] diff --git a/activerecord/lib/active_record/deprecated_associations.rb b/activerecord/lib/active_record/deprecated_associations.rb index 7a595eb216..a3d0f1d947 100644 --- a/activerecord/lib/active_record/deprecated_associations.rb +++ b/activerecord/lib/active_record/deprecated_associations.rb @@ -66,7 +66,7 @@ module ActiveRecord end_eval end - def deprecated_association_comparison_method(association_name, association_class_name) + def deprecated_association_comparison_method(association_name, association_class_name) # :nodoc: module_eval <<-"end_eval", __FILE__, __LINE__ def #{association_name}?(comparison_object, force_reload = false) if comparison_object.kind_of?(#{association_class_name}) @@ -78,7 +78,7 @@ module ActiveRecord end_eval end - def deprecated_has_association_method(association_name) + def deprecated_has_association_method(association_name) # :nodoc: module_eval <<-"end_eval", __FILE__, __LINE__ def has_#{association_name}?(force_reload = false) !#{association_name}(force_reload).nil? @@ -86,7 +86,7 @@ module ActiveRecord end_eval end - def deprecated_build_method(method_prefix, collection_name, collection_class_name, class_primary_key_name) + def deprecated_build_method(method_prefix, collection_name, collection_class_name, class_primary_key_name)# :nodoc: module_eval <<-"end_eval", __FILE__, __LINE__ def #{method_prefix + collection_name}(attributes = {}) association = #{collection_class_name}.new @@ -96,7 +96,7 @@ module ActiveRecord end_eval end - def deprecated_create_method(method_prefix, collection_name, collection_class_name, class_primary_key_name) + def deprecated_create_method(method_prefix, collection_name, collection_class_name, class_primary_key_name)# :nodoc: module_eval <<-"end_eval", __FILE__, __LINE__ def #{method_prefix + collection_name}(attributes = nil) #{collection_class_name}.create((attributes || {}).merge({ "#{class_primary_key_name}" => id})) diff --git a/activerecord/lib/active_record/locking.rb b/activerecord/lib/active_record/locking.rb index e08e2fcec8..635fae89d8 100644 --- a/activerecord/lib/active_record/locking.rb +++ b/activerecord/lib/active_record/locking.rb @@ -1,25 +1,25 @@ module ActiveRecord + # Active Records support optimistic locking if the field <tt>lock_version</tt> is present. Each update to the + # record increments the lock_version column and the locking facilities ensure that records instantiated twice + # will let the last one saved raise a StaleObjectError if the first was also updated. Example: + # + # p1 = Person.find(1) + # p2 = Person.find(1) + # + # p1.first_name = "Michael" + # p1.save + # + # p2.first_name = "should fail" + # p2.save # Raises a ActiveRecord::StaleObjectError + # + # You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging, + # or otherwise apply the business logic needed to resolve the conflict. + # + # You must ensure that your database schema defaults the lock_version column to 0. + # + # This behavior can be turned off by setting <tt>ActiveRecord::Base.lock_optimistically = false</tt>. module Locking - # Active Records support optimistic locking if the field <tt>lock_version</tt> is present. Each update to the - # record increments the lock_version column and the locking facilities ensure that records instantiated twice - # will let the last one saved raise a StaleObjectError if the first was also updated. Example: - # - # p1 = Person.find(1) - # p2 = Person.find(1) - # - # p1.first_name = "Michael" - # p1.save - # - # p2.first_name = "should fail" - # p2.save # Raises a ActiveRecord::StaleObjectError - # - # You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging, - # or otherwise apply the business logic needed to resolve the conflict. - # - # You must ensure that your database schema defaults the lock_version column to 0. - # - # This behavior can be turned off by setting <tt>ActiveRecord::Base.lock_optimistically = false</tt>. - def self.append_features(base) + def self.append_features(base) #:nodoc: super base.class_eval do alias_method :update_without_lock, :update @@ -27,7 +27,7 @@ module ActiveRecord end end - def update_with_lock + def update_with_lock #:nodoc: if locking_enabled? previous_value = self.lock_version self.lock_version = previous_value + 1 @@ -50,7 +50,7 @@ module ActiveRecord @@lock_optimistically = true cattr_accessor :lock_optimistically - def locking_enabled? + def locking_enabled? #:nodoc: lock_optimistically && respond_to?(:lock_version) end end diff --git a/activerecord/lib/active_record/observer.rb b/activerecord/lib/active_record/observer.rb index f08374596d..856d3fc968 100644 --- a/activerecord/lib/active_record/observer.rb +++ b/activerecord/lib/active_record/observer.rb @@ -21,7 +21,8 @@ module ActiveRecord # something else than the class you're interested in observing, you can implement the observed_class class method. Like this: # # class AuditObserver < ActiveRecord::Observer - # def self.observed_class() Account end + # observe Account + # # def after_update(account) # AuditTrail.new(account, "UPDATED") # end @@ -32,7 +33,8 @@ module ActiveRecord # If the audit observer needs to watch more than one kind of object, this can be specified in an array, like this: # # class AuditObserver < ActiveRecord::Observer - # def self.observed_class() [ Account, Balance ] end + # observe Account, Balance + # # def after_update(record) # AuditTrail.new(record, "UPDATED") # end @@ -44,6 +46,7 @@ module ActiveRecord class Observer include Singleton + # Attaches the observer to the supplied model classes. def self.observe(*models) define_method(:observed_class) { models } end @@ -55,7 +58,7 @@ module ActiveRecord end end - def update(callback_method, object) + def update(callback_method, object) #:nodoc: send(callback_method, object) if respond_to?(callback_method) end diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index 2c61f9e2d5..01a9720f52 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -18,7 +18,7 @@ module ActiveRecord end end - def create_with_timestamps + def create_with_timestamps #:nodoc: t = timestamps_gmt ? Time.now.gmtime : Time.now write_attribute("created_at", t) if record_timestamps && respond_to?(:created_at) && created_at.nil? write_attribute("created_on", t) if record_timestamps && respond_to?(:created_on) && created_on.nil? @@ -29,7 +29,7 @@ module ActiveRecord create_without_timestamps end - def update_with_timestamps + def update_with_timestamps #:nodoc: t = timestamps_gmt ? Time.now.gmtime : Time.now write_attribute("updated_at", t) if record_timestamps && respond_to?(:updated_at) write_attribute("updated_on", t) if record_timestamps && respond_to?(:updated_on) diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index 937955dd72..d6b99008ee 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -96,14 +96,14 @@ module ActiveRecord end end - def lock_mutex + def lock_mutex#:nodoc: Thread.current['open_transactions'] ||= 0 TRANSACTION_MUTEX.lock if Thread.current['open_transactions'] == 0 Thread.current['start_db_transaction'] = (Thread.current['open_transactions'] == 0) Thread.current['open_transactions'] += 1 end - def unlock_mutex + def unlock_mutex#:nodoc: Thread.current['open_transactions'] -= 1 TRANSACTION_MUTEX.unlock if Thread.current['open_transactions'] == 0 end diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index a3cce5afa0..520ebd8458 100755 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -17,6 +17,8 @@ module ActiveRecord :wrong_length => "is the wrong length (should be %d characters)", :taken => "has already been taken", } + + # Holds a hash with all the default error messages, such that they can be replaced by your own copy or localizations. cattr_accessor :default_error_messages @@ -29,7 +31,7 @@ module ActiveRecord end # Adds an error message (+msg+) to the +attribute+, which will be returned on a call to <tt>on(attribute)</tt> - # for the same attribute and ensure that this error object returns false when asked if +empty?+. More than one + # for the same attribute and ensure that this error object returns false when asked if <tt>empty?</tt>. More than one # error can be added to the same +attribute+ in which case an array will be returned on a call to <tt>on(attribute)</tt>. # If no +msg+ is supplied, "invalid" is assumed. def add(attribute, msg = @@default_error_messages[:invalid]) |