request_migrations 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f9ade55e7b503c08190a46b58d68dfc35f619c9cf949c12ef98e7cb58548d2b6
4
- data.tar.gz: 0e2a334989b6d79ec9296e9ef3c5866b42c0121e87cc2d9fa219835ff6e225e7
3
+ metadata.gz: 1575eecb9ad23c9dae9534b03a31acbcef8c6ed7bf46f4ffca1748ef21fcead4
4
+ data.tar.gz: 141dbbf4576e8b2da641ab32bd377173bbe61717d330c741c0b10c5cf9eff854
5
5
  SHA512:
6
- metadata.gz: 15e401e45c34e2054505e2c85968cbe7b81b20b7e987b2034acce71ece1d8fb48ebf5906a2166c957cd6bbdb3f3a8e7fccdab66e27bccf1f1960288efa748f4d
7
- data.tar.gz: 97a1233a8c01c6d818e5682b06164bf15d6e75f890a6aebbc0188712e0fa996d0d40b48f1d72e83f478573d0e8bc97350f7450cd254bbf5a1cb0efe1a9992ba1
6
+ metadata.gz: 119241518c4d8a9a954bd4918a6e2edbc0338938c7173953a406821f34f0f4da735e7819b7cc0e929be45c78a7da88f035f1456d5b98d53d6cb00b0fca1c8362
7
+ data.tar.gz: 5afffe316b08692daeaf2366fab161f23794b80326112a2b4c4ece1a13f0d40f8d61423aa81d4bf28c62274acf8a33dd63c01214295524cd7691c42203a71575
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.1
4
+
5
+ - Fix application order of `request` migrations.
6
+
3
7
  ## 1.0.0
4
8
 
5
9
  - Initial release.
data/README.md CHANGED
@@ -3,11 +3,13 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/request_migrations.svg)](https://badge.fury.io/rb/request_migrations)
4
4
 
5
5
  **Make breaking API changes without breaking things!** Use `request_migrations` to craft
6
- backwards-compatible migrations for API requests, responses, and more. This gem was extracted
7
- from [Keygen](https://keygen.sh) and is being used in production to serve millions of API
8
- requests per day.
6
+ backwards-compatible migrations for API requests, responses, and more. Read [the blog
7
+ post](https://keygen.sh/blog/breaking-things-without-breaking-things/).
9
8
 
10
- ![request_migrations diagram](https://user-images.githubusercontent.com/6979737/175406011-883b2671-152c-4e6e-8716-d6c4c3ed2676.png)
9
+ This gem was extracted from [Keygen](https://keygen.sh) and is being used in production
10
+ to serve millions of API requests per day.
11
+
12
+ ![request_migrations diagram](https://user-images.githubusercontent.com/6979737/175964358-a2d8951d-46c6-4962-9f5e-0569cbf5972e.png)
11
13
 
12
14
  Sponsored by:
13
15
 
@@ -50,7 +52,7 @@ _We're working on improving the docs._
50
52
 
51
53
  - Define migrations for migrating a response between versions.
52
54
  - Define migrations for migrating a request between versions.
53
- - Define migrations for applying one-off migrations.
55
+ - Define migrations for applying data migrations.
54
56
  - Define version-based routing constraints.
55
57
  - It's fast.
56
58
 
@@ -130,7 +132,7 @@ Next, we'll need to configure `request_migrations` via an initializer under
130
132
 
131
133
  ```ruby
132
134
  RequestMigrations.configure do |config|
133
- # Define a resolver to determine the current version. Here, you can perform
135
+ # Define a resolver to determine the target version. Here, you can perform
134
136
  # a lookup on the current user using request parameters, or simply use
135
137
  # a header like we are here, defaulting to the latest version.
136
138
  config.request_version_resolver = -> request {
@@ -189,7 +191,12 @@ end
189
191
 
190
192
  The `response` method accepts an `:if` keyword, which should be a lambda
191
193
  that evaluates to a boolean, which determines whether or not the migration
192
- should be applied.
194
+ should be applied. An `ActionDispatch::Response` will be yielded, the
195
+ current response (calls `controller#response`).
196
+
197
+ The gem makes no assumption on a response's content type or what the migration
198
+ will do. You could, for example, migrate the response body, or mutate the
199
+ headers, or even change the response's status code.
193
200
 
194
201
  ### Request migrations
195
202
 
@@ -209,19 +216,25 @@ end
209
216
 
210
217
  The `request` method accepts an `:if` keyword, which should be a lambda
211
218
  that evaluates to a boolean, which determines whether or not the migration
212
- should be applied.
219
+ should be applied. An `ActionDispatch::Request` object will be yielded,
220
+ the current request (calls `controller#request`).
221
+
222
+ Again, like with response migrations, the gem makes no assumption on what
223
+ a migration does. A migration could mutate a request's params, or mutate
224
+ headers. It's up to you, all it does is provide the request.
225
+
226
+ Request migrations should [avoid using the `migrate` method](#avoid-migrate-for-request-migrations).
213
227
 
214
- ### One-off migrations
228
+ ### Data migrations
215
229
 
216
230
  In our first scenario, where we combined our user's name attributes, we defined
217
231
  our migration using the `migrate` class method. At this point, you may be wondering
218
232
  why we did that, since we didn't use that method for the 2 previous request and
219
233
  response migrations above.
220
234
 
221
- Well, it comes down to support for one-off migrations (as well as offering
222
- a nice interface for pattern matching inputs).
223
-
224
- Let's go back to our first example, `CombineNamesForUserMigration`.
235
+ Well, it comes down to support for data migrations (as well as offering a nice
236
+ interface for pattern matching inputs). Let's go back to our first example,
237
+ `CombineNamesForUserMigration`.
225
238
 
226
239
  ```ruby
227
240
  class CombineNamesForUserMigration < RequestMigrations::Migration
@@ -251,7 +264,7 @@ end
251
264
  ```
252
265
 
253
266
  What if we had [a webhook system](https://keygen.sh/blog/how-to-build-a-webhook-system-in-rails-using-sidekiq/)
254
- that we also needed to apply these migrations to? Well, we can use a one-off migration
267
+ that we also needed to apply these migrations to? Well, we can use a data migration
255
268
  here, via the `Migrator` class:
256
269
 
257
270
  ```ruby
@@ -277,17 +290,19 @@ class WebhookWorker
277
290
  end
278
291
  ```
279
292
 
280
- Now, we've successfully applied a migration to both our API responses, as well
293
+ This will apply the block defined in `migrate` onto our data. With that,
294
+ we've successfully applied a migration to both our API responses, as well
281
295
  as to the webhook events we send. In this case, if our `event` matches the
282
296
  our user shape, e.g. `type: 'user'`, then the migration will be applied.
283
297
 
284
- In addition to one-off migrations, this allows for easier testing.
298
+ In addition to data migrations, this allows for easier testing.
285
299
 
286
300
  ### Routing constraints
287
301
 
288
302
  When you want to encourage API clients to upgrade, you can utilize a routing `version_constraint`
289
- to define routes only available for certain versions. You can also utilize routing constraints
290
- to remove an API endpoint entirely.
303
+ to define routes only available for certain versions.
304
+
305
+ You can also utilize routing constraints to remove an API endpoint entirely.
291
306
 
292
307
  ```ruby
293
308
  Rails.application.routes.draw do
@@ -305,13 +320,13 @@ Rails.application.routes.draw do
305
320
  end
306
321
  ```
307
322
 
308
- Currently, routing constraints only work for the `:semver` version format.
323
+ Currently, routing constraints only work for the `:semver` version format. (PRs welcome!)
309
324
 
310
325
  ### Configuration
311
326
 
312
327
  ```ruby
313
328
  RequestMigrations.configure do |config|
314
- # Define a resolver to determine the current version. Here, you can perform
329
+ # Define a resolver to determine the target version. Here, you can perform
315
330
  # a lookup on the current user using request parameters, or simply use
316
331
  # a header like we are here, defaulting to the latest version.
317
332
  config.request_version_resolver = -> request {
@@ -348,17 +363,19 @@ end
348
363
  By default, `request_migrations` uses a `:semver` version format, but it can be configured
349
364
  to instead use one of the following, set via `config.version_format=`.
350
365
 
351
- | Format | |
352
- |:-----------|:----------------------------------------------------|
353
- | `:semver` | Use semantic versions, e.g. `1.0`, `1.1, and `2.0`. |
354
- | `:date` | Use date versions, e.g. `2020-09-02`, `2021-01-01`. |
355
- | `:integer` | Use integer versions, e.g. `1`, `2`, and `3`. |
356
- | `:float` | Use float versions, e.g. `1.0`, `1.1`, and `2.0`. |
357
- | `:string` | Use string versions, e.g. `a`, `b`, and `z`. |
366
+ | Format | |
367
+ |:-----------|:-----------------------------------------------------|
368
+ | `:semver` | Use semantic versions, e.g. `1.0`, `1.1`, and `2.0`. |
369
+ | `:date` | Use date versions, e.g. `2020-09-02`, `2021-01-01`. |
370
+ | `:integer` | Use integer versions, e.g. `1`, `2`, and `3`. |
371
+ | `:float` | Use float versions, e.g. `1.0`, `1.1`, and `2.0`. |
372
+ | `:string` | Use string versions, e.g. `a`, `b`, and `z`. |
373
+
374
+ All versions will be sorted according to the format's type.
358
375
 
359
376
  ## Testing
360
377
 
361
- Using one-offs allows for easier testing of migrations. For example, using Rspec:
378
+ Using data migrations allows for easier testing of migrations. For example, using Rspec:
362
379
 
363
380
  ```ruby
364
381
  describe CombineNamesForUserMigration do
@@ -390,7 +407,7 @@ end
390
407
 
391
408
  ## Tips and tricks
392
409
 
393
- Over the years, we're learned a thing or two about writing request migrations. We'll share tips here.
410
+ Over the years, we're learned a thing or two about versioning an API. We'll share tips here.
394
411
 
395
412
  ### Use pattern matching
396
413
 
@@ -544,14 +561,14 @@ end
544
561
 
545
562
  ### Avoid migrate for request migrations
546
563
 
547
- Avoid using `migrate` for request migrations. If you do, one-off migrations, e.g. for webhooks
548
- will apply the request migrations, which may erroneously produce bad output, or even undo a
549
- response migration. Instead, keep all request migration logic, e.g. transforming params,
550
- inside of the `request` block.
564
+ Avoid using `migrate` for request migrations. If you do, then data migrations, e.g. for
565
+ webhooks, will attempt to apply the request migrations. This may erroneously produce bad
566
+ output, or even undo a response migration. Instead, keep all request migration logic,
567
+ e.g. transforming params, inside of the `request` block.
551
568
 
552
569
  ```ruby
553
570
  class SomeMigration < RequestMigrations::Migration
554
- # Bad (side-effects for one-off migrations)
571
+ # Bad (side-effects for data migrations)
555
572
  migrate do |params|
556
573
  params[:foo] = params.delete(:bar)
557
574
  end
@@ -570,8 +587,8 @@ end
570
587
  ### Avoid routing contraints
571
588
 
572
589
  Avoid using routing version constraints that remove functionality. They can be a headache
573
- during upgrades. Consider only making _additive_ changes. You should remove docs for old
574
- or deprecated endpoints to limit any new usage.
590
+ during upgrades. Consider only making _additive_ changes. Instead, consider removing or
591
+ hiding the documenation for old or deprecated endpoints, to limit any new usage.
575
592
 
576
593
  ```ruby
577
594
  Rails.application.routes.draw do
@@ -591,7 +608,7 @@ end
591
608
 
592
609
  ### Avoid n+1s
593
610
 
594
- Avoid introducing n+1 queries in your migration. Try to utilize the current data you have
611
+ Avoid introducing n+1 queries in your migrations. Try to utilize the current data you have
595
612
  to perform more meaningful queries, returning only the data needed for the migration.
596
613
 
597
614
  ```ruby
@@ -642,7 +659,7 @@ end
642
659
  ```
643
660
 
644
661
  Instead of potentially tens or hundreds of queries, we make a single purposeful query
645
- to get the data we need to complete the migration.
662
+ to get the data we need in order to complete the migration.
646
663
 
647
664
  ---
648
665
 
@@ -26,13 +26,13 @@ module RequestMigrations
26
26
  ##
27
27
  # current_version defines the latest version.
28
28
  #
29
- # @return [String, Integer, Float] the current version.
29
+ # @return [String, Integer, Float, nil] the current version.
30
30
  config_accessor(:current_version) { nil }
31
31
 
32
32
  ##
33
33
  # versions defines past versions and their migrations.
34
34
  #
35
- # @return [Hash] past versions.
36
- config_accessor(:versions) { [] }
35
+ # @return [Hash<String, Array<Symbol, String, Class>>] past versions.
36
+ config_accessor(:versions) { {} }
37
37
  end
38
38
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RequestMigrations
4
- VERSION = "1.0.1"
4
+ VERSION = "1.0.2"
5
5
  end
@@ -77,7 +77,7 @@ module RequestMigrations
77
77
  #
78
78
  # @param if [Proc] the proc which determines if the migration should run.
79
79
  #
80
- # @yield [request] the block containing the migration.
80
+ # @yield [ActionDispatch::Request] the current request.
81
81
  def request(if: nil, &block)
82
82
  self.request_blocks << ConditionalBlock.new(if:, &block)
83
83
  end
@@ -87,7 +87,7 @@ module RequestMigrations
87
87
  #
88
88
  # @param if [Proc] the proc which determines if the migration should run.
89
89
  #
90
- # @yield [data] the block containing the migration.
90
+ # @yield [Any] the provided data.
91
91
  def migrate(if: nil, &block)
92
92
  self.migration_blocks << ConditionalBlock.new(if:, &block)
93
93
  end
@@ -97,7 +97,7 @@ module RequestMigrations
97
97
  #
98
98
  # @param if [Proc] the proc which determines if the migration should run.
99
99
  #
100
- # @yield [response] the block containing the migration.
100
+ # @yield [ActionDispatch::Response] the current response.
101
101
  def response(if: nil, &block)
102
102
  self.response_blocks << ConditionalBlock.new(if:, &block)
103
103
  end
@@ -15,9 +15,9 @@ module RequestMigrations
15
15
  ##
16
16
  # migrate! attempts to apply all matching migrations on data.
17
17
  #
18
- # @param data [*] the data to be migrated.
18
+ # @param data [Any] the data to be migrated.
19
19
  #
20
- # @return [*] the migrated data.
20
+ # @return [void]
21
21
  def migrate!(data:)
22
22
  logger.debug { "Migrating from #{current_version} to #{target_version} (#{migrations.size} potential migrations)" }
23
23
 
@@ -1,4 +1,6 @@
1
1
  module RequestMigrations
2
+ ##
3
+ # @private
2
4
  class Railtie < ::Rails::Railtie
3
5
  ActionDispatch::Routing::Mapper.send(:include, Router::Constraints)
4
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: request_migrations
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zeke Gabrielse
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-24 00:00:00.000000000 Z
11
+ date: 2022-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails