activerecord 3.1.0.rc1 → 3.1.0.rc2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

data/CHANGELOG CHANGED
@@ -1,5 +1,13 @@
1
1
  *Rails 3.1.0 (unreleased)*
2
2
 
3
+ * AR#pluralize_table_names can be used to singularize/pluralize table name of an individual model:
4
+
5
+ class User < ActiveRecord::Base
6
+ self.pluralize_table_names = false
7
+ end
8
+
9
+ Previously this could only be set globally for all models through ActiveRecord::Base.pluralize_table_names. [Guillermo Iguaran]
10
+
3
11
  * Add block setting of attributes to singular associations:
4
12
 
5
13
  class User < ActiveRecord::Base
@@ -229,19 +237,13 @@
229
237
  rails g model post user:belongs_to will generate the following:
230
238
 
231
239
  class CreatePosts < ActiveRecord::Migration
232
- def up
240
+ def change
233
241
  create_table :posts do |t|
234
242
  t.belongs_to :user
235
-
236
243
  t.timestamps
237
244
  end
238
-
239
245
  add_index :posts, :user_id
240
246
  end
241
-
242
- def down
243
- drop_table :posts
244
- end
245
247
  end
246
248
 
247
249
  [Santiago Pastorino]
@@ -3,7 +3,7 @@
3
3
  Active Record connects classes to relational database tables to establish an
4
4
  almost zero-configuration persistence layer for applications. The library
5
5
  provides a base class that, when subclassed, sets up a mapping between the new
6
- class and an existing table in the database. In context of an application,
6
+ class and an existing table in the database. In the context of an application,
7
7
  these classes are commonly referred to as *models*. Models can also be
8
8
  connected to other models; this is done by defining *associations*.
9
9
 
@@ -70,7 +70,7 @@ A short rundown of some of the major features:
70
70
  {Learn more}[link:classes/ActiveRecord/Validations.html]
71
71
 
72
72
 
73
- * Callbacks available for the entire life cycle (instantiation, saving, destroying, validating, etc.)
73
+ * Callbacks available for the entire life cycle (instantiation, saving, destroying, validating, etc.).
74
74
 
75
75
  class Person < ActiveRecord::Base
76
76
  before_destroy :invalidate_payment_plan
@@ -80,7 +80,7 @@ A short rundown of some of the major features:
80
80
  {Learn more}[link:classes/ActiveRecord/Callbacks.html]
81
81
 
82
82
 
83
- * Observers that react to changes in a model
83
+ * Observers that react to changes in a model.
84
84
 
85
85
  class CommentObserver < ActiveRecord::Observer
86
86
  def after_create(comment) # is called just after Comment#save
@@ -91,7 +91,7 @@ A short rundown of some of the major features:
91
91
  {Learn more}[link:classes/ActiveRecord/Observer.html]
92
92
 
93
93
 
94
- * Inheritance hierarchies
94
+ * Inheritance hierarchies.
95
95
 
96
96
  class Company < ActiveRecord::Base; end
97
97
  class Firm < Company; end
@@ -101,7 +101,7 @@ A short rundown of some of the major features:
101
101
  {Learn more}[link:classes/ActiveRecord/Base.html]
102
102
 
103
103
 
104
- * Transactions
104
+ * Transactions.
105
105
 
106
106
  # Database transaction
107
107
  Account.transaction do
@@ -112,7 +112,7 @@ A short rundown of some of the major features:
112
112
  {Learn more}[link:classes/ActiveRecord/Transactions/ClassMethods.html]
113
113
 
114
114
 
115
- * Reflections on columns, associations, and aggregations
115
+ * Reflections on columns, associations, and aggregations.
116
116
 
117
117
  reflection = Firm.reflect_on_association(:clients)
118
118
  reflection.klass # => Client (class)
@@ -121,7 +121,7 @@ A short rundown of some of the major features:
121
121
  {Learn more}[link:classes/ActiveRecord/Reflection/ClassMethods.html]
122
122
 
123
123
 
124
- * Database abstraction through simple adapters
124
+ * Database abstraction through simple adapters.
125
125
 
126
126
  # connect to SQLite3
127
127
  ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => "dbfile.sqlite3")
@@ -141,13 +141,13 @@ A short rundown of some of the major features:
141
141
  SQLite3[link:classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html].
142
142
 
143
143
 
144
- * Logging support for Log4r[http://log4r.sourceforge.net] and Logger[http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc]
144
+ * Logging support for Log4r[http://log4r.sourceforge.net] and Logger[http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc].
145
145
 
146
146
  ActiveRecord::Base.logger = Logger.new(STDOUT)
147
147
  ActiveRecord::Base.logger = Log4r::Logger.new("Application Log")
148
148
 
149
149
 
150
- * Database agnostic schema management with Migrations
150
+ * Database agnostic schema management with Migrations.
151
151
 
152
152
  class AddSystemSettings < ActiveRecord::Migration
153
153
  def self.up
@@ -458,12 +458,12 @@ module ActiveRecord
458
458
  # end
459
459
  #
460
460
  # Some extensions can only be made to work with knowledge of the association's internals.
461
- # Extensions can access relevant state using the following methods (where 'items' is the
461
+ # Extensions can access relevant state using the following methods (where +items+ is the
462
462
  # name of the association):
463
463
  #
464
- # * +record.association(:items).owner+ - Returns the object the association is part of.
465
- # * +record.association(:items).reflection+ - Returns the reflection object that describes the association.
466
- # * +record.association(:items).target+ - Returns the associated object for +belongs_to+ and +has_one+, or
464
+ # * <tt>record.association(:items).owner</tt> - Returns the object the association is part of.
465
+ # * <tt>record.association(:items).reflection</tt> - Returns the reflection object that describes the association.
466
+ # * <tt>record.association(:items).target</tt> - Returns the associated object for +belongs_to+ and +has_one+, or
467
467
  # the collection of associated objects for +has_many+ and +has_and_belongs_to_many+.
468
468
  #
469
469
  # === Association Join Models
@@ -75,10 +75,16 @@ module ActiveRecord
75
75
  foreign_key = reflection.active_record_primary_key
76
76
  end
77
77
 
78
+ conditions = self.conditions[i]
79
+
78
80
  if reflection == chain.last
79
81
  scope = scope.where(table[key].eq(owner[foreign_key]))
80
82
 
81
- conditions[i].each do |condition|
83
+ if reflection.type
84
+ scope = scope.where(table[reflection.type].eq(owner.class.base_class.name))
85
+ end
86
+
87
+ conditions.each do |condition|
82
88
  if options[:through] && condition.is_a?(Hash)
83
89
  condition = { table.name => condition }
84
90
  end
@@ -87,12 +93,16 @@ module ActiveRecord
87
93
  end
88
94
  else
89
95
  constraint = table[key].eq(foreign_table[foreign_key])
90
- join = join(foreign_table, constraint)
91
96
 
92
- scope = scope.joins(join)
97
+ if reflection.type
98
+ type = chain[i + 1].klass.base_class.name
99
+ constraint = constraint.and(table[reflection.type].eq(type))
100
+ end
101
+
102
+ scope = scope.joins(join(foreign_table, constraint))
93
103
 
94
- unless conditions[i].empty?
95
- scope = scope.where(sanitize(conditions[i], table))
104
+ unless conditions.empty?
105
+ scope = scope.where(sanitize(conditions, table))
96
106
  end
97
107
  end
98
108
  end
@@ -104,26 +104,11 @@ module ActiveRecord
104
104
  end
105
105
 
106
106
  def create(attributes = {}, options = {}, &block)
107
- unless owner.persisted?
108
- raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
109
- end
110
-
111
- if attributes.is_a?(Array)
112
- attributes.collect { |attr| create(attr, options, &block) }
113
- else
114
- transaction do
115
- add_to_target(build_record(attributes, options)) do |record|
116
- yield(record) if block_given?
117
- insert_record(record)
118
- end
119
- end
120
- end
107
+ create_record(attributes, options, &block)
121
108
  end
122
109
 
123
- def create!(attrs = {}, options = {}, &block)
124
- record = create(attrs, options, &block)
125
- Array.wrap(record).each(&:save!)
126
- record
110
+ def create!(attributes = {}, options = {}, &block)
111
+ create_record(attributes, options, true, &block)
127
112
  end
128
113
 
129
114
  # Add +records+ to this association. Returns +self+ so method calls may be chained.
@@ -402,9 +387,13 @@ module ActiveRecord
402
387
  return memory if persisted.empty?
403
388
 
404
389
  persisted.map! do |record|
405
- mem_record = memory.delete(record)
390
+ # Unfortunately we cannot simply do memory.delete(record) since on 1.8 this returns
391
+ # record rather than memory.at(memory.index(record)). The behaviour is fixed in 1.9.
392
+ mem_index = memory.index(record)
393
+
394
+ if mem_index
395
+ mem_record = memory.delete_at(mem_index)
406
396
 
407
- if mem_record
408
397
  (record.attribute_names - mem_record.changes.keys).each do |name|
409
398
  mem_record[name] = record[name]
410
399
  end
@@ -418,8 +407,25 @@ module ActiveRecord
418
407
  persisted + memory
419
408
  end
420
409
 
410
+ def create_record(attributes, options, raise = false, &block)
411
+ unless owner.persisted?
412
+ raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
413
+ end
414
+
415
+ if attributes.is_a?(Array)
416
+ attributes.collect { |attr| create_record(attr, options, raise, &block) }
417
+ else
418
+ transaction do
419
+ add_to_target(build_record(attributes, options)) do |record|
420
+ yield(record) if block_given?
421
+ insert_record(record, true, raise)
422
+ end
423
+ end
424
+ end
425
+ end
426
+
421
427
  # Do the relevant stuff to insert the given record into the association collection.
422
- def insert_record(record, validate = true)
428
+ def insert_record(record, validate = true, raise = false)
423
429
  raise NotImplementedError
424
430
  end
425
431
 
@@ -430,7 +436,6 @@ module ActiveRecord
430
436
  def build_record(attributes, options)
431
437
  record = reflection.build_association(attributes, options)
432
438
  record.assign_attributes(create_scope.except(*record.changed), :without_protection => true)
433
- record.assign_attributes(attributes, options)
434
439
  record
435
440
  end
436
441
 
@@ -56,6 +56,8 @@ module ActiveRecord
56
56
  Array.wrap(association.options[:extend]).each { |ext| proxy_extend(ext) }
57
57
  end
58
58
 
59
+ alias_method :new, :build
60
+
59
61
  def respond_to?(*args)
60
62
  super ||
61
63
  (load_target && target.respond_to?(*args)) ||
@@ -116,14 +118,6 @@ module ActiveRecord
116
118
  self
117
119
  end
118
120
 
119
- def new(*args, &block)
120
- if @association.is_a?(HasManyThroughAssociation)
121
- @association.build(*args, &block)
122
- else
123
- method_missing(:new, *args, &block)
124
- end
125
- end
126
-
127
121
  def proxy_owner
128
122
  ActiveSupport::Deprecation.warn(
129
123
  "Calling record.#{@association.reflection.name}.proxy_owner is deprecated. Please use " \
@@ -9,8 +9,14 @@ module ActiveRecord
9
9
  super
10
10
  end
11
11
 
12
- def insert_record(record, validate = true)
13
- return if record.new_record? && !record.save(:validate => validate)
12
+ def insert_record(record, validate = true, raise = false)
13
+ if record.new_record?
14
+ if raise
15
+ record.save!(:validate => validate)
16
+ else
17
+ return unless record.save(:validate => validate)
18
+ end
19
+ end
14
20
 
15
21
  if options[:insert_sql]
16
22
  owner.connection.insert(interpolate(options[:insert_sql], record))
@@ -7,9 +7,14 @@ module ActiveRecord
7
7
  # is provided by its child HasManyThroughAssociation.
8
8
  class HasManyAssociation < CollectionAssociation #:nodoc:
9
9
 
10
- def insert_record(record, validate = true)
10
+ def insert_record(record, validate = true, raise = false)
11
11
  set_owner_attributes(record)
12
- record.save(:validate => validate)
12
+
13
+ if raise
14
+ record.save!(:validate => validate)
15
+ else
16
+ record.save(:validate => validate)
17
+ end
13
18
  end
14
19
 
15
20
  private
@@ -6,8 +6,6 @@ module ActiveRecord
6
6
  class HasManyThroughAssociation < HasManyAssociation #:nodoc:
7
7
  include ThroughAssociation
8
8
 
9
- alias_method :new, :build
10
-
11
9
  # Returns the size of the collection by executing a SELECT COUNT(*) query if the collection hasn't been
12
10
  # loaded and calling collection.size if it has. If it's more likely than not that the collection does
13
11
  # have a size larger than zero, and you need to fetch that collection afterwards, it'll take one fewer
@@ -33,9 +31,16 @@ module ActiveRecord
33
31
  super
34
32
  end
35
33
 
36
- def insert_record(record, validate = true)
34
+ def insert_record(record, validate = true, raise = false)
37
35
  ensure_not_nested
38
- return if record.new_record? && !record.save(:validate => validate)
36
+
37
+ if record.new_record?
38
+ if raise
39
+ record.save!(:validate => validate)
40
+ else
41
+ return unless record.save(:validate => validate)
42
+ end
43
+ end
39
44
 
40
45
  through_record(record).save!
41
46
  update_counter(1)
@@ -62,6 +62,7 @@ module ActiveRecord
62
62
  def join_to(relation)
63
63
  tables = @tables.dup
64
64
  foreign_table = parent_table
65
+ foreign_klass = parent.active_record
65
66
 
66
67
  # The chain starts with the target table, but we want to end with it here (makes
67
68
  # more sense in this context), so we reverse
@@ -91,14 +92,17 @@ module ActiveRecord
91
92
 
92
93
  constraint = build_constraint(reflection, table, key, foreign_table, foreign_key)
93
94
 
94
- unless conditions[i].empty?
95
- constraint = constraint.and(sanitize(conditions[i], table))
95
+ conditions = self.conditions[i].dup
96
+ conditions << { reflection.type => foreign_klass.base_class.name } if reflection.type
97
+
98
+ unless conditions.empty?
99
+ constraint = constraint.and(sanitize(conditions, table))
96
100
  end
97
101
 
98
102
  relation.from(join(table, constraint))
99
103
 
100
104
  # The current table in this iteration becomes the foreign table in the next
101
- foreign_table = table
105
+ foreign_table, foreign_klass = table, reflection.klass
102
106
  end
103
107
 
104
108
  relation
@@ -16,7 +16,7 @@ module ActiveRecord
16
16
  chain[1..-1].each do |reflection|
17
17
  scope = scope.merge(
18
18
  reflection.klass.scoped.with_default_scope.
19
- except(:select, :create_with)
19
+ except(:select, :create_with, :includes)
20
20
  )
21
21
  end
22
22
  scope
@@ -48,7 +48,7 @@ module ActiveRecord
48
48
  end
49
49
 
50
50
  attr_accessor :original_primary_key
51
-
51
+
52
52
  # Attribute writer for the primary key column
53
53
  def primary_key=(value)
54
54
  @quoted_primary_key = nil
@@ -428,6 +428,10 @@ module ActiveRecord #:nodoc:
428
428
  class_attribute :default_scopes, :instance_writer => false
429
429
  self.default_scopes = []
430
430
 
431
+ # Boolean flag to prevent infinite recursion when evaluating default scopes
432
+ class_attribute :apply_default_scope, :instance_writer => false
433
+ self.apply_default_scope = true
434
+
431
435
  # Returns a hash of all the attributes that have been specified for serialization as
432
436
  # keys and their class restriction as values.
433
437
  class_attribute :serialized_attributes
@@ -1261,11 +1265,14 @@ MSG
1261
1265
  self.default_scopes = default_scopes + [scope]
1262
1266
  end
1263
1267
 
1268
+ # The apply_default_scope flag is used to prevent an infinite recursion situation where
1269
+ # a default scope references a scope which has a default scope which references a scope...
1264
1270
  def build_default_scope #:nodoc:
1271
+ return unless apply_default_scope
1272
+ self.apply_default_scope = false
1273
+
1265
1274
  if method(:default_scope).owner != Base.singleton_class
1266
- # Use relation.scoping to ensure we ignore whatever the current value of
1267
- # self.current_scope may be.
1268
- relation.scoping { default_scope }
1275
+ default_scope
1269
1276
  elsif default_scopes.any?
1270
1277
  default_scopes.inject(relation) do |default_scope, scope|
1271
1278
  if scope.is_a?(Hash)
@@ -1277,6 +1284,8 @@ MSG
1277
1284
  end
1278
1285
  end
1279
1286
  end
1287
+ ensure
1288
+ self.apply_default_scope = true
1280
1289
  end
1281
1290
 
1282
1291
  # Returns the class type of the record using the current module as a prefix. So descendants of
@@ -1299,7 +1308,6 @@ MSG
1299
1308
  rescue NameError => e
1300
1309
  # We don't want to swallow NoMethodError < NameError errors
1301
1310
  raise e unless e.instance_of?(NameError)
1302
- rescue ArgumentError
1303
1311
  end
1304
1312
  end
1305
1313
 
@@ -1666,7 +1674,7 @@ MSG
1666
1674
  # user.is_admin? # => false
1667
1675
  def attributes=(new_attributes, guard_protected_attributes = nil)
1668
1676
  unless guard_protected_attributes.nil?
1669
- message = "the use of 'guard_protected_attributes' will be removed from the next major release of rails, " +
1677
+ message = "the use of 'guard_protected_attributes' will be removed from the next minor release of rails, " +
1670
1678
  "if you want to bypass mass-assignment security then look into using assign_attributes"
1671
1679
  ActiveSupport::Deprecation.warn(message)
1672
1680
  end
@@ -103,6 +103,7 @@ module ActiveRecord
103
103
 
104
104
  # Clears the prepared statements cache.
105
105
  def clear_cache!
106
+ @statements.values.each { |hash| hash[:stmt].close }
106
107
  @statements.clear
107
108
  end
108
109
 
@@ -53,7 +53,7 @@ module ActiveRecord
53
53
  #
54
54
  # This migration will add a boolean flag to the accounts table and remove it
55
55
  # if you're backing out of the migration. It shows how all migrations have
56
- # two class methods +up+ and +down+ that describes the transformations
56
+ # two methods +up+ and +down+ that describes the transformations
57
57
  # required to implement or remove the migration. These methods can consist
58
58
  # of both the migration specific methods like add_column and remove_column,
59
59
  # but may also contain regular Ruby code for generating data needed for the
@@ -50,9 +50,9 @@ module ActiveRecord
50
50
 
51
51
  [:create_table, :rename_table, :add_column, :remove_column, :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps, :change_column, :change_column_default].each do |method|
52
52
  class_eval <<-EOV, __FILE__, __LINE__ + 1
53
- def #{method}(*args)
54
- record(:"#{method}", args)
55
- end
53
+ def #{method}(*args) # def create_table(*args)
54
+ record(:"#{method}", args) # record(:create_table, args)
55
+ end # end
56
56
  EOV
57
57
  end
58
58
 
@@ -33,7 +33,11 @@ module ActiveRecord
33
33
  # +save+ returns +false+. See ActiveRecord::Callbacks for further
34
34
  # details.
35
35
  def save(*)
36
- create_or_update
36
+ begin
37
+ create_or_update
38
+ rescue ActiveRecord::RecordInvalid
39
+ false
40
+ end
37
41
  end
38
42
 
39
43
  # Saves the model.
@@ -273,7 +277,7 @@ module ActiveRecord
273
277
 
274
278
  @changed_attributes.except!(*changes.keys)
275
279
  primary_key = self.class.primary_key
276
- self.class.update_all(changes, { primary_key => self[primary_key] }) == 1
280
+ self.class.unscoped.update_all(changes, { primary_key => self[primary_key] }) == 1
277
281
  end
278
282
  end
279
283
 
@@ -29,8 +29,8 @@ module ActiveRecord
29
29
  # When loading console, force ActiveRecord::Base to be loaded
30
30
  # to avoid cross references when loading a constant for the
31
31
  # first time. Also, make it output to STDERR.
32
- console do |sandbox|
33
- require "active_record/railties/console_sandbox" if sandbox
32
+ console do |app|
33
+ require "active_record/railties/console_sandbox" if app.sandbox?
34
34
  ActiveRecord::Base.logger = Logger.new(STDERR)
35
35
  end
36
36
 
@@ -212,7 +212,7 @@ module ActiveRecord
212
212
  end
213
213
 
214
214
  def type
215
- @type ||= "#{options[:as]}_type"
215
+ @type ||= options[:as] && "#{options[:as]}_type"
216
216
  end
217
217
 
218
218
  def primary_key_column
@@ -280,9 +280,7 @@ module ActiveRecord
280
280
  # in the #chain. The inside arrays are simply conditions (and each condition may itself be
281
281
  # a hash, array, arel predicate, etc...)
282
282
  def conditions
283
- conditions = [options[:conditions]].compact
284
- conditions << { type => active_record.base_class.name } if options[:as]
285
- [conditions]
283
+ [[options[:conditions]].compact]
286
284
  end
287
285
 
288
286
  alias :source_macro :macro
@@ -378,7 +376,8 @@ module ActiveRecord
378
376
  # Holds all the meta-data about a :through association as it was specified
379
377
  # in the Active Record class.
380
378
  class ThroughReflection < AssociationReflection #:nodoc:
381
- delegate :foreign_key, :foreign_type, :association_foreign_key, :active_record_primary_key, :to => :source_reflection
379
+ delegate :foreign_key, :foreign_type, :association_foreign_key,
380
+ :active_record_primary_key, :type, :to => :source_reflection
382
381
 
383
382
  # Gets the source of the through reflection. It checks both a singularized
384
383
  # and pluralized form for <tt>:belongs_to</tt> or <tt>:has_many</tt>.
@@ -6,7 +6,7 @@ module ActiveRecord
6
6
  JoinOperation = Struct.new(:relation, :join_class, :on)
7
7
  ASSOCIATION_METHODS = [:includes, :eager_load, :preload]
8
8
  MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind]
9
- SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :create_with, :from, :reorder]
9
+ SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :create_with, :from, :reorder, :reverse_order]
10
10
 
11
11
  include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches
12
12
 
@@ -102,24 +102,30 @@ module ActiveRecord
102
102
  def to_a
103
103
  return @records if loaded?
104
104
 
105
- @records = if @readonly_value.nil? && !@klass.locking_enabled?
106
- eager_loading? ? find_with_associations : @klass.find_by_sql(arel.to_sql, @bind_values)
107
- else
108
- IdentityMap.without do
105
+ default_scoped = with_default_scope
106
+
107
+ if default_scoped.equal?(self)
108
+ @records = if @readonly_value.nil? && !@klass.locking_enabled?
109
109
  eager_loading? ? find_with_associations : @klass.find_by_sql(arel.to_sql, @bind_values)
110
+ else
111
+ IdentityMap.without do
112
+ eager_loading? ? find_with_associations : @klass.find_by_sql(arel.to_sql, @bind_values)
113
+ end
110
114
  end
111
- end
112
115
 
113
- preload = @preload_values
114
- preload += @includes_values unless eager_loading?
115
- preload.each do |associations|
116
- ActiveRecord::Associations::Preloader.new(@records, associations).run
117
- end
116
+ preload = @preload_values
117
+ preload += @includes_values unless eager_loading?
118
+ preload.each do |associations|
119
+ ActiveRecord::Associations::Preloader.new(@records, associations).run
120
+ end
118
121
 
119
- # @readonly_value is true only if set explicitly. @implicit_readonly is true if there
120
- # are JOINS and no explicit SELECT.
121
- readonly = @readonly_value.nil? ? @implicit_readonly : @readonly_value
122
- @records.each { |record| record.readonly! } if readonly
122
+ # @readonly_value is true only if set explicitly. @implicit_readonly is true if there
123
+ # are JOINS and no explicit SELECT.
124
+ readonly = @readonly_value.nil? ? @implicit_readonly : @readonly_value
125
+ @records.each { |record| record.readonly! } if readonly
126
+ else
127
+ @records = default_scoped.to_a
128
+ end
123
129
 
124
130
  @loaded = true
125
131
  @records
@@ -418,9 +424,10 @@ module ActiveRecord
418
424
  end
419
425
 
420
426
  def with_default_scope #:nodoc:
421
- if default_scoped?
422
- default_scope = @klass.send(:build_default_scope)
423
- default_scope ? default_scope.merge(self) : self
427
+ if default_scoped? && default_scope = klass.send(:build_default_scope)
428
+ default_scope = default_scope.merge(self)
429
+ default_scope.default_scoped = false
430
+ default_scope
424
431
  else
425
432
  self
426
433
  end
@@ -196,7 +196,7 @@ module ActiveRecord
196
196
 
197
197
  def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
198
198
  # Postgresql doesn't like ORDER BY when there are no GROUP BY
199
- relation = reorder(nil)
199
+ relation = with_default_scope.reorder(nil)
200
200
 
201
201
  if operation == "count" && (relation.limit_value || relation.offset_value)
202
202
  # Shortcut when limit is zero.
@@ -245,7 +245,7 @@ module ActiveRecord
245
245
  "#{field} AS #{aliaz}"
246
246
  }
247
247
 
248
- relation = except(:group).group(group.join(','))
248
+ relation = with_default_scope.except(:group).group(group.join(','))
249
249
  relation.select_values = select_values
250
250
 
251
251
  calculated_data = @klass.connection.select_all(relation.to_sql)
@@ -9,7 +9,7 @@ module ActiveRecord
9
9
  :select_values, :group_values, :order_values, :joins_values,
10
10
  :where_values, :having_values, :bind_values,
11
11
  :limit_value, :offset_value, :lock_value, :readonly_value, :create_with_value,
12
- :from_value, :reorder_value
12
+ :from_value, :reorder_value, :reverse_order_value
13
13
 
14
14
  def includes(*args)
15
15
  args.reject! {|a| a.blank? }
@@ -158,13 +158,9 @@ module ActiveRecord
158
158
  end
159
159
 
160
160
  def reverse_order
161
- order_clause = arel.order_clauses
162
-
163
- order = order_clause.empty? ?
164
- "#{table_name}.#{primary_key} DESC" :
165
- reverse_sql_order(order_clause).join(', ')
166
-
167
- except(:order).order(Arel.sql(order))
161
+ relation = clone
162
+ relation.reverse_order_value = !relation.reverse_order_value
163
+ relation
168
164
  end
169
165
 
170
166
  def arel
@@ -186,6 +182,7 @@ module ActiveRecord
186
182
  arel.group(*@group_values.uniq.reject{|g| g.blank?}) unless @group_values.empty?
187
183
 
188
184
  order = @reorder_value ? @reorder_value : @order_values
185
+ order = reverse_sql_order(order) if @reverse_order_value
189
186
  arel.order(*order.uniq.reject{|o| o.blank?}) unless order.empty?
190
187
 
191
188
  build_select(arel, @select_values.uniq)
@@ -306,6 +303,8 @@ module ActiveRecord
306
303
  end
307
304
 
308
305
  def reverse_sql_order(order_query)
306
+ order_query = ["#{quoted_table_name}.#{quoted_primary_key} ASC"] if order_query.empty?
307
+
309
308
  order_query.join(', ').split(',').collect do |s|
310
309
  s.gsub!(/\sasc\Z/i, ' DESC') || s.gsub!(/\sdesc\Z/i, ' ASC') || s.concat(' DESC')
311
310
  end
@@ -165,7 +165,7 @@ module ActiveRecord
165
165
  # writing, the only database that we're aware of that supports true nested
166
166
  # transactions, is MS-SQL. Because of this, Active Record emulates nested
167
167
  # transactions by using savepoints on MySQL and PostgreSQL. See
168
- # http://dev.mysql.com/doc/refman/5.0/en/savepoints.html
168
+ # http://dev.mysql.com/doc/refman/5.0/en/savepoint.html
169
169
  # for more information about savepoints.
170
170
  #
171
171
  # === Callbacks
@@ -3,7 +3,7 @@ module ActiveRecord
3
3
  MAJOR = 3
4
4
  MINOR = 1
5
5
  TINY = 0
6
- PRE = "rc1"
6
+ PRE = "rc2"
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
9
9
  end
metadata CHANGED
@@ -1,8 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 15424097
4
5
  prerelease: 6
5
- version: 3.1.0.rc1
6
+ segments:
7
+ - 3
8
+ - 1
9
+ - 0
10
+ - rc
11
+ - 2
12
+ version: 3.1.0.rc2
6
13
  platform: ruby
7
14
  authors:
8
15
  - David Heinemeier Hansson
@@ -10,8 +17,7 @@ autorequire:
10
17
  bindir: bin
11
18
  cert_chain: []
12
19
 
13
- date: 2011-05-21 00:00:00 -05:00
14
- default_executable:
20
+ date: 2011-06-07 00:00:00 Z
15
21
  dependencies:
16
22
  - !ruby/object:Gem::Dependency
17
23
  name: activesupport
@@ -21,7 +27,14 @@ dependencies:
21
27
  requirements:
22
28
  - - "="
23
29
  - !ruby/object:Gem::Version
24
- version: 3.1.0.rc1
30
+ hash: 15424097
31
+ segments:
32
+ - 3
33
+ - 1
34
+ - 0
35
+ - rc
36
+ - 2
37
+ version: 3.1.0.rc2
25
38
  type: :runtime
26
39
  version_requirements: *id001
27
40
  - !ruby/object:Gem::Dependency
@@ -32,7 +45,14 @@ dependencies:
32
45
  requirements:
33
46
  - - "="
34
47
  - !ruby/object:Gem::Version
35
- version: 3.1.0.rc1
48
+ hash: 15424097
49
+ segments:
50
+ - 3
51
+ - 1
52
+ - 0
53
+ - rc
54
+ - 2
55
+ version: 3.1.0.rc2
36
56
  type: :runtime
37
57
  version_requirements: *id002
38
58
  - !ruby/object:Gem::Dependency
@@ -43,6 +63,11 @@ dependencies:
43
63
  requirements:
44
64
  - - ~>
45
65
  - !ruby/object:Gem::Version
66
+ hash: 9
67
+ segments:
68
+ - 2
69
+ - 1
70
+ - 1
46
71
  version: 2.1.1
47
72
  type: :runtime
48
73
  version_requirements: *id003
@@ -54,6 +79,11 @@ dependencies:
54
79
  requirements:
55
80
  - - ~>
56
81
  - !ruby/object:Gem::Version
82
+ hash: 37
83
+ segments:
84
+ - 0
85
+ - 3
86
+ - 27
57
87
  version: 0.3.27
58
88
  type: :runtime
59
89
  version_requirements: *id004
@@ -193,7 +223,6 @@ files:
193
223
  - lib/rails/generators/active_record/session_migration/session_migration_generator.rb
194
224
  - lib/rails/generators/active_record/session_migration/templates/migration.rb
195
225
  - lib/rails/generators/active_record.rb
196
- has_rdoc: true
197
226
  homepage: http://www.rubyonrails.org
198
227
  licenses: []
199
228
 
@@ -208,17 +237,27 @@ required_ruby_version: !ruby/object:Gem::Requirement
208
237
  requirements:
209
238
  - - ">="
210
239
  - !ruby/object:Gem::Version
240
+ hash: 57
241
+ segments:
242
+ - 1
243
+ - 8
244
+ - 7
211
245
  version: 1.8.7
212
246
  required_rubygems_version: !ruby/object:Gem::Requirement
213
247
  none: false
214
248
  requirements:
215
249
  - - ">"
216
250
  - !ruby/object:Gem::Version
251
+ hash: 25
252
+ segments:
253
+ - 1
254
+ - 3
255
+ - 1
217
256
  version: 1.3.1
218
257
  requirements: []
219
258
 
220
259
  rubyforge_project:
221
- rubygems_version: 1.6.2
260
+ rubygems_version: 1.8.2
222
261
  signing_key:
223
262
  specification_version: 3
224
263
  summary: Object-relational mapper framework (part of Rails).