mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-01-26 17:51:47 +08:00
Added prefixed IDs to repository rows (items) [SCI-5909] (#3441)
* Added prefixed IDs to repository rows (items) [SCI-5909] * Fix prefixed id queries to work with joins, use subquery in repository search [SCI-5909] * Fixed accessing repository_row parent code [SCI-5909] * Better handling of repository_row code display [SCI-5909] * Fix index warning for id prefixed models issue setting up project [SCI-5909]
This commit is contained in:
parent
ef6c46a19c
commit
5f9c04844f
13 changed files with 91 additions and 24 deletions
|
@ -9,7 +9,7 @@ module RepositoryDatatableHelper
|
|||
'DT_RowId': record.id,
|
||||
'DT_RowAttr': { 'data-state': row_style(record) },
|
||||
'1': assigned_row(record),
|
||||
'2': record.id,
|
||||
'2': record.code,
|
||||
'3': escape_input(record.name),
|
||||
'4': I18n.l(record.created_at, format: :full),
|
||||
'5': escape_input(record.created_by.full_name),
|
||||
|
@ -52,7 +52,7 @@ module RepositoryDatatableHelper
|
|||
row = {
|
||||
'DT_RowId': record.id,
|
||||
'DT_RowAttr': { 'data-state': row_style(record) },
|
||||
'1': record.parent_id,
|
||||
'1': record.code,
|
||||
'2': escape_input(record.name),
|
||||
'3': I18n.l(record.created_at, format: :full),
|
||||
'4': escape_input(record.created_by.full_name),
|
||||
|
|
27
app/models/concerns/prefixed_id_model.rb
Normal file
27
app/models/concerns/prefixed_id_model.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module PrefixedIdModel
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
begin
|
||||
indexdef = "CREATE INDEX index_#{table_name}_on_#{name.underscore}_code"\
|
||||
" ON public.#{table_name} USING gin ((('#{self::ID_PREFIX}'::text || id)) gin_trgm_ops)"
|
||||
|
||||
index_exists = ActiveRecord::Base.connection.execute(
|
||||
"SELECT indexdef FROM pg_indexes WHERE tablename NOT LIKE 'pg%';"
|
||||
).to_a.map(&:values).flatten.include?(indexdef)
|
||||
|
||||
# rubocop:disable Rails/Output
|
||||
puts("\nWARNING missing index\n#{indexdef}\nfor prefixed id model #{name}!\n\n") unless index_exists
|
||||
# rubocop:enable Rails/Output
|
||||
rescue ActiveRecord::NoDatabaseError # only applicable when setting up project
|
||||
end
|
||||
|
||||
self::PREFIXED_ID_SQL = "('#{self::ID_PREFIX}' || #{table_name}.id)"
|
||||
|
||||
def code
|
||||
"#{self.class::ID_PREFIX}#{id}"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module SearchableModel
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
|
@ -43,8 +45,8 @@ module SearchableModel
|
|||
(attrs.map.with_index do |a, i|
|
||||
if %w(repository_rows.id repository_number_values.data).include?(a)
|
||||
"((#{a})::text) #{like} :t#{i} OR "
|
||||
elsif a == Experiment::EXPERIMENT_CODE_SQL
|
||||
"#{Experiment::EXPERIMENT_CODE_SQL} #{like} :t#{i} OR "
|
||||
elsif defined?(model::PREFIXED_ID_SQL) && a == model::PREFIXED_ID_SQL
|
||||
"#{a} #{like} :t#{i} OR "
|
||||
else
|
||||
col = options[:at_search].to_s == 'true' ? "lower(#{a})": a
|
||||
"(trim_html_tags(#{col})) #{like} :t#{i} OR "
|
||||
|
@ -69,8 +71,8 @@ module SearchableModel
|
|||
(attrs.map.with_index do |a, i|
|
||||
if %w(repository_rows.id repository_number_values.data).include?(a)
|
||||
"((#{a})::text) #{like} ANY (array[:t#{i}]) OR "
|
||||
elsif a == Experiment::EXPERIMENT_CODE_SQL
|
||||
"#{Experiment::EXPERIMENT_CODE_SQL} #{like} ANY (array[:t#{i}]) OR "
|
||||
elsif defined?(model::PREFIXED_ID_SQL) && a == model::PREFIXED_ID_SQL
|
||||
"#{a} #{like} ANY (array[:t#{i}]) OR "
|
||||
else
|
||||
"(trim_html_tags(#{a})) #{like} ANY (array[:t#{i}]) OR "
|
||||
end
|
||||
|
@ -90,8 +92,8 @@ module SearchableModel
|
|||
(attrs.map.with_index do |a, i|
|
||||
if %w(repository_rows.id repository_number_values.data).include?(a)
|
||||
"((#{a})::text) #{like} :t#{i} OR "
|
||||
elsif a == Experiment::EXPERIMENT_CODE_SQL
|
||||
"#{Experiment::EXPERIMENT_CODE_SQL} #{like} :t#{i} OR "
|
||||
elsif defined?(model::PREFIXED_ID_SQL) && a == model::PREFIXED_ID_SQL
|
||||
"#{a} #{like} :t#{i} OR "
|
||||
else
|
||||
"(trim_html_tags(#{a})) #{like} :t#{i} OR "
|
||||
end
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Experiment < ApplicationRecord
|
||||
include ArchivableModel
|
||||
include SearchableModel
|
||||
include SearchableByNameModel
|
||||
|
||||
EXPERIMENT_CODE_SQL = "('EX' || id)".freeze
|
||||
ID_PREFIX = 'EX'
|
||||
include PrefixedIdModel
|
||||
|
||||
before_save -> { report_elements.destroy_all }, if: -> { !new_record? && project_id_changed? }
|
||||
|
||||
|
@ -73,7 +76,7 @@ class Experiment < ApplicationRecord
|
|||
Experiment
|
||||
.where('experiments.project_id IN (?)', projects_ids)
|
||||
.where_attributes_like(
|
||||
[:name, :description, EXPERIMENT_CODE_SQL], query, options
|
||||
[:name, :description, PREFIXED_ID_SQL], query, options
|
||||
)
|
||||
return include_archived ? new_query : new_query.active
|
||||
elsif include_archived
|
||||
|
@ -81,7 +84,7 @@ class Experiment < ApplicationRecord
|
|||
Experiment
|
||||
.where(project: project_ids)
|
||||
.where_attributes_like(
|
||||
[:name, :description, EXPERIMENT_CODE_SQL], query, options
|
||||
[:name, :description, PREFIXED_ID_SQL], query, options
|
||||
)
|
||||
else
|
||||
new_query =
|
||||
|
@ -89,7 +92,7 @@ class Experiment < ApplicationRecord
|
|||
.active
|
||||
.where(project: project_ids)
|
||||
.where_attributes_like(
|
||||
[:name, :description, EXPERIMENT_CODE_SQL], query, options
|
||||
[:name, :description, PREFIXED_ID_SQL], query, options
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -107,10 +110,6 @@ class Experiment < ApplicationRecord
|
|||
where(project: Project.viewable_by_user(user, teams))
|
||||
end
|
||||
|
||||
def code
|
||||
"EX#{id}"
|
||||
end
|
||||
|
||||
def archived_branch?
|
||||
archived? || project.archived?
|
||||
end
|
||||
|
|
|
@ -313,7 +313,7 @@ class MyModule < ApplicationRecord
|
|||
rows = repository.assigned_rows(self).includes(:created_by).order(created_at: order)
|
||||
rows.find_each do |row|
|
||||
row_json = []
|
||||
row_json << (row.repository.is_a?(RepositorySnapshot) ? row.parent_id : row.id)
|
||||
row_json << row.code
|
||||
row_json << (row.archived ? "#{row.name} [#{I18n.t('general.archived')}]" : row.name)
|
||||
row_json << I18n.l(row.created_at, format: :full)
|
||||
row_json << row.created_by.full_name
|
||||
|
|
|
@ -80,8 +80,14 @@ class Repository < RepositoryBase
|
|||
|
||||
matched_by_user = readable_rows.joins(:created_by).where_attributes_like('users.full_name', query, options)
|
||||
|
||||
prefixed_repository_row_ids = RepositoryRow.where(repository_id: repositories)
|
||||
.where_attributes_like([RepositoryRow::PREFIXED_ID_SQL], query, options)
|
||||
.select(:id)
|
||||
|
||||
repository_row_matches =
|
||||
readable_rows.where_attributes_like(['repository_rows.name', 'repository_rows.id'], query, options)
|
||||
readable_rows.where_attributes_like(['repository_rows.name'], query, options).or(
|
||||
readable_rows.where('repository_rows.id' => prefixed_repository_row_ids)
|
||||
)
|
||||
|
||||
repository_rows = readable_rows.where(id: repository_row_matches)
|
||||
repository_rows = repository_rows.or(readable_rows.where(id: matched_by_user))
|
||||
|
|
|
@ -5,7 +5,11 @@ class RepositoryRow < ApplicationRecord
|
|||
include SearchableByNameModel
|
||||
include ArchivableModel
|
||||
|
||||
ID_PREFIX = 'IT'
|
||||
include PrefixedIdModel
|
||||
|
||||
belongs_to :repository, class_name: 'RepositoryBase'
|
||||
belongs_to :parent, class_name: 'RepositoryRow', optional: true
|
||||
belongs_to :created_by, foreign_key: :created_by_id, class_name: 'User'
|
||||
belongs_to :last_modified_by, foreign_key: :last_modified_by_id, class_name: 'User'
|
||||
belongs_to :archived_by,
|
||||
|
@ -33,6 +37,10 @@ class RepositoryRow < ApplicationRecord
|
|||
scope :active, -> { where(archived: false) }
|
||||
scope :archived, -> { where(archived: true) }
|
||||
|
||||
def code
|
||||
"#{ID_PREFIX}#{parent_id || id}"
|
||||
end
|
||||
|
||||
def self.viewable_by_user(user, teams)
|
||||
where(repository: Repository.viewable_by_user(user, teams))
|
||||
end
|
||||
|
|
|
@ -7,7 +7,7 @@ module Reports::Docx::RepositoryHelper
|
|||
result = [repository_data[:headers]]
|
||||
repository_data[:rows].each do |record|
|
||||
row = []
|
||||
row.push(record.repository.is_a?(RepositorySnapshot) ? record.parent_id : record.id)
|
||||
row.push(record.code)
|
||||
row.push(escape_input(record.archived ? "#{record.name} [#{I18n.t('general.archived')}]" : record.name))
|
||||
row.push(I18n.l(record.created_at, format: :full))
|
||||
row.push(escape_input(record.created_by.full_name))
|
||||
|
|
|
@ -78,8 +78,11 @@ class RepositoryDatatableService
|
|||
if search_value.present?
|
||||
matched_by_user = repository_rows.joins(:created_by).where_attributes_like('users.full_name', search_value)
|
||||
|
||||
repository_row_matches = repository_rows
|
||||
.where_attributes_like(['repository_rows.name', 'repository_rows.id'], search_value)
|
||||
repository_row_matches = repository_rows
|
||||
.where_attributes_like(
|
||||
['repository_rows.name', RepositoryRow::PREFIXED_ID_SQL],
|
||||
search_value
|
||||
)
|
||||
results = repository_rows.where(id: repository_row_matches)
|
||||
results = results.or(repository_rows.where(id: matched_by_user))
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<p>
|
||||
<span>
|
||||
<%= t('repository_row.modal_info.ID') %>
|
||||
<%= @repository_row.parent_id || @repository_row.id %>
|
||||
<%= @repository_row.code %>
|
||||
</span>
|
||||
<br>
|
||||
<span>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<p>
|
||||
<span>
|
||||
<%=t 'repository_row.modal_info.ID' %>
|
||||
<%= repository_row.id %>
|
||||
<%= repository_row.code %>
|
||||
</span>
|
||||
<br />
|
||||
<span>
|
||||
|
|
14
db/migrate/20210715125349_add_repository_row_code_index.rb
Normal file
14
db/migrate/20210715125349_add_repository_row_code_index.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddRepositoryRowCodeIndex < ActiveRecord::Migration[6.1]
|
||||
def up
|
||||
ActiveRecord::Base.connection.execute(
|
||||
"CREATE INDEX index_repository_rows_on_repository_row_code ON "\
|
||||
"repository_rows using gin (('IT'::text || id) gin_trgm_ops);"
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
remove_index :repository_rows, name: 'index_repository_rows_on_repository_row_code'
|
||||
end
|
||||
end
|
|
@ -5196,6 +5196,13 @@ CREATE INDEX index_repository_rows_on_name ON public.repository_rows USING gin (
|
|||
CREATE INDEX index_repository_rows_on_repository_id ON public.repository_rows USING btree (repository_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_repository_rows_on_repository_row_code; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_repository_rows_on_repository_row_code ON public.repository_rows USING gin ((('IT'::text || id)) public.gin_trgm_ops);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_repository_rows_on_restored_by_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -7250,6 +7257,7 @@ INSERT INTO "schema_migrations" (version) VALUES
|
|||
('20210407143303'),
|
||||
('20210410100006'),
|
||||
('20210506125657'),
|
||||
('20210622101238');
|
||||
('20210622101238'),
|
||||
('20210715125349');
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue