activerecord 5.2.0.beta2 → 5.2.0.rc1

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 (80) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +231 -2
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_record.rb +1 -1
  6. data/lib/active_record/aggregations.rb +4 -5
  7. data/lib/active_record/association_relation.rb +2 -2
  8. data/lib/active_record/associations.rb +18 -12
  9. data/lib/active_record/associations/alias_tracker.rb +2 -10
  10. data/lib/active_record/associations/association.rb +1 -1
  11. data/lib/active_record/associations/belongs_to_association.rb +9 -9
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -6
  13. data/lib/active_record/associations/builder/association.rb +2 -2
  14. data/lib/active_record/associations/builder/belongs_to.rb +7 -3
  15. data/lib/active_record/associations/collection_association.rb +2 -2
  16. data/lib/active_record/associations/collection_proxy.rb +1 -1
  17. data/lib/active_record/associations/has_many_association.rb +1 -1
  18. data/lib/active_record/associations/has_many_through_association.rb +4 -17
  19. data/lib/active_record/associations/has_one_through_association.rb +5 -6
  20. data/lib/active_record/associations/preloader.rb +1 -1
  21. data/lib/active_record/associations/preloader/association.rb +2 -2
  22. data/lib/active_record/associations/through_association.rb +22 -9
  23. data/lib/active_record/attribute_methods.rb +1 -5
  24. data/lib/active_record/attribute_methods/dirty.rb +2 -4
  25. data/lib/active_record/attributes.rb +1 -1
  26. data/lib/active_record/autosave_association.rb +3 -0
  27. data/lib/active_record/callbacks.rb +2 -2
  28. data/lib/active_record/collection_cache_key.rb +5 -6
  29. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1 -3
  30. data/lib/active_record/connection_adapters/abstract/database_statements.rb +57 -21
  31. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +1 -0
  32. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +20 -3
  33. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +55 -15
  34. data/lib/active_record/connection_adapters/abstract_adapter.rb +19 -6
  35. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +55 -64
  36. data/lib/active_record/connection_adapters/mysql/database_statements.rb +8 -1
  37. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +0 -4
  38. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +21 -6
  39. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +1 -1
  40. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
  41. data/lib/active_record/connection_adapters/postgresql/quoting.rb +9 -1
  42. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +12 -0
  43. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +13 -4
  44. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +170 -48
  45. data/lib/active_record/connection_adapters/postgresql_adapter.rb +15 -5
  46. data/lib/active_record/connection_adapters/schema_cache.rb +2 -2
  47. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +63 -18
  48. data/lib/active_record/core.rb +12 -3
  49. data/lib/active_record/enum.rb +2 -0
  50. data/lib/active_record/fixtures.rb +28 -37
  51. data/lib/active_record/gem_version.rb +1 -1
  52. data/lib/active_record/inheritance.rb +3 -4
  53. data/lib/active_record/log_subscriber.rb +41 -0
  54. data/lib/active_record/migration.rb +138 -120
  55. data/lib/active_record/migration/compatibility.rb +20 -0
  56. data/lib/active_record/model_schema.rb +19 -16
  57. data/lib/active_record/persistence.rb +8 -11
  58. data/lib/active_record/railtie.rb +7 -2
  59. data/lib/active_record/railties/databases.rake +8 -11
  60. data/lib/active_record/reflection.rb +10 -13
  61. data/lib/active_record/relation.rb +27 -17
  62. data/lib/active_record/relation/calculations.rb +17 -12
  63. data/lib/active_record/relation/finder_methods.rb +30 -37
  64. data/lib/active_record/relation/merger.rb +30 -2
  65. data/lib/active_record/relation/predicate_builder.rb +12 -0
  66. data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -1
  67. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
  68. data/lib/active_record/relation/query_methods.rb +14 -24
  69. data/lib/active_record/relation/spawn_methods.rb +1 -1
  70. data/lib/active_record/relation/where_clause.rb +16 -2
  71. data/lib/active_record/relation/where_clause_factory.rb +1 -2
  72. data/lib/active_record/sanitization.rb +130 -128
  73. data/lib/active_record/schema.rb +1 -1
  74. data/lib/active_record/schema_dumper.rb +12 -3
  75. data/lib/active_record/scoping/named.rb +6 -0
  76. data/lib/active_record/store.rb +1 -1
  77. data/lib/active_record/table_metadata.rb +10 -3
  78. data/lib/active_record/tasks/database_tasks.rb +4 -4
  79. data/lib/active_record/type_caster/map.rb +1 -1
  80. metadata +9 -9
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Make sure we're using pg high enough for type casts and Ruby 2.2+ compatibility
4
- gem "pg", "~> 0.18"
4
+ gem "pg", ">= 0.18", "< 2.0"
5
5
  require "pg"
6
6
 
7
7
  require "active_record/connection_adapters/abstract_adapter"
@@ -122,6 +122,10 @@ module ActiveRecord
122
122
  include PostgreSQL::SchemaStatements
123
123
  include PostgreSQL::DatabaseStatements
124
124
 
125
+ def supports_bulk_alter?
126
+ true
127
+ end
128
+
125
129
  def supports_index_sort_order?
126
130
  true
127
131
  end
@@ -142,6 +146,10 @@ module ActiveRecord
142
146
  true
143
147
  end
144
148
 
149
+ def supports_validate_constraints?
150
+ true
151
+ end
152
+
145
153
  def supports_views?
146
154
  true
147
155
  end
@@ -166,7 +174,7 @@ module ActiveRecord
166
174
  { concurrently: "CONCURRENTLY" }
167
175
  end
168
176
 
169
- class StatementPool < ConnectionAdapters::StatementPool
177
+ class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
170
178
  def initialize(connection, max)
171
179
  super(max)
172
180
  @connection = connection
@@ -182,7 +190,6 @@ module ActiveRecord
182
190
  end
183
191
 
184
192
  private
185
-
186
193
  def dealloc(key)
187
194
  @connection.query "DEALLOCATE #{key}" if connection_active?
188
195
  rescue PG::Error
@@ -274,7 +281,7 @@ module ActiveRecord
274
281
  end
275
282
 
276
283
  def discard! # :nodoc:
277
- @connection.socket_io.reopen(IO::NULL)
284
+ @connection.socket_io.reopen(IO::NULL) rescue nil
278
285
  @connection = nil
279
286
  end
280
287
 
@@ -311,6 +318,10 @@ module ActiveRecord
311
318
  postgresql_version >= 90300
312
319
  end
313
320
 
321
+ def supports_foreign_tables?
322
+ postgresql_version >= 90300
323
+ end
324
+
314
325
  def supports_pgcrypto_uuid?
315
326
  postgresql_version >= 90400
316
327
  end
@@ -387,7 +398,6 @@ module ActiveRecord
387
398
  end
388
399
 
389
400
  private
390
-
391
401
  # See https://www.postgresql.org/docs/current/static/errcodes-appendix.html
392
402
  VALUE_LIMIT_VIOLATION = "22001"
393
403
  NUMERIC_VALUE_OUT_OF_RANGE = "22003"
@@ -28,7 +28,7 @@ module ActiveRecord
28
28
  coder["columns_hash"] = @columns_hash
29
29
  coder["primary_keys"] = @primary_keys
30
30
  coder["data_sources"] = @data_sources
31
- coder["version"] = ActiveRecord::Migrator.current_version
31
+ coder["version"] = connection.migration_context.current_version
32
32
  end
33
33
 
34
34
  def init_with(coder)
@@ -100,7 +100,7 @@ module ActiveRecord
100
100
 
101
101
  def marshal_dump
102
102
  # if we get current version during initialization, it happens stack over flow.
103
- @version = ActiveRecord::Migrator.current_version
103
+ @version = connection.migration_context.current_version
104
104
  [@version, @columns, @columns_hash, @primary_keys, @data_sources]
105
105
  end
106
106
 
@@ -60,7 +60,7 @@ module ActiveRecord
60
60
  include SQLite3::SchemaStatements
61
61
 
62
62
  NATIVE_DATABASE_TYPES = {
63
- primary_key: "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL",
63
+ primary_key: "integer PRIMARY KEY AUTOINCREMENT NOT NULL",
64
64
  string: { name: "varchar" },
65
65
  text: { name: "text" },
66
66
  integer: { name: "integer" },
@@ -70,7 +70,8 @@ module ActiveRecord
70
70
  time: { name: "time" },
71
71
  date: { name: "date" },
72
72
  binary: { name: "blob" },
73
- boolean: { name: "boolean" }
73
+ boolean: { name: "boolean" },
74
+ json: { name: "json" },
74
75
  }
75
76
 
76
77
  ##
@@ -90,9 +91,8 @@ module ActiveRecord
90
91
  # Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
91
92
  class_attribute :represent_boolean_as_integer, default: false
92
93
 
93
- class StatementPool < ConnectionAdapters::StatementPool
94
+ class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
94
95
  private
95
-
96
96
  def dealloc(stmt)
97
97
  stmt[:stmt].close unless stmt[:stmt].closed?
98
98
  end
@@ -101,7 +101,7 @@ module ActiveRecord
101
101
  def initialize(connection, logger, connection_options, config)
102
102
  super(connection, logger, config)
103
103
 
104
- @active = nil
104
+ @active = true
105
105
  @statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit]))
106
106
 
107
107
  configure_connection
@@ -135,12 +135,16 @@ module ActiveRecord
135
135
  true
136
136
  end
137
137
 
138
+ def supports_json?
139
+ true
140
+ end
141
+
138
142
  def supports_multi_insert?
139
143
  sqlite_version >= "3.7.11"
140
144
  end
141
145
 
142
146
  def active?
143
- @active != false
147
+ @active
144
148
  end
145
149
 
146
150
  # Disconnects from the database if already connected. Otherwise, this
@@ -286,19 +290,18 @@ module ActiveRecord
286
290
  rename_table_indexes(table_name, new_name)
287
291
  end
288
292
 
289
- # See: https://www.sqlite.org/lang_altertable.html
290
- # SQLite has an additional restriction on the ALTER TABLE statement
291
- def valid_alter_table_type?(type)
292
- type.to_sym != :primary_key
293
+ def valid_alter_table_type?(type, options = {})
294
+ !invalid_alter_table_type?(type, options)
293
295
  end
296
+ deprecate :valid_alter_table_type?
294
297
 
295
298
  def add_column(table_name, column_name, type, options = {}) #:nodoc:
296
- if valid_alter_table_type?(type)
297
- super(table_name, column_name, type, options)
298
- else
299
+ if invalid_alter_table_type?(type, options)
299
300
  alter_table(table_name) do |definition|
300
301
  definition.column(column_name, type, options)
301
302
  end
303
+ else
304
+ super
302
305
  end
303
306
  end
304
307
 
@@ -364,12 +367,30 @@ module ActiveRecord
364
367
  end
365
368
 
366
369
  def insert_fixtures(rows, table_name)
367
- rows.each do |row|
368
- insert_fixture(row, table_name)
370
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
371
+ `insert_fixtures` is deprecated and will be removed in the next version of Rails.
372
+ Consider using `insert_fixtures_set` for performance improvement.
373
+ MSG
374
+ insert_fixtures_set(table_name => rows)
375
+ end
376
+
377
+ def insert_fixtures_set(fixture_set, tables_to_delete = [])
378
+ disable_referential_integrity do
379
+ transaction(requires_new: true) do
380
+ tables_to_delete.each { |table| delete "DELETE FROM #{quote_table_name(table)}", "Fixture Delete" }
381
+
382
+ fixture_set.each do |table_name, rows|
383
+ rows.each { |row| insert_fixture(row, table_name) }
384
+ end
385
+ end
369
386
  end
370
387
  end
371
388
 
372
389
  private
390
+ def initialize_type_map(m = type_map)
391
+ super
392
+ register_class_with_limit m, %r(int)i, SQLite3Integer
393
+ end
373
394
 
374
395
  def table_structure(table_name)
375
396
  structure = exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", "SCHEMA")
@@ -378,6 +399,12 @@ module ActiveRecord
378
399
  end
379
400
  alias column_definitions table_structure
380
401
 
402
+ # See: https://www.sqlite.org/lang_altertable.html
403
+ # SQLite has an additional restriction on the ALTER TABLE statement
404
+ def invalid_alter_table_type?(type, options)
405
+ type.to_sym == :primary_key || options[:primary_key]
406
+ end
407
+
381
408
  def alter_table(table_name, options = {})
382
409
  altered_table_name = "a#{table_name}"
383
410
  caller = lambda { |definition| yield definition if block_given? }
@@ -399,18 +426,21 @@ module ActiveRecord
399
426
  options[:id] = false
400
427
  create_table(to, options) do |definition|
401
428
  @definition = definition
402
- @definition.primary_key(from_primary_key) if from_primary_key.present?
429
+ if from_primary_key.is_a?(Array)
430
+ @definition.primary_keys from_primary_key
431
+ end
403
432
  columns(from).each do |column|
404
433
  column_name = options[:rename] ?
405
434
  (options[:rename][column.name] ||
406
435
  options[:rename][column.name.to_sym] ||
407
436
  column.name) : column.name
408
- next if column_name == from_primary_key
409
437
 
410
438
  @definition.column(column_name, column.type,
411
439
  limit: column.limit, default: column.default,
412
440
  precision: column.precision, scale: column.scale,
413
- null: column.null, collation: column.collation)
441
+ null: column.null, collation: column.collation,
442
+ primary_key: column_name == from_primary_key
443
+ )
414
444
  end
415
445
  yield @definition if block_given?
416
446
  end
@@ -423,6 +453,9 @@ module ActiveRecord
423
453
  def copy_table_indexes(from, to, rename = {})
424
454
  indexes(from).each do |index|
425
455
  name = index.name
456
+ # indexes sqlite creates for internal use start with `sqlite_` and
457
+ # don't need to be copied
458
+ next if name.starts_with?("sqlite_")
426
459
  if to == "a#{from}"
427
460
  name = "t#{name}"
428
461
  elsif from == "a#{to}"
@@ -438,6 +471,7 @@ module ActiveRecord
438
471
  # index name can't be the same
439
472
  opts = { name: name.gsub(/(^|_)(#{from})_/, "\\1#{to}_"), internal: true }
440
473
  opts[:unique] = true if index.unique
474
+ opts[:where] = index.where if index.where
441
475
  add_index(to, columns, opts)
442
476
  end
443
477
  end
@@ -525,6 +559,17 @@ module ActiveRecord
525
559
  def configure_connection
526
560
  execute("PRAGMA foreign_keys = ON", "SCHEMA")
527
561
  end
562
+
563
+ class SQLite3Integer < Type::Integer # :nodoc:
564
+ private
565
+ def _limit
566
+ # INTEGER storage class can be stored 8 bytes value.
567
+ # See https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes
568
+ limit || 8
569
+ end
570
+ end
571
+
572
+ ActiveRecord::Type.register(:integer, SQLite3Integer, adapter: :sqlite3)
528
573
  end
529
574
  ActiveSupport.run_load_hooks(:active_record_sqlite3adapter, SQLite3Adapter)
530
575
  end
@@ -17,6 +17,13 @@ module ActiveRecord
17
17
  # retrieved on both a class and instance level by calling +logger+.
18
18
  mattr_accessor :logger, instance_writer: false
19
19
 
20
+ ##
21
+ # :singleton-method:
22
+ #
23
+ # Specifies if the methods calling database queries should be logged below
24
+ # their relevant queries. Defaults to false.
25
+ mattr_accessor :verbose_query_logs, instance_writer: false, default: false
26
+
20
27
  ##
21
28
  # Contains the database configuration - as is typically stored in config/database.yml -
22
29
  # as a Hash.
@@ -274,7 +281,7 @@ module ActiveRecord
274
281
  end
275
282
 
276
283
  def relation
277
- relation = Relation.create(self, arel_table, predicate_builder)
284
+ relation = Relation.create(self)
278
285
 
279
286
  if finder_needs_type_condition? && !ignore_default_scope?
280
287
  relation.where!(type_condition)
@@ -375,8 +382,10 @@ module ActiveRecord
375
382
 
376
383
  _run_initialize_callbacks
377
384
 
378
- @new_record = true
379
- @destroyed = false
385
+ @new_record = true
386
+ @destroyed = false
387
+ @_start_transaction_state = {}
388
+ @transaction_state = nil
380
389
 
381
390
  super
382
391
  end
@@ -221,6 +221,8 @@ module ActiveRecord
221
221
  def detect_enum_conflict!(enum_name, method_name, klass_method = false)
222
222
  if klass_method && dangerous_class_method?(method_name)
223
223
  raise_conflict_error(enum_name, method_name, type: "class")
224
+ elsif klass_method && method_defined_within?(method_name, Relation)
225
+ raise_conflict_error(enum_name, method_name, type: "class", source: Relation.name)
224
226
  elsif !klass_method && dangerous_attribute_method?(method_name)
225
227
  raise_conflict_error(enum_name, method_name)
226
228
  elsif !klass_method && method_defined_within?(method_name, _enum_methods_module, Module)
@@ -169,13 +169,13 @@ module ActiveRecord
169
169
  # self.use_transactional_tests = true
170
170
  #
171
171
  # test "godzilla" do
172
- # assert !Foo.all.empty?
172
+ # assert_not_empty Foo.all
173
173
  # Foo.destroy_all
174
- # assert Foo.all.empty?
174
+ # assert_empty Foo.all
175
175
  # end
176
176
  #
177
177
  # test "godzilla aftermath" do
178
- # assert !Foo.all.empty?
178
+ # assert_not_empty Foo.all
179
179
  # end
180
180
  # end
181
181
  #
@@ -540,47 +540,38 @@ module ActiveRecord
540
540
  }
541
541
 
542
542
  unless files_to_read.empty?
543
- connection.disable_referential_integrity do
544
- fixtures_map = {}
545
-
546
- fixture_sets = files_to_read.map do |fs_name|
547
- klass = class_names[fs_name]
548
- conn = klass ? klass.connection : connection
549
- fixtures_map[fs_name] = new( # ActiveRecord::FixtureSet.new
550
- conn,
551
- fs_name,
552
- klass,
553
- ::File.join(fixtures_directory, fs_name))
554
- end
555
-
556
- update_all_loaded_fixtures fixtures_map
557
-
558
- connection.transaction(requires_new: true) do
559
- deleted_tables = Hash.new { |h, k| h[k] = Set.new }
560
- fixture_sets.each do |fs|
561
- conn = fs.model_class.respond_to?(:connection) ? fs.model_class.connection : connection
562
- table_rows = fs.table_rows
543
+ fixtures_map = {}
544
+
545
+ fixture_sets = files_to_read.map do |fs_name|
546
+ klass = class_names[fs_name]
547
+ conn = klass ? klass.connection : connection
548
+ fixtures_map[fs_name] = new( # ActiveRecord::FixtureSet.new
549
+ conn,
550
+ fs_name,
551
+ klass,
552
+ ::File.join(fixtures_directory, fs_name))
553
+ end
563
554
 
564
- table_rows.each_key do |table|
565
- unless deleted_tables[conn].include? table
566
- conn.delete "DELETE FROM #{conn.quote_table_name(table)}", "Fixture Delete"
567
- end
568
- deleted_tables[conn] << table
569
- end
555
+ update_all_loaded_fixtures fixtures_map
556
+ fixture_sets_by_connection = fixture_sets.group_by { |fs| fs.model_class ? fs.model_class.connection : connection }
570
557
 
571
- table_rows.each do |fixture_set_name, rows|
572
- conn.insert_fixtures(rows, fixture_set_name)
573
- end
558
+ fixture_sets_by_connection.each do |conn, set|
559
+ table_rows_for_connection = Hash.new { |h, k| h[k] = [] }
574
560
 
575
- # Cap primary key sequences to max(pk).
576
- if conn.respond_to?(:reset_pk_sequence!)
577
- conn.reset_pk_sequence!(fs.table_name)
578
- end
561
+ set.each do |fs|
562
+ fs.table_rows.each do |table, rows|
563
+ table_rows_for_connection[table].unshift(*rows)
579
564
  end
580
565
  end
566
+ conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
581
567
 
582
- cache_fixtures(connection, fixtures_map)
568
+ # Cap primary key sequences to max(pk).
569
+ if conn.respond_to?(:reset_pk_sequence!)
570
+ set.each { |fs| conn.reset_pk_sequence!(fs.table_name) }
571
+ end
583
572
  end
573
+
574
+ cache_fixtures(connection, fixtures_map)
584
575
  end
585
576
  cached_fixtures(connection, fixture_set_names)
586
577
  end
@@ -10,7 +10,7 @@ module ActiveRecord
10
10
  MAJOR = 5
11
11
  MINOR = 2
12
12
  TINY = 0
13
- PRE = "beta2"
13
+ PRE = "rc1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -47,14 +47,13 @@ module ActiveRecord
47
47
  # Determines if one of the attributes passed in is the inheritance column,
48
48
  # and if the inheritance column is attr accessible, it initializes an
49
49
  # instance of the given subclass instead of the base class.
50
- def new(*args, &block)
50
+ def new(attributes = nil, &block)
51
51
  if abstract_class? || self == Base
52
52
  raise NotImplementedError, "#{self} is an abstract class and cannot be instantiated."
53
53
  end
54
54
 
55
- attrs = args.first
56
55
  if has_attribute?(inheritance_column)
57
- subclass = subclass_from_attributes(attrs)
56
+ subclass = subclass_from_attributes(attributes)
58
57
 
59
58
  if subclass.nil? && base_class == self
60
59
  subclass = subclass_from_attributes(column_defaults)
@@ -62,7 +61,7 @@ module ActiveRecord
62
61
  end
63
62
 
64
63
  if subclass && subclass != self
65
- subclass.new(*args, &block)
64
+ subclass.new(attributes, &block)
66
65
  else
67
66
  super
68
67
  end
@@ -90,6 +90,47 @@ module ActiveRecord
90
90
  def logger
91
91
  ActiveRecord::Base.logger
92
92
  end
93
+
94
+ def debug(progname = nil, &block)
95
+ return unless super
96
+
97
+ if ActiveRecord::Base.verbose_query_logs
98
+ log_query_source
99
+ end
100
+ end
101
+
102
+ def log_query_source
103
+ source_line, line_number = extract_callstack(caller_locations)
104
+
105
+ if source_line
106
+ if defined?(::Rails.root)
107
+ app_root = "#{::Rails.root.to_s}/".freeze
108
+ source_line = source_line.sub(app_root, "")
109
+ end
110
+
111
+ logger.debug(" ↳ #{ source_line }:#{ line_number }")
112
+ end
113
+ end
114
+
115
+ def extract_callstack(callstack)
116
+ line = callstack.find do |frame|
117
+ frame.absolute_path && !ignored_callstack(frame.absolute_path)
118
+ end
119
+
120
+ offending_line = line || callstack.first
121
+
122
+ [
123
+ offending_line.path,
124
+ offending_line.lineno
125
+ ]
126
+ end
127
+
128
+ RAILS_GEM_ROOT = File.expand_path("../../../..", __FILE__) + "/"
129
+
130
+ def ignored_callstack(path)
131
+ path.start_with?(RAILS_GEM_ROOT) ||
132
+ path.start_with?(RbConfig::CONFIG["rubylibdir"])
133
+ end
93
134
  end
94
135
  end
95
136