diff --git a/server/Gemfile b/server/Gemfile index 166cdfddf..920950ba0 100644 --- a/server/Gemfile +++ b/server/Gemfile @@ -8,7 +8,7 @@ gem 'rails', '~> 6.1', '>= 6.1.3.1' # Use postgresql as the database for Active Record gem 'pg', '~> 1.1' # Use Puma as the app server -gem 'puma', '5.6.4' +gem 'puma', '5.6.7' # Use SCSS for stylesheets gem 'sass-rails', '>= 6' # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker diff --git a/server/Gemfile.lock b/server/Gemfile.lock index b42edc496..cf84c4c90 100644 --- a/server/Gemfile.lock +++ b/server/Gemfile.lock @@ -288,7 +288,7 @@ GEM pry-rails (0.3.9) pry (>= 0.10.4) public_suffix (5.0.1) - puma (5.6.4) + puma (5.6.7) nio4r (~> 2.0) raabro (1.4.0) racc (1.7.1) @@ -495,7 +495,7 @@ DEPENDENCIES pg (~> 1.1) pry pry-rails - puma (= 5.6.4) + puma (= 5.6.7) rack-cors (~> 1.1.1) rack-mini-profiler (~> 2.0) rails (~> 6.1, >= 6.1.3.1) diff --git a/server/app/admin/users_admin.rb b/server/app/admin/users_admin.rb index a25ca98b6..e2915c223 100644 --- a/server/app/admin/users_admin.rb +++ b/server/app/admin/users_admin.rb @@ -3,6 +3,10 @@ item :users, icon: "fa fa-user" end + search do |q| + q ? collection.where("username ILIKE ? OR name ILIKE ?", "%#{q}%", "%#{q}%") : collection + end + # Customize the table columns shown on the index view. table do column :id diff --git a/server/app/models/actions/suggest_revision_set.rb b/server/app/models/actions/suggest_revision_set.rb index 8395a14d4..a2678db46 100644 --- a/server/app/models/actions/suggest_revision_set.rb +++ b/server/app/models/actions/suggest_revision_set.rb @@ -14,6 +14,8 @@ def initialize(existing_obj:, updated_obj:, originating_user:, organization_id:, end def execute + updated_obj.in_revision_validation_context = true + updated_obj.revision_target_id = existing_obj.id updated_obj.validate! any_changes = false diff --git a/server/app/models/concerns/moderated.rb b/server/app/models/concerns/moderated.rb index f969d2925..e4a780cd7 100644 --- a/server/app/models/concerns/moderated.rb +++ b/server/app/models/concerns/moderated.rb @@ -25,6 +25,8 @@ module Moderated ->() { where(action: 'revision suggested').includes(:originating_user).order('events.updated_at DESC') }, as: :subject, class_name: 'Event' + + attr_accessor :in_revision_validation_context, :revision_target_id end #TODO: Refactor to use new Revision format diff --git a/server/app/models/molecular_profile.rb b/server/app/models/molecular_profile.rb index 5eba96888..18ed2c304 100644 --- a/server/app/models/molecular_profile.rb +++ b/server/app/models/molecular_profile.rb @@ -22,10 +22,7 @@ class MolecularProfile < ActiveRecord::Base validates :name, presence: true - #this breaks when we do updated_obj.validate! during propose revision set. we need a workaround - #validates_uniqueness_of :name, - #conditions: -> { where(deprecated: false) }, - #message: 'must be unique' + validate :unique_name_in_context searchkick highlight: [:name, :aliases], callbacks: :async, word_start: [:name] scope :search_import, -> { includes(:molecular_profile_aliases, variants: [:gene])} @@ -85,4 +82,30 @@ def self.timepoint_query .count } end + + def unique_name_in_context + base_query = self.class.where( + deprecated: false, + name: name + ) + + duplicate_name = if in_revision_validation_context + base_query + .where.not(id: revision_target_id) + .exists? + else + if persisted? + base_query + .where.not(id: id) + .exists? + else + base_query + .exists? + end + end + + if duplicate_name + errors.add(:name, 'must be unique. There is already a Molecular Profile with this name.') + end + end end diff --git a/server/app/models/variant.rb b/server/app/models/variant.rb index 349c9b162..ca2c39029 100644 --- a/server/app/models/variant.rb +++ b/server/app/models/variant.rb @@ -32,6 +32,8 @@ class Variant < ApplicationRecord after_commit :reindex_mps + validates :name, presence: true + validates :reference_bases, format: { with: /\A[ACTG]+\z|\A[ACTG]+\/[ACTG]+\z/, message: "only allows A,C,T,G or /" @@ -42,10 +44,7 @@ class Variant < ApplicationRecord message: "only allows A,C,T,G or /" }, allow_nil: true - #this breaks when we do updated_obj.validate! during propose revision set. we need a workaround - #validates_uniqueness_of :name, scope: :gene_id, - #conditions: -> { where(deprecated: false) }, - #message: 'must be unique within a Gene' + validate :unique_name_in_context searchkick highlight: [:name, :aliases], callbacks: :async scope :search_import, -> { includes(:variant_aliases, :gene) } @@ -87,4 +86,31 @@ def on_revision_accepted SetAlleleRegistryIdSingleVariant.perform_later(self) if Rails.env.production? GenerateOpenCravatLink.perform_later(self) end + + def unique_name_in_context + base_query = self.class.where( + deprecated: false, + gene_id: gene_id, + name: name + ) + + duplicate_name = if in_revision_validation_context + base_query + .where.not(id: revision_target_id) + .exists? + else + if persisted? + base_query + .where.not(id: id) + .exists? + else + base_query + .exists? + end + end + + if duplicate_name + errors.add(:name, 'must be unique within a Gene') + end + end end