mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-07 13:44:23 +08:00
Merge pull request #8402 from artoscinote/ma_SCI_11771
Add metadata column to projects and expose it in API [SCI-11771]
This commit is contained in:
commit
8e949bd68f
7 changed files with 101 additions and 5 deletions
|
@ -15,11 +15,11 @@ module Api
|
|||
projects = archived_filter(projects).page(params.dig(:page, :number))
|
||||
.per(params.dig(:page, :size))
|
||||
|
||||
render jsonapi: projects, each_serializer: ProjectSerializer, include: include_params
|
||||
render jsonapi: projects, each_serializer: ProjectSerializer, scope: { metadata: params['with-metadata'] == 'true' }, include: include_params
|
||||
end
|
||||
|
||||
def show
|
||||
render jsonapi: @project, serializer: ProjectSerializer, include: include_params
|
||||
render jsonapi: @project, serializer: ProjectSerializer, scope: { metadata: params['with-metadata'] == 'true' }, include: include_params
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -33,7 +33,7 @@ module Api
|
|||
|
||||
project.save!
|
||||
|
||||
render jsonapi: project, serializer: ProjectSerializer, status: :created
|
||||
render jsonapi: project, serializer: ProjectSerializer, scope: { metadata: params['with-metadata'] == 'true' }, status: :created
|
||||
end
|
||||
|
||||
def update
|
||||
|
@ -50,7 +50,7 @@ module Api
|
|||
end
|
||||
@project.last_modified_by = current_user
|
||||
@project.save!
|
||||
render jsonapi: @project, serializer: ProjectSerializer, status: :ok
|
||||
render jsonapi: @project, serializer: ProjectSerializer, scope: { metadata: params['with-metadata'] == 'true' }, status: :ok
|
||||
end
|
||||
|
||||
def activities
|
||||
|
@ -66,7 +66,7 @@ module Api
|
|||
def project_params
|
||||
raise TypeError unless params.require(:data).require(:type) == 'projects'
|
||||
|
||||
params.require(:data).require(:attributes).permit(:name, :visibility, :archived, :project_folder_id)
|
||||
params.require(:data).require(:attributes).permit(:name, :visibility, :archived, :project_folder_id, metadata: {})
|
||||
end
|
||||
|
||||
def permitted_includes
|
||||
|
|
22
app/models/concerns/metadata_model.rb
Normal file
22
app/models/concerns/metadata_model.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module MetadataModel
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
scope :with_metadata_value, lambda { |key, value|
|
||||
# sanitize key, replace . with -> and replace last -> with ->> to ensure string comparison at last level
|
||||
db_key =
|
||||
"metadata->#{key.to_s.split('.').map { |k| "'#{k.parameterize(separator: '_')}'" }.join('->')}".sub(/->(?!.*->)/, '->>')
|
||||
where("#{db_key} = ?", value.to_s)
|
||||
}
|
||||
|
||||
before_save :sanitize_metadata_keys!
|
||||
|
||||
def sanitize_metadata_keys!
|
||||
return unless metadata
|
||||
|
||||
self.metadata = metadata.deep_transform_keys { |k| k.parameterize(separator: '_') }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -11,6 +11,7 @@ class Project < ApplicationRecord
|
|||
include ViewableModel
|
||||
include PermissionCheckableModel
|
||||
include Assignable
|
||||
include MetadataModel
|
||||
|
||||
enum visibility: { hidden: 0, visible: 1 }
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ module Api
|
|||
class ProjectSerializer < ActiveModel::Serializer
|
||||
type :projects
|
||||
attributes :name, :visibility, :start_date, :archived
|
||||
attribute :metadata, if: -> { scope && scope[:metadata] == true }
|
||||
|
||||
belongs_to :project_folder, serializer: ProjectFolderSerializer
|
||||
has_many :project_comments, key: :comments, serializer: CommentSerializer
|
||||
|
|
7
db/migrate/20250407114708_add_metadata_to_projects.rb
Normal file
7
db/migrate/20250407114708_add_metadata_to_projects.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddMetadataToProjects < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :projects, :metadata, :jsonb
|
||||
end
|
||||
end
|
56
spec/models/concerns/metadata_model_spec.rb
Normal file
56
spec/models/concerns/metadata_model_spec.rb
Normal file
|
@ -0,0 +1,56 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe MetadataModel, type: :concern do
|
||||
let!(:user) { create :user }
|
||||
let!(:team) { create :team, created_by: user }
|
||||
|
||||
let!(:project_1) do
|
||||
Project.create!(
|
||||
name: 'Project 1',
|
||||
team: user.teams.first,
|
||||
created_by: user,
|
||||
metadata: {
|
||||
status: 'processed',
|
||||
info: {
|
||||
tag: 'important',
|
||||
number: 2
|
||||
}
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
let!(:project_2) do
|
||||
Project.create!(
|
||||
name: 'Project 2',
|
||||
team: user.teams.first,
|
||||
created_by: user,
|
||||
metadata: {
|
||||
status: 'failed'
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
it '#with_metadata_value finds the correct project by metadata value' do
|
||||
results = Project.with_metadata_value(:status, 'processed')
|
||||
expect(results.count).to eq 1
|
||||
expect(results.last.id).to eq project_1.id
|
||||
end
|
||||
|
||||
it '#with_metadata_value finds the correct project by nested metadata value' do
|
||||
results = Project.with_metadata_value('info.tag', 'important')
|
||||
expect(results.count).to eq 1
|
||||
expect(results.last.id).to eq project_1.id
|
||||
|
||||
results = Project.with_metadata_value('info.number', 2)
|
||||
expect(results.count).to eq 1
|
||||
expect(results.last.id).to eq project_1.id
|
||||
end
|
||||
|
||||
it '#with_metadata_value escapes key input' do
|
||||
results = nil
|
||||
expect { results = Project.with_metadata_value("project'->>'tag' = \'one\') AND name", nil) }.to_not raise_error
|
||||
expect(results.count).to eq 0
|
||||
end
|
||||
end
|
|
@ -106,6 +106,15 @@ RSpec.describe 'Api::V1::ProjectsController', type: :request do
|
|||
)
|
||||
end
|
||||
|
||||
it 'When metadata parameter is set to true, it serializes metadata' do
|
||||
@team1.projects.first.update(metadata: { status: 'processed' })
|
||||
hash_body = nil
|
||||
get api_v1_team_project_path(team_id: @team1.id, id: @team1.projects.first.id, 'with-metadata' => 'true'),
|
||||
headers: @valid_headers
|
||||
expect { hash_body = json }.not_to raise_exception
|
||||
expect(hash_body[:data]['attributes']['metadata']['status']).to eq 'processed'
|
||||
end
|
||||
|
||||
it 'When invalid request, user in not member of the team' do
|
||||
hash_body = nil
|
||||
get api_v1_team_project_path(team_id: @team2.id,
|
||||
|
|
Loading…
Add table
Reference in a new issue