activerecord 6.0.0.rc1 → 6.0.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.

Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -0
  3. data/lib/active_record/associations/builder/collection_association.rb +2 -2
  4. data/lib/active_record/associations/collection_proxy.rb +1 -1
  5. data/lib/active_record/associations/join_dependency.rb +10 -9
  6. data/lib/active_record/associations/join_dependency/join_association.rb +11 -2
  7. data/lib/active_record/associations/preloader/association.rb +3 -1
  8. data/lib/active_record/attribute_methods.rb +0 -51
  9. data/lib/active_record/attribute_methods/dirty.rb +6 -1
  10. data/lib/active_record/autosave_association.rb +1 -1
  11. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +93 -11
  12. data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -3
  13. data/lib/active_record/connection_adapters/abstract/quoting.rb +53 -0
  14. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -1
  15. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +8 -7
  16. data/lib/active_record/connection_adapters/abstract/transaction.rb +12 -4
  17. data/lib/active_record/connection_adapters/abstract_adapter.rb +40 -20
  18. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -2
  19. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
  20. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +3 -1
  21. data/lib/active_record/connection_adapters/mysql2_adapter.rb +10 -1
  22. data/lib/active_record/connection_adapters/postgresql/quoting.rb +39 -2
  23. data/lib/active_record/connection_adapters/postgresql_adapter.rb +8 -1
  24. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +38 -2
  25. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +12 -2
  26. data/lib/active_record/connection_handling.rb +6 -2
  27. data/lib/active_record/database_configurations.rb +6 -6
  28. data/lib/active_record/gem_version.rb +1 -1
  29. data/lib/active_record/middleware/database_selector.rb +3 -3
  30. data/lib/active_record/middleware/database_selector/resolver.rb +2 -2
  31. data/lib/active_record/migration.rb +26 -23
  32. data/lib/active_record/railtie.rb +0 -1
  33. data/lib/active_record/railties/databases.rake +57 -23
  34. data/lib/active_record/reflection.rb +1 -1
  35. data/lib/active_record/relation/calculations.rb +1 -1
  36. data/lib/active_record/relation/finder_methods.rb +4 -2
  37. data/lib/active_record/relation/merger.rb +6 -2
  38. data/lib/active_record/relation/query_methods.rb +32 -32
  39. data/lib/active_record/sanitization.rb +30 -2
  40. data/lib/active_record/schema.rb +1 -1
  41. data/lib/active_record/schema_dumper.rb +5 -1
  42. data/lib/active_record/table_metadata.rb +6 -10
  43. data/lib/active_record/tasks/database_tasks.rb +41 -8
  44. data/lib/active_record/tasks/mysql_database_tasks.rb +3 -1
  45. data/lib/active_record/timestamp.rb +26 -16
  46. data/lib/active_record/touch_later.rb +2 -0
  47. data/lib/active_record/transactions.rb +9 -10
  48. data/lib/active_record/type_caster/connection.rb +16 -10
  49. data/lib/arel/visitors/depth_first.rb +1 -1
  50. data/lib/arel/visitors/to_sql.rb +23 -26
  51. data/lib/arel/visitors/visitor.rb +9 -5
  52. metadata +8 -8
@@ -477,7 +477,7 @@ module ActiveRecord
477
477
  def check_preloadable!
478
478
  return unless scope
479
479
 
480
- if scope.arity > 0
480
+ unless scope.arity == 0
481
481
  raise ArgumentError, <<-MSG.squish
482
482
  The association scope '#{name}' is instance dependent (the scope
483
483
  block takes an argument). Preloading instance dependent scopes is
@@ -340,7 +340,7 @@ module ActiveRecord
340
340
  }
341
341
 
342
342
  relation = except(:group).distinct!(false)
343
- relation.group_values = group_aliases
343
+ relation.group_values = group_fields
344
344
  relation.select_values = select_values
345
345
 
346
346
  calculated_data = skip_query_cache_if_necessary { @klass.connection.select_all(relation.arel, nil) }
@@ -355,7 +355,7 @@ module ActiveRecord
355
355
  conditions = sanitize_forbidden_attributes(conditions)
356
356
 
357
357
  if distinct_value && offset_value
358
- relation = limit(1)
358
+ relation = except(:order).limit!(1)
359
359
  else
360
360
  relation = except(:select, :distinct, :order)._select!(ONE_AS_ONE).limit!(1)
361
361
  end
@@ -371,7 +371,9 @@ module ActiveRecord
371
371
  end
372
372
 
373
373
  def apply_join_dependency(eager_loading: group_values.empty?)
374
- join_dependency = construct_join_dependency(eager_load_values + includes_values)
374
+ join_dependency = construct_join_dependency(
375
+ eager_load_values + includes_values, Arel::Nodes::OuterJoin
376
+ )
375
377
  relation = except(:includes, :eager_load, :preload).joins!(join_dependency)
376
378
 
377
379
  if eager_loading && !using_limitable_reflections?(join_dependency.reflections)
@@ -123,7 +123,9 @@ module ActiveRecord
123
123
  end
124
124
  end
125
125
 
126
- join_dependency = other.construct_join_dependency(associations)
126
+ join_dependency = other.construct_join_dependency(
127
+ associations, Arel::Nodes::InnerJoin
128
+ )
127
129
  relation.joins!(join_dependency, *others)
128
130
  end
129
131
  end
@@ -135,7 +137,9 @@ module ActiveRecord
135
137
  relation.left_outer_joins!(*other.left_outer_joins_values)
136
138
  else
137
139
  associations = other.left_outer_joins_values
138
- join_dependency = other.construct_join_dependency(associations)
140
+ join_dependency = other.construct_join_dependency(
141
+ associations, Arel::Nodes::OuterJoin
142
+ )
139
143
  relation.joins!(join_dependency)
140
144
  end
141
145
  end
@@ -952,7 +952,7 @@ module ActiveRecord
952
952
  def optimizer_hints!(*args) # :nodoc:
953
953
  args.flatten!
954
954
 
955
- self.optimizer_hints_values += args
955
+ self.optimizer_hints_values |= args
956
956
  self
957
957
  end
958
958
 
@@ -1005,9 +1005,9 @@ module ActiveRecord
1005
1005
  @arel ||= build_arel(aliases)
1006
1006
  end
1007
1007
 
1008
- def construct_join_dependency(associations) # :nodoc:
1008
+ def construct_join_dependency(associations, join_type) # :nodoc:
1009
1009
  ActiveRecord::Associations::JoinDependency.new(
1010
- klass, table, associations
1010
+ klass, table, associations, join_type
1011
1011
  )
1012
1012
  end
1013
1013
 
@@ -1102,7 +1102,7 @@ module ActiveRecord
1102
1102
  def build_joins(manager, joins, aliases)
1103
1103
  unless left_outer_joins_values.empty?
1104
1104
  left_joins = valid_association_list(left_outer_joins_values.flatten)
1105
- joins << construct_join_dependency(left_joins)
1105
+ joins.unshift construct_join_dependency(left_joins, Arel::Nodes::OuterJoin)
1106
1106
  end
1107
1107
 
1108
1108
  buckets = joins.group_by do |join|
@@ -1128,27 +1128,21 @@ module ActiveRecord
1128
1128
 
1129
1129
  association_joins = buckets[:association_join]
1130
1130
  stashed_joins = buckets[:stashed_join]
1131
- join_nodes = buckets[:join_node].uniq
1132
- string_joins = buckets[:string_join].map(&:strip).uniq
1131
+ join_nodes = buckets[:join_node].tap(&:uniq!)
1132
+ string_joins = buckets[:string_join].delete_if(&:blank?).map!(&:strip).tap(&:uniq!)
1133
1133
 
1134
- join_list = join_nodes + convert_join_strings_to_ast(string_joins)
1135
- alias_tracker = alias_tracker(join_list, aliases)
1134
+ string_joins.map! { |join| table.create_string_join(Arel.sql(join)) }
1136
1135
 
1137
- join_dependency = construct_join_dependency(association_joins)
1136
+ join_sources = manager.join_sources
1137
+ join_sources.concat(join_nodes) unless join_nodes.empty?
1138
1138
 
1139
- joins = join_dependency.join_constraints(stashed_joins, join_type, alias_tracker)
1140
- joins.each { |join| manager.from(join) }
1141
-
1142
- manager.join_sources.concat(join_list)
1143
-
1144
- alias_tracker.aliases
1145
- end
1139
+ unless association_joins.empty? && stashed_joins.empty?
1140
+ alias_tracker = alias_tracker(join_nodes + string_joins, aliases)
1141
+ join_dependency = construct_join_dependency(association_joins, join_type)
1142
+ join_sources.concat(join_dependency.join_constraints(stashed_joins, alias_tracker))
1143
+ end
1146
1144
 
1147
- def convert_join_strings_to_ast(joins)
1148
- joins
1149
- .flatten
1150
- .reject(&:blank?)
1151
- .map { |join| table.create_string_join(Arel.sql(join)) }
1145
+ join_sources.concat(string_joins) unless string_joins.empty?
1152
1146
  end
1153
1147
 
1154
1148
  def build_select(arel)
@@ -1165,8 +1159,9 @@ module ActiveRecord
1165
1159
  columns.flat_map do |field|
1166
1160
  case field
1167
1161
  when Symbol
1168
- field = field.to_s
1169
- arel_column(field, &connection.method(:quote_table_name))
1162
+ arel_column(field.to_s) do |attr_name|
1163
+ connection.quote_table_name(attr_name)
1164
+ end
1170
1165
  when String
1171
1166
  arel_column(field, &:itself)
1172
1167
  when Proc
@@ -1253,6 +1248,7 @@ module ActiveRecord
1253
1248
  end
1254
1249
 
1255
1250
  def preprocess_order_args(order_args)
1251
+ order_args.reject!(&:blank?)
1256
1252
  order_args.map! do |arg|
1257
1253
  klass.sanitize_sql_for_order(arg)
1258
1254
  end
@@ -1260,7 +1256,7 @@ module ActiveRecord
1260
1256
 
1261
1257
  @klass.disallow_raw_sql!(
1262
1258
  order_args.flat_map { |a| a.is_a?(Hash) ? a.keys : a },
1263
- permit: AttributeMethods::ClassMethods::COLUMN_NAME_WITH_ORDER
1259
+ permit: connection.column_name_with_order_matcher
1264
1260
  )
1265
1261
 
1266
1262
  validate_order_args(order_args)
@@ -1273,20 +1269,14 @@ module ActiveRecord
1273
1269
  order_args.map! do |arg|
1274
1270
  case arg
1275
1271
  when Symbol
1276
- arg = arg.to_s
1277
- arel_column(arg) {
1278
- Arel.sql(connection.quote_table_name(arg))
1279
- }.asc
1272
+ order_column(arg.to_s).asc
1280
1273
  when Hash
1281
1274
  arg.map { |field, dir|
1282
1275
  case field
1283
1276
  when Arel::Nodes::SqlLiteral
1284
1277
  field.send(dir.downcase)
1285
1278
  else
1286
- field = field.to_s
1287
- arel_column(field) {
1288
- Arel.sql(connection.quote_table_name(field))
1289
- }.send(dir.downcase)
1279
+ order_column(field.to_s).send(dir.downcase)
1290
1280
  end
1291
1281
  }
1292
1282
  else
@@ -1295,6 +1285,16 @@ module ActiveRecord
1295
1285
  end.flatten!
1296
1286
  end
1297
1287
 
1288
+ def order_column(field)
1289
+ arel_column(field) do |attr_name|
1290
+ if attr_name == "count" && !group_values.empty?
1291
+ arel_attribute(attr_name)
1292
+ else
1293
+ Arel.sql(connection.quote_table_name(attr_name))
1294
+ end
1295
+ end
1296
+ end
1297
+
1298
1298
  # Checks to make sure that the arguments are not blank. Note that if some
1299
1299
  # blank-like object were initially passed into the query method, then this
1300
1300
  # method will not raise an error.
@@ -61,8 +61,9 @@ module ActiveRecord
61
61
  # # => "id ASC"
62
62
  def sanitize_sql_for_order(condition)
63
63
  if condition.is_a?(Array) && condition.first.to_s.include?("?")
64
- disallow_raw_sql!([condition.first],
65
- permit: AttributeMethods::ClassMethods::COLUMN_NAME_WITH_ORDER
64
+ disallow_raw_sql!(
65
+ [condition.first],
66
+ permit: connection.column_name_with_order_matcher
66
67
  )
67
68
 
68
69
  # Ensure we aren't dealing with a subclass of String that might
@@ -133,6 +134,33 @@ module ActiveRecord
133
134
  end
134
135
  end
135
136
 
137
+ def disallow_raw_sql!(args, permit: connection.column_name_matcher) # :nodoc:
138
+ unexpected = nil
139
+ args.each do |arg|
140
+ next if arg.is_a?(Symbol) || Arel.arel_node?(arg) || permit.match?(arg.to_s)
141
+ (unexpected ||= []) << arg
142
+ end
143
+
144
+ return unless unexpected
145
+
146
+ if allow_unsafe_raw_sql == :deprecated
147
+ ActiveSupport::Deprecation.warn(
148
+ "Dangerous query method (method whose arguments are used as raw " \
149
+ "SQL) called with non-attribute argument(s): " \
150
+ "#{unexpected.map(&:inspect).join(", ")}. Non-attribute " \
151
+ "arguments will be disallowed in Rails 6.1. This method should " \
152
+ "not be called with user-provided values, such as request " \
153
+ "parameters or model attributes. Known-safe values can be passed " \
154
+ "by wrapping them in Arel.sql()."
155
+ )
156
+ else
157
+ raise(ActiveRecord::UnknownAttributeReference,
158
+ "Query method called with non-attribute argument(s): " +
159
+ unexpected.map(&:inspect).join(", ")
160
+ )
161
+ end
162
+ end
163
+
136
164
  private
137
165
  def replace_bind_variables(statement, values)
138
166
  raise_if_bind_arity_mismatch(statement, statement.count("?"), values.size)
@@ -50,7 +50,7 @@ module ActiveRecord
50
50
  instance_eval(&block)
51
51
 
52
52
  if info[:version].present?
53
- ActiveRecord::SchemaMigration.create_table
53
+ connection.schema_migration.create_table
54
54
  connection.assume_migrated_upto_version(info[:version])
55
55
  end
56
56
 
@@ -146,7 +146,11 @@ HEADER
146
146
  raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
147
147
  next if column.name == pk
148
148
  type, colspec = column_spec(column)
149
- tbl.print " t.#{type} #{column.name.inspect}"
149
+ if type.is_a?(Symbol)
150
+ tbl.print " t.#{type} #{column.name.inspect}"
151
+ else
152
+ tbl.print " t.column #{column.name.inspect}, #{type.inspect}"
153
+ end
150
154
  tbl.print ", #{format_colspec(colspec)}" if colspec.present?
151
155
  tbl.puts
152
156
  end
@@ -4,8 +4,9 @@ module ActiveRecord
4
4
  class TableMetadata # :nodoc:
5
5
  delegate :foreign_type, :foreign_key, :join_primary_key, :join_foreign_key, to: :association, prefix: true
6
6
 
7
- def initialize(klass, arel_table, association = nil)
7
+ def initialize(klass, arel_table, association = nil, types = klass)
8
8
  @klass = klass
9
+ @types = types
9
10
  @arel_table = arel_table
10
11
  @association = association
11
12
  end
@@ -29,11 +30,7 @@ module ActiveRecord
29
30
  end
30
31
 
31
32
  def type(column_name)
32
- if klass
33
- klass.type_for_attribute(column_name)
34
- else
35
- Type.default_value
36
- end
33
+ types.type_for_attribute(column_name)
37
34
  end
38
35
 
39
36
  def has_column?(column_name)
@@ -52,13 +49,12 @@ module ActiveRecord
52
49
  elsif association && !association.polymorphic?
53
50
  association_klass = association.klass
54
51
  arel_table = association_klass.arel_table.alias(table_name)
52
+ TableMetadata.new(association_klass, arel_table, association)
55
53
  else
56
54
  type_caster = TypeCaster::Connection.new(klass, table_name)
57
- association_klass = nil
58
55
  arel_table = Arel::Table.new(table_name, type_caster: type_caster)
56
+ TableMetadata.new(nil, arel_table, association, type_caster)
59
57
  end
60
-
61
- TableMetadata.new(association_klass, arel_table, association)
62
58
  end
63
59
 
64
60
  def polymorphic_association?
@@ -74,6 +70,6 @@ module ActiveRecord
74
70
  end
75
71
 
76
72
  private
77
- attr_reader :klass, :arel_table, :association
73
+ attr_reader :klass, :types, :arel_table, :association
78
74
  end
79
75
  end
@@ -141,10 +141,19 @@ module ActiveRecord
141
141
  end
142
142
  end
143
143
 
144
- def for_each
144
+ def setup_initial_database_yaml
145
145
  return {} unless defined?(Rails)
146
146
 
147
- databases = Rails.application.config.load_database_yaml
147
+ begin
148
+ Rails.application.config.load_database_yaml
149
+ rescue
150
+ $stderr.puts "Rails couldn't infer whether you are using multiple databases from your database.yml and can't generate the tasks for the non-primary databases. If you'd like to use this feature, please simplify your ERB."
151
+
152
+ {}
153
+ end
154
+ end
155
+
156
+ def for_each(databases)
148
157
  database_configs = ActiveRecord::DatabaseConfigurations.new(databases).configs_for(env_name: Rails.env)
149
158
 
150
159
  # if this is a single database application we don't want tasks for each primary database
@@ -169,8 +178,8 @@ module ActiveRecord
169
178
  end
170
179
  end
171
180
 
172
- def create_current(environment = env)
173
- each_current_configuration(environment) { |configuration|
181
+ def create_current(environment = env, spec_name = nil)
182
+ each_current_configuration(environment, spec_name) { |configuration|
174
183
  create configuration
175
184
  }
176
185
  ActiveRecord::Base.establish_connection(environment.to_sym)
@@ -200,9 +209,10 @@ module ActiveRecord
200
209
 
201
210
  def truncate_tables(configuration)
202
211
  ActiveRecord::Base.connected_to(database: { truncation: configuration }) do
203
- table_names = ActiveRecord::Base.connection.tables
212
+ conn = ActiveRecord::Base.connection
213
+ table_names = conn.tables
204
214
  table_names -= [
205
- SchemaMigration.table_name,
215
+ conn.schema_migration.table_name,
206
216
  InternalMetadata.table_name
207
217
  ]
208
218
 
@@ -233,7 +243,7 @@ module ActiveRecord
233
243
  end
234
244
 
235
245
  def migrate_status
236
- unless ActiveRecord::SchemaMigration.table_exists?
246
+ unless ActiveRecord::Base.connection.schema_migration.table_exists?
237
247
  Kernel.abort "Schema migrations table does not exist yet."
238
248
  end
239
249
 
@@ -325,6 +335,27 @@ module ActiveRecord
325
335
  Migration.verbose = verbose_was
326
336
  end
327
337
 
338
+ def dump_schema(configuration, format = ActiveRecord::Base.schema_format, spec_name = "primary") # :nodoc:
339
+ require "active_record/schema_dumper"
340
+ filename = dump_filename(spec_name, format)
341
+ connection = ActiveRecord::Base.connection
342
+
343
+ case format
344
+ when :ruby
345
+ File.open(filename, "w:utf-8") do |file|
346
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
347
+ end
348
+ when :sql
349
+ structure_dump(configuration, filename)
350
+ if connection.schema_migration.table_exists?
351
+ File.open(filename, "a") do |f|
352
+ f.puts connection.dump_schema_information
353
+ f.print "\n"
354
+ end
355
+ end
356
+ end
357
+ end
358
+
328
359
  def schema_file(format = ActiveRecord::Base.schema_format)
329
360
  File.join(db_dir, schema_file_type(format))
330
361
  end
@@ -406,12 +437,14 @@ module ActiveRecord
406
437
  task.is_a?(String) ? task.constantize : task
407
438
  end
408
439
 
409
- def each_current_configuration(environment)
440
+ def each_current_configuration(environment, spec_name = nil)
410
441
  environments = [environment]
411
442
  environments << "test" if environment == "development"
412
443
 
413
444
  environments.each do |env|
414
445
  ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
446
+ next if spec_name && spec_name != db_config.spec_name
447
+
415
448
  yield db_config.config, db_config.spec_name, env
416
449
  end
417
450
  end
@@ -3,6 +3,8 @@
3
3
  module ActiveRecord
4
4
  module Tasks # :nodoc:
5
5
  class MySQLDatabaseTasks # :nodoc:
6
+ ER_DB_CREATE_EXISTS = 1007
7
+
6
8
  delegate :connection, :establish_connection, to: ActiveRecord::Base
7
9
 
8
10
  def initialize(configuration)
@@ -14,7 +16,7 @@ module ActiveRecord
14
16
  connection.create_database configuration["database"], creation_options
15
17
  establish_connection configuration
16
18
  rescue ActiveRecord::StatementInvalid => error
17
- if error.message.include?("database exists")
19
+ if error.cause.error_number == ER_DB_CREATE_EXISTS
18
20
  raise DatabaseAlreadyExists
19
21
  else
20
22
  raise
@@ -59,19 +59,26 @@ module ActiveRecord
59
59
  attribute_names.index_with(time || current_time_from_proper_timezone)
60
60
  end
61
61
 
62
- private
63
- def timestamp_attributes_for_create_in_model
64
- timestamp_attributes_for_create.select { |c| column_names.include?(c) }
65
- end
62
+ def timestamp_attributes_for_create_in_model
63
+ @timestamp_attributes_for_create_in_model ||=
64
+ (timestamp_attributes_for_create & column_names).freeze
65
+ end
66
66
 
67
- def timestamp_attributes_for_update_in_model
68
- timestamp_attributes_for_update.select { |c| column_names.include?(c) }
69
- end
67
+ def timestamp_attributes_for_update_in_model
68
+ @timestamp_attributes_for_update_in_model ||=
69
+ (timestamp_attributes_for_update & column_names).freeze
70
+ end
70
71
 
71
- def all_timestamp_attributes_in_model
72
- timestamp_attributes_for_create_in_model + timestamp_attributes_for_update_in_model
73
- end
72
+ def all_timestamp_attributes_in_model
73
+ @all_timestamp_attributes_in_model ||=
74
+ (timestamp_attributes_for_create_in_model + timestamp_attributes_for_update_in_model).freeze
75
+ end
74
76
 
77
+ def current_time_from_proper_timezone
78
+ default_timezone == :utc ? Time.now.utc : Time.now
79
+ end
80
+
81
+ private
75
82
  def timestamp_attributes_for_create
76
83
  ["created_at", "created_on"]
77
84
  end
@@ -80,8 +87,11 @@ module ActiveRecord
80
87
  ["updated_at", "updated_on"]
81
88
  end
82
89
 
83
- def current_time_from_proper_timezone
84
- default_timezone == :utc ? Time.now.utc : Time.now
90
+ def reload_schema_from_cache
91
+ @timestamp_attributes_for_create_in_model = nil
92
+ @timestamp_attributes_for_update_in_model = nil
93
+ @all_timestamp_attributes_in_model = nil
94
+ super
85
95
  end
86
96
  end
87
97
 
@@ -124,19 +134,19 @@ module ActiveRecord
124
134
  end
125
135
 
126
136
  def timestamp_attributes_for_create_in_model
127
- self.class.send(:timestamp_attributes_for_create_in_model)
137
+ self.class.timestamp_attributes_for_create_in_model
128
138
  end
129
139
 
130
140
  def timestamp_attributes_for_update_in_model
131
- self.class.send(:timestamp_attributes_for_update_in_model)
141
+ self.class.timestamp_attributes_for_update_in_model
132
142
  end
133
143
 
134
144
  def all_timestamp_attributes_in_model
135
- self.class.send(:all_timestamp_attributes_in_model)
145
+ self.class.all_timestamp_attributes_in_model
136
146
  end
137
147
 
138
148
  def current_time_from_proper_timezone
139
- self.class.send(:current_time_from_proper_timezone)
149
+ self.class.current_time_from_proper_timezone
140
150
  end
141
151
 
142
152
  def max_updated_column_timestamp