Class: Autoselect::Base
- Inherits:
-
Object
- Object
- Autoselect::Base
- Includes:
- Operators
- Defined in:
- lib/autoselect/base.rb
Overview
lib/autoselect/base.rb
Base class for all model-specific autoselect implementations.
Mirrors the pattern of lib/queries/ where each model subclasses a shared base.
Generated via rails generate taxon_works:autoselect.
Usage:
class Autoselect::TaxonName::Autoselect < Autoselect::Base
...
end
Claude wrote > 50% of this class.
Direct Known Subclasses
Constant Summary
Constants included from Operators
Instance Attribute Summary collapse
-
#level_params ⇒ Hash
readonly
Extra level-specific params passed through from the controller.
- #project_id ⇒ Integer? readonly
-
#raw_term ⇒ String?
readonly
The raw search term including any operator prefix.
-
#requested_level ⇒ String?
readonly
The level key being queried (e.g. 'fast', 'smart').
- #user_id ⇒ Integer? readonly
Instance Method Summary collapse
- #build_config ⇒ Object private
- #config_response ⇒ Object private
- #execute_level(level_instance, effective_term, operator) ⇒ Object private
- #find_level(key) ⇒ Object private
-
#format_results(records, level_instance) ⇒ Array<Hash>
private
Build response item hashes from an array of records.
-
#initialize(term: nil, level: nil, project_id: nil, user_id: nil, show_info: true, **kwargs) ⇒ Base
constructor
A new instance of Base.
- #level_map_keys ⇒ Object private
-
#levels ⇒ Array<Autoselect::Level>
Subclasses must override with their own level stack.
- #next_level_key(current_key) ⇒ Object private
- #record_list_operator?(operator) ⇒ Boolean private
-
#resource_path ⇒ String
Override in subclasses, e.g.
-
#response ⇒ Hash
The full response (config or term response), ready for render json:.
-
#response_values(record) ⇒ Hash
Subclasses override to specify which attribute keys to inject into the parent form.
- #term_response ⇒ Object private
Methods included from Operators
Constructor Details
#initialize(term: nil, level: nil, project_id: nil, user_id: nil, show_info: true, **kwargs) ⇒ Base
Returns a new instance of Base.
37 38 39 40 41 42 43 44 |
# File 'lib/autoselect/base.rb', line 37 def initialize(term: nil, level: nil, project_id: nil, user_id: nil, show_info: true, **kwargs) @raw_term = term.presence @requested_level = level.presence @project_id = project_id @user_id = user_id @show_info = show_info.to_s != 'false' @level_params = kwargs end |
Instance Attribute Details
#level_params ⇒ Hash (readonly)
Returns extra level-specific params passed through from the controller.
29 30 31 |
# File 'lib/autoselect/base.rb', line 29 def level_params @level_params end |
#project_id ⇒ Integer? (readonly)
23 24 25 |
# File 'lib/autoselect/base.rb', line 23 def project_id @project_id end |
#raw_term ⇒ String? (readonly)
Returns the raw search term including any operator prefix.
17 18 19 |
# File 'lib/autoselect/base.rb', line 17 def raw_term @raw_term end |
#requested_level ⇒ String? (readonly)
Returns the level key being queried (e.g. 'fast', 'smart').
20 21 22 |
# File 'lib/autoselect/base.rb', line 20 def requested_level @requested_level end |
#user_id ⇒ Integer? (readonly)
26 27 28 |
# File 'lib/autoselect/base.rb', line 26 def user_id @user_id end |
Instance Method Details
#build_config ⇒ Object (private)
108 109 110 111 112 113 114 115 116 |
# File 'lib/autoselect/base.rb', line 108 def build_config { resource: resource_path, levels: levels.map(&:metadata), operators: self.class.operator_definitions, map: level_map_keys, user_preferences: {} } end |
#config_response ⇒ Object (private)
76 77 78 79 80 81 82 83 84 85 |
# File 'lib/autoselect/base.rb', line 76 def config_response Autoselect::Response.new( config: build_config, request: nil, level: nil, results: nil, next_level: nil, level_map: level_map_keys ).as_json end |
#execute_level(level_instance, effective_term, operator) ⇒ Object (private)
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/autoselect/base.rb', line 133 def execute_level(level_instance, effective_term, operator) # Record-list operators are disabled on external levels (e.g. CoL) return [] if level_instance.external? && record_list_operator?(operator) if record_list_operator?(operator) # Always route to the Smart level regardless of the client's active level, # so !b/!! work even when the user is on the Fast level (the default). smart = levels.find { |l| l.is_a?(::Autoselect::Levels::Smart) } target = smart || level_instance return target.call(term: effective_term, operator:, project_id:, user_id:, **level_params) end level_instance.call( term: effective_term, operator:, project_id:, user_id:, **level_params ) end |
#find_level(key) ⇒ Object (private)
122 123 124 |
# File 'lib/autoselect/base.rb', line 122 def find_level(key) levels.find { |l| l.key.to_s == key.to_s } || levels.first end |
#format_results(records, level_instance) ⇒ Array<Hash> (private)
Build response item hashes from an array of records. Rendering is delegated to level_instance so external levels can supply their own. Subclasses may override to handle extension data (e.g. CoL pseudo-records).
164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/autoselect/base.rb', line 164 def format_results(records, level_instance) records.map do |record| { id: record.id, global_id: record.respond_to?(:to_global_id) ? record.to_global_id.to_s : nil, label: level_instance.record_label(record), label_html: level_instance.record_label_html(record), info_html: @show_info ? level_instance.record_info_html(record) : '', response_values: response_values(record), extension: {} } end end |
#level_map_keys ⇒ Object (private)
118 119 120 |
# File 'lib/autoselect/base.rb', line 118 def level_map_keys levels.map { |l| l.key.to_s } end |
#levels ⇒ Array<Autoselect::Level>
Subclasses must override with their own level stack.
57 58 59 |
# File 'lib/autoselect/base.rb', line 57 def levels raise NotImplementedError, "#{self.class} must implement #levels" end |
#next_level_key(current_key) ⇒ Object (private)
126 127 128 129 130 131 |
# File 'lib/autoselect/base.rb', line 126 def next_level_key(current_key) map = level_map_keys idx = map.index(current_key.to_s) return nil if idx.nil? || idx >= map.length - 1 map[idx + 1] end |
#record_list_operator?(operator) ⇒ Boolean (private)
154 155 156 |
# File 'lib/autoselect/base.rb', line 154 def record_list_operator?(operator) %i[recent recent_mine pinboard pinboard_top].include?(operator) end |
#resource_path ⇒ String
Override in subclasses, e.g. '/taxon_names/autoselect'
70 71 72 |
# File 'lib/autoselect/base.rb', line 70 def resource_path raise NotImplementedError, "#{self.class} must implement #resource_path" end |
#response ⇒ Hash
Returns the full response (config or term response), ready for render json:.
47 48 49 50 51 52 53 |
# File 'lib/autoselect/base.rb', line 47 def response if raw_term.blank? config_response else term_response end end |
#response_values(record) ⇒ Hash
Subclasses override to specify which attribute keys to inject into the parent form.
64 65 66 |
# File 'lib/autoselect/base.rb', line 64 def response_values(record) raise NotImplementedError, "#{self.class} must implement #response_values(record)" end |
#term_response ⇒ Object (private)
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/autoselect/base.rb', line 87 def term_response parsed = parse_operators(raw_term) operator = parsed[:operator] effective_term = parsed[:effective_term] level_instance = find_level(requested_level) results = execute_level(level_instance, effective_term, operator) formatted = format_results(results, level_instance) suppress_escalation = %i[pinboard pinboard_top].include?(operator) Autoselect::Response.new( config: nil, request: { term: raw_term, level: requested_level, project_id:, operator: operator&.to_s }, level: requested_level, results: formatted, next_level: (!suppress_escalation && formatted.empty?) ? next_level_key(requested_level) : nil, level_map: nil ).as_json end |