Class: Pragma::Migration::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/pragma/migration/base.rb

Overview

A migration describes a change in your API's request or response payloads.

API migrations can be run in two directions: up when a client on an old version performs a request, and down when the response from the latest version must be converted into one that the client can understand.

Migrations can also skip the definition of the up and down logic, in which case they become no-ops. This is useful when containing side effects (for instance, you can use a migration just to indicate that a certain behavior has become opt-out rather than opt-in). You can check the readme for more details on how to use no-op migrations.

Examples:

A regular migration

class RemoveIdSuffixFromAuthorInArticles < Pragma::Migration::Base
  apply_to '/api/v1/articles/:id'
  describe 'The _id suffix has been removed from the author property in the Articles API.'

  def up
    request.update_param 'author', request.delete_param('author_id')
  end

  def down
    parsed_body = JSON.parse(response.body.join(''))
    Rack::Response.new(
      JSON.dump(parsed_body.merge('author' => parsed_body['author_id'])),
      response.status,
      response.headers
    )
  end
end

A no-op migration

class NotifyArticleSubscribersAutomatically < Pragma::Migration::Base
  describe 'Subscribers are now notified of new articles automatically.'
end

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(request:, response: nil) ⇒ Base

Initializes the migration.

The migration will be instantiated only with a request when it's being run upwards, and with both a request and a response when it's being run downwards.

Parameters:

  • request (Rack::Request)

    the request to migrate

  • response (Rack::Response)

    the response to migrate


143
144
145
146
# File 'lib/pragma/migration/base.rb', line 143

def initialize(request:, response: nil)
  @request = request
  @response = response
end

Class Attribute Details

.descriptionObject (readonly)

Returns the value of attribute description


48
# File 'lib/pragma/migration/base.rb', line 48

attr_reader :pattern, :description

.patternString (readonly)

Returns The pattern that the request path must match in order for the migration to be applied. This is a pattern compatible with Mustermann.

Returns:

  • (String)

    The pattern that the request path must match in order for the migration to be applied. This is a pattern compatible with Mustermann.


48
49
50
# File 'lib/pragma/migration/base.rb', line 48

def pattern
  @pattern
end

Instance Attribute Details

#requestObject (readonly)

Returns the value of attribute request


134
135
136
# File 'lib/pragma/migration/base.rb', line 134

def request
  @request
end

Class Method Details

.applies_to?(request) ⇒ Boolean

Checks whether the migration applies to the request.

By default, this checks whether the migration's pattern matches the request's path, but more complex logic can be implemented by overriding this method (it is recommended to retain the original behavior as well).

Note that you shouldn't check the version of the user in this method: when this method is called, it has already been determined that the migration applies to the user's API version.

Examples:

Override the check

def self.applies_to?(request)
  super && request.get_header('X-Custom-Header') == '1'
end

Parameters:

  • request (Rack::Request)

    the request to check

Returns:

  • (Boolean)

    whether the migration applies to the request


68
69
70
71
# File 'lib/pragma/migration/base.rb', line 68

def applies_to?(request)
  return false unless pattern
  request.path =~ Mustermann.new(pattern)
end

.down(request, response) ⇒ Rack::Request

Note:

This method should not be overridden. You should override the instance-level #down method instead.

Migrates the API's response down.

This is a convenience method that instantiates the migration with the provided request and response and runs #down.

Parameters:

  • request (Rack::Request)

    the user's request

  • response (Rack::Response)

    the API's response

Returns:

  • (Rack::Request)

    if the value returned by #down is an instance of Rack::Response, the new response is returned, otherwise the existing response is returned


104
105
106
107
# File 'lib/pragma/migration/base.rb', line 104

def down(request, response)
  result = new(request: request, response: response).down
  result.is_a?(Rack::Response) ? result : response
end

.up(request) ⇒ Rack::Request

Note:

This method should not be overridden. You should override the instance-level #up method instead.

Migrates the user's request up.

This is a convenience method that instantiates the migration with the provided request and runs #up.

Parameters:

  • request (Rack::Request)

    the user's request

Returns:

  • (Rack::Request)

    if the value returned by #up is an instance of Rack::Request, the new request is returned, otherwise the existing request is returned


85
86
87
88
# File 'lib/pragma/migration/base.rb', line 85

def up(request)
  result = new(request: request).up
  result.is_a?(Rack::Request) ? result : request
end

Instance Method Details

#downRack::Response|Object

Migrates the response down.

This method should alter the migration's #response in such a way that the response will be compatible with clients running on the old API version.

Returns:

  • (Rack::Response|Object)

    if a Rack::Response object is returned, the API's response will be replaced with the new one, otherwise the existing response will be used


176
# File 'lib/pragma/migration/base.rb', line 176

def down; end

#responseRack::Response

TODO:

Create our own exception class for when the response is not accessible.

Returns the response the migration was instantiated with.

Returns:

  • (Rack::Response)

Raises:

  • (RuntimeError)

    when the migration is being run upwards


155
156
157
158
# File 'lib/pragma/migration/base.rb', line 155

def response
  fail 'Cannot access response when migrating upwards!' unless @response
  @response
end

#upRack::Request|Object

Migrates the request up.

This method should alter the migration's #request in such a way that the request will be compatible with the new API version.

Returns:

  • (Rack::Request|Object)

    if a Rack::Request object is returned, the user's request will be replaced with the new one, otherwise the existing request will be used


167
# File 'lib/pragma/migration/base.rb', line 167

def up; end