diff --git a/app/controllers/concerns/name_filterable.rb b/app/controllers/concerns/name_filterable.rb index 50ad9569..0575d817 100644 --- a/app/controllers/concerns/name_filterable.rb +++ b/app/controllers/concerns/name_filterable.rb @@ -37,14 +37,10 @@ def apply_name_filters(query, filters) next if value.nil? case key.to_sym - when :status - query = query.where(status: map_status_to_value(value)) - when :rank - query = query.where(rank: value) - when :redirect - query = query.where(redirect: value) - else + when :rank, :redirect, :status query = query.where(key => value) + when :where + query = query.where(value) end end query diff --git a/app/controllers/names_controller.rb b/app/controllers/names_controller.rb index 545f7f2b..75912f3e 100644 --- a/app/controllers/names_controller.rb +++ b/app/controllers/names_controller.rb @@ -1,4 +1,12 @@ +# frozen_string_literal: true + +# Controller for managing names in the SeqCode Registry. +# Uses concerns for modularity and service objects for business logic. class NamesController < ApplicationController + include Paginatable + include Filterable + include NameFilterable + before_action(:set_tutorial) before_action(:set_name_and_notifications, only: %i[show]) before_action( @@ -46,11 +54,13 @@ class NamesController < ApplicationController def autocomplete name = params[:q].downcase rank = params[:rank]&.downcase - @names = - Name.where('LOWER(name) LIKE ?', "#{name}%") - .or(Name.where('LOWER(name) LIKE ?', "% #{name}%")) - .limit(20) - @names = @names.where(rank: rank) if rank + @names = Services::Name::FuzzySearch.call( + name, + method: :similarity, + threshold: 0.7, + limit: 20, + selection: rank ? Name.where(rank: rank) : Name.all + ) end # GET /names @@ -72,37 +82,13 @@ def index(opts = {}) ].compact.join(' ') opts[:rank] = params[:rank] if params[:rank].present? - opts[:status] ||= - case @status.to_s.downcase - when 'public'; Name.public_status - when 'automated'; 0 - when 'seqcode'; 15 - when 'icnp'; 20 - when 'icnafp'; 25 - when 'valid'; Name.valid_status - end + opts[:status] ||= map_status_to_value(@status) - @names ||= - case @sort.to_s.downcase - when 'date' - if opts[:status] == 15 - Name.order(validated_at: :desc) - else - Name.order(created_at: :desc) - end - when 'citations' - Name - .left_joins(:publication_names).group(:id) - .order('COUNT(publication_names.id) DESC') - else - @sort = 'alphabetically' - Name.order(name: :asc) - end + @names ||= apply_name_sort(Name.all) + @names = apply_name_filters(@names, {}) + @names = apply_name_filters(@names, opts) @names = @names.where(redirect: nil) - @names = @names.where(status: opts[:status]) if opts[:status] - @names = @names.where(rank: opts[:rank]) if opts[:rank] - @names = @names.where(opts[:where]) if opts[:where] - @names = @names.paginate(page: params[:page], per_page: 30) + @names = paginate(@names) @count = @names.count @count = @count.size if @count.is_a? Hash @@ -238,10 +224,7 @@ def linkout Name.where('status >= 15') .where.not(ncbi_taxonomy: nil) .order(created_at: :asc) - @names = - @names.paginate( - page: params[:page] || 1, per_page: params[:per_page] || 10 - ) + @names = paginate(@names, per_page: params[:per_page] || 10) end # GET /names/1/network @@ -366,13 +349,13 @@ def destroy # GET /names/unranked def unranked @names = Name.where(rank: nil).order(created_at: :asc) - @names = @names.paginate(page: params[:page], per_page: 30) + @names = paginate(@names) end # GET /names/unknown_proposal def unknown_proposal @names = Name.where(proposed_in: nil).where('name LIKE ?', 'Candidatus %').order(created_at: :asc) - @names = @names.paginate(page: params[:page], per_page: 30) + @names = paginate(@names) end # POST /names/1/proposed_in/2 @@ -475,7 +458,7 @@ def claim # POST /names/1/unclaim def unclaim - change_status(:unclaim, 'Name successfully claimed', current_user) + change_status(:unclaim, 'Name successfully unclaimed', current_user) end # GET /names/1/transfer_user diff --git a/app/views/names/_nomenclatural_type.json.jbuilder b/app/views/names/_nomenclatural_type.json.jbuilder index b22ea5f4..fae8590f 100644 --- a/app/views/names/_nomenclatural_type.json.jbuilder +++ b/app/views/names/_nomenclatural_type.json.jbuilder @@ -1,5 +1,5 @@ -json.class(object&.respond_to?(:type_of_type) ? object.type_of_type : 'unknown') +json.class Services::Name::TypeResolver.resolve(object) json.id(object.try(:id)) json.url(object ? polymorphic_url(object, format: :json) : nil) json.uri object.try(:uri) -json.display(object.try(:display, false)) \ No newline at end of file +json.display(object.try(:display, false)) diff --git a/config/initializers/services.rb b/config/initializers/services.rb new file mode 100644 index 00000000..756e9e44 --- /dev/null +++ b/config/initializers/services.rb @@ -0,0 +1,8 @@ +# config/initializers/services.rb +# Ensure service objects are loaded before views are rendered +Rails.application.config.to_prepare do + # Load all service objects under app/services/ + Dir.glob(Rails.root.join('app/services/**/*.rb')).each do |file| + require_dependency file + end +end