bemi-rails 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7c0601f1bb209e0d1d0e0b08f7e9f6ed1b32575b5bb6b3dfd1c6262a249afaec
4
+ data.tar.gz: ea404c16b60f45fedfef06dfbd017aaba63649d99a4fc0e001bf015ede6c42c5
5
+ SHA512:
6
+ metadata.gz: 78e7ab750b1adcab1bb9675fdb5425ed9404f01fb920b1ed5c9712ce94c6f1a8972add88d94e0d6b3d977ff9835c14eff9bec78c346e80c73e934f959825e1b5
7
+ data.tar.gz: 1bc3a6fb17ad990a96eb92f05f2d85f813c3580f343715a64d45df25da2aa5d0451911df681210fe9c100acc9cc43ac6b52d39e6e302009cc4cb27334b32a01d
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ #### v0.1.0 - 2024-03-08
2
+
3
+ - Create the gem
data/LICENSE ADDED
@@ -0,0 +1,165 @@
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
data/README.md ADDED
@@ -0,0 +1,138 @@
1
+ <div align="center">
2
+ <a href="https://bemi.io">
3
+ <img width="1201" alt="bemi-banner" src="https://docs.bemi.io/img/bemi-banner.png">
4
+ </a>
5
+
6
+ <p align="center">
7
+ <a href="https://bemi.io">Website</a>
8
+ ·
9
+ <a href="https://docs.bemi.io">Docs</a>
10
+ ·
11
+ <a href="https://github.com/BemiHQ/bemi-rails-example">Example</a>
12
+ ·
13
+ <a href="https://github.com/BemiHQ/bemi-rails/issues/new">Report Bug</a>
14
+ ·
15
+ <a href="https://github.com/BemiHQ/bemi-rails/issues/new">Request Feature</a>
16
+ ·
17
+ <a href="https://discord.gg/mXeZ6w2tGf">Discord</a>
18
+ ·
19
+ <a href="https://twitter.com/BemiHQ">Twitter</a>
20
+ ·
21
+ <a href="https://www.linkedin.com/company/bemihq/about">LinkedIn</a>
22
+ </p>
23
+ </div>
24
+
25
+ # Bemi Rails
26
+
27
+ [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.
28
+
29
+ Designed with simplicity and non-invasiveness in mind, Bemi doesn't require any alterations to your existing database structure. It operates in the background, empowering you with data change tracking features.
30
+
31
+ 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.
32
+
33
+ ## Contents
34
+
35
+ - [Highlights](#highlights)
36
+ - [Use cases](#use-cases)
37
+ - [Quickstart](#quickstart)
38
+ - [Architecture overview](#architecture-overview)
39
+ - [Alternatives](#alternatives)
40
+ - [License](#license)
41
+
42
+ ## Highlights
43
+
44
+ - Automatic and secure database change tracking with application-specific context in a structured form
45
+ - 100% reliability in capturing data changes, even if executed through direct SQL outside the application
46
+ - High performance without affecting code runtime execution and database workload
47
+ - Easy-to-use without changing table structures and rewriting the code
48
+ - Time travel querying and ability to easily group and filter changes
49
+ - Scalability with an automatically provisioned cloud infrastructure
50
+ - Full ownership of your data
51
+
52
+ See [an example repo](https://github.com/BemiHQ/bemi-rails-example) for a Ruby on Rails app that automatically tracks all changes.
53
+
54
+ ## Use cases
55
+
56
+ There's a wide range of use cases that Bemi is built for! The tech was initially built as a compliance engineering system for fintech that supported $15B worth of assets under management, but has since been extracted into a general-purpose utility. Some use cases include:
57
+
58
+ - **Audit Trails:** Use logs for compliance purposes or surface them to customer support and external customers.
59
+ - **Change Reversion:** Revert changes made by a user or rollback all data changes within an API request.
60
+ - **Time Travel:** Retrieve historical data without implementing event sourcing.
61
+ - **Troubleshooting:** Identify the root cause of application issues.
62
+ - **Distributed Tracing:** Track changes across distributed systems.
63
+ - **Testing:** Rollback or roll-forward to different application test states.
64
+ - **Analyzing Trends:** Gain insights into historical trends and changes for informed decision-making.
65
+
66
+ ## Quickstart
67
+
68
+ Install the gem by adding it to your `Gemfile`
69
+
70
+ ```
71
+ gem 'bemi-rails'
72
+ ```
73
+
74
+ Specify custom application context that will be automatically passed with all data changes
75
+
76
+ ```rb
77
+ class ApplicationController < ActionController::Base
78
+ before_action :set_bemi_context
79
+
80
+ private
81
+
82
+ def set_bemi_context
83
+ Bemi.set_context(
84
+ user_id: current_user&.id,
85
+ endpoint: "#{request.method} #{request.path}",
86
+ method: "#{self.class}##{action_name}",
87
+ )
88
+ end
89
+ end
90
+ ```
91
+
92
+ Make database changes and make sure they're all stored in a table called `changes` in the destination DB
93
+
94
+ ```
95
+ psql -h [HOSTNAME] -U [USERNAME] -d [DATABASE] -c 'SELECT "primary_key", "table", "operation", "before", "after", "context", "committed_at" FROM changes;'
96
+
97
+ primary_key | table | operation | before | after | context | committed_at
98
+ -------------+--------+-----------+-------------------------------------------------+--------------------------------------------------+------------------------------------------------------------------------------------------+------------------------
99
+ 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
100
+ 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
101
+ 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
102
+ 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
103
+ 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
104
+ ```
105
+
106
+ Check out our [docs](https://docs.bemi.io/orms/rails) for more details.
107
+
108
+ ## Architecture overview
109
+
110
+ Bemi is designed to be lightweight and secure. It takes a practical approach to achieving the benefits of [event sourcing](https://martinfowler.com/eaaDev/EventSourcing.html) without requiring rearchitecting existing code, switching to highly specialized databases, or using unnecessary git-like abstractions on top of databases. We want your system to work the way it already does with your existing database to allow keeping things as simple as possible.
111
+
112
+ Bemi plugs into both the database and application levels, ensuring 100% reliability and a comprehensive understanding of every change.
113
+
114
+ On the database level, Bemi securely connects to PostgreSQL's [Write-Ahead Log](https://www.postgresql.org/docs/current/wal-intro.html) and implements [Change Data Capture](https://en.wikipedia.org/wiki/Change_data_capture). This allows tracking even the changes that get triggered via direct SQL.
115
+
116
+ On the application level, this gem automatically passes application context to the replication logs to enhance the low-level database changes. For example, information about a user who made a change, an API endpoint where the change was triggered, a worker name that automatically triggered database changes, etc.
117
+
118
+ Bemi workers then stitch the low-level data with the application context and store this information in a structured easily queryable format, as depicted below:
119
+
120
+ ![bemi-architechture](https://docs.bemi.io/img/architecture.png)
121
+
122
+ The cloud solution includes worker ingesters, queues for fault tolerance, and an automatically scalable cloud-hosted PostgreSQL. Bemi currently doesn't support a self hosted option, but [contact us](mailto:hi@bemi.io) if this is required.
123
+
124
+ ## Alternatives
125
+
126
+ | | [Bemi](https://github.com/BemiHQ/bemi-rails)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | [PaperTrail](https://github.com/paper-trail-gem/paper_trail) | [Audited](https://github.com/collectiveidea/audited)&nbsp;&nbsp;&nbsp;&nbsp; | [Logidze](https://github.com/palkan/logidze)&nbsp;&nbsp;&nbsp;&nbsp; |
127
+ |----------------------------|------|------|------|------|
128
+ | Open source | ✅ | ✅ | ✅ | ✅ |
129
+ | Capturing record deletions | ✅ | ✅ | ✅ | ❌ |
130
+ | Reliability and accuracy | ✅ | ❌ | ❌ | ❌ |
131
+ | Scalability | ✅ | ❌ | ❌ | ❌ |
132
+ | No performance impact | ✅ | ❌ | ❌ | ❌ |
133
+ | Easy-to-use UI | ✅ | ❌ | ❌ | ❌ |
134
+
135
+ ## License
136
+
137
+ Distributed under the terms of the [LGPL-3.0 License](LICENSE).
138
+ If you need to modify and distribute the code, please release it to contribute back to the open-source community.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/bemi/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "bemi-rails"
7
+ spec.version = Bemi::VERSION
8
+ spec.authors = ["exAspArk"]
9
+ spec.email = ["exaspark@gmail.com"]
10
+
11
+ spec.summary = "Automatic data change tracking for Ruby on Rails."
12
+ spec.description = "Automatic data change tracking for Ruby on Rails."
13
+ spec.homepage = "https://github.com/BemiHQ/bemi-rails"
14
+ spec.license = "LGPL-3.0"
15
+ spec.required_ruby_version = ">= 2.6.0"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = "https://github.com/BemiHQ/bemi-rails"
19
+ spec.metadata["changelog_uri"] = "https://github.com/BemiHQ/bemi-rails/blob/main/CHANGELOG.md"
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(__dir__) do
24
+ `git ls-files -z`.split("\x0").reject do |f|
25
+ (File.expand_path(f) == __FILE__) ||
26
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
27
+ end
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+
33
+ # Uncomment to register a new dependency of your gem
34
+ # spec.add_dependency "example-gem", "~> 1.0"
35
+
36
+ spec.add_dependency "railties", ">= 6.0.0"
37
+ spec.add_dependency "activerecord", ">= 6.0.0"
38
+
39
+ # For more information and examples about making a new gem, check out our
40
+ # guide at: https://bundler.io/guides/creating_gem.html
41
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_record'
4
+
5
+ class Bemi
6
+ def self.set_context(context)
7
+ Thread.current[:bemi_context] = context
8
+ end
9
+
10
+ def self.context
11
+ Thread.current[:bemi_context]
12
+ end
13
+
14
+ def self.append_context
15
+ ->(sql, adapter) do
16
+ if adapter.write_query?(sql)
17
+ "#{sql} /*Bemi #{Bemi.context.to_json} Bemi*/"
18
+ else
19
+ sql
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ ActiveRecord.query_transformers << Bemi.append_context
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Bemi
4
+ def self.migrate
5
+ %{
6
+ CREATE OR REPLACE FUNCTION _bemi_row_trigger_func()
7
+ RETURNS TRIGGER
8
+ AS $$
9
+ DECLARE
10
+ _bemi_metadata TEXT;
11
+ BEGIN
12
+ SELECT split_part(split_part(current_query(), '/*Bemi ', 2), ' Bemi*/', 1) INTO _bemi_metadata;
13
+ IF _bemi_metadata <> '' THEN
14
+ PERFORM pg_logical_emit_message(true, '_bemi', _bemi_metadata);
15
+ END IF;
16
+
17
+ IF (TG_OP = 'DELETE') THEN
18
+ RETURN OLD;
19
+ ELSE
20
+ RETURN NEW;
21
+ END IF;
22
+ END;
23
+ $$ LANGUAGE plpgsql;
24
+
25
+ CREATE OR REPLACE PROCEDURE _bemi_create_triggers()
26
+ AS $$
27
+ DECLARE
28
+ current_tablename TEXT;
29
+ BEGIN
30
+ FOR current_tablename IN
31
+ SELECT tablename FROM pg_tables WHERE schemaname = 'public'
32
+ LOOP
33
+ EXECUTE format(
34
+ 'CREATE OR REPLACE TRIGGER _bemi_row_trigger_%s
35
+ BEFORE INSERT OR UPDATE OR DELETE ON %I FOR EACH ROW
36
+ EXECUTE FUNCTION _bemi_row_trigger_func()',
37
+ current_tablename, current_tablename
38
+ );
39
+ END LOOP;
40
+ END;
41
+ $$ LANGUAGE plpgsql;
42
+
43
+ CALL _bemi_create_triggers();
44
+
45
+ CREATE OR REPLACE FUNCTION _bemi_create_table_trigger_func()
46
+ RETURNS event_trigger
47
+ AS $$
48
+ BEGIN
49
+ CALL _bemi_create_triggers();
50
+ END
51
+ $$ LANGUAGE plpgsql;
52
+
53
+ DO $$
54
+ BEGIN
55
+ DROP EVENT TRIGGER IF EXISTS _bemi_create_table_trigger;
56
+ CREATE EVENT TRIGGER _bemi_create_table_trigger ON ddl_command_end WHEN TAG IN ('CREATE TABLE') EXECUTE FUNCTION _bemi_create_table_trigger_func();
57
+ EXCEPTION WHEN insufficient_privilege THEN
58
+ RAISE NOTICE 'Please execute "CALL _bemi_create_triggers();" manually after adding new tables you want to track. (%) %.', SQLSTATE, SQLERRM;
59
+ END
60
+ $$ LANGUAGE plpgsql;
61
+ }
62
+ end
63
+
64
+ def self.rollback
65
+ %{
66
+ DROP EVENT TRIGGER _bemi_create_table_trigger;
67
+ DROP FUNCTION _bemi_create_table_trigger_func;
68
+ DROP PROCEDURE _bemi_create_triggers;
69
+ DROP FUNCTION _bemi_row_trigger_func CASCADE;
70
+ }
71
+ end
72
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ require 'rails/generators/active_record'
5
+
6
+ class Bemi
7
+ class MigrationGenerator < Rails::Generators::Base
8
+ include ActiveRecord::Generators::Migration
9
+
10
+ source_root File.expand_path('templates', __dir__)
11
+
12
+ def create_migration_file
13
+ migration_template 'migration.rb.erb', File.join(db_migrate_path, "bemi_migration.rb")
14
+ end
15
+
16
+ private
17
+
18
+ def migration_version
19
+ "[#{ActiveRecord::VERSION::STRING.to_f}]"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class BemiMigration < ActiveRecord::Migration<%= migration_version %>
4
+ def up
5
+ execute(Bemi.migrate)
6
+ end
7
+
8
+ def down
9
+ execute(Bemi.rollback)
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Bemi
4
+ VERSION = "0.1.0"
5
+ end
data/lib/bemi-rails.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./bemi"
data/lib/bemi.rb ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Bemi
4
+ end
5
+
6
+ require_relative "./bemi/context"
7
+ require_relative "./bemi/migration"
8
+ require_relative "./bemi/migration_generator"
9
+ require_relative "./bemi/version"
@@ -0,0 +1,10 @@
1
+ class Bemi
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+
5
+ self.migrate: -> void
6
+ self.rollback: -> void
7
+ self.set_context: (context: ::Hash[untyped, untyped]) -> void
8
+ self.context: -> ::Hash[untyped, untyped]
9
+ self.append_context: -> ^(String, untyped) -> String
10
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bemi-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - exAspArk
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-03-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: railties
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 6.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 6.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 6.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 6.0.0
41
+ description: Automatic data change tracking for Ruby on Rails.
42
+ email:
43
+ - exaspark@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".rspec"
49
+ - CHANGELOG.md
50
+ - LICENSE
51
+ - README.md
52
+ - Rakefile
53
+ - bemi-rails.gemspec
54
+ - lib/bemi-rails.rb
55
+ - lib/bemi.rb
56
+ - lib/bemi/context.rb
57
+ - lib/bemi/migration.rb
58
+ - lib/bemi/migration_generator.rb
59
+ - lib/bemi/templates/migration.rb.erb
60
+ - lib/bemi/version.rb
61
+ - sig/bemi-rails.rbs
62
+ homepage: https://github.com/BemiHQ/bemi-rails
63
+ licenses:
64
+ - LGPL-3.0
65
+ metadata:
66
+ homepage_uri: https://github.com/BemiHQ/bemi-rails
67
+ source_code_uri: https://github.com/BemiHQ/bemi-rails
68
+ changelog_uri: https://github.com/BemiHQ/bemi-rails/blob/main/CHANGELOG.md
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 2.6.0
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubygems_version: 3.4.19
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: Automatic data change tracking for Ruby on Rails.
88
+ test_files: []