Add metadata to MyModules and expose it in API [11773]

This commit is contained in:
Andrej 2025-04-10 15:54:58 +02:00
parent ac6787cac6
commit 5ef4df5ad6
6 changed files with 122 additions and 15 deletions

View file

@ -23,16 +23,18 @@ module Api
.per(params.dig(:page, :size))
render jsonapi: tasks, each_serializer: TaskSerializer,
include: include_params,
rte_rendering: render_rte?,
team: @team
scope: { metadata: params['with-metadata'] == 'true' },
include: include_params,
rte_rendering: render_rte?,
team: @team
end
def show
render jsonapi: @task, serializer: TaskSerializer,
include: include_params,
rte_rendering: render_rte?,
team: @team
include: include_params,
scope: { metadata: params['with-metadata'] == 'true' },
rte_rendering: render_rte?,
team: @team
end
def create
@ -41,15 +43,16 @@ module Api
my_module = @experiment.my_modules.create!(task_params_create.merge(created_by: current_user))
render jsonapi: my_module, serializer: TaskSerializer,
rte_rendering: render_rte?,
status: :created
scope: { metadata: params['with-metadata'] == 'true' },
rte_rendering: render_rte?,
status: :created
end
def update
@task.assign_attributes(task_params_update)
if @task.changed? && @task.save!
render jsonapi: @task, serializer: TaskSerializer, status: :ok
render jsonapi: @task, serializer: TaskSerializer, scope: { metadata: params['with-metadata'] == 'true' }, status: :ok
else
render body: nil, status: :no_content
end
@ -68,13 +71,12 @@ module Api
def task_params_create
raise TypeError unless params.require(:data).require(:type) == 'tasks'
params.require(:data).require(:attributes).permit(%i(name x y description))
params.require(:data).require(:attributes).permit(:name, :x, :y, :description, metadata: {})
end
def task_params_update
raise TypeError unless params.require(:data).require(:type) == 'tasks'
params.require(:data).require(:attributes).permit(%i(name x y description my_module_status_id))
params.require(:data).require(:attributes).permit(:name, :x, :y, :description, :my_module_status_id, metadata: {})
end
def permitted_includes

View file

@ -13,6 +13,7 @@ class MyModule < ApplicationRecord
include PermissionCheckableModel
include Assignable
include Cloneable
include MetadataModel
attr_accessor :transition_error_rollback, :my_module_status_created_by

View file

@ -10,6 +10,7 @@ module Api
type :tasks
attributes :id, :name, :started_on, :due_date, :description, :state, :archived, :status_id, :status_name,
:prev_status_id, :prev_status_name, :next_status_id, :next_status_name, :x, :y
attribute :metadata, if: -> { scope && scope[:metadata] == true }
has_many :output_tasks, key: :outputs,
serializer: TaskSerializer,
class_name: 'MyModule'

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddMetadataToMyModules < ActiveRecord::Migration[7.0]
def change
add_column :my_modules, :metadata, :jsonb
end
end

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2025_04_10_115032) do
ActiveRecord::Schema[7.0].define(version: 2025_04_10_124417) do
# These are extensions that must be enabled in order to support this database
enable_extension "btree_gist"
enable_extension "pg_trgm"
@ -472,6 +472,7 @@ ActiveRecord::Schema[7.0].define(version: 2025_04_10_115032) do
t.jsonb "last_transition_error"
t.integer "provisioning_status"
t.boolean "due_date_notification_sent", default: false
t.jsonb "metadata"
t.index "(('TA'::text || id)) gin_trgm_ops", name: "index_my_modules_on_my_module_code", using: :gin
t.index "trim_html_tags((description)::text) gin_trgm_ops", name: "index_my_modules_on_description", using: :gin
t.index "trim_html_tags((name)::text) gin_trgm_ops", name: "index_my_modules_on_name", using: :gin
@ -574,6 +575,7 @@ ActiveRecord::Schema[7.0].define(version: 2025_04_10_115032) do
t.boolean "demo", default: false, null: false
t.bigint "project_folder_id"
t.bigint "default_public_user_role_id"
t.jsonb "metadata"
t.index "(('PR'::text || id)) gin_trgm_ops", name: "index_projects_on_project_code", using: :gin
t.index "trim_html_tags((name)::text) gin_trgm_ops", name: "index_projects_on_name", using: :gin
t.index ["archived"], name: "index_projects_on_archived"

View file

@ -181,6 +181,33 @@ RSpec.describe 'Api::V1::TasksController', type: :request do
expect { hash_body = json }.not_to raise_exception
expect(hash_body['errors'][0]).to include('status': 404)
end
it 'When metadata parameter is set to true, it serializes metadata' do
@valid_experiment.my_modules.first.update(metadata: { status: 'processed' })
hash_body = nil
get api_v1_team_project_experiment_task_path(
team_id: @team1.id,
project_id: @valid_project,
experiment_id: @valid_experiment,
id: @valid_experiment.my_modules.first.id,
'with-metadata': true
), headers: @valid_headers
expect { hash_body = json }.not_to raise_exception
expect(hash_body.dig(:data, 'attributes', 'metadata', 'status')).to eq 'processed'
end
it 'When metadata parameter is set to false, it does not serializes metadata' do
@valid_experiment.my_modules.first.update(metadata: { status: 'processed' })
hash_body = nil
get api_v1_team_project_experiment_task_path(
team_id: @team1.id,
project_id: @valid_project,
experiment_id: @valid_experiment,
id: @valid_experiment.my_modules.first.id
), headers: @valid_headers
expect { hash_body = json }.not_to raise_exception
expect(hash_body.dig(:data, 'attributes', 'metadata')).to be_nil
end
end
describe 'POST tasks, #create' do
@ -196,7 +223,14 @@ RSpec.describe 'Api::V1::TasksController', type: :request do
attributes: {
name: 'task name',
x: 1,
y: 4
y: 4,
metadata: {
status: 'processed',
info: {
tag: 'important',
number: 2
}
}
}
}
}
@ -213,6 +247,17 @@ RSpec.describe 'Api::V1::TasksController', type: :request do
headers: @valid_headers)
end
let(:action_with_metadata) do
post(api_v1_team_project_experiment_tasks_path(
team_id: @team1.id,
project_id: @valid_project.id,
experiment_id: @valid_experiment.id,
'with-metadata': true
),
params: request_body.to_json,
headers: @valid_headers)
end
it 'creates new my module' do
expect { action }.to change { MyModule.count }.by(1)
end
@ -236,6 +281,22 @@ RSpec.describe 'Api::V1::TasksController', type: :request do
)
)
end
it 'returns with metadata' do
hash_body = nil
action_with_metadata
expect { hash_body = json }.not_to raise_exception
expect(hash_body.dig(:data, 'attributes', 'metadata', 'status')).to eq 'processed'
end
it 'returns without metadata' do
hash_body = nil
action
expect { hash_body = json }.not_to raise_exception
expect(hash_body.dig(:data, 'attributes', 'metadata')).to be_nil
end
end
context 'when has not valid params' do
@ -300,6 +361,20 @@ RSpec.describe 'Api::V1::TasksController', type: :request do
)
end
let(:action_with_metadata) do
patch(
api_v1_team_project_experiment_task_path(
team_id: @valid_project.team.id,
project_id: @valid_project.id,
experiment_id: @valid_experiment.id,
id: task.id,
'with-metadata': true
),
params: request_body.to_json,
headers: @valid_headers
)
end
context 'when has valid params' do
let(:request_body) do
{
@ -307,7 +382,10 @@ RSpec.describe 'Api::V1::TasksController', type: :request do
type: 'tasks',
attributes: {
name: 'New task name',
description: 'New description about task'
description: 'New description about task',
metadata: {
status: 'processed'
}
}
}
}
@ -331,6 +409,22 @@ RSpec.describe 'Api::V1::TasksController', type: :request do
)
)
end
it 'returns metadata' do
hash_body = nil
action_with_metadata
expect { hash_body = json }.not_to raise_exception
expect(hash_body.dig(:data, 'attributes', 'metadata', 'status')).to eq 'processed'
end
it 'returns without metadata' do
hash_body = nil
action
expect { hash_body = json }.not_to raise_exception
expect(hash_body.dig(:data, 'attributes', 'metadata')).to be_nil
end
end
context 'direct task completion disabled, when has valid params' do