Skip to content

Commit

Permalink
rename columns, start developing model integration
Browse files Browse the repository at this point in the history
  • Loading branch information
andrepiske committed Nov 22, 2024
1 parent 6cda976 commit e62ad99
Show file tree
Hide file tree
Showing 18 changed files with 133 additions and 23 deletions.
2 changes: 1 addition & 1 deletion gemfiles/rails_7.1.gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: ..
specs:
iron_trail (0.1.2)
iron_trail (0.1.3)
rails (>= 7.1)
request_store (~> 1.5)

Expand Down
2 changes: 1 addition & 1 deletion gemfiles/rails_7.2.gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: ..
specs:
iron_trail (0.1.2)
iron_trail (0.1.3)
rails (>= 7.1)
request_store (~> 1.5)

Expand Down
2 changes: 1 addition & 1 deletion gemfiles/rails_8.0.gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ GIT
PATH
remote: ..
specs:
iron_trail (0.1.2)
iron_trail (0.1.3)
rails (>= 7.1)
request_store (~> 1.5)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@ class CreateIrontrailChanges < ActiveRecord::Migration[<%= ActiveRecord::Migrati
t.column :id, :bigserial, null: false
t.column :actor_type, :text
t.column :actor_id, :text
t.column :record_table, :text
t.column :record_id, :text
t.column :rec_table, :text
t.column :rec_id, :text
t.column :operation, :text

t.column :rec_old, :jsonb
t.column :rec_new, :jsonb
t.column :rec_changes, :jsonb
t.column :rec_delta, :jsonb
t.column :metadata, :jsonb

t.column :created_at, :timestamp, null: false
end

# CREATE INDEX irontrail_changes_rec_id ON irontrail_changes (record_id);
# CREATE INDEX irontrail_changes_actor_id ON irontrail_changes (actor_id);
# CREATE INDEX irontrail_changes_rec_type ON irontrail_changes USING BRIN (record_table);
# CREATE INDEX irontrail_changes_actor_typr ON irontrail_changes USING BRIN (actor_type);
# CREATE INDEX irontrail_changes_created_at ON irontrail_changes USING BRIN (change_created_at);
add_index :irontrail_changes, :rec_id
add_index :irontrail_changes, :rec_table
add_index :irontrail_changes, :actor_id
add_index :irontrail_changes, :actor_type
add_index :irontrail_changes, :created_at, using: :brin
end
end
1 change: 1 addition & 0 deletions lib/iron_trail.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
require 'iron_trail/association'
require 'iron_trail/reflection'
require 'iron_trail/model'
require 'iron_trail/change_model_concern'

module IronTrail
# These tables are owned by IronTrail and will always be ignored, that is,
Expand Down
2 changes: 1 addition & 1 deletion lib/iron_trail/association.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def association_scope
pk_value = owner._read_attribute(foreign_key)
pk_table = owner.class.arel_table

scope.where!('record_id' => pk_value, 'record_table' => pk_table.name)
scope.where!('rec_id' => pk_value, 'rec_table' => pk_table.name)

scope
end
Expand Down
33 changes: 33 additions & 0 deletions lib/iron_trail/change_model_concern.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# frozen_string_literal: true

module IronTrail
module ChangeModelConcern
extend ::ActiveSupport::Concern

module ClassMethods
def where_object_changes_to(args = {})
scope = all

args.each do |col_name, value|
scope.where!(
::Arel::Nodes::SqlLiteral.new("rec_delta->#{connection.quote col_name}->>1").eq(
::Arel::Nodes::BindParam.new(value)
)
)
end

scope
# where_object_changes(0, args)
end

def where_object_changes_from(args = {})
where_object_changes(0, args)
end

private

def where_object_changes(ary_index, args)
end
end
end
end
4 changes: 3 additions & 1 deletion lib/iron_trail/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ class Config
attr_accessor \
:track_by_default,
:enable,
:ignored_tables
:ignored_tables,
:track_migrations_starting_at_version

def initialize
@enable = true
@track_by_default = true
@ignored_tables = nil
@track_migrations_starting_at_version = nil
end
end
end
10 changes: 5 additions & 5 deletions lib/iron_trail/irontrail_log_row_function.sql
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ BEGIN

IF (TG_OP = 'INSERT') THEN
INSERT INTO "irontrail_changes" ("actor_id", "actor_type",
"record_table", "operation", "record_id", "rec_new", "metadata", "created_at")
"rec_table", "operation", "rec_id", "rec_new", "metadata", "created_at")
VALUES (actor_id, actor_type,
TG_TABLE_NAME, 'i', NEW.id, row_to_json(NEW), it_meta_obj, NOW());

Expand All @@ -49,15 +49,15 @@ BEGIN
END IF;
END LOOP;

INSERT INTO "irontrail_changes" ("actor_id", "actor_type", "record_table", "operation",
"record_id", "rec_old", "rec_new", "rec_changes", "metadata", "created_at")
INSERT INTO "irontrail_changes" ("actor_id", "actor_type", "rec_table", "operation",
"rec_id", "rec_old", "rec_new", "rec_delta", "metadata", "created_at")
VALUES (actor_id, actor_type, TG_TABLE_NAME, 'u', NEW.id, row_to_json(OLD), row_to_json(NEW),
u_changes, it_meta_obj, NOW());

END IF;
ELSIF (TG_OP = 'DELETE') THEN
INSERT INTO "irontrail_changes" ("actor_id", "actor_type", "record_table", "operation",
"record_id", "rec_old", "metadata", "created_at")
INSERT INTO "irontrail_changes" ("actor_id", "actor_type", "rec_table", "operation",
"rec_id", "rec_old", "metadata", "created_at")
VALUES (actor_id, actor_type, TG_TABLE_NAME, 'd', OLD.id, row_to_json(OLD), it_meta_obj, NOW());

END IF;
Expand Down
5 changes: 5 additions & 0 deletions lib/iron_trail/migration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ def method_missing(method, *args)

return result unless IronTrail.enabled? && method == :create_table

start_at_version = IronTrail.config.track_migrations_starting_at_version
if !running_from_schema && start_at_version
return result if self.version < Integer(start_at_version)
end

table_name = args.first.to_s
return result if IronTrail.ignore_table?(table_name)

Expand Down
Empty file.
4 changes: 2 additions & 2 deletions lib/iron_trail/reflection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ def join_scope(table, foreign_table, foreign_klass)
)

scope.where!(
table['record_id']
table['rec_id']
.eq(foreign_value)
.and(
table['record_table']
table['rec_table']
.eq(foreign_table.name)
)
)
Expand Down
2 changes: 1 addition & 1 deletion lib/iron_trail/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_literal_string: true

module IronTrail
VERSION = '0.1.2'
VERSION = '0.1.3'
end
1 change: 1 addition & 0 deletions spec/dummy_app/app/models/irontrail_change.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

class IrontrailChange < ApplicationRecord
include PgParty::Model
include IronTrail::ChangeModelConcern

range_partition_by { "(created_at::date)" }
end
2 changes: 2 additions & 0 deletions spec/dummy_app/app/models/person.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

class Person < ApplicationRecord
include IronTrail::Model

has_many :guitars
belongs_to :converted_by_pill,
optional: true,
Expand Down
1 change: 1 addition & 0 deletions spec/dummy_app/db/migrate/20241112090542_setup_test_db.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ def up
create_table :people, id: :bigserial, force: true do |t|
t.string :first_name, null: false
t.string :last_name, null: false
t.string :favorite_planet
t.bigint :converted_by_pill_id
t.timestamp :first_acquired_guitar_at
end
Expand Down
65 changes: 65 additions & 0 deletions spec/models/irontrail_change_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# frozen_string_literal: true

RSpec.describe IrontrailChange do
let(:person) { Person.create!(first_name: 'Arthur', last_name: 'Klarkey') }

before do
# let's have other people to ensure tests are picking up the right person
@other_people = 3.times do |index|
Person.create!(first_name: "Joey#{index}", last_name: "Doe#{index}").tap do |t|
t.update!(first_name: "Ashley#{index}")
t.update!(last_name: "X#{index}")
end.reload
end
end

describe 'IronTrail::ChangeModelConcern' do
it 'tests the test' do
# just ensure other people have been created
expect(Person.count).to be >= 3
expect(IrontrailChange.count).to be >= 9
end

describe 'where_object_changes_to' do
before do
person.update!(first_name: 'Michael')
person.update!(first_name: 'Johnny', last_name: 'Tod')
person.update!(first_name: 'Michael', favorite_planet: 'Saturn')
person.update!(last_name: 'Cash')
end

it 'finds the expected records' do
scope = person.iron_trails.where_object_changes_to(last_name: 'Cash')
expect(scope.count).to eq(1)

expect(scope.first.rec_old).to include('first_name' => 'Michael', 'last_name' => 'Tod')
expect(scope.first.rec_new).to include('first_name' => 'Michael', 'last_name' => 'Cash')
expect(scope.first.rec_delta).to eq({ 'last_name' => ['Tod', 'Cash'] })

scope = person.iron_trails.where_object_changes_to(first_name: 'Michael')
.order({
described_class.arel_table[:created_at] => :asc,
described_class.arel_table[:id] => :asc
})

expect(scope.first.rec_old).to include('first_name' => 'Arthur', 'last_name' => 'Klarkey')
expect(scope.first.rec_new).to include('first_name' => 'Michael', 'last_name' => 'Klarkey')
expect(scope.first.rec_delta).to eq({ 'first_name' => ['Arthur', 'Michael'] })

expect(scope.last.rec_old).to include('first_name' => 'Johnny', 'last_name' => 'Tod', 'favorite_planet' => nil)
expect(scope.last.rec_new).to include('first_name' => 'Michael', 'last_name' => 'Tod', 'favorite_planet' => 'Saturn')
expect(scope.last.rec_delta).to eq({
'first_name' => ['Johnny', 'Michael'],
'favorite_planet' => [nil, 'Saturn']
})

planet_changed_record = scope.last.clone

scope = person.iron_trails.where_object_changes_to(favorite_planet: 'Saturn')
expect(scope.count).to eq(1)

expect(scope.first.id).to eq(planet_changed_record.id)
end
end
end
end
4 changes: 2 additions & 2 deletions spec/services/people_manager_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

expect(person.persisted?).to be true

results = ActiveRecord::Base.connection.execute("select * from irontrail_changes WHERE record_table='people' AND record_id=#{person.id}::text").to_a
results = ActiveRecord::Base.connection.execute("select * from irontrail_changes WHERE rec_table='people' AND rec_id=#{person.id}::text").to_a
expect(results.length).to be 1

record_new = JSON.parse(results.first['rec_new'])
Expand Down Expand Up @@ -46,7 +46,7 @@
people.each do |person|
res = ActiveRecord::Base.connection.execute(<<~SQL).to_a
SELECT * FROM irontrail_changes WHERE
record_table='guitars' AND rec_new->>'person_id'='#{person.id}'
rec_table='guitars' AND rec_new->>'person_id'='#{person.id}'
ORDER BY id ASC
SQL

Expand Down

0 comments on commit e62ad99

Please sign in to comment.