Skip to content

Commit c65088f

Browse files
authored
Implement #1707 (#1719)
* Extract Rails 5.0 and 5.1 * Give each major Rails change their own app files * Reduce duplicated app init logic
1 parent 32d7e64 commit c65088f

6 files changed

Lines changed: 658 additions & 172 deletions

File tree

Lines changed: 27 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -1,180 +1,42 @@
11
ENV["RAILS_ENV"] = "test"
22

3-
require 'rails'
3+
require "rails"
4+
45
require "active_record"
56
require "active_job/railtie"
6-
require "active_storage/engine" if Rails.version.to_f >= 5.2
7-
require "action_cable/engine" if Rails.version.to_f >= 6.0
87
require "action_view/railtie"
98
require "action_controller/railtie"
109

11-
# require "action_mailer/railtie"
12-
# require "sprockets/railtie"
13-
# require "rails/test_unit/railtie"
1410
require 'sentry/rails'
1511

1612
ActiveSupport::Deprecation.silenced = true
13+
ActiveRecord::Base.logger = Logger.new(nil)
1714

1815
# need to init app before establish connection so sqlite can place the database file under the correct project root
1916
class TestApp < Rails::Application
2017
end
2118

22-
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: "db")
23-
ActiveRecord::Base.logger = Logger.new(nil)
24-
25-
ActiveRecord::Schema.define do
26-
create_table "active_storage_attachments", force: :cascade do |t|
27-
t.string "name", null: false
28-
t.string "record_type", null: false
29-
t.integer "record_id", null: false
30-
t.integer "blob_id", null: false
31-
t.datetime "created_at", null: false
32-
t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
33-
t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
34-
end
35-
36-
create_table "active_storage_blobs", force: :cascade do |t|
37-
t.string "key", null: false
38-
t.string "filename", null: false
39-
t.string "content_type"
40-
t.text "metadata"
41-
t.string "service_name"
42-
t.bigint "byte_size", null: false
43-
t.string "checksum", null: false
44-
t.datetime "created_at", null: false
45-
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
46-
end
47-
48-
create_table "active_storage_variant_records", force: :cascade do |t|
49-
t.integer "blob_id", null: false
50-
t.string "variation_digest", null: false
51-
t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
52-
end
53-
54-
create_table :posts, force: true do |t|
55-
end
56-
57-
create_table :comments, force: true do |t|
58-
t.integer :post_id
59-
end
19+
v5_2 = Gem::Version.new("5.2")
20+
v6_0 = Gem::Version.new("6.0")
21+
v6_1 = Gem::Version.new("6.1")
22+
v7_0 = Gem::Version.new("7.0")
23+
v7_1 = Gem::Version.new("7.1")
24+
25+
case Gem::Version.new(Rails.version)
26+
when -> (v) { v < v5_2 }
27+
require "support/test_rails_app/apps/5-0"
28+
when -> (v) { v.between?(v5_2, v6_0) }
29+
require "support/test_rails_app/apps/5-2"
30+
when -> (v) { v.between?(v6_0, v6_1) }
31+
require "support/test_rails_app/apps/6-0"
32+
when -> (v) { v.between?(v6_1, v7_0) }
33+
require "support/test_rails_app/apps/6-1"
34+
when -> (v) { v.between?(v7_0, v7_1) }
35+
require "support/test_rails_app/apps/7-0"
6036
end
6137

62-
class ApplicationRecord < ActiveRecord::Base
63-
self.abstract_class = true
64-
65-
if defined?(ActiveStorage)
66-
if Rails.version.to_f < 6.0
67-
extend ActiveStorage::Attached::Macros
68-
else
69-
include ActiveStorage::Attached::Model
70-
include ActiveStorage::Reflection::ActiveRecordExtensions
71-
ActiveRecord::Reflection.singleton_class.prepend(ActiveStorage::Reflection::ReflectionExtension)
72-
end
73-
end
74-
end
75-
76-
class Post < ApplicationRecord
77-
has_many :comments
78-
has_one_attached :cover if defined?(ActiveStorage)
79-
end
80-
81-
class Comment < ApplicationRecord
82-
belongs_to :post
83-
end
84-
85-
class PostsController < ActionController::Base
86-
def index
87-
Post.all.to_a
88-
raise "foo"
89-
end
90-
91-
def show
92-
p = Post.find(params[:id])
93-
94-
render plain: p.id
95-
end
96-
97-
def attach
98-
p = Post.find(params[:id])
99-
100-
attach_params = {
101-
io: File.open(File.join(Rails.root, 'public', 'sentry-logo.png')),
102-
filename: 'sentry-logo.png',
103-
}
104-
105-
unless Rails.version.to_f < 6.1
106-
attach_params[:service_name] = "test"
107-
end
108-
109-
p.cover.attach(attach_params)
110-
111-
render plain: p.id end
112-
end
113-
114-
class HelloController < ActionController::Base
115-
prepend_view_path "spec/support/test_rails_app"
116-
117-
def exception
118-
raise "An unhandled exception!"
119-
end
120-
121-
def reporting
122-
render plain: Sentry.last_event_id
123-
end
124-
125-
def view_exception
126-
render inline: "<%= foo %>"
127-
end
128-
129-
def view
130-
render template: "test_template"
131-
end
132-
133-
def world
134-
render :plain => "Hello World!"
135-
end
136-
137-
def with_custom_instrumentation
138-
custom_event = "custom.instrument"
139-
ActiveSupport::Notifications.subscribe(custom_event) do |*args|
140-
data = args[-1]
141-
data += 1
142-
end
143-
144-
ActiveSupport::Notifications.instrument(custom_event, 1)
145-
146-
head :ok
147-
end
148-
149-
def not_found
150-
raise ActionController::BadRequest
151-
end
152-
end
153-
154-
def make_basic_app
155-
# Zeitwerk checks if registered loaders load paths repeatedly and raises error if that happens.
156-
# And because every new Rails::Application instance registers its own loader, we need to clear previously registered ones from Zeitwerk.
157-
Zeitwerk::Registry.loaders.clear if defined?(Zeitwerk)
158-
159-
# Rails removes the support of multiple instances, which includes freezing some setting values.
160-
# This is the workaround to avoid FrozenError. Related issue: https://github.com/rails/rails/issues/42319
161-
ActiveSupport::Dependencies.autoload_once_paths = []
162-
ActiveSupport::Dependencies.autoload_paths = []
163-
164-
# there are a few Rails initializers/finializers that register hook to the executor
165-
# because the callbacks are stored inside the `ActiveSupport::Executor` class instead of an instance
166-
# the callbacks duplicate after each time we initialize the application and cause issues when they're executed
167-
ActiveSupport::Executor.reset_callbacks(:run)
168-
ActiveSupport::Executor.reset_callbacks(:complete)
169-
170-
# Rails uses this module to set a global context for its ErrorReporter feature.
171-
# this needs to be cleared so previously set context won't pollute later reportings (see ErrorSubscriber).
172-
ActiveSupport::ExecutionContext.clear if defined?(ActiveSupport::ExecutionContext)
173-
174-
if defined?(ActionCable)
175-
ActionCable::Channel::Base.reset_callbacks(:subscribe)
176-
ActionCable::Channel::Base.reset_callbacks(:unsubscribe)
177-
end
38+
def make_basic_app(&block)
39+
run_pre_initialize_cleanup
17840

17941
app = Class.new(TestApp) do
18042
def self.name
@@ -187,14 +49,7 @@ def self.name
18749
app.config.logger = Logger.new(nil)
18850
app.config.eager_load = true
18951

190-
if ::Rails.version.to_f >= 5.2
191-
app.config.active_storage.service = :test
192-
end
193-
194-
if ::Rails.version.to_f == 6.0
195-
app.config.active_record.sqlite3 = ActiveSupport::OrderedOptions.new
196-
app.config.active_record.sqlite3.represent_boolean_as_integer = nil
197-
end
52+
configure_app(app)
19853

19954
app.routes.append do
20055
get "/exception", :to => "hello#exception"
@@ -226,12 +81,12 @@ def self.name
22681

22782
app.initialize!
22883

84+
Rails.application = app
85+
22986
Post.all.to_a # to run the sqlte version query first
23087

231-
if Sentry.initialized?
232-
Sentry.get_current_scope.clear_breadcrumbs # and then clear breadcrumbs in case the above query is recorded
233-
end
88+
# and then clear breadcrumbs in case the above query is recorded
89+
Sentry.get_current_scope.clear_breadcrumbs if Sentry.initialized?
23490

235-
Rails.application = app
23691
app
23792
end
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: "db")
2+
3+
ActiveRecord::Schema.define do
4+
create_table :posts, force: true do |t|
5+
end
6+
7+
create_table :comments, force: true do |t|
8+
t.integer :post_id
9+
end
10+
end
11+
12+
class ApplicationRecord < ActiveRecord::Base
13+
self.abstract_class = true
14+
end
15+
16+
class Post < ApplicationRecord
17+
has_many :comments
18+
end
19+
20+
class Comment < ApplicationRecord
21+
belongs_to :post
22+
end
23+
24+
class PostsController < ActionController::Base
25+
def index
26+
Post.all.to_a
27+
raise "foo"
28+
end
29+
30+
def show
31+
p = Post.find(params[:id])
32+
33+
render plain: p.id
34+
end
35+
end
36+
37+
class HelloController < ActionController::Base
38+
prepend_view_path "spec/support/test_rails_app"
39+
40+
def exception
41+
raise "An unhandled exception!"
42+
end
43+
44+
def reporting
45+
render plain: Sentry.last_event_id
46+
end
47+
48+
def view_exception
49+
render inline: "<%= foo %>"
50+
end
51+
52+
def view
53+
render template: "test_template"
54+
end
55+
56+
def world
57+
render :plain => "Hello World!"
58+
end
59+
60+
def with_custom_instrumentation
61+
custom_event = "custom.instrument"
62+
ActiveSupport::Notifications.subscribe(custom_event) do |*args|
63+
data = args[-1]
64+
data += 1
65+
end
66+
67+
ActiveSupport::Notifications.instrument(custom_event, 1)
68+
69+
head :ok
70+
end
71+
72+
def not_found
73+
raise ActionController::BadRequest
74+
end
75+
end
76+
77+
def run_pre_initialize_cleanup; end
78+
79+
def configure_app(app); end

0 commit comments

Comments
 (0)