Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TASK: Create database model for representing a Metadata Template #882

Merged
merged 9 commits into from
Jan 9, 2025
Merged
34 changes: 34 additions & 0 deletions app/models/metadata_template.rb
ericenns marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

# MetadataTemplate represents a template for structured metadata fields
class MetadataTemplate < ApplicationRecord
include TrackActivity
METADATA_TEMPLATE_JSON_SCHEMA = Rails.root.join('config/schemas/metadata_template_metadata.json')

has_logidze
acts_as_paranoid

# Associations
belongs_to :created_by, class_name: 'User'

# Validations
validates :name, presence: true, uniqueness: { scope: [:namespace_id] }
validates :description, length: { maximum: 1000 }

belongs_to :namespace, autosave: true

belongs_to :group, optional: true, foreign_key: :namespace_id # rubocop:disable Rails/InverseOf
belongs_to :project_namespace, optional: true, foreign_key: :namespace_id, class_name: 'Namespaces::ProjectNamespace' # rubocop:disable Rails/InverseOf

validates :fields, presence: true, json: { message: ->(errors) { errors }, schema: METADATA_TEMPLATE_JSON_SCHEMA }
validate :validate_namespace

private

def validate_namespace
# Only Groups and Projects should have metadata templates
return if %w[Group Project].include?(namespace.type)

errors.add(namespace.type, 'namespace cannot have metadata templates')
end
end
2 changes: 1 addition & 1 deletion app/models/workflow_execution.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
end

def cancellable?
%w[submitted running prepared initial].include?(state)
%w[submitted running prepared initial].include?(state)

Check warning on line 43 in app/models/workflow_execution.rb

View workflow job for this annotation

GitHub Actions / runner / rubocop

[rubocop] reported by reviewdog 🐶 Trailing whitespace detected. Raw Output: app/models/workflow_execution.rb:43:59: C: Layout/TrailingWhitespace: Trailing whitespace detected.
end

def deletable?
Expand Down
10 changes: 10 additions & 0 deletions config/schemas/metadata_template_metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"type": "array",
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "",
"minItems": 1,
"uniqueItems": true,
"items": {
"type": "string"
}
}
20 changes: 20 additions & 0 deletions db/migrate/20250106153442_create_metadata_templates.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

# Migration to add MetadataTemplates table
class CreateMetadataTemplates < ActiveRecord::Migration[7.2]
def change
create_table :metadata_templates, id: :uuid do |t|
t.references :namespace, type: :uuid, foreign_key: true, index: true
t.references :created_by, type: :uuid, null: false, foreign_key: { to_table: :users }
t.string :name
t.string :description
t.jsonb :fields, null: false, default: []
t.datetime :deleted_at
t.timestamps
end
add_index :metadata_templates, %i[namespace_id name],
unique: true,
where: '(deleted_at IS NULL)',
name: 'index_template_name_with_namespace'
end
end
20 changes: 20 additions & 0 deletions db/migrate/20250107194839_add_logidze_to_metadata_templates.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

# Migration to add Logidze to MetadataTemplates table
class AddLogidzeToMetadataTemplates < ActiveRecord::Migration[7.2]
def change
add_column :metadata_templates, :log_data, :jsonb

reversible do |dir|
dir.up do
create_trigger :logidze_on_metadata_templates, on: :metadata_templates
end

dir.down do
execute <<~SQL.squish
DROP TRIGGER IF EXISTS "logidze_on_metadata_template" on "metadata_templates";
SQL
end
end
end
end
56 changes: 38 additions & 18 deletions db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions db/triggers/logidze_on_metadata_templates_v01.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TRIGGER "logidze_on_metadata_templates"
BEFORE UPDATE OR INSERT ON "metadata_templates" FOR EACH ROW
WHEN (coalesce(current_setting('logidze.disabled', true), '') <> 'on')
-- Parameters: history_size_limit (integer), timestamp_column (text), filtered_columns (text[]),
-- include_columns (boolean), debounce_time_ms (integer)
EXECUTE PROCEDURE logidze_logger(null, 'updated_at');
9 changes: 9 additions & 0 deletions test/fixtures/metadata_templates.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html

valid_metadata_template:
name: "Valid Template"
description: "This is a valid template."
fields: ["field_1", "field_2", "field_3"]
created_at: <%= 3.hours.ago %>
namespace_id: <%= ActiveRecord::FixtureSet.identify(:project1_namespace, :uuid) %>
created_by_id: <%= ActiveRecord::FixtureSet.identify(:john_doe, :uuid) %>
91 changes: 91 additions & 0 deletions test/models/metadata_template_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# frozen_string_literal: true

require 'test_helper'

class MetadataTemplateTest < ActiveSupport::TestCase
setup do
@user = users(:john_doe)
@valid_metadata_template = metadata_templates(:valid_metadata_template)
end

test 'valid metadata template' do
assert @valid_metadata_template.valid?
assert_not_nil @valid_metadata_template.name
end

test 'invalid without name' do
@valid_metadata_template.name = nil
assert_not @valid_metadata_template.valid?
assert_not_nil @valid_metadata_template.errors[:name]
end

test 'invalid with duplicate name in same namespace' do
duplicate = @valid_metadata_template.dup
assert_not duplicate.valid?
assert_includes duplicate.errors[:name], 'has already been taken'
end

test 'valid with same name in different namespace' do
duplicate = @valid_metadata_template.dup
duplicate.namespace = groups(:subgroup_one_group_three)
assert duplicate.valid?
end

test 'description length validation' do
@valid_metadata_template.description = 'a' * 1001
assert_not @valid_metadata_template.valid?
end

# Association Tests
test 'belongs to namespace' do
assert_respond_to @valid_metadata_template, :namespace
assert_instance_of Namespaces::ProjectNamespace, @valid_metadata_template.namespace
end

test 'belongs to created_by user' do
assert_respond_to @valid_metadata_template, :created_by
assert_instance_of User, @valid_metadata_template.created_by
end

test 'has many metadata fields' do
assert_respond_to @valid_metadata_template, :fields
assert_kind_of Array, @valid_metadata_template.fields
end

# Soft Delete Tests
test 'soft deletes record' do
@valid_metadata_template.destroy
assert_not_nil @valid_metadata_template.deleted_at
assert_not MetadataTemplate.find_by(id: @valid_metadata_template.id)
assert MetadataTemplate.with_deleted.find_by(id: @valid_metadata_template.id)
end

# Activity Tracking Tests
test 'tracks activity on create' do
skip 'TrackActivity concern is not yet implemented'
template = MetadataTemplate.new(
name: 'Activity Test',
namespace: project_namespace(:project1),
created_by: @user
)
assert_difference 'Activity.count' do
template.save
end
end

test 'tracks history changes' do
@valid_metadata_template.create_logidze_snapshot!

assert_equal 1, @valid_metadata_template.log_data.version
assert_equal 1, @valid_metadata_template.log_data.size

assert_changes -> { @valid_metadata_template.name }, to: 'Updated Name' do
@valid_metadata_template.update(name: 'Updated Name')
end

@valid_metadata_template.create_logidze_snapshot!

assert_equal 2, @valid_metadata_template.log_data.version
assert_equal 2, @valid_metadata_template.log_data.size
end
end
Loading