activerecord 1.0.0 → 3.0.0
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 +5518 -76
- data/README.rdoc +222 -0
- data/examples/performance.rb +162 -0
- data/examples/simple.rb +14 -0
- data/lib/active_record/aggregations.rb +192 -80
- data/lib/active_record/association_preload.rb +403 -0
- data/lib/active_record/associations/association_collection.rb +545 -53
- data/lib/active_record/associations/association_proxy.rb +295 -0
- data/lib/active_record/associations/belongs_to_association.rb +91 -0
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +78 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +127 -36
- data/lib/active_record/associations/has_many_association.rb +108 -84
- data/lib/active_record/associations/has_many_through_association.rb +116 -0
- data/lib/active_record/associations/has_one_association.rb +143 -0
- data/lib/active_record/associations/has_one_through_association.rb +40 -0
- data/lib/active_record/associations/through_association_scope.rb +154 -0
- data/lib/active_record/associations.rb +2086 -368
- data/lib/active_record/attribute_methods/before_type_cast.rb +33 -0
- data/lib/active_record/attribute_methods/dirty.rb +95 -0
- data/lib/active_record/attribute_methods/primary_key.rb +50 -0
- data/lib/active_record/attribute_methods/query.rb +39 -0
- data/lib/active_record/attribute_methods/read.rb +116 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -0
- data/lib/active_record/attribute_methods/write.rb +37 -0
- data/lib/active_record/attribute_methods.rb +60 -0
- data/lib/active_record/autosave_association.rb +369 -0
- data/lib/active_record/base.rb +1603 -721
- data/lib/active_record/callbacks.rb +176 -225
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +365 -0
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +113 -0
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +57 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +329 -0
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +81 -0
- data/lib/active_record/connection_adapters/abstract/quoting.rb +72 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +739 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +543 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +165 -279
- data/lib/active_record/connection_adapters/mysql_adapter.rb +594 -82
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +988 -135
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +53 -0
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +365 -71
- data/lib/active_record/counter_cache.rb +115 -0
- data/lib/active_record/dynamic_finder_match.rb +53 -0
- data/lib/active_record/dynamic_scope_match.rb +32 -0
- data/lib/active_record/errors.rb +172 -0
- data/lib/active_record/fixtures.rb +941 -105
- data/lib/active_record/locale/en.yml +40 -0
- data/lib/active_record/locking/optimistic.rb +172 -0
- data/lib/active_record/locking/pessimistic.rb +55 -0
- data/lib/active_record/log_subscriber.rb +48 -0
- data/lib/active_record/migration.rb +617 -0
- data/lib/active_record/named_scope.rb +138 -0
- data/lib/active_record/nested_attributes.rb +417 -0
- data/lib/active_record/observer.rb +105 -36
- data/lib/active_record/persistence.rb +291 -0
- data/lib/active_record/query_cache.rb +36 -0
- data/lib/active_record/railtie.rb +91 -0
- data/lib/active_record/railties/controller_runtime.rb +38 -0
- data/lib/active_record/railties/databases.rake +512 -0
- data/lib/active_record/reflection.rb +364 -87
- data/lib/active_record/relation/batches.rb +89 -0
- data/lib/active_record/relation/calculations.rb +286 -0
- data/lib/active_record/relation/finder_methods.rb +355 -0
- data/lib/active_record/relation/predicate_builder.rb +41 -0
- data/lib/active_record/relation/query_methods.rb +261 -0
- data/lib/active_record/relation/spawn_methods.rb +112 -0
- data/lib/active_record/relation.rb +393 -0
- data/lib/active_record/schema.rb +59 -0
- data/lib/active_record/schema_dumper.rb +195 -0
- data/lib/active_record/serialization.rb +60 -0
- data/lib/active_record/serializers/xml_serializer.rb +244 -0
- data/lib/active_record/session_store.rb +340 -0
- data/lib/active_record/test_case.rb +67 -0
- data/lib/active_record/timestamp.rb +88 -0
- data/lib/active_record/transactions.rb +329 -75
- data/lib/active_record/validations/associated.rb +48 -0
- data/lib/active_record/validations/uniqueness.rb +185 -0
- data/lib/active_record/validations.rb +58 -179
- data/lib/active_record/version.rb +9 -0
- data/lib/active_record.rb +100 -24
- data/lib/rails/generators/active_record/migration/migration_generator.rb +25 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +17 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +38 -0
- data/lib/rails/generators/active_record/model/templates/migration.rb +16 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +5 -0
- data/lib/rails/generators/active_record/model/templates/module.rb +5 -0
- data/lib/rails/generators/active_record/observer/observer_generator.rb +15 -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 +24 -0
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +16 -0
- data/lib/rails/generators/active_record.rb +27 -0
- metadata +216 -158
- data/README +0 -361
- data/RUNNING_UNIT_TESTS +0 -36
- data/dev-utils/eval_debugger.rb +0 -9
- data/examples/associations.rb +0 -87
- data/examples/shared_setup.rb +0 -15
- data/examples/validation.rb +0 -88
- data/install.rb +0 -60
- data/lib/active_record/deprecated_associations.rb +0 -70
- data/lib/active_record/support/class_attribute_accessors.rb +0 -43
- data/lib/active_record/support/class_inheritable_attributes.rb +0 -37
- data/lib/active_record/support/clean_logger.rb +0 -10
- data/lib/active_record/support/inflector.rb +0 -70
- data/lib/active_record/vendor/mysql.rb +0 -1117
- data/lib/active_record/vendor/simple.rb +0 -702
- data/lib/active_record/wrappers/yaml_wrapper.rb +0 -15
- data/lib/active_record/wrappings.rb +0 -59
- data/rakefile +0 -122
- data/test/abstract_unit.rb +0 -16
- data/test/aggregations_test.rb +0 -34
- data/test/all.sh +0 -8
- data/test/associations_test.rb +0 -477
- data/test/base_test.rb +0 -513
- data/test/class_inheritable_attributes_test.rb +0 -33
- data/test/connections/native_mysql/connection.rb +0 -24
- data/test/connections/native_postgresql/connection.rb +0 -24
- data/test/connections/native_sqlite/connection.rb +0 -24
- data/test/deprecated_associations_test.rb +0 -336
- data/test/finder_test.rb +0 -67
- data/test/fixtures/accounts/signals37 +0 -3
- data/test/fixtures/accounts/unknown +0 -2
- data/test/fixtures/auto_id.rb +0 -4
- data/test/fixtures/column_name.rb +0 -3
- data/test/fixtures/companies/first_client +0 -6
- data/test/fixtures/companies/first_firm +0 -4
- data/test/fixtures/companies/second_client +0 -6
- data/test/fixtures/company.rb +0 -37
- data/test/fixtures/company_in_module.rb +0 -33
- data/test/fixtures/course.rb +0 -3
- data/test/fixtures/courses/java +0 -2
- data/test/fixtures/courses/ruby +0 -2
- data/test/fixtures/customer.rb +0 -30
- data/test/fixtures/customers/david +0 -6
- data/test/fixtures/db_definitions/mysql.sql +0 -96
- data/test/fixtures/db_definitions/mysql2.sql +0 -4
- data/test/fixtures/db_definitions/postgresql.sql +0 -113
- data/test/fixtures/db_definitions/postgresql2.sql +0 -4
- data/test/fixtures/db_definitions/sqlite.sql +0 -85
- data/test/fixtures/db_definitions/sqlite2.sql +0 -4
- data/test/fixtures/default.rb +0 -2
- data/test/fixtures/developer.rb +0 -8
- data/test/fixtures/developers/david +0 -2
- data/test/fixtures/developers/jamis +0 -2
- data/test/fixtures/developers_projects/david_action_controller +0 -2
- data/test/fixtures/developers_projects/david_active_record +0 -2
- data/test/fixtures/developers_projects/jamis_active_record +0 -2
- data/test/fixtures/entrant.rb +0 -3
- data/test/fixtures/entrants/first +0 -3
- data/test/fixtures/entrants/second +0 -3
- data/test/fixtures/entrants/third +0 -3
- data/test/fixtures/fixture_database.sqlite +0 -0
- data/test/fixtures/fixture_database_2.sqlite +0 -0
- data/test/fixtures/movie.rb +0 -5
- data/test/fixtures/movies/first +0 -2
- data/test/fixtures/movies/second +0 -2
- data/test/fixtures/project.rb +0 -3
- data/test/fixtures/projects/action_controller +0 -2
- data/test/fixtures/projects/active_record +0 -2
- data/test/fixtures/reply.rb +0 -21
- data/test/fixtures/subscriber.rb +0 -5
- data/test/fixtures/subscribers/first +0 -2
- data/test/fixtures/subscribers/second +0 -2
- data/test/fixtures/topic.rb +0 -20
- data/test/fixtures/topics/first +0 -9
- data/test/fixtures/topics/second +0 -8
- data/test/fixtures_test.rb +0 -20
- data/test/inflector_test.rb +0 -104
- data/test/inheritance_test.rb +0 -125
- data/test/lifecycle_test.rb +0 -110
- data/test/modules_test.rb +0 -21
- data/test/multiple_db_test.rb +0 -46
- data/test/pk_test.rb +0 -57
- data/test/reflection_test.rb +0 -78
- data/test/thread_safety_test.rb +0 -33
- data/test/transactions_test.rb +0 -83
- data/test/unconnected_test.rb +0 -24
- data/test/validations_test.rb +0 -126
@@ -0,0 +1,40 @@
|
|
1
|
+
en:
|
2
|
+
# Attributes names common to most models
|
3
|
+
#attributes:
|
4
|
+
#created_at: "Created at"
|
5
|
+
#updated_at: "Updated at"
|
6
|
+
|
7
|
+
# Active Record models configuration
|
8
|
+
activerecord:
|
9
|
+
errors:
|
10
|
+
messages:
|
11
|
+
taken: "has already been taken"
|
12
|
+
record_invalid: "Validation failed: %{errors}"
|
13
|
+
# Append your own errors here or at the model/attributes scope.
|
14
|
+
|
15
|
+
# You can define own errors for models or model attributes.
|
16
|
+
# The values :model, :attribute and :value are always available for interpolation.
|
17
|
+
#
|
18
|
+
# For example,
|
19
|
+
# models:
|
20
|
+
# user:
|
21
|
+
# blank: "This is a custom blank message for %{model}: %{attribute}"
|
22
|
+
# attributes:
|
23
|
+
# login:
|
24
|
+
# blank: "This is a custom blank message for User login"
|
25
|
+
# Will define custom blank validation message for User model and
|
26
|
+
# custom blank validation message for login attribute of User model.
|
27
|
+
#models:
|
28
|
+
|
29
|
+
# Translate model names. Used in Model.human_name().
|
30
|
+
#models:
|
31
|
+
# For example,
|
32
|
+
# user: "Dude"
|
33
|
+
# will translate User model name to "Dude"
|
34
|
+
|
35
|
+
# Translate model attribute names. Used in Model.human_attribute_name(attribute).
|
36
|
+
#attributes:
|
37
|
+
# For example,
|
38
|
+
# user:
|
39
|
+
# login: "Handle"
|
40
|
+
# will translate User attribute "login" as "Handle"
|
@@ -0,0 +1,172 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Locking
|
3
|
+
# == What is Optimistic Locking
|
4
|
+
#
|
5
|
+
# Optimistic locking allows multiple users to access the same record for edits, and assumes a minimum of
|
6
|
+
# conflicts with the data. It does this by checking whether another process has made changes to a record since
|
7
|
+
# it was opened, an ActiveRecord::StaleObjectError is thrown if that has occurred and the update is ignored.
|
8
|
+
#
|
9
|
+
# Check out ActiveRecord::Locking::Pessimistic for an alternative.
|
10
|
+
#
|
11
|
+
# == Usage
|
12
|
+
#
|
13
|
+
# Active Records support optimistic locking if the field <tt>lock_version</tt> is present. Each update to the
|
14
|
+
# record increments the lock_version column and the locking facilities ensure that records instantiated twice
|
15
|
+
# will let the last one saved raise a StaleObjectError if the first was also updated. Example:
|
16
|
+
#
|
17
|
+
# p1 = Person.find(1)
|
18
|
+
# p2 = Person.find(1)
|
19
|
+
#
|
20
|
+
# p1.first_name = "Michael"
|
21
|
+
# p1.save
|
22
|
+
#
|
23
|
+
# p2.first_name = "should fail"
|
24
|
+
# p2.save # Raises a ActiveRecord::StaleObjectError
|
25
|
+
#
|
26
|
+
# Optimistic locking will also check for stale data when objects are destroyed. Example:
|
27
|
+
#
|
28
|
+
# p1 = Person.find(1)
|
29
|
+
# p2 = Person.find(1)
|
30
|
+
#
|
31
|
+
# p1.first_name = "Michael"
|
32
|
+
# p1.save
|
33
|
+
#
|
34
|
+
# p2.destroy # Raises a ActiveRecord::StaleObjectError
|
35
|
+
#
|
36
|
+
# You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging,
|
37
|
+
# or otherwise apply the business logic needed to resolve the conflict.
|
38
|
+
#
|
39
|
+
# You must ensure that your database schema defaults the lock_version column to 0.
|
40
|
+
#
|
41
|
+
# This behavior can be turned off by setting <tt>ActiveRecord::Base.lock_optimistically = false</tt>.
|
42
|
+
# To override the name of the lock_version column, invoke the <tt>set_locking_column</tt> method.
|
43
|
+
# This method uses the same syntax as <tt>set_table_name</tt>
|
44
|
+
module Optimistic
|
45
|
+
extend ActiveSupport::Concern
|
46
|
+
|
47
|
+
included do
|
48
|
+
cattr_accessor :lock_optimistically, :instance_writer => false
|
49
|
+
self.lock_optimistically = true
|
50
|
+
|
51
|
+
class << self
|
52
|
+
alias_method :locking_column=, :set_locking_column
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def locking_enabled? #:nodoc:
|
57
|
+
self.class.locking_enabled?
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def attributes_from_column_definition
|
62
|
+
result = super
|
63
|
+
|
64
|
+
# If the locking column has no default value set,
|
65
|
+
# start the lock version at zero. Note we can't use
|
66
|
+
# locking_enabled? at this point as @attributes may
|
67
|
+
# not have been initialized yet
|
68
|
+
|
69
|
+
if lock_optimistically && result.include?(self.class.locking_column)
|
70
|
+
result[self.class.locking_column] ||= 0
|
71
|
+
end
|
72
|
+
|
73
|
+
return result
|
74
|
+
end
|
75
|
+
|
76
|
+
def update(attribute_names = @attributes.keys) #:nodoc:
|
77
|
+
return super unless locking_enabled?
|
78
|
+
return 0 if attribute_names.empty?
|
79
|
+
|
80
|
+
lock_col = self.class.locking_column
|
81
|
+
previous_value = send(lock_col).to_i
|
82
|
+
send(lock_col + '=', previous_value + 1)
|
83
|
+
|
84
|
+
attribute_names += [lock_col]
|
85
|
+
attribute_names.uniq!
|
86
|
+
|
87
|
+
begin
|
88
|
+
relation = self.class.unscoped
|
89
|
+
|
90
|
+
affected_rows = relation.where(
|
91
|
+
relation.table[self.class.primary_key].eq(quoted_id).and(
|
92
|
+
relation.table[self.class.locking_column].eq(quote_value(previous_value))
|
93
|
+
)
|
94
|
+
).arel.update(arel_attributes_values(false, false, attribute_names))
|
95
|
+
|
96
|
+
unless affected_rows == 1
|
97
|
+
raise ActiveRecord::StaleObjectError, "Attempted to update a stale object: #{self.class.name}"
|
98
|
+
end
|
99
|
+
|
100
|
+
affected_rows
|
101
|
+
|
102
|
+
# If something went wrong, revert the version.
|
103
|
+
rescue Exception
|
104
|
+
send(lock_col + '=', previous_value)
|
105
|
+
raise
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def destroy #:nodoc:
|
110
|
+
return super unless locking_enabled?
|
111
|
+
|
112
|
+
unless new_record?
|
113
|
+
lock_col = self.class.locking_column
|
114
|
+
previous_value = send(lock_col).to_i
|
115
|
+
|
116
|
+
table = self.class.arel_table
|
117
|
+
predicate = table[self.class.primary_key].eq(id)
|
118
|
+
predicate = predicate.and(table[self.class.locking_column].eq(previous_value))
|
119
|
+
|
120
|
+
affected_rows = self.class.unscoped.where(predicate).delete_all
|
121
|
+
|
122
|
+
unless affected_rows == 1
|
123
|
+
raise ActiveRecord::StaleObjectError, "Attempted to delete a stale object: #{self.class.name}"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
@destroyed = true
|
128
|
+
freeze
|
129
|
+
end
|
130
|
+
|
131
|
+
module ClassMethods
|
132
|
+
DEFAULT_LOCKING_COLUMN = 'lock_version'
|
133
|
+
|
134
|
+
# Is optimistic locking enabled for this table? Returns true if the
|
135
|
+
# +lock_optimistically+ flag is set to true (which it is, by default)
|
136
|
+
# and the table includes the +locking_column+ column (defaults to
|
137
|
+
# +lock_version+).
|
138
|
+
def locking_enabled?
|
139
|
+
lock_optimistically && columns_hash[locking_column]
|
140
|
+
end
|
141
|
+
|
142
|
+
# Set the column to use for optimistic locking. Defaults to +lock_version+.
|
143
|
+
def set_locking_column(value = nil, &block)
|
144
|
+
define_attr_method :locking_column, value, &block
|
145
|
+
value
|
146
|
+
end
|
147
|
+
|
148
|
+
# The version column used for optimistic locking. Defaults to +lock_version+.
|
149
|
+
def locking_column
|
150
|
+
reset_locking_column
|
151
|
+
end
|
152
|
+
|
153
|
+
# Quote the column name used for optimistic locking.
|
154
|
+
def quoted_locking_column
|
155
|
+
connection.quote_column_name(locking_column)
|
156
|
+
end
|
157
|
+
|
158
|
+
# Reset the column used for optimistic locking back to the +lock_version+ default.
|
159
|
+
def reset_locking_column
|
160
|
+
set_locking_column DEFAULT_LOCKING_COLUMN
|
161
|
+
end
|
162
|
+
|
163
|
+
# Make sure the lock version column gets updated when counters are
|
164
|
+
# updated.
|
165
|
+
def update_counters(id, counters)
|
166
|
+
counters = counters.merge(locking_column => 1) if locking_enabled?
|
167
|
+
super
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Locking
|
3
|
+
# Locking::Pessimistic provides support for row-level locking using
|
4
|
+
# SELECT ... FOR UPDATE and other lock types.
|
5
|
+
#
|
6
|
+
# Pass <tt>:lock => true</tt> to ActiveRecord::Base.find to obtain an exclusive
|
7
|
+
# lock on the selected rows:
|
8
|
+
# # select * from accounts where id=1 for update
|
9
|
+
# Account.find(1, :lock => true)
|
10
|
+
#
|
11
|
+
# Pass <tt>:lock => 'some locking clause'</tt> to give a database-specific locking clause
|
12
|
+
# of your own such as 'LOCK IN SHARE MODE' or 'FOR UPDATE NOWAIT'.
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
# Account.transaction do
|
16
|
+
# # select * from accounts where name = 'shugo' limit 1 for update
|
17
|
+
# shugo = Account.find(:first, :conditions => "name = 'shugo'", :lock => true)
|
18
|
+
# yuko = Account.find(:first, :conditions => "name = 'yuko'", :lock => true)
|
19
|
+
# shugo.balance -= 100
|
20
|
+
# shugo.save!
|
21
|
+
# yuko.balance += 100
|
22
|
+
# yuko.save!
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# You can also use ActiveRecord::Base#lock! method to lock one record by id.
|
26
|
+
# This may be better if you don't need to lock every row. Example:
|
27
|
+
# Account.transaction do
|
28
|
+
# # select * from accounts where ...
|
29
|
+
# accounts = Account.find(:all, :conditions => ...)
|
30
|
+
# account1 = accounts.detect { |account| ... }
|
31
|
+
# account2 = accounts.detect { |account| ... }
|
32
|
+
# # select * from accounts where id=? for update
|
33
|
+
# account1.lock!
|
34
|
+
# account2.lock!
|
35
|
+
# account1.balance -= 100
|
36
|
+
# account1.save!
|
37
|
+
# account2.balance += 100
|
38
|
+
# account2.save!
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# Database-specific information on row locking:
|
42
|
+
# MySQL: http://dev.mysql.com/doc/refman/5.1/en/innodb-locking-reads.html
|
43
|
+
# PostgreSQL: http://www.postgresql.org/docs/8.1/interactive/sql-select.html#SQL-FOR-UPDATE-SHARE
|
44
|
+
module Pessimistic
|
45
|
+
# Obtain a row lock on this record. Reloads the record to obtain the requested
|
46
|
+
# lock. Pass an SQL locking clause to append the end of the SELECT statement
|
47
|
+
# or pass true for "FOR UPDATE" (the default, an exclusive row lock). Returns
|
48
|
+
# the locked record.
|
49
|
+
def lock!(lock = true)
|
50
|
+
reload(:lock => lock) unless new_record?
|
51
|
+
self
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class LogSubscriber < ActiveSupport::LogSubscriber
|
3
|
+
def self.runtime=(value)
|
4
|
+
Thread.current["active_record_sql_runtime"] = value
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.runtime
|
8
|
+
Thread.current["active_record_sql_runtime"] ||= 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.reset_runtime
|
12
|
+
rt, self.runtime = runtime, 0
|
13
|
+
rt
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
super
|
18
|
+
@odd_or_even = false
|
19
|
+
end
|
20
|
+
|
21
|
+
def sql(event)
|
22
|
+
self.class.runtime += event.duration
|
23
|
+
return unless logger.debug?
|
24
|
+
|
25
|
+
name = '%s (%.1fms)' % [event.payload[:name], event.duration]
|
26
|
+
sql = event.payload[:sql].squeeze(' ')
|
27
|
+
|
28
|
+
if odd?
|
29
|
+
name = color(name, CYAN, true)
|
30
|
+
sql = color(sql, nil, true)
|
31
|
+
else
|
32
|
+
name = color(name, MAGENTA, true)
|
33
|
+
end
|
34
|
+
|
35
|
+
debug " #{name} #{sql}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def odd?
|
39
|
+
@odd_or_even = !@odd_or_even
|
40
|
+
end
|
41
|
+
|
42
|
+
def logger
|
43
|
+
ActiveRecord::Base.logger
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
ActiveRecord::LogSubscriber.attach_to :active_record
|