activerecord 3.0.20 → 3.1.0.beta1
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 +220 -91
- data/README.rdoc +3 -3
- data/examples/performance.rb +88 -109
- data/lib/active_record.rb +6 -2
- data/lib/active_record/aggregations.rb +22 -45
- data/lib/active_record/associations.rb +264 -991
- data/lib/active_record/associations/alias_tracker.rb +85 -0
- data/lib/active_record/associations/association.rb +231 -0
- data/lib/active_record/associations/association_scope.rb +120 -0
- data/lib/active_record/associations/belongs_to_association.rb +40 -60
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +15 -63
- data/lib/active_record/associations/builder/association.rb +53 -0
- data/lib/active_record/associations/builder/belongs_to.rb +85 -0
- data/lib/active_record/associations/builder/collection_association.rb +75 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +63 -0
- data/lib/active_record/associations/builder/has_many.rb +65 -0
- data/lib/active_record/associations/builder/has_one.rb +63 -0
- data/lib/active_record/associations/builder/singular_association.rb +32 -0
- data/lib/active_record/associations/collection_association.rb +524 -0
- data/lib/active_record/associations/collection_proxy.rb +125 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +27 -118
- data/lib/active_record/associations/has_many_association.rb +50 -79
- data/lib/active_record/associations/has_many_through_association.rb +98 -67
- data/lib/active_record/associations/has_one_association.rb +45 -115
- data/lib/active_record/associations/has_one_through_association.rb +21 -25
- data/lib/active_record/associations/join_dependency.rb +215 -0
- data/lib/active_record/associations/join_dependency/join_association.rb +150 -0
- data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
- data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
- data/lib/active_record/associations/join_helper.rb +56 -0
- data/lib/active_record/associations/preloader.rb +177 -0
- data/lib/active_record/associations/preloader/association.rb +126 -0
- data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
- data/lib/active_record/associations/preloader/collection_association.rb +24 -0
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
- data/lib/active_record/associations/preloader/has_many.rb +17 -0
- data/lib/active_record/associations/preloader/has_many_through.rb +15 -0
- data/lib/active_record/associations/preloader/has_one.rb +23 -0
- data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
- data/lib/active_record/associations/preloader/singular_association.rb +21 -0
- data/lib/active_record/associations/preloader/through_association.rb +67 -0
- data/lib/active_record/associations/singular_association.rb +55 -0
- data/lib/active_record/associations/through_association.rb +80 -0
- data/lib/active_record/attribute_methods.rb +19 -5
- data/lib/active_record/attribute_methods/before_type_cast.rb +9 -8
- data/lib/active_record/attribute_methods/dirty.rb +8 -2
- data/lib/active_record/attribute_methods/primary_key.rb +33 -13
- data/lib/active_record/attribute_methods/read.rb +17 -17
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -4
- data/lib/active_record/attribute_methods/write.rb +2 -1
- data/lib/active_record/autosave_association.rb +66 -45
- data/lib/active_record/base.rb +445 -273
- data/lib/active_record/callbacks.rb +24 -33
- data/lib/active_record/coders/yaml_column.rb +41 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +106 -13
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +16 -2
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +12 -11
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +83 -12
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +16 -16
- data/lib/active_record/connection_adapters/abstract/quoting.rb +61 -22
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +16 -273
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +80 -42
- data/lib/active_record/connection_adapters/abstract_adapter.rb +44 -25
- data/lib/active_record/connection_adapters/column.rb +268 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +686 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +331 -88
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +295 -267
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +3 -7
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +108 -26
- data/lib/active_record/counter_cache.rb +7 -4
- data/lib/active_record/fixtures.rb +174 -192
- data/lib/active_record/identity_map.rb +131 -0
- data/lib/active_record/locking/optimistic.rb +20 -14
- data/lib/active_record/locking/pessimistic.rb +4 -4
- data/lib/active_record/log_subscriber.rb +24 -4
- data/lib/active_record/migration.rb +265 -144
- data/lib/active_record/migration/command_recorder.rb +103 -0
- data/lib/active_record/named_scope.rb +68 -25
- data/lib/active_record/nested_attributes.rb +58 -15
- data/lib/active_record/observer.rb +3 -7
- data/lib/active_record/persistence.rb +58 -38
- data/lib/active_record/query_cache.rb +25 -3
- data/lib/active_record/railtie.rb +21 -12
- data/lib/active_record/railties/console_sandbox.rb +6 -0
- data/lib/active_record/railties/databases.rake +147 -116
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/reflection.rb +176 -44
- data/lib/active_record/relation.rb +125 -49
- data/lib/active_record/relation/batches.rb +7 -5
- data/lib/active_record/relation/calculations.rb +50 -18
- data/lib/active_record/relation/finder_methods.rb +47 -26
- data/lib/active_record/relation/predicate_builder.rb +24 -21
- data/lib/active_record/relation/query_methods.rb +117 -101
- data/lib/active_record/relation/spawn_methods.rb +27 -20
- data/lib/active_record/result.rb +34 -0
- data/lib/active_record/schema.rb +5 -6
- data/lib/active_record/schema_dumper.rb +11 -13
- data/lib/active_record/serialization.rb +2 -2
- data/lib/active_record/serializers/xml_serializer.rb +10 -10
- data/lib/active_record/session_store.rb +8 -2
- data/lib/active_record/test_case.rb +9 -20
- data/lib/active_record/timestamp.rb +21 -9
- data/lib/active_record/transactions.rb +16 -15
- data/lib/active_record/validations.rb +21 -22
- data/lib/active_record/validations/associated.rb +3 -1
- data/lib/active_record/validations/uniqueness.rb +48 -58
- data/lib/active_record/version.rb +3 -3
- data/lib/rails/generators/active_record.rb +6 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +10 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +2 -1
- data/lib/rails/generators/active_record/model/templates/migration.rb +6 -5
- data/lib/rails/generators/active_record/model/templates/model.rb +2 -0
- data/lib/rails/generators/active_record/model/templates/module.rb +2 -0
- data/lib/rails/generators/active_record/observer/templates/observer.rb +2 -0
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +2 -1
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +2 -2
- metadata +106 -77
- checksums.yaml +0 -7
- data/lib/active_record/association_preload.rb +0 -431
- data/lib/active_record/associations/association_collection.rb +0 -572
- data/lib/active_record/associations/association_proxy.rb +0 -304
- data/lib/active_record/associations/through_association_scope.rb +0 -160
@@ -3,10 +3,13 @@ require 'active_support/core_ext/object/blank'
|
|
3
3
|
module ActiveRecord
|
4
4
|
module SpawnMethods
|
5
5
|
def merge(r)
|
6
|
-
|
7
|
-
return merged_relation unless r
|
6
|
+
return self unless r
|
8
7
|
return to_a & r if r.is_a?(Array)
|
9
8
|
|
9
|
+
merged_relation = clone
|
10
|
+
|
11
|
+
r = r.with_default_scope if r.default_scoped? && r.klass != klass
|
12
|
+
|
10
13
|
Relation::ASSOCIATION_METHODS.each do |method|
|
11
14
|
value = r.send(:"#{method}_values")
|
12
15
|
|
@@ -19,21 +22,12 @@ module ActiveRecord
|
|
19
22
|
end
|
20
23
|
end
|
21
24
|
|
22
|
-
(Relation::MULTI_VALUE_METHODS - [:joins, :where
|
25
|
+
(Relation::MULTI_VALUE_METHODS - [:joins, :where]).each do |method|
|
23
26
|
value = r.send(:"#{method}_values")
|
24
27
|
merged_relation.send(:"#{method}_values=", merged_relation.send(:"#{method}_values") + value) if value.present?
|
25
28
|
end
|
26
29
|
|
27
|
-
|
28
|
-
if order_value.present?
|
29
|
-
if r.reorder_flag
|
30
|
-
merged_relation.order_values = order_value
|
31
|
-
else
|
32
|
-
merged_relation.order_values = merged_relation.order_values + order_value
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
merged_relation = merged_relation.joins(r.joins_values)
|
30
|
+
merged_relation.joins_values += r.joins_values
|
37
31
|
|
38
32
|
merged_wheres = @where_values + r.where_values
|
39
33
|
|
@@ -54,26 +48,31 @@ module ActiveRecord
|
|
54
48
|
|
55
49
|
merged_relation.where_values = merged_wheres
|
56
50
|
|
57
|
-
Relation::SINGLE_VALUE_METHODS
|
51
|
+
(Relation::SINGLE_VALUE_METHODS - [:lock, :create_with]).each do |method|
|
58
52
|
value = r.send(:"#{method}_value")
|
59
53
|
merged_relation.send(:"#{method}_value=", value) unless value.nil?
|
60
54
|
end
|
61
55
|
|
62
56
|
merged_relation.lock_value = r.lock_value unless merged_relation.lock_value
|
63
57
|
|
58
|
+
merged_relation = merged_relation.create_with(r.create_with_value) if r.create_with_value
|
59
|
+
|
64
60
|
# Apply scope extension modules
|
65
61
|
merged_relation.send :apply_modules, r.extensions
|
66
62
|
|
67
63
|
merged_relation
|
68
64
|
end
|
69
65
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
66
|
+
# Removes from the query the condition(s) specified in +skips+.
|
67
|
+
#
|
68
|
+
# Example:
|
69
|
+
#
|
70
|
+
# Post.order('id asc').except(:order) # discards the order condition
|
71
|
+
# Post.where('id > 10').order('id asc').except(:where) # discards the where condition but keeps the order
|
72
|
+
#
|
75
73
|
def except(*skips)
|
76
74
|
result = self.class.new(@klass, table)
|
75
|
+
result.default_scoped = default_scoped
|
77
76
|
|
78
77
|
((Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS) - skips).each do |method|
|
79
78
|
result.send(:"#{method}_values=", send(:"#{method}_values"))
|
@@ -89,8 +88,16 @@ module ActiveRecord
|
|
89
88
|
result
|
90
89
|
end
|
91
90
|
|
91
|
+
# Removes any condition from the query other than the one(s) specified in +onlies+.
|
92
|
+
#
|
93
|
+
# Example:
|
94
|
+
#
|
95
|
+
# Post.order('id asc').only(:where) # discards the order condition
|
96
|
+
# Post.order('id asc').only(:where, :order) # uses the specified order
|
97
|
+
#
|
92
98
|
def only(*onlies)
|
93
99
|
result = self.class.new(@klass, table)
|
100
|
+
result.default_scoped = default_scoped
|
94
101
|
|
95
102
|
((Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS) & onlies).each do |method|
|
96
103
|
result.send(:"#{method}_values=", send(:"#{method}_values"))
|
@@ -115,7 +122,7 @@ module ActiveRecord
|
|
115
122
|
|
116
123
|
options.assert_valid_keys(VALID_FIND_OPTIONS)
|
117
124
|
finders = options.dup
|
118
|
-
finders.delete_if { |key, value| value.nil? }
|
125
|
+
finders.delete_if { |key, value| value.nil? && key != :limit }
|
119
126
|
|
120
127
|
([:joins, :select, :group, :order, :having, :limit, :offset, :from, :lock, :readonly] & finders.keys).each do |finder|
|
121
128
|
relation = relation.send(finder, finders[finder])
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
###
|
3
|
+
# This class encapsulates a Result returned from calling +exec_query+ on any
|
4
|
+
# database connection adapter. For example:
|
5
|
+
#
|
6
|
+
# x = ActiveRecord::Base.connection.exec_query('SELECT * FROM foo')
|
7
|
+
# x # => #<ActiveRecord::Result:0xdeadbeef>
|
8
|
+
class Result
|
9
|
+
include Enumerable
|
10
|
+
|
11
|
+
attr_reader :columns, :rows
|
12
|
+
|
13
|
+
def initialize(columns, rows)
|
14
|
+
@columns = columns
|
15
|
+
@rows = rows
|
16
|
+
@hash_rows = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def each
|
20
|
+
hash_rows.each { |row| yield row }
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_hash
|
24
|
+
hash_rows
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def hash_rows
|
29
|
+
@hash_rows ||= @rows.map { |row|
|
30
|
+
Hash[@columns.zip(row)]
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/active_record/schema.rb
CHANGED
@@ -30,10 +30,8 @@ module ActiveRecord
|
|
30
30
|
# ActiveRecord::Schema is only supported by database adapters that also
|
31
31
|
# support migrations, the two features being very similar.
|
32
32
|
class Schema < Migration
|
33
|
-
|
34
|
-
|
35
|
-
def self.migrations_path
|
36
|
-
ActiveRecord::Migrator.migrations_path
|
33
|
+
def migrations_paths
|
34
|
+
ActiveRecord::Migrator.migrations_paths
|
37
35
|
end
|
38
36
|
|
39
37
|
# Eval the given block. All methods available to the current connection
|
@@ -48,11 +46,12 @@ module ActiveRecord
|
|
48
46
|
# ...
|
49
47
|
# end
|
50
48
|
def self.define(info={}, &block)
|
51
|
-
|
49
|
+
schema = new
|
50
|
+
schema.instance_eval(&block)
|
52
51
|
|
53
52
|
unless info[:version].blank?
|
54
53
|
initialize_schema_migrations_table
|
55
|
-
assume_migrated_upto_version(info[:version],
|
54
|
+
assume_migrated_upto_version(info[:version], schema.migrations_paths)
|
56
55
|
end
|
57
56
|
end
|
58
57
|
end
|
@@ -40,10 +40,6 @@ module ActiveRecord
|
|
40
40
|
def header(stream)
|
41
41
|
define_params = @version ? ":version => #{@version}" : ""
|
42
42
|
|
43
|
-
if stream.respond_to?(:external_encoding) && stream.external_encoding
|
44
|
-
stream.puts "# encoding: #{stream.external_encoding.name}"
|
45
|
-
end
|
46
|
-
|
47
43
|
stream.puts <<HEADER
|
48
44
|
# This file is auto-generated from the current state of the database. Instead
|
49
45
|
# of editing this file, please use the migrations feature of Active Record to
|
@@ -87,7 +83,7 @@ HEADER
|
|
87
83
|
|
88
84
|
# first dump primary key column
|
89
85
|
if @connection.respond_to?(:pk_and_sequence_for)
|
90
|
-
pk,
|
86
|
+
pk, _ = @connection.pk_and_sequence_for(table)
|
91
87
|
elsif @connection.respond_to?(:primary_key)
|
92
88
|
pk = @connection.primary_key(table)
|
93
89
|
end
|
@@ -118,9 +114,9 @@ HEADER
|
|
118
114
|
column.type.to_s
|
119
115
|
end
|
120
116
|
spec[:limit] = column.limit.inspect if column.limit != @types[column.type][:limit] && spec[:type] != 'decimal'
|
121
|
-
spec[:precision] = column.precision.inspect if
|
122
|
-
spec[:scale] = column.scale.inspect if
|
123
|
-
spec[:null] = 'false'
|
117
|
+
spec[:precision] = column.precision.inspect if column.precision
|
118
|
+
spec[:scale] = column.scale.inspect if column.scale
|
119
|
+
spec[:null] = 'false' unless column.null
|
124
120
|
spec[:default] = default_string(column.default) if column.has_default?
|
125
121
|
(spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.inspect} => ")}
|
126
122
|
spec
|
@@ -180,13 +176,15 @@ HEADER
|
|
180
176
|
def indexes(table, stream)
|
181
177
|
if (indexes = @connection.indexes(table)).any?
|
182
178
|
add_index_statements = indexes.map do |index|
|
183
|
-
statement_parts = [
|
184
|
-
|
185
|
-
|
179
|
+
statement_parts = [
|
180
|
+
('add_index ' + index.table.inspect),
|
181
|
+
index.columns.inspect,
|
182
|
+
(':name => ' + index.name.inspect),
|
183
|
+
]
|
186
184
|
statement_parts << ':unique => true' if index.unique
|
187
185
|
|
188
|
-
index_lengths = index.lengths
|
189
|
-
statement_parts << (':length => ' + Hash[
|
186
|
+
index_lengths = (index.lengths || []).compact
|
187
|
+
statement_parts << (':length => ' + Hash[index.columns.zip(index.lengths)].inspect) unless index_lengths.empty?
|
190
188
|
|
191
189
|
' ' + statement_parts.join(', ')
|
192
190
|
end
|
@@ -22,7 +22,7 @@ module ActiveRecord #:nodoc:
|
|
22
22
|
end
|
23
23
|
|
24
24
|
private
|
25
|
-
# Add associations specified via the <tt>:
|
25
|
+
# Add associations specified via the <tt>:include</tt> option.
|
26
26
|
#
|
27
27
|
# Expects a block that takes as arguments:
|
28
28
|
# +association+ - name of the association
|
@@ -45,7 +45,7 @@ module ActiveRecord #:nodoc:
|
|
45
45
|
send(association)
|
46
46
|
end
|
47
47
|
|
48
|
-
|
48
|
+
if records
|
49
49
|
association_options = include_has_options ? include_associations[association] : base_only_or_except
|
50
50
|
opts = options.merge(association_options)
|
51
51
|
yield(association, records, opts)
|
@@ -226,17 +226,17 @@ module ActiveRecord #:nodoc:
|
|
226
226
|
|
227
227
|
class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute #:nodoc:
|
228
228
|
def compute_type
|
229
|
-
|
230
|
-
|
229
|
+
klass = @serializable.class
|
230
|
+
type = if klass.serialized_attributes.key?(name)
|
231
|
+
super
|
232
|
+
elsif klass.columns_hash.key?(name)
|
233
|
+
klass.columns_hash[name].type
|
234
|
+
else
|
235
|
+
NilClass
|
236
|
+
end
|
231
237
|
|
232
|
-
|
233
|
-
|
234
|
-
:string
|
235
|
-
when :time
|
236
|
-
:datetime
|
237
|
-
else
|
238
|
-
type
|
239
|
-
end
|
238
|
+
{ :text => :string,
|
239
|
+
:time => :datetime }[type] || type
|
240
240
|
end
|
241
241
|
protected :compute_type
|
242
242
|
end
|
@@ -59,10 +59,12 @@ module ActiveRecord
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def drop_table!
|
62
|
+
connection_pool.clear_table_cache!(table_name)
|
62
63
|
connection.drop_table table_name
|
63
64
|
end
|
64
65
|
|
65
66
|
def create_table!
|
67
|
+
connection_pool.clear_table_cache!(table_name)
|
66
68
|
connection.create_table(table_name) do |t|
|
67
69
|
t.string session_id_column, :limit => 255
|
68
70
|
t.text data_column_name
|
@@ -288,6 +290,7 @@ module ActiveRecord
|
|
288
290
|
self.session_class = Session
|
289
291
|
|
290
292
|
SESSION_RECORD_KEY = 'rack.session.record'
|
293
|
+
ENV_SESSION_OPTIONS_KEY = Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY
|
291
294
|
|
292
295
|
private
|
293
296
|
def get_session(env, sid)
|
@@ -299,7 +302,7 @@ module ActiveRecord
|
|
299
302
|
end
|
300
303
|
end
|
301
304
|
|
302
|
-
def set_session(env, sid, session_data)
|
305
|
+
def set_session(env, sid, session_data, options)
|
303
306
|
Base.silence do
|
304
307
|
record = get_session_model(env, sid)
|
305
308
|
record.data = session_data
|
@@ -316,12 +319,15 @@ module ActiveRecord
|
|
316
319
|
sid
|
317
320
|
end
|
318
321
|
|
319
|
-
def
|
322
|
+
def destroy_session(env, session_id, options)
|
320
323
|
if sid = current_session_id(env)
|
321
324
|
Base.silence do
|
322
325
|
get_session_model(env, sid).destroy
|
326
|
+
env[SESSION_RECORD_KEY] = nil
|
323
327
|
end
|
324
328
|
end
|
329
|
+
|
330
|
+
generate_sid unless options[:drop]
|
325
331
|
end
|
326
332
|
|
327
333
|
def get_session_model(env, sid)
|
@@ -3,11 +3,14 @@ module ActiveRecord
|
|
3
3
|
#
|
4
4
|
# Defines some test assertions to test against SQL queries.
|
5
5
|
class TestCase < ActiveSupport::TestCase #:nodoc:
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
setup :cleanup_identity_map
|
7
|
+
|
8
|
+
def setup
|
9
|
+
cleanup_identity_map
|
10
|
+
end
|
11
|
+
|
12
|
+
def cleanup_identity_map
|
13
|
+
ActiveRecord::IdentityMap.clear
|
11
14
|
end
|
12
15
|
|
13
16
|
def assert_date_from_db(expected, actual, message = nil)
|
@@ -23,6 +26,7 @@ module ActiveRecord
|
|
23
26
|
def assert_sql(*patterns_to_match)
|
24
27
|
$queries_executed = []
|
25
28
|
yield
|
29
|
+
$queries_executed
|
26
30
|
ensure
|
27
31
|
failed_patterns = []
|
28
32
|
patterns_to_match.each do |pattern|
|
@@ -43,21 +47,6 @@ module ActiveRecord
|
|
43
47
|
assert_queries(0, &block)
|
44
48
|
end
|
45
49
|
|
46
|
-
def self.use_concurrent_connections
|
47
|
-
setup :connection_allow_concurrency_setup
|
48
|
-
teardown :connection_allow_concurrency_teardown
|
49
|
-
end
|
50
|
-
|
51
|
-
def connection_allow_concurrency_setup
|
52
|
-
@connection = ActiveRecord::Base.remove_connection
|
53
|
-
ActiveRecord::Base.establish_connection(@connection.merge({:allow_concurrency => true}))
|
54
|
-
end
|
55
|
-
|
56
|
-
def connection_allow_concurrency_teardown
|
57
|
-
ActiveRecord::Base.clear_all_connections!
|
58
|
-
ActiveRecord::Base.establish_connection(@connection)
|
59
|
-
end
|
60
|
-
|
61
50
|
def with_kcode(kcode)
|
62
51
|
if RUBY_VERSION < '1.9'
|
63
52
|
orig_kcode, $KCODE = $KCODE, kcode
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/core_ext/class/attribute'
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# = Active Record Timestamp
|
3
5
|
#
|
@@ -7,36 +9,38 @@ module ActiveRecord
|
|
7
9
|
#
|
8
10
|
# Timestamping can be turned off by setting:
|
9
11
|
#
|
10
|
-
#
|
12
|
+
# config.active_record.record_timestamps = false
|
11
13
|
#
|
12
14
|
# Timestamps are in the local timezone by default but you can use UTC by setting:
|
13
15
|
#
|
14
|
-
#
|
16
|
+
# config.active_record.default_timezone = :utc
|
15
17
|
#
|
16
18
|
# == Time Zone aware attributes
|
17
19
|
#
|
18
20
|
# By default, ActiveRecord::Base keeps all the datetime columns time zone aware by executing following code.
|
19
21
|
#
|
20
|
-
#
|
22
|
+
# config.active_record.time_zone_aware_attributes = true
|
21
23
|
#
|
22
24
|
# This feature can easily be turned off by assigning value <tt>false</tt> .
|
23
25
|
#
|
24
|
-
# If your attributes are time zone aware and you desire to skip time zone conversion
|
25
|
-
# attributes then you can do following:
|
26
|
+
# If your attributes are time zone aware and you desire to skip time zone conversion to the current Time.zone
|
27
|
+
# when reading certain attributes then you can do following:
|
26
28
|
#
|
27
|
-
# Topic
|
29
|
+
# class Topic < ActiveRecord::Base
|
30
|
+
# self.skip_time_zone_conversion_for_attributes = [:written_on]
|
31
|
+
# end
|
28
32
|
module Timestamp
|
29
33
|
extend ActiveSupport::Concern
|
30
34
|
|
31
35
|
included do
|
32
|
-
|
36
|
+
class_attribute :record_timestamps, :instance_writer => false
|
33
37
|
self.record_timestamps = true
|
34
38
|
end
|
35
39
|
|
36
40
|
private
|
37
41
|
|
38
42
|
def create #:nodoc:
|
39
|
-
if record_timestamps
|
43
|
+
if self.record_timestamps
|
40
44
|
current_time = current_time_from_proper_timezone
|
41
45
|
|
42
46
|
all_timestamp_attributes.each do |column|
|
@@ -61,13 +65,21 @@ module ActiveRecord
|
|
61
65
|
end
|
62
66
|
|
63
67
|
def should_record_timestamps?
|
64
|
-
record_timestamps && (!partial_updates? || changed?)
|
68
|
+
self.record_timestamps && (!partial_updates? || changed? || (attributes.keys & self.class.serialized_attributes.keys).present?)
|
69
|
+
end
|
70
|
+
|
71
|
+
def timestamp_attributes_for_create_in_model
|
72
|
+
timestamp_attributes_for_create.select { |c| self.class.column_names.include?(c.to_s) }
|
65
73
|
end
|
66
74
|
|
67
75
|
def timestamp_attributes_for_update_in_model
|
68
76
|
timestamp_attributes_for_update.select { |c| self.class.column_names.include?(c.to_s) }
|
69
77
|
end
|
70
78
|
|
79
|
+
def all_timestamp_attributes_in_model
|
80
|
+
timestamp_attributes_for_create_in_model + timestamp_attributes_for_update_in_model
|
81
|
+
end
|
82
|
+
|
71
83
|
def timestamp_attributes_for_update #:nodoc:
|
72
84
|
[:updated_at, :updated_on]
|
73
85
|
end
|
@@ -11,6 +11,7 @@ module ActiveRecord
|
|
11
11
|
included do
|
12
12
|
define_callbacks :commit, :rollback, :terminator => "result == false", :scope => [:kind, :name]
|
13
13
|
end
|
14
|
+
|
14
15
|
# = Active Record Transactions
|
15
16
|
#
|
16
17
|
# Transactions are protective blocks where SQL statements are only permanent
|
@@ -227,8 +228,8 @@ module ActiveRecord
|
|
227
228
|
end
|
228
229
|
|
229
230
|
# See ActiveRecord::Transactions::ClassMethods for detailed documentation.
|
230
|
-
def transaction(&block)
|
231
|
-
self.class.transaction(&block)
|
231
|
+
def transaction(options = {}, &block)
|
232
|
+
self.class.transaction(options, &block)
|
232
233
|
end
|
233
234
|
|
234
235
|
def destroy #:nodoc:
|
@@ -250,6 +251,7 @@ module ActiveRecord
|
|
250
251
|
remember_transaction_record_state
|
251
252
|
yield
|
252
253
|
rescue Exception
|
254
|
+
IdentityMap.remove(self) if IdentityMap.enabled?
|
253
255
|
restore_transaction_record_state
|
254
256
|
raise
|
255
257
|
ensure
|
@@ -258,7 +260,7 @@ module ActiveRecord
|
|
258
260
|
|
259
261
|
# Call the after_commit callbacks
|
260
262
|
def committed! #:nodoc:
|
261
|
-
|
263
|
+
run_callbacks :commit
|
262
264
|
ensure
|
263
265
|
clear_transaction_record_state
|
264
266
|
end
|
@@ -266,8 +268,9 @@ module ActiveRecord
|
|
266
268
|
# Call the after rollback callbacks. The restore_state argument indicates if the record
|
267
269
|
# state should be rolled back to the beginning or just to the last savepoint.
|
268
270
|
def rolledback!(force_restore_state = false) #:nodoc:
|
269
|
-
|
271
|
+
run_callbacks :rollback
|
270
272
|
ensure
|
273
|
+
IdentityMap.remove(self) if IdentityMap.enabled?
|
271
274
|
restore_transaction_record_state(force_restore_state)
|
272
275
|
end
|
273
276
|
|
@@ -300,8 +303,8 @@ module ActiveRecord
|
|
300
303
|
# Save the new record state and id of a record so it can be restored later if a transaction fails.
|
301
304
|
def remember_transaction_record_state #:nodoc
|
302
305
|
@_start_transaction_state ||= {}
|
306
|
+
@_start_transaction_state[:id] = id if has_attribute?(self.class.primary_key)
|
303
307
|
unless @_start_transaction_state.include?(:new_record)
|
304
|
-
@_start_transaction_state[:id] = id if has_attribute?(self.class.primary_key)
|
305
308
|
@_start_transaction_state[:new_record] = @new_record
|
306
309
|
end
|
307
310
|
unless @_start_transaction_state.include?(:destroyed)
|
@@ -324,16 +327,14 @@ module ActiveRecord
|
|
324
327
|
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
|
325
328
|
if @_start_transaction_state[:level] < 1
|
326
329
|
restore_state = remove_instance_variable(:@_start_transaction_state)
|
327
|
-
if
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
@attributes_cache.delete(self.class.primary_key)
|
336
|
-
end
|
330
|
+
@attributes = @attributes.dup if @attributes.frozen?
|
331
|
+
@new_record = restore_state[:new_record]
|
332
|
+
@destroyed = restore_state[:destroyed]
|
333
|
+
if restore_state.has_key?(:id)
|
334
|
+
self.id = restore_state[:id]
|
335
|
+
else
|
336
|
+
@attributes.delete(self.class.primary_key)
|
337
|
+
@attributes_cache.delete(self.class.primary_key)
|
337
338
|
end
|
338
339
|
end
|
339
340
|
end
|