-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
137 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
# Ruby on Rails | ||
|
||
<a class="github-button" href="https://github.com/BemiHQ/bemi-rails" data-size="large" data-show-count="true" aria-label="Star BemiHQ/bemi-rails on GitHub">BemiHQ/bemi-rails</a> | ||
<br /> | ||
<br /> | ||
|
||
[Bemi](https://bemi.io) plugs into [Ruby on Rails](https://github.com/rails/rails) with Active Record and PostgreSQL to track database changes automatically. It unlocks robust context-aware audit trails and time travel querying inside your application. | ||
|
||
This Ruby gem is a recommended Ruby on Rails integration, enabling you to pass application-specific context when performing database changes. This can include context such as the 'where' (API endpoint, worker, etc.), 'who' (user, cron job, etc.), and 'how' behind a change, thereby enriching the information captured by Bemi. | ||
|
||
## Prerequisites | ||
|
||
- PostgreSQL 14+ | ||
- Ruby on Rails | ||
|
||
## Installation | ||
|
||
1. Install the gem by adding it to your `Gemfile` | ||
|
||
``` | ||
gem 'bemi-rails' | ||
``` | ||
|
||
2. Generate a Rails migration file to add lightweight [PostgreSQL triggers](https://www.postgresql.org/docs/current/plpgsql-trigger.html) for passing application context with all data changes into PostgreSQL replication log | ||
|
||
```sh | ||
bin/rails g bemi:migration | ||
``` | ||
|
||
3. Run the rails migration | ||
|
||
```sh | ||
bin/rails db:migrate | ||
``` | ||
|
||
## Usage | ||
|
||
Now you can easily specify custom application context that will be automatically passed with all data changes. | ||
|
||
```rb | ||
class ApplicationController < ActionController::Base | ||
before_action :set_bemi_context | ||
|
||
private | ||
|
||
def set_bemi_context | ||
Bemi.set_context( | ||
user_id: current_user&.id, | ||
endpoint: "#{request.method} #{request.path}", | ||
method: "#{self.class}##{action_name}", | ||
) | ||
end | ||
end | ||
``` | ||
|
||
Application context: | ||
|
||
* Is bound to the current Ruby thread. So it is isolated to a single HTTP request or background job. | ||
* Is used only with `INSERT`, `UPDATE`, `DELETE` SQL queries performed via Active Record. Otherwise, it is a no-op. | ||
* Is passed directly into PG [Write-Ahead Log](https://www.postgresql.org/docs/current/wal-intro.html) with data changes without affecting the structure of the database and SQL queries. | ||
|
||
|
||
## Data change tracking | ||
|
||
Connect your PostgreSQL source database on [bemi.io](https://bemi.io) to start ingesting and storing all data changes stitched together with application-specific context. The database connection details can be securely configured through the [dashboard UI](https://dashboard.bemi.io/log-in?ref=rails) in a few seconds. | ||
|
||
![dashboard](/img/dashboard.png) | ||
|
||
Once your destination PostgreSQL database has been fully provisioned, you'll see a "Connected" status. You can now test the connection after making database changes in your connected source database: | ||
|
||
``` | ||
psql -h us-west-1-prod-destination-pool.ctbxbtz4ojdc.us-west-1.rds.amazonaws.com -p 5432 -U u_9adb30103a55 -d db_9adb30103a55 -c \ | ||
'SELECT "primary_key", "table", "operation", "before", "after", "context", "committed_at" FROM changes;' | ||
Password for user u_9adb30103a55: | ||
primary_key | table | operation | before | after | context | committed_at | ||
-------------+--------+-----------+-------------------------------------------------+--------------------------------------------------+------------------------------------------------------------------------------------------+------------------------ | ||
26 | todos | CREATE | {} | {"id": 26, "task": "Sleep", "completed": false} | {"user_id": 187234, "endpoint": "POST /todos", "method": "TodosController#create"} | 2023-12-11 17:09:09+00 | ||
27 | todos | CREATE | {} | {"id": 27, "task": "Eat", "completed": false} | {"user_id": 187234, "endpoint": "POST /todos", "method": "TodosController#create"} | 2023-12-11 17:09:11+00 | ||
28 | todos | CREATE | {} | {"id": 28, "task": "Repeat", "completed": false} | {"user_id": 187234, "endpoint": "POST /todos", "method": "TodosController#create"} | 2023-12-11 17:09:13+00 | ||
26 | todos | UPDATE | {"id": 26, "task": "Sleep", "completed": false} | {"id": 26, "task": "Sleep", "completed": true} | {"user_id": 187234, "endpoint": "POST /todos/26", "method": "TodosController#update"} | 2023-12-11 17:09:15+00 | ||
27 | todos | DELETE | {"id": 27, "task": "Eat", "completed": false} | {} | {"user_id": 187234, "endpoint": "DELETE /todos/27", "method": "TodosController#destroy"} | 2023-12-11 17:09:18+00 | ||
``` | ||
|
||
See [Destination Database](/postgresql/destination-database) for more details. | ||
|
||
## Alternative gems | ||
|
||
| | [Bemi](https://github.com/BemiHQ/bemi-rails) | [PaperTrail](https://github.com/paper-trail-gem/paper_trail) | [Audited](https://github.com/collectiveidea/audited) | [Logidze](https://github.com/palkan/logidze) | | ||
|----------------------------|------|------|------|------| | ||
| Open source | ✅ | ✅ | ✅ | ✅ | | ||
| Capturing record deletions | ✅ | ✅ | ✅ | ❌ | | ||
| Reliability and accuracy | ✅ | ❌ | ❌ | ❌ | | ||
| Scalability | ✅ | ❌ | ❌ | ❌ | | ||
| No performance impact | ✅ | ❌ | ❌ | ❌ | | ||
| Easy-to-use UI | ✅ | ❌ | ❌ | ❌ | | ||
|
||
## License | ||
|
||
Distributed under the terms of the [LGPL-3.0](https://github.com/BemiHQ/bemi-rails/blob/main/LICENSE). | ||
If you need to modify and distribute the code, please release it to contribute back to the open-source community. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,7 +24,7 @@ Changes performed by creating, updating, or deleting each row are stored in a ta | |
| `operation` | `text` | Enum that can be either `CREATE`, `UPDATE`, or `DELETE` | | ||
| `before` | `jsonb` | Record's values before the change | | ||
| `after` | `jsonb` | Record's values after the change | | ||
| `context` | `jsonb` | App context passed by using our recommended [ORM packages](/#supported-nodejs-orms) | | ||
| `context` | `jsonb` | App context passed by using our recommended [ORM packages](/#supported-orms) | | ||
| `committed_at` | `timestamptz(0)` | When the record was changed | | ||
| `queued_at` | `timestamptz(0)` | When the changed record was ingested from WAL | | ||
| `created_at` | `timestamptz(0)` | When the change record was stored in the database | | ||
|
@@ -33,7 +33,7 @@ Changes performed by creating, updating, or deleting each row are stored in a ta | |
|
||
## Querying Changes | ||
|
||
You can query changes by using our [ORM packages](/#supported-nodejs-orms) or by directly connecting and executing SQL queries. | ||
You can query changes by using our [ORM packages](/#supported-orms) or by directly connecting and executing SQL queries. | ||
For example, if you need to find when and how a user record with ID `b7267340-5011-40f4-ab9a-902b68fc5b25` had its email updated to `[email protected]` in the last 3 months: | ||
|
||
```sql | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ Bemi consists of three main parts: | |
|
||
1. [Debezium](https://github.com/debezium/debezium), a very flexible tool for implementing Change Data Capture that is written in Java. It is used by many companies that need to implement ETL such as [Airbyte](https://github.com/airbytehq/airbyte) and [Materialize](https://github.com/MaterializeInc/materialize). We rely on it to be able to connect to PostgreSQL replication log, perform logical decoding, and send raw data to a data sink. | ||
2. [NATS JetStream](https://github.com/nats-io/nats-server), a cloud-native messaging system written in Go. Debezium is historically designed to send data to Kafka, but it can be also re-configured to send data to NATS JetStream. It is much more lightweight and easy to manage while being very performant and having over 45 clients for different programming languages. | ||
3. Bemi Worker, a process responsible for stitching data change with app context sent via our open-source [ORM packages](https://docs.bemi.io/#supported-nodejs-orms) and storing data changes. It is written in TypeScript and uses the [`core`](https://github.com/BemiHQ/bemi) that we rely on for our [Bemi](https://bemi.io/) cloud platform. | ||
3. Bemi Worker, a process responsible for stitching data change with app context sent via our open-source [ORM packages](https://docs.bemi.io/#supported-orms) and storing data changes. It is written in TypeScript and uses the [`core`](https://github.com/BemiHQ/bemi) that we rely on for our [Bemi](https://bemi.io/) cloud platform. | ||
|
||
If you want to self-host our solution in a production environment, please [contact us](mailto:[email protected]), | ||
and we'll be happy to provide you with a Docker image and assist with configuring the system in exchange for your feedback :) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.