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 +9 -7
- data/README.rdoc +9 -9
- data/lib/active_record/associations.rb +4 -4
- data/lib/active_record/associations/association_scope.rb +15 -5
- data/lib/active_record/associations/collection_association.rb +27 -22
- data/lib/active_record/associations/collection_proxy.rb +2 -8
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +8 -2
- data/lib/active_record/associations/has_many_association.rb +7 -2
- data/lib/active_record/associations/has_many_through_association.rb +9 -4
- data/lib/active_record/associations/join_dependency/join_association.rb +7 -3
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/attribute_methods/primary_key.rb +1 -1
- data/lib/active_record/base.rb +13 -5
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +1 -0
- data/lib/active_record/migration.rb +1 -1
- data/lib/active_record/migration/command_recorder.rb +3 -3
- data/lib/active_record/persistence.rb +6 -2
- data/lib/active_record/railtie.rb +2 -2
- data/lib/active_record/reflection.rb +4 -5
- data/lib/active_record/relation.rb +25 -18
- data/lib/active_record/relation/calculations.rb +2 -2
- data/lib/active_record/relation/query_methods.rb +7 -8
- data/lib/active_record/transactions.rb +1 -1
- data/lib/active_record/version.rb +1 -1
- metadata +46 -7
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
|
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]
|
data/README.rdoc
CHANGED
@@ -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
|
461
|
+
# Extensions can access relevant state using the following methods (where +items+ is the
|
462
462
|
# name of the association):
|
463
463
|
#
|
464
|
-
# *
|
465
|
-
# *
|
466
|
-
# *
|
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
|
-
|
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
|
-
|
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
|
95
|
-
scope = scope.where(sanitize(conditions
|
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
|
-
|
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!(
|
124
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
95
|
-
|
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
|
data/lib/active_record/base.rb
CHANGED
@@ -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
|
-
|
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
|
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
|
@@ -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
|
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
|
-
|
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 |
|
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
|
-
|
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,
|
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
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
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
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
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 =
|
423
|
-
default_scope
|
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
|
-
|
162
|
-
|
163
|
-
|
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/
|
168
|
+
# http://dev.mysql.com/doc/refman/5.0/en/savepoint.html
|
169
169
|
# for more information about savepoints.
|
170
170
|
#
|
171
171
|
# === Callbacks
|
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
|
-
|
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-
|
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
|
-
|
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
|
-
|
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.
|
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).
|