diff options
Diffstat (limited to 'activerecord/lib/active_record')
7 files changed, 109 insertions, 103 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index f0f3288937..d1382df7a1 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -9,7 +9,7 @@ require 'active_record/associations/has_and_belongs_to_many_association' require 'active_record/deprecated_associations' module ActiveRecord - class HasManyThroughAssociationNotFoundError < ActiveRecordError + class HasManyThroughAssociationNotFoundError < ActiveRecordError #:nodoc: def initialize(reflection) @reflection = reflection end @@ -19,7 +19,7 @@ module ActiveRecord end end - class HasManyThroughAssociationPolymorphicError < ActiveRecordError + class HasManyThroughAssociationPolymorphicError < ActiveRecordError #:nodoc: def initialize(owner_class_name, reflection, source_reflection) @owner_class_name = owner_class_name @reflection = reflection @@ -31,7 +31,7 @@ module ActiveRecord end end - class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError + class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError #:nodoc: def initialize(reflection) @reflection = reflection @through_reflection = reflection.through_reflection @@ -44,7 +44,7 @@ module ActiveRecord end end - class EagerLoadPolymorphicError < ActiveRecordError + class EagerLoadPolymorphicError < ActiveRecordError #:nodoc: def initialize(reflection) @reflection = reflection end diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 5b02d17f59..e86dad58f5 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -253,7 +253,7 @@ module ActiveRecord #:nodoc: super end - def self.reset_subclasses + def self.reset_subclasses #:nodoc: nonreloadables = [] subclasses.each do |klass| unless klass.reloadable? @@ -561,7 +561,7 @@ module ActiveRecord #:nodoc: reset_table_name end - def reset_table_name + def reset_table_name #:nodoc: name = "#{table_name_prefix}#{undecorated_table_name(base_class.name)}#{table_name_suffix}" set_table_name(name) name @@ -573,7 +573,7 @@ module ActiveRecord #:nodoc: reset_primary_key end - def reset_primary_key + def reset_primary_key #:nodoc: key = 'id' case primary_key_prefix_type when :table_name @@ -592,11 +592,11 @@ module ActiveRecord #:nodoc: # Lazy-set the sequence name to the connection's default. This method # is only ever called once since set_sequence_name overrides it. - def sequence_name + def sequence_name #:nodoc: reset_sequence_name end - def reset_sequence_name + def reset_sequence_name #:nodoc: default = connection.default_sequence_name(table_name, primary_key) set_sequence_name(default) default @@ -704,6 +704,7 @@ module ActiveRecord #:nodoc: @columns_hash ||= columns.inject({}) { |hash, column| hash[column.name] = column; hash } end + # Returns an array of column names as strings. def column_names @column_names ||= columns.map { |column| column.name } end @@ -717,7 +718,7 @@ module ActiveRecord #:nodoc: # Returns a hash of all the methods added to query each of the columns in the table with the name of the method as the key # and true as the value. This makes it possible to do O(1) lookups in respond_to? to check if a given method for attribute # is available. - def column_methods_hash + def column_methods_hash #:nodoc: @dynamic_methods_hash ||= column_names.inject(Hash.new(false)) do |methods, attr| attr_name = attr.to_s methods[attr.to_sym] = attr_name @@ -729,7 +730,7 @@ module ActiveRecord #:nodoc: end # Contains the names of the generated reader methods. - def read_methods + def read_methods #:nodoc: @read_methods ||= Set.new end @@ -1190,20 +1191,20 @@ module ActiveRecord #:nodoc: end protected - def subclasses + def subclasses #:nodoc: @@subclasses[self] ||= [] @@subclasses[self] + extra = @@subclasses[self].inject([]) {|list, subclass| list + subclass.subclasses } end # Test whether the given method and optional key are scoped. - def scoped?(method, key = nil) + def scoped?(method, key = nil) #:nodoc: if current_scoped_methods && (scope = current_scoped_methods[method]) !key || scope.has_key?(key) end end # Retrieve the scope for the given method and optional key. - def scope(method, key = nil) + def scope(method, key = nil) #:nodoc: if current_scoped_methods && (scope = current_scoped_methods[method]) key ? scope[key] : scope end @@ -1225,7 +1226,7 @@ module ActiveRecord #:nodoc: alias_method :scoped_methods, :single_threaded_scoped_methods end - def current_scoped_methods + def current_scoped_methods #:nodoc: scoped_methods.last end @@ -1254,7 +1255,7 @@ module ActiveRecord #:nodoc: end # Returns the name of the class descending directly from ActiveRecord in the inheritance hierarchy. - def class_name_of_active_record_descendant(klass) + def class_name_of_active_record_descendant(klass) #:nodoc: klass.base_class.name end @@ -1276,13 +1277,13 @@ module ActiveRecord #:nodoc: alias_method :sanitize_conditions, :sanitize_sql - def replace_bind_variables(statement, values) + def replace_bind_variables(statement, values) #:nodoc: raise_if_bind_arity_mismatch(statement, statement.count('?'), values.size) bound = values.dup statement.gsub('?') { quote_bound_value(bound.shift) } end - def replace_named_bind_variables(statement, bind_vars) + def replace_named_bind_variables(statement, bind_vars) #:nodoc: statement.gsub(/:(\w+)/) do match = $1.to_sym if bind_vars.include?(match) @@ -1293,7 +1294,7 @@ module ActiveRecord #:nodoc: end end - def quote_bound_value(value) + def quote_bound_value(value) #:nodoc: if (value.respond_to?(:map) && !value.is_a?(String)) value.map { |v| connection.quote(v) }.join(',') else @@ -1301,24 +1302,24 @@ module ActiveRecord #:nodoc: end end - def raise_if_bind_arity_mismatch(statement, expected, provided) + def raise_if_bind_arity_mismatch(statement, expected, provided) #:nodoc: unless expected == provided raise PreparedStatementInvalid, "wrong number of bind variables (#{provided} for #{expected}) in: #{statement}" end end - def extract_options_from_args!(args) + def extract_options_from_args!(args) #:nodoc: args.last.is_a?(Hash) ? args.pop : {} end VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :order, :select, :readonly, :group, :from ] - def validate_find_options(options) + def validate_find_options(options) #:nodoc: options.assert_valid_keys(VALID_FIND_OPTIONS) end - def set_readonly_option!(options) + def set_readonly_option!(options) #:nodoc: # Inherit :readonly from finder scope if set. Otherwise, # if :joins is not blank then :readonly defaults to true. unless options.has_key?(:readonly) @@ -1330,7 +1331,7 @@ module ActiveRecord #:nodoc: end end - def encode_quoted_value(value) + def encode_quoted_value(value) #:nodoc: quoted_value = connection.quote(value) quoted_value = "'#{quoted_value[1..-2].gsub(/\'/, "\\\\'")}'" if quoted_value.include?("\\\'") # (for ruby mode) " quoted_value @@ -1604,11 +1605,12 @@ module ActiveRecord #:nodoc: @attributes.frozen? end + # Records loaded through joins with piggy-back attributes will be marked as read only as they cannot be saved and return true to this query. def readonly? @readonly == true end - def readonly! + def readonly! #:nodoc: @readonly = true end diff --git a/activerecord/lib/active_record/calculations.rb b/activerecord/lib/active_record/calculations.rb index 59a7647213..a4c6b71398 100644 --- a/activerecord/lib/active_record/calculations.rb +++ b/activerecord/lib/active_record/calculations.rb @@ -1,5 +1,5 @@ module ActiveRecord - module Calculations + module Calculations #:nodoc: CALCULATIONS_OPTIONS = [:conditions, :joins, :order, :select, :group, :having, :distinct] def self.included(base) base.extend(ClassMethods) @@ -143,83 +143,83 @@ module ActiveRecord end protected - def construct_calculation_sql(aggregate, aggregate_alias, options) - scope = scope(:find) - sql = ["SELECT #{aggregate} AS #{aggregate_alias}"] - sql << ", #{options[:group_field]} AS #{options[:group_alias]}" if options[:group] - sql << " FROM #{table_name} " - add_joins!(sql, options, scope) - add_conditions!(sql, options[:conditions], scope) - sql << " GROUP BY #{options[:group_field]}" if options[:group] - sql << " HAVING #{options[:having]}" if options[:group] && options[:having] - sql << " ORDER BY #{options[:order]}" if options[:order] - sql.join - end - - def execute_simple_calculation(operation, column_name, column, aggregate, aggregate_alias, options) - value = connection.select_value(construct_calculation_sql(aggregate, aggregate_alias, options)) - type_cast_calculated_value(value, column, operation) - end + def construct_calculation_sql(aggregate, aggregate_alias, options) #:nodoc: + scope = scope(:find) + sql = ["SELECT #{aggregate} AS #{aggregate_alias}"] + sql << ", #{options[:group_field]} AS #{options[:group_alias]}" if options[:group] + sql << " FROM #{table_name} " + add_joins!(sql, options, scope) + add_conditions!(sql, options[:conditions], scope) + sql << " GROUP BY #{options[:group_field]}" if options[:group] + sql << " HAVING #{options[:having]}" if options[:group] && options[:having] + sql << " ORDER BY #{options[:order]}" if options[:order] + sql.join + end - def execute_grouped_calculation(operation, column_name, column, aggregate, aggregate_alias, options) - group_attr = options[:group].to_s - association = reflect_on_association(group_attr.to_sym) - associated = association && association.macro == :belongs_to # only count belongs_to associations - group_field = (associated ? "#{options[:group]}_id" : options[:group]).to_s - group_alias = column_alias_for(group_field) - group_column = column_for group_field - sql = construct_calculation_sql(aggregate, aggregate_alias, options.merge(:group_field => group_field, :group_alias => group_alias)) - calculated_data = connection.select_all(sql) - - if association - key_ids = calculated_data.collect { |row| row[group_alias] } - key_records = association.klass.base_class.find(key_ids) - key_records = key_records.inject({}) { |hsh, r| hsh.merge(r.id => r) } + def execute_simple_calculation(operation, column_name, column, aggregate, aggregate_alias, options) #:nodoc: + value = connection.select_value(construct_calculation_sql(aggregate, aggregate_alias, options)) + type_cast_calculated_value(value, column, operation) end - calculated_data.inject(OrderedHash.new) do |all, row| - key = associated ? key_records[row[group_alias].to_i] : type_cast_calculated_value(row[group_alias], group_column) - value = row[aggregate_alias] - all << [key, type_cast_calculated_value(value, column, operation)] + def execute_grouped_calculation(operation, column_name, column, aggregate, aggregate_alias, options) #:nodoc: + group_attr = options[:group].to_s + association = reflect_on_association(group_attr.to_sym) + associated = association && association.macro == :belongs_to # only count belongs_to associations + group_field = (associated ? "#{options[:group]}_id" : options[:group]).to_s + group_alias = column_alias_for(group_field) + group_column = column_for group_field + sql = construct_calculation_sql(aggregate, aggregate_alias, options.merge(:group_field => group_field, :group_alias => group_alias)) + calculated_data = connection.select_all(sql) + + if association + key_ids = calculated_data.collect { |row| row[group_alias] } + key_records = association.klass.base_class.find(key_ids) + key_records = key_records.inject({}) { |hsh, r| hsh.merge(r.id => r) } + end + + calculated_data.inject(OrderedHash.new) do |all, row| + key = associated ? key_records[row[group_alias].to_i] : type_cast_calculated_value(row[group_alias], group_column) + value = row[aggregate_alias] + all << [key, type_cast_calculated_value(value, column, operation)] + end end - end private - def validate_calculation_options(operation, options = {}) - if operation.to_s == 'count' - options.assert_valid_keys(CALCULATIONS_OPTIONS + [:include]) - else - options.assert_valid_keys(CALCULATIONS_OPTIONS) + def validate_calculation_options(operation, options = {}) + if operation.to_s == 'count' + options.assert_valid_keys(CALCULATIONS_OPTIONS + [:include]) + else + options.assert_valid_keys(CALCULATIONS_OPTIONS) + end end - end - def select_aggregate(operation, column_name, options) - "#{operation}(#{'DISTINCT ' if options[:distinct]}#{column_name})" - end + def select_aggregate(operation, column_name, options) + "#{operation}(#{'DISTINCT ' if options[:distinct]}#{column_name})" + end - # converts a given key to the value that the database adapter returns as - # - # users.id #=> users_id - # sum(id) #=> sum_id - # count(distinct users.id) #=> count_distinct_users_id - # count(*) #=> count_all - def column_alias_for(*keys) - keys.join(' ').downcase.gsub(/\*/, 'all').gsub(/\W+/, ' ').strip.gsub(/ +/, '_') - end + # converts a given key to the value that the database adapter returns as + # + # users.id #=> users_id + # sum(id) #=> sum_id + # count(distinct users.id) #=> count_distinct_users_id + # count(*) #=> count_all + def column_alias_for(*keys) + keys.join(' ').downcase.gsub(/\*/, 'all').gsub(/\W+/, ' ').strip.gsub(/ +/, '_') + end - def column_for(field) - field_name = field.to_s.split('.').last - columns.detect { |c| c.name.to_s == field_name } - end + def column_for(field) + field_name = field.to_s.split('.').last + columns.detect { |c| c.name.to_s == field_name } + end - def type_cast_calculated_value(value, column, operation = nil) - operation = operation.to_s.downcase - case operation - when 'count' then value.to_i - when 'avg' then value.to_f - else column ? column.type_cast(value) : value + def type_cast_calculated_value(value, column, operation = nil) + operation = operation.to_s.downcase + case operation + when 'count' then value.to_i + when 'avg' then value.to_f + else column ? column.type_cast(value) : value + end end - end end end end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb index 8b70b2f047..2cdc8af688 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb @@ -38,7 +38,7 @@ module ActiveRecord end # set concurrency support flag (not thread safe, like most of the methods in this file) - def allow_concurrency=(threaded) + def allow_concurrency=(threaded) #:nodoc: logger.debug "allow_concurrency=#{threaded}" if logger return if @@allow_concurrency == threaded clear_all_cached_connections! @@ -51,7 +51,7 @@ module ActiveRecord log_connections if logger end - def active_connection_name + def active_connection_name #:nodoc: @active_connection_name ||= if active_connections[name] || @@defined_connections[name] name @@ -62,7 +62,7 @@ module ActiveRecord end end - def clear_active_connection_name + def clear_active_connection_name #:nodoc: @active_connection_name = nil subclasses.each { |klass| klass.clear_active_connection_name } end @@ -88,7 +88,7 @@ module ActiveRecord end # Verify active connections. - def verify_active_connections! + def verify_active_connections! #:nodoc: if @@allow_concurrency remove_stale_cached_threads!(@@active_connections) do |name, conn| conn.disconnect! @@ -244,7 +244,7 @@ module ActiveRecord end # Set the connection for the class. - def self.connection=(spec) + def self.connection=(spec) #:nodoc: if spec.kind_of?(ActiveRecord::ConnectionAdapters::AbstractAdapter) active_connections[name] = spec elsif spec.kind_of?(ConnectionSpecification) @@ -257,7 +257,7 @@ module ActiveRecord end # connection state logging - def self.log_connections + def self.log_connections #:nodoc: if logger logger.info "Defined connections: #{@@defined_connections.inspect}" logger.info "Active connections: #{active_connections.inspect}" diff --git a/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb b/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb index 00d8aa7330..92120920fe 100644 --- a/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb @@ -44,7 +44,11 @@ begin # 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. - alias :attributes_with_quotes_pre_oracle :attributes_with_quotes #:nodoc: + def attributes_with_quotes_pre_oracle #:nodoc: + attributes_with_quotes + end + + def attributes_with_quotes(creating = true) #:nodoc: aq = attributes_with_quotes_pre_oracle creating if connection.class == ConnectionAdapters::OracleAdapter @@ -542,7 +546,7 @@ begin @desc.attrGet(OCI_ATTR_PARAM) end - class OraObject + class OraObject #:nodoc: attr_reader :schema, :name def initialize(info) case info.attrGet(OCI_ATTR_PTYPE) diff --git a/activerecord/lib/active_record/locking.rb b/activerecord/lib/active_record/locking.rb index 572dd29ba0..ca83a98b30 100644 --- a/activerecord/lib/active_record/locking.rb +++ b/activerecord/lib/active_record/locking.rb @@ -60,15 +60,15 @@ module ActiveRecord end class << self - def set_locking_column( value=nil, &block ) + def set_locking_column(value = nil, &block) define_attr_method :locking_column, value, &block end - def locking_column + def locking_column #:nodoc: reset_locking_column end - def reset_locking_column + def reset_locking_column #:nodoc: default = 'lock_version' set_locking_column(default) default diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index c5c38ff4fd..024e799ea3 100755 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -6,7 +6,7 @@ module ActiveRecord # rescue ActiveRecord::RecordInvalid => invalid # puts invalid.record.errors # end - class RecordInvalid < ActiveRecordError + class RecordInvalid < ActiveRecordError #:nodoc: attr_reader :record def initialize(record) @record = record |