diff options
16 files changed, 86 insertions, 54 deletions
diff --git a/activemodel/lib/active_model/callbacks.rb b/activemodel/lib/active_model/callbacks.rb index 80385c2614..e669113001 100644 --- a/activemodel/lib/active_model/callbacks.rb +++ b/activemodel/lib/active_model/callbacks.rb @@ -89,11 +89,11 @@ module ActiveModel def define_model_callbacks(*callbacks) options = callbacks.extract_options! options = { - :terminator => "result == false", - :skip_after_callbacks_if_terminated => true, - :scope => [:kind, :name], - :only => [:before, :around, :after] - }.merge(options) + :terminator => "result == false", + :skip_after_callbacks_if_terminated => true, + :scope => [:kind, :name], + :only => [:before, :around, :after] + }.merge!(options) types = Array(options.delete(:only)) @@ -106,6 +106,8 @@ module ActiveModel end end + private + def _define_before_model_callback(klass, callback) #:nodoc: klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1 def self.before_#{callback}(*args, &block) diff --git a/activemodel/lib/active_model/mass_assignment_security/permission_set.rb b/activemodel/lib/active_model/mass_assignment_security/permission_set.rb index 415ab0ad17..f104d0306c 100644 --- a/activemodel/lib/active_model/mass_assignment_security/permission_set.rb +++ b/activemodel/lib/active_model/mass_assignment_security/permission_set.rb @@ -2,7 +2,7 @@ require 'set' module ActiveModel module MassAssignmentSecurity - class PermissionSet < Set + class PermissionSet < Set #:nodoc: def +(values) super(values.compact.map(&:to_s)) @@ -23,14 +23,14 @@ module ActiveModel end end - class WhiteList < PermissionSet + class WhiteList < PermissionSet #:nodoc: def deny?(key) !include?(key) end end - class BlackList < PermissionSet + class BlackList < PermissionSet #:nodoc: def deny?(key) include?(key) diff --git a/activemodel/lib/active_model/validations/acceptance.rb b/activemodel/lib/active_model/validations/acceptance.rb index 38abd0c1fa..c49f831cae 100644 --- a/activemodel/lib/active_model/validations/acceptance.rb +++ b/activemodel/lib/active_model/validations/acceptance.rb @@ -2,7 +2,7 @@ module ActiveModel # == Active Model Acceptance Validator module Validations - class AcceptanceValidator < EachValidator + class AcceptanceValidator < EachValidator #:nodoc: def initialize(options) super(options.reverse_merge(:allow_nil => true, :accept => "1")) end @@ -58,7 +58,7 @@ module ActiveModel # <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). # The method, proc or string should return or evaluate to a true or # false value. - # * <tt>:strict</tt> - Specifies whether validation should be strict. + # * <tt>:strict</tt> - Specifies whether validation should be strict. # See <tt>ActiveModel::Validation#validates!</tt> for more information. def validates_acceptance_of(*attr_names) validates_with AcceptanceValidator, _merge_attributes(attr_names) diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb index ede34d15bc..b6cf82fb19 100644 --- a/activemodel/lib/active_model/validations/confirmation.rb +++ b/activemodel/lib/active_model/validations/confirmation.rb @@ -2,7 +2,7 @@ module ActiveModel # == Active Model Confirmation Validator module Validations - class ConfirmationValidator < EachValidator + class ConfirmationValidator < EachValidator #:nodoc: def validate_each(record, attribute, value) if (confirmed = record.send("#{attribute}_confirmation")) && (value != confirmed) human_attribute_name = record.class.human_attribute_name(attribute) @@ -59,7 +59,7 @@ module ActiveModel # <tt>:unless => :skip_validation</tt>, or # <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The # method, proc or string should return or evaluate to a true or false value. - # * <tt>:strict</tt> - Specifies whether validation should be strict. + # * <tt>:strict</tt> - Specifies whether validation should be strict. # See <tt>ActiveModel::Validation#validates!</tt> for more information. def validates_confirmation_of(*attr_names) validates_with ConfirmationValidator, _merge_attributes(attr_names) diff --git a/activemodel/lib/active_model/validations/exclusion.rb b/activemodel/lib/active_model/validations/exclusion.rb index edd42d85f2..c8d7057606 100644 --- a/activemodel/lib/active_model/validations/exclusion.rb +++ b/activemodel/lib/active_model/validations/exclusion.rb @@ -4,7 +4,7 @@ module ActiveModel # == Active Model Exclusion Validator module Validations - class ExclusionValidator < EachValidator + class ExclusionValidator < EachValidator #:nodoc: include Clusivity def validate_each(record, attribute, value) diff --git a/activemodel/lib/active_model/validations/format.rb b/activemodel/lib/active_model/validations/format.rb index ffdf842d94..d48987c482 100644 --- a/activemodel/lib/active_model/validations/format.rb +++ b/activemodel/lib/active_model/validations/format.rb @@ -2,7 +2,7 @@ module ActiveModel # == Active Model Format Validator module Validations - class FormatValidator < EachValidator + class FormatValidator < EachValidator #:nodoc: def validate_each(record, attribute, value) if options[:with] regexp = option_call(record, :with) @@ -32,12 +32,12 @@ module ActiveModel def record_error(record, attribute, name, value) record.errors.add(attribute, :invalid, options.except(name).merge!(:value => value)) end - + def regexp_using_multiline_anchors?(regexp) regexp.source.start_with?("^") || (regexp.source.end_with?("$") && !regexp.source.end_with?("\\$")) end - + def check_options_validity(options, name) option = options[name] if option && !option.is_a?(Regexp) && !option.respond_to?(:call) @@ -110,7 +110,7 @@ module ActiveModel # if the validation should not occur (e.g. <tt>:unless => :skip_validation</tt>, # or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The # method, proc or string should return or evaluate to a true or false value. - # * <tt>:strict</tt> - Specifies whether validation should be strict. + # * <tt>:strict</tt> - Specifies whether validation should be strict. # See <tt>ActiveModel::Validation#validates!</tt> for more information. # * <tt>:multiline</tt> - Set to true if your regular expression contains # anchors that match the beginning or end of lines as opposed to the diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb index 8810f2a3c1..154db5aedc 100644 --- a/activemodel/lib/active_model/validations/inclusion.rb +++ b/activemodel/lib/active_model/validations/inclusion.rb @@ -4,7 +4,7 @@ module ActiveModel # == Active Model Inclusion Validator module Validations - class InclusionValidator < EachValidator + class InclusionValidator < EachValidator #:nodoc: include Clusivity def validate_each(record, attribute, value) diff --git a/activemodel/lib/active_model/validations/length.rb b/activemodel/lib/active_model/validations/length.rb index 64b4fe2d74..40ebe0cd2e 100644 --- a/activemodel/lib/active_model/validations/length.rb +++ b/activemodel/lib/active_model/validations/length.rb @@ -2,7 +2,7 @@ module ActiveModel # == Active Model Length Validator module Validations - class LengthValidator < EachValidator + class LengthValidator < EachValidator #:nodoc: MESSAGES = { :is => :wrong_length, :minimum => :too_short, :maximum => :too_long }.freeze CHECKS = { :is => :==, :minimum => :>=, :maximum => :<= }.freeze diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb index 40b5b92b84..1069ed3906 100644 --- a/activemodel/lib/active_model/validations/numericality.rb +++ b/activemodel/lib/active_model/validations/numericality.rb @@ -2,7 +2,7 @@ module ActiveModel # == Active Model Numericality Validator module Validations - class NumericalityValidator < EachValidator + class NumericalityValidator < EachValidator #:nodoc: CHECKS = { :greater_than => :>, :greater_than_or_equal_to => :>=, :equal_to => :==, :less_than => :<, :less_than_or_equal_to => :<=, :odd => :odd?, :even => :even?, :other_than => :!= }.freeze diff --git a/activemodel/lib/active_model/validations/presence.rb b/activemodel/lib/active_model/validations/presence.rb index 018ef1e733..a7dcdbba3d 100644 --- a/activemodel/lib/active_model/validations/presence.rb +++ b/activemodel/lib/active_model/validations/presence.rb @@ -4,7 +4,7 @@ module ActiveModel # == Active Model Presence Validator module Validations - class PresenceValidator < EachValidator + class PresenceValidator < EachValidator #:nodoc: def validate(record) record.errors.add_on_blank(attributes, options) end @@ -40,7 +40,7 @@ module ActiveModel # if the validation should not occur (e.g. <tt>:unless => :skip_validation</tt>, # or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The method, # proc or string should return or evaluate to a true or false value. - # * <tt>:strict</tt> - Specifies whether validation should be strict. + # * <tt>:strict</tt> - Specifies whether validation should be strict. # See <tt>ActiveModel::Validation#validates!</tt> for more information. def validates_presence_of(*attr_names) validates_with PresenceValidator, _merge_attributes(attr_names) diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb index 66cc9daa2c..3158f36b6e 100644 --- a/activemodel/lib/active_model/validations/with.rb +++ b/activemodel/lib/active_model/validations/with.rb @@ -8,7 +8,7 @@ module ActiveModel end end - class WithValidator < EachValidator + class WithValidator < EachValidator #:nodoc: def validate_each(record, attr, val) method_name = options[:with] @@ -61,7 +61,7 @@ module ActiveModel # (e.g. <tt>:unless => :skip_validation</tt>, or # <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). # The method, proc or string should return or evaluate to a true or false value. - # * <tt>:strict</tt> - Specifies whether validation should be strict. + # * <tt>:strict</tt> - Specifies whether validation should be strict. # See <tt>ActiveModel::Validation#validates!</tt> for more information. # # If you pass any additional configuration options, they will be passed diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index 8199b5c2e0..1dcd0a5a32 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -35,7 +35,7 @@ db_namespace = namespace :db do ActiveRecord::Tasks::DatabaseTasks.drop_current end - desc "Migrate the database (options: VERSION=x, VERBOSE=false)." + desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)." task :migrate => [:environment, :load_config] do ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, ENV["VERSION"] ? ENV["VERSION"].to_i : nil) do |migration| @@ -270,6 +270,15 @@ db_namespace = namespace :db do end namespace :structure do + def set_firebird_env(config) + ENV['ISC_USER'] = config['username'].to_s if config['username'] + ENV['ISC_PASSWORD'] = config['password'].to_s if config['password'] + end + + def firebird_db_string(config) + FireRuby::Database.db_string_for(config.symbolize_keys) + end + desc 'Dump the database structure to db/structure.sql. Specify another file with DB_STRUCTURE=db/my_structure.sql' task :dump => [:environment, :load_config] do abcs = ActiveRecord::Base.configurations @@ -338,6 +347,13 @@ db_namespace = namespace :db do end end + # desc "Recreate the test database from an existent schema.rb file" + task :load_schema => 'db:test:purge' do + ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test']) + ActiveRecord::Schema.verbose = false + db_namespace["schema:load"].invoke + end + # desc "Recreate the test database from an existent structure.sql file" task :load_structure => 'db:test:purge' do begin @@ -348,15 +364,18 @@ db_namespace = namespace :db do end end - # desc "Recreate the test database from an existent schema.rb file" - task :load_schema => 'db:test:purge' do - ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test']) - ActiveRecord::Schema.verbose = false - db_namespace["schema:load"].invoke + # desc "Recreate the test database from a fresh schema" + task :clone do + case ActiveRecord::Base.schema_format + when :ruby + db_namespace["test:clone_schema"].invoke + when :sql + db_namespace["test:clone_structure"].invoke + end end # desc "Recreate the test database from a fresh schema.rb file" - task :clone => %w(db:schema:dump db:test:load_schema) + task :clone_schema => ["db:schema:dump", "db:test:load_schema"] # desc "Recreate the test database from a fresh structure.sql file" task :clone_structure => [ "db:structure:dump", "db:test:load_structure" ] @@ -389,7 +408,7 @@ db_namespace = namespace :db do # desc 'Check for pending migrations and load the test schema' task :prepare => 'db:abort_if_pending_migrations' do unless ActiveRecord::Base.configurations.blank? - db_namespace[{ :sql => 'test:clone_structure', :ruby => 'test:load' }[ActiveRecord::Base.schema_format]].invoke + db_namespace['test:load'].invoke end end end @@ -405,7 +424,7 @@ db_namespace = namespace :db do # desc "Clear the sessions table" task :clear => [:environment, :load_config] do - ActiveRecord::Base.connection.execute "DELETE FROM #{session_table_name}" + ActiveRecord::Base.connection.execute "DELETE FROM #{ActiveRecord::SessionStore::Session.table_name}" end end end @@ -440,15 +459,3 @@ end task 'test:prepare' => 'db:test:prepare' -def session_table_name - ActiveRecord::SessionStore::Session.table_name -end - -def set_firebird_env(config) - ENV['ISC_USER'] = config['username'].to_s if config['username'] - ENV['ISC_PASSWORD'] = config['password'].to_s if config['password'] -end - -def firebird_db_string(config) - FireRuby::Database.db_string_for(config.symbolize_keys) -end diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index a1d74f3bfb..e40b958b54 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -265,9 +265,9 @@ module ActiveRecord group_attrs = group_values if group_attrs.first.respond_to?(:to_sym) - association = @klass.reflect_on_association(group_attrs.first.to_sym) - associated = group_attrs.size == 1 && association && association.macro == :belongs_to # only count belongs_to associations - group_fields = Array(associated ? association.foreign_key : group_attrs) + association = @klass.reflect_on_association(group_attrs.first.to_sym) + associated = group_attrs.size == 1 && association && association.macro == :belongs_to # only count belongs_to associations + group_fields = Array(associated ? association.foreign_key : group_attrs) else group_fields = group_attrs end @@ -313,10 +313,10 @@ module ActiveRecord end Hash[calculated_data.map do |row| - key = group_columns.map { |aliaz, column| + key = group_columns.map { |aliaz, column| type_cast_calculated_value(row[aliaz], column) } - key = key.first if key.size == 1 + key = key.first if key.size == 1 key = key_records[key] if associated [key, type_cast_calculated_value(row[aggregate_alias], column_for(column_name), operation)] end] @@ -343,7 +343,7 @@ module ActiveRecord end def column_for(field) - field_name = field.to_s.split('.').last + field_name = field.respond_to?(:name) ? field.name.to_s : field.to_s.split('.').last @klass.columns.detect { |c| c.name.to_s == field_name } end diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index b766b92007..e1c1e449ef 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -58,12 +58,16 @@ class CalculationsTest < ActiveRecord::TestCase def test_should_group_by_field c = Account.group(:firm_id).sum(:credit_limit) - [1,6,2].each { |firm_id| assert c.keys.include?(firm_id) } + [1,6,2].each do |firm_id| + assert c.keys.include?(firm_id), "Group #{c.inspect} does not contain firm_id #{firm_id}" + end end def test_should_group_by_arel_attribute - c = Account.sum(:credit_limit, :group => Account.arel_table[:firm_id]) - [1,6,2].each { |firm_id| assert c.keys.include?(firm_id) } + c = Account.group(Account.arel_table[:firm_id]).sum(:credit_limit) + [1,6,2].each do |firm_id| + assert c.keys.include?(firm_id), "Group #{c.inspect} does not contain firm_id #{firm_id}" + end end def test_should_group_by_multiple_fields diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 28c8b53b78..e8623a9c54 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -1,5 +1,6 @@ require 'active_support/duration' require 'active_support/core_ext/time/conversions' +require 'active_support/time_with_zone' class Time COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index e0ee349550..6bb50fea19 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -144,6 +144,24 @@ module ApplicationTests assert_no_match(/Errors running/, output) end + def test_db_test_clone_when_using_sql_format + add_to_config "config.active_record.schema_format = :sql" + output = Dir.chdir(app_path) do + `rails generate scaffold user username:string; + bundle exec rake db:migrate db:test:clone 2>&1 --trace` + end + assert_match(/Execute db:test:clone_structure/, output) + end + + def test_db_test_prepare_when_using_sql_format + add_to_config "config.active_record.schema_format = :sql" + output = Dir.chdir(app_path) do + `rails generate scaffold user username:string; + bundle exec rake db:migrate db:test:clone 2>&1 --trace` + end + assert_match(/Execute db:test:load_structure/, output) + end + def test_rake_dump_structure_should_respect_db_structure_env_variable Dir.chdir(app_path) do # ensure we have a schema_migrations table to dump |