ardb 0.28.0 → 0.29.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +7 -7
  2. data/Gemfile +19 -8
  3. data/README.md +252 -3
  4. data/ardb.gemspec +8 -7
  5. data/bin/ardb +1 -1
  6. data/lib/ardb.rb +55 -39
  7. data/lib/ardb/adapter/base.rb +35 -30
  8. data/lib/ardb/adapter/mysql.rb +2 -17
  9. data/lib/ardb/adapter/postgresql.rb +24 -30
  10. data/lib/ardb/adapter/sqlite.rb +4 -8
  11. data/lib/ardb/adapter_spy.rb +2 -16
  12. data/lib/ardb/cli.rb +15 -15
  13. data/lib/ardb/cli/clirb.rb +14 -17
  14. data/lib/ardb/cli/commands.rb +204 -114
  15. data/lib/ardb/db_tests.rb +2 -4
  16. data/lib/ardb/default_order_by.rb +3 -13
  17. data/lib/ardb/migration.rb +9 -13
  18. data/lib/ardb/record_spy.rb +7 -26
  19. data/lib/ardb/relation_spy.rb +0 -6
  20. data/lib/ardb/require_autoloaded_active_record_files.rb +172 -58
  21. data/lib/ardb/test_helpers.rb +2 -5
  22. data/lib/ardb/use_db_default.rb +4 -15
  23. data/lib/ardb/version.rb +1 -1
  24. data/script/determine_autoloaded_active_record_files.rb +14 -9
  25. data/test/helper.rb +4 -13
  26. data/test/support/factory.rb +2 -2
  27. data/test/support/postgresql/migrations/{.gitkeep → .keep} +0 -0
  28. data/test/support/postgresql/schema.rb +0 -1
  29. data/test/support/postgresql/setup_test_db.rb +15 -15
  30. data/test/system/.keep +0 -0
  31. data/test/unit/adapter/base_tests.rb +76 -52
  32. data/test/unit/adapter/mysql_tests.rb +2 -19
  33. data/test/unit/adapter/postgresql_tests.rb +14 -23
  34. data/test/unit/adapter/sqlite_tests.rb +3 -11
  35. data/test/unit/adapter_spy_tests.rb +2 -16
  36. data/test/unit/ardb_tests.rb +57 -44
  37. data/test/unit/cli_tests.rb +220 -158
  38. data/test/unit/db_tests_tests.rb +3 -6
  39. data/test/unit/default_order_by_tests.rb +4 -8
  40. data/test/unit/migration_tests.rb +11 -15
  41. data/test/unit/record_spy_tests.rb +17 -22
  42. data/test/unit/relation_spy_tests.rb +17 -46
  43. data/test/unit/test_helpers_tests.rb +3 -14
  44. data/test/unit/use_db_default_tests.rb +7 -11
  45. metadata +100 -83
  46. data/lib/ardb/has_slug.rb +0 -107
  47. data/lib/ardb/migration_helpers.rb +0 -77
  48. data/lib/ardb/pg_json.rb +0 -90
  49. data/test/support/postgresql/pg_json_migrations/20160519133432_create_pg_json_migrate_test.rb +0 -13
  50. data/test/system/pg_json_tests.rb +0 -85
  51. data/test/unit/has_slug_tests.rb +0 -341
  52. data/test/unit/migration_helpers_tests.rb +0 -65
  53. data/test/unit/pg_json_tests.rb +0 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
- ---
2
- SHA1:
3
- data.tar.gz: 33194d527399daa093277e134bbcda8dee5c6069
4
- metadata.gz: 7718eb32a25016d2d620a820b5a2b04244445b6a
5
- SHA512:
6
- data.tar.gz: 1597717aba91e83109628879b8ab51c52a81fe47c9f8182bf8bff32e91b7fe30f72a0543d97e1200b77926824b1d669790144fc3bf39bb9e9a30a95110192a69
7
- metadata.gz: 02366a02d6aff1a513ea34969017cc07b56be184e906a7cb34b446811c6d4ebaa6fb97f6eddd04344b3f4d2dbca51624c4c57316f996e1b6b98809826e5d03f4
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 50d874e2df679ac2dff5d8617591ec70eb92cdf236324c6b9ba58e815c3a0f97
4
+ data.tar.gz: 28023038c65d75d082cd49545934657e3e11efb9be64cf7055335d09a68707ef
5
+ SHA512:
6
+ metadata.gz: b7a3cfcb5f7bc262540e68ff4b0d259b8d9d95d5b109e521506229b4276bad96d3123c8cce6e7b0bf4f36777041fdbe2c714a17ca1f39e29846ba5d11b81b80b
7
+ data.tar.gz: 8cb2f15786e1a57c35ce32a39522aab648aa361ef29f4e0e6e8b63f70a3d5de3f41bfad99477751195a9d1ae68adf8363980211b1bd841841a508d57425246b0
data/Gemfile CHANGED
@@ -1,13 +1,24 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gemspec
3
+ ruby "~> 2.5"
4
4
 
5
- gem 'pg', "~> 0.17.1"
6
- gem 'pry', "~> 0.9.0"
5
+ gemspec
7
6
 
8
- # Lock down gem versions because they require a newer version of ruby
9
- gem 'i18n', "< 0.7"
7
+ # Uncomment one of these and run:
8
+ #
9
+ # bundle update activerecord activesupport
10
+ #
11
+ # to test a specific version.
12
+ #
13
+ # Rails 6.1
14
+ gem "activerecord", "~> 6.1"
15
+ gem "activesupport", "~> 6.1"
16
+ # Rails 6.0
17
+ # gem "activerecord", "~> 6.0.3"
18
+ # gem "activesupport", "~> 6.0.3"
19
+ # Rails 5.2
20
+ # gem "activerecord", "~> 5.2.4"
21
+ # gem "activesupport", "~> 5.2.4"
10
22
 
11
- platform :ruby_18 do
12
- gem 'json', '~> 1.8'
13
- end
23
+ gem "pg", "~> 1.1.4"
24
+ gem "pry", "~> 0.12.2"
data/README.md CHANGED
@@ -1,16 +1,265 @@
1
1
  # Ardb
2
2
 
3
- Activerecord database tools.
3
+ Tools for using ActiveRecord with or without Rails.
4
4
 
5
5
  ## Usage
6
6
 
7
- TODO: Write code samples and usage instructions here
7
+ Given configured database connection parameters, Ardb provides a CLI and assorted tools for working with an ActiveRecord database. Ardb is designed to be used with or without Rails.
8
+
9
+ ### Configuration
10
+
11
+ By default, Ardb looks for database configuration in the `config/db.rb` file. You can override this using the `ENV["ARDB_DB_FILE"]` env var.
12
+
13
+ The configuration includes typical database configuration parameters:
14
+
15
+ ```ruby
16
+ # in config/db.rb
17
+ require "ardb"
18
+
19
+ Ardb.configure do |c|
20
+ c.logger Logger.new($stdout)
21
+ c.root_path File.expand_path("../..", __FILE__)
22
+
23
+ c.db.adapter "postgresql"
24
+ c.db.encoding "unicode"
25
+ c.db.min_messages "WARNING"
26
+ c.db.url "localhost:5432"
27
+ c.db.username "testuser"
28
+ c.db.password "secret"
29
+ c.db.database "testdb"
30
+ end
31
+ ```
32
+
33
+ #### Rails configuration
34
+
35
+ If using Ardb with Rails, add a `config/db.rb` file to have Ardb use Rails's configuration settings:
36
+
37
+ ```ruby
38
+ # in config/db.rb
39
+ require_relative "./environment"
40
+ require "ardb"
41
+
42
+ # This Ardb configuration matches Rails's settings.
43
+ Ardb.configure do |c|
44
+ rails_db_config = Rails.application.config_for("database")
45
+ c.root_path = Rails.root
46
+ c.logger = Rails.logger
47
+ c.schema_format = Rails.application.config.active_record.schema_format || :ruby
48
+ c.default_timezone = :utc
49
+ c.adapter = rails_db_config["adapter"]
50
+ c.host = rails_db_config["host"]
51
+ c.port = rails_db_config["port"]
52
+ c.username = rails_db_config["username"]
53
+ c.password = rails_db_config["password"]
54
+ c.database = rails_db_config["database"]
55
+ c.encoding = rails_db_config["encoding"]
56
+ c.min_messages = rails_db_config["min_messages"]
57
+
58
+ c.migrations_path = "db/migrate"
59
+ c.schema_path = "db/schema"
60
+ end
61
+ ```
62
+
63
+ ### CLI
64
+
65
+ ```
66
+ $ ardb --help
67
+ Usage: ardb [COMMAND] [options]
68
+
69
+ Options:
70
+ --version
71
+ --help
72
+
73
+ Commands:
74
+ connect Connect to the configured DB
75
+ create Create the configured DB
76
+ drop Drop the configured DB
77
+ generate-migration Generate a MIGRATION-NAME migration file
78
+ migrate Migrate the configured DB
79
+ migrate-up Migrate the configured DB up
80
+ migrate-down Migrate the configured DB down
81
+ migrate-forward Migrate the configured DB forward
82
+ migrate-backward Migrate the configured DB backward
83
+ ```
84
+
85
+ #### `connect` command
86
+
87
+ ```
88
+ $ ardb connect --help
89
+ Usage: ardb connect [options]
90
+
91
+ Options:
92
+ --version
93
+ --help
94
+
95
+ Description:
96
+ Connect to the configured DB
97
+ $ ardb connect
98
+ error: database "some_database" does not exist
99
+ $ ardb create
100
+ created postgresql db "some_database"
101
+ $ ardb connect
102
+ connected to postgresql db "some_database"
103
+ ```
104
+
105
+ Use this command to verify the connection parameter configuration is correct.
106
+
107
+ #### `create` command
108
+
109
+ ```
110
+ $ ardb create --help
111
+ Usage: ardb create [options]
112
+
113
+ Options:
114
+ --version
115
+ --help
116
+
117
+ Description:
118
+ Create the configured DB
119
+ $ ardb create
120
+ created postgresql db "some_database"
121
+ $ ardb create
122
+ error: database "some_database" already exists
123
+ ```
124
+
125
+ #### `drop` command
126
+
127
+ ```
128
+ $ ardb drop --help
129
+ Usage: ardb drop [options]
130
+
131
+ Options:
132
+ --version
133
+ --help
134
+
135
+ Description:
136
+ Drop the configured DB
137
+ $ ardb drop
138
+ dropped postgresql db "some_database"
139
+ $ ardb drop
140
+ error: database "some_database" does not exist
141
+ ```
142
+
143
+ #### `generate-migration` command
144
+
145
+ ```
146
+ $ ardb generate-migration add_projects --help
147
+ Usage: ardb generate-migration MIGRATION-NAME [options]
148
+
149
+ Options:
150
+ --version
151
+ --help
152
+
153
+ Description:
154
+ Generate a MIGRATION-NAME migration file
155
+ $ ardb generate-migration add_projects
156
+ generated /path/to/app/db/migrate/20191222074043_add_projects.rb
157
+ ```
158
+
159
+ #### `migrate` command
160
+
161
+ ```
162
+ $ ardb migrate --help
163
+ Usage: ardb migrate [options]
164
+
165
+ Options:
166
+ --version
167
+ --help
168
+
169
+ Description:
170
+ Migrate the configured DB
171
+ $ ardb migrate
172
+ == 20191222074043 AddProjects: migrating ======================================
173
+ -- create_table(:projects)
174
+ -> 0.0276s
175
+ == 20191222074043 AddProjects: migrated (0.0277s) =============================
176
+ ```
177
+
178
+ #### `migrate-up` command
179
+
180
+ ```
181
+ $ ardb migrate-up --help
182
+ Usage: ardb migrate-up [options]
183
+
184
+ Options:
185
+ -t, --target-version VALUE version to migrate to
186
+ --version
187
+ --help
188
+
189
+ Description:
190
+ Migrate the configured DB up
191
+ $ ardb migrate-up
192
+ == 20191222074043 AddProjects: migrating ======================================
193
+ -- create_table(:projects)
194
+ -> 0.0510s
195
+ == 20191222074043 AddProjects: migrated (0.0511s) =============================
196
+ ```
197
+
198
+ #### `migrate-down` command
199
+
200
+ ```
201
+ $ ardb migrate-down --help
202
+ Usage: ardb migrate-down [options]
203
+
204
+ Options:
205
+ -t, --target-version VALUE version to migrate to
206
+ --version
207
+ --help
208
+
209
+ Description:
210
+ Migrate the configured DB down
211
+ $ ardb migrate-down
212
+ == 20191222074043 AddProjects: reverting ======================================
213
+ -- drop_table(:projects)
214
+ -> 0.0092s
215
+ == 20191222074043 AddProjects: reverted (0.0132s) =============================
216
+ ```
217
+
218
+ #### `migrate-forward` command
219
+
220
+ ```
221
+ $ ardb migrate-forward --help
222
+ Usage: ardb migrate-forward [options]
223
+
224
+ Options:
225
+ -s, --steps VALUE number of migrations to migrate
226
+ --version
227
+ --help
228
+
229
+ Description:
230
+ Migrate the configured DB forward
231
+ $ ardb migrate-forward
232
+ == 20191222074043 AddProjects: migrating ======================================
233
+ -- create_table(:projects)
234
+ -> 0.0510s
235
+ == 20191222074043 AddProjects: migrated (0.0511s) =============================
236
+ ```
237
+
238
+ #### `migrate-backward` command
239
+
240
+ ```
241
+ $ ardb migrate-backward --help
242
+ Usage: ardb migrate-backward [options]
243
+
244
+ Options:
245
+ -s, --steps VALUE number of migrations to migrate
246
+ --version
247
+ --help
248
+
249
+ Description:
250
+ Migrate the configured DB backward
251
+ $ ardb migrate-backward
252
+ == 20191222074043 AddProjects: reverting ======================================
253
+ -- drop_table(:projects)
254
+ -> 0.0092s
255
+ == 20191222074043 AddProjects: reverted (0.0132s) =============================
256
+ ```
8
257
 
9
258
  ## Installation
10
259
 
11
260
  Add this line to your application's Gemfile:
12
261
 
13
- gem 'ardb'
262
+ gem "ardb"
14
263
 
15
264
  And then execute:
16
265
 
@@ -1,5 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
- lib = File.expand_path('../lib', __FILE__)
2
+ lib = File.expand_path("../lib", __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require "ardb/version"
5
5
 
@@ -11,18 +11,19 @@ Gem::Specification.new do |gem|
11
11
  gem.summary = %q{Activerecord database tools.}
12
12
  gem.description = %q{Activerecord database tools.}
13
13
  gem.homepage = "http://github.com/redding/ardb"
14
- gem.license = 'MIT'
14
+ gem.license = "MIT"
15
15
 
16
16
  gem.files = `git ls-files`.split($/)
17
17
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
19
  gem.require_paths = ["lib"]
20
20
 
21
- gem.add_development_dependency("assert", ["~> 2.16.1"])
21
+ gem.required_ruby_version = "~> 2.5"
22
22
 
23
- gem.add_dependency('activerecord', ["~> 3.2"])
24
- gem.add_dependency('activesupport', ["~> 3.2"])
25
- gem.add_dependency('much-plugin', ["~> 0.1.1"])
26
- gem.add_dependency('scmd', ["~> 3.0.2"])
23
+ gem.add_development_dependency("assert", ["~> 2.19.0"])
27
24
 
25
+ gem.add_dependency("activerecord", ["> 5.0", "< 7.0"])
26
+ gem.add_dependency("activesupport", ["> 5.0", "< 7.0"])
27
+ gem.add_dependency("much-plugin", ["~> 0.2.1"])
28
+ gem.add_dependency("scmd", ["~> 3.0.3"])
28
29
  end
data/bin/ardb CHANGED
@@ -3,5 +3,5 @@
3
3
  # Copyright (c) 2013-Present Kelly Redding and Collin Redding
4
4
  #
5
5
 
6
- require 'ardb/cli'
6
+ require "ardb/cli"
7
7
  Ardb::CLI.run ARGV
@@ -1,12 +1,11 @@
1
- require 'active_record'
2
- require 'logger'
1
+ require "active_record"
2
+ require "logger"
3
3
 
4
- require 'ardb/version'
4
+ require "ardb/version"
5
5
 
6
- ENV['ARDB_DB_FILE'] ||= 'config/db'
6
+ ENV["ARDB_DB_FILE"] ||= "config/db"
7
7
 
8
8
  module Ardb
9
-
10
9
  def self.config
11
10
  @config ||= Config.new
12
11
  end
@@ -15,26 +14,35 @@ module Ardb
15
14
  self.config.tap(&block)
16
15
  end
17
16
 
18
- def self.adapter; @adapter; end
17
+ def self.adapter
18
+ @adapter || raise(NotInitializedError.new(caller))
19
+ end
20
+
21
+ def self.reset_adapter; @adapter = nil; end
19
22
 
20
23
  def self.init(establish_connection = true)
21
- require 'ardb/require_autoloaded_active_record_files'
24
+ require "ardb/require_autoloaded_active_record_files"
22
25
  begin
23
26
  require_db_file
24
27
  rescue InvalidDBFileError => exception
25
- raise exception.tap{ |e| e.set_backtrace(caller) }
28
+ exception.set_backtrace(caller)
29
+ raise exception
26
30
  end
27
31
 
28
32
  self.config.validate!
29
33
  @adapter = Adapter.new(self.config)
30
34
 
31
35
  # setup AR
36
+ ActiveRecord::Base.default_timezone = self.config.default_timezone
32
37
  ActiveRecord::Base.logger = self.config.logger
33
38
  self.adapter.connect_db if establish_connection
34
39
  end
35
40
 
36
41
  def self.escape_like_pattern(pattern, escape_char = nil)
37
42
  self.adapter.escape_like_pattern(pattern, escape_char)
43
+ rescue NotInitializedError => exception
44
+ exception.set_backtrace(caller)
45
+ raise exception
38
46
  end
39
47
 
40
48
  private
@@ -43,18 +51,17 @@ module Ardb
43
51
  # that fails it tries requiring relative to the current working directory
44
52
  def self.require_db_file
45
53
  begin
46
- require ENV['ARDB_DB_FILE']
54
+ require ENV["ARDB_DB_FILE"]
47
55
  rescue LoadError
48
- require File.expand_path(ENV['ARDB_DB_FILE'], ENV['PWD'])
56
+ require File.expand_path(ENV["ARDB_DB_FILE"], ENV["PWD"])
49
57
  end
50
58
  rescue LoadError
51
- raise InvalidDBFileError, "can't require `#{ENV['ARDB_DB_FILE']}`, " \
59
+ raise InvalidDBFileError, "can't require `#{ENV["ARDB_DB_FILE"]}`, " \
52
60
  "check that the ARDB_DB_FILE env var is set to " \
53
61
  "the file path of your db file"
54
62
  end
55
63
 
56
64
  class Config
57
-
58
65
  ACTIVERECORD_ATTRS = [
59
66
  :adapter,
60
67
  :database,
@@ -67,23 +74,25 @@ module Ardb
67
74
  :checkout_timeout,
68
75
  :min_messages
69
76
  ].freeze
70
- DEFAULT_MIGRATIONS_PATH = 'db/migrations'.freeze
71
- DEFAULT_SCHEMA_PATH = 'db/schema'.freeze
77
+
78
+ DEFAULT_MIGRATIONS_PATH = "db/migrations".freeze
79
+ DEFAULT_SCHEMA_PATH = "db/schema".freeze
72
80
  RUBY_SCHEMA_FORMAT = :ruby.freeze
73
81
  SQL_SCHEMA_FORMAT = :sql.freeze
74
82
  VALID_SCHEMA_FORMATS = [RUBY_SCHEMA_FORMAT, SQL_SCHEMA_FORMAT].freeze
75
83
 
76
- attr_accessor *ACTIVERECORD_ATTRS
77
- attr_accessor :logger, :root_path
84
+ attr_accessor(*ACTIVERECORD_ATTRS)
85
+ attr_accessor :default_timezone, :logger, :root_path
78
86
  attr_reader :schema_format
79
87
  attr_writer :migrations_path, :schema_path
80
88
 
81
89
  def initialize
82
- @logger = Logger.new(STDOUT)
83
- @root_path = ENV['PWD']
84
- @migrations_path = DEFAULT_MIGRATIONS_PATH
85
- @schema_path = DEFAULT_SCHEMA_PATH
86
- @schema_format = RUBY_SCHEMA_FORMAT
90
+ @default_timezone = :utc
91
+ @logger = Logger.new(STDOUT)
92
+ @root_path = ENV["PWD"]
93
+ @migrations_path = DEFAULT_MIGRATIONS_PATH
94
+ @schema_path = DEFAULT_SCHEMA_PATH
95
+ @schema_format = RUBY_SCHEMA_FORMAT
87
96
  end
88
97
 
89
98
  def migrations_path
@@ -112,37 +121,39 @@ module Ardb
112
121
  def validate!
113
122
  if self.adapter.to_s.empty? || self.database.to_s.empty?
114
123
  raise ConfigurationError, "an adapter and database must be provided"
115
- elsif !VALID_SCHEMA_FORMATS.include?(self.schema_format)
124
+ end
125
+
126
+ if !VALID_SCHEMA_FORMATS.include?(self.schema_format)
116
127
  raise ConfigurationError, "schema format must be one of: " \
117
- "#{VALID_SCHEMA_FORMATS.join(', ')}"
128
+ "#{VALID_SCHEMA_FORMATS.join(", ")}"
118
129
  end
130
+
119
131
  true
120
132
  end
121
133
 
122
134
  def ==(other)
123
135
  if other.kind_of?(self.class)
124
136
  self.activerecord_connect_hash == other.activerecord_connect_hash &&
125
- self.logger == other.logger &&
126
- self.root_path == other.root_path &&
127
- self.schema_format == other.schema_format &&
128
- self.migrations_path == other.migrations_path &&
137
+ self.default_timezone == other.default_timezone &&
138
+ self.logger == other.logger &&
139
+ self.root_path == other.root_path &&
140
+ self.schema_format == other.schema_format &&
141
+ self.migrations_path == other.migrations_path &&
129
142
  self.schema_path == other.schema_path
130
143
  else
131
144
  super
132
145
  end
133
146
  end
134
-
135
147
  end
136
148
 
137
149
  module Adapter
138
-
139
150
  VALID_ADAPTERS = [
140
- 'sqlite',
141
- 'sqlite3',
142
- 'postgresql',
143
- 'postgres',
144
- 'mysql',
145
- 'mysql2'
151
+ "sqlite",
152
+ "sqlite3",
153
+ "postgresql",
154
+ "postgres",
155
+ "mysql",
156
+ "mysql2"
146
157
  ].freeze
147
158
 
148
159
  def self.new(config)
@@ -153,30 +164,35 @@ module Ardb
153
164
  end
154
165
 
155
166
  def self.sqlite(config)
156
- require 'ardb/adapter/sqlite'
167
+ require "ardb/adapter/sqlite"
157
168
  Adapter::Sqlite.new(config)
158
169
  end
159
170
 
160
171
  def self.sqlite3(config); self.sqlite(config); end
161
172
 
162
173
  def self.postgresql(config)
163
- require 'ardb/adapter/postgresql'
174
+ require "ardb/adapter/postgresql"
164
175
  Adapter::Postgresql.new(config)
165
176
  end
166
177
 
167
178
  def self.postgres(config); self.postgresql(config); end
168
179
 
169
180
  def self.mysql(config)
170
- require 'ardb/adapter/mysql'
181
+ require "ardb/adapter/mysql"
171
182
  Adapter::Mysql.new(config)
172
183
  end
173
184
 
174
185
  def self.mysql2(config); self.mysql(config); end
175
-
176
186
  end
177
187
 
178
188
  InvalidDBFileError = Class.new(ArgumentError)
179
189
  ConfigurationError = Class.new(ArgumentError)
180
190
  InvalidAdapterError = Class.new(RuntimeError)
181
191
 
192
+ class NotInitializedError < RuntimeError
193
+ def initialize(backtrace)
194
+ super("ardb hasn't been initialized yet, run `Ardb.init`")
195
+ set_backtrace(backtrace)
196
+ end
197
+ end
182
198
  end