mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-10-07 20:40:26 +08:00
Implement metadata model concern [SCI-11774]
This commit is contained in:
parent
a274ffce7e
commit
65b94afafa
3 changed files with 79 additions and 0 deletions
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 ViewableModel
|
||||||
include PermissionCheckableModel
|
include PermissionCheckableModel
|
||||||
include Assignable
|
include Assignable
|
||||||
|
include MetadataModel
|
||||||
|
|
||||||
enum visibility: { hidden: 0, visible: 1 }
|
enum visibility: { hidden: 0, visible: 1 }
|
||||||
|
|
||||||
|
|
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
|
Loading…
Add table
Reference in a new issue