Class: Autoselect::Levels::Smart

Inherits:
Autoselect::Level show all
Defined in:
lib/autoselect/levels/smart.rb

Overview

lib/autoselect/levels/smart.rb

Default level that delegates to the existing Queries::::Autocomplete class. Wraps all existing autocomplete logic and makes it available as a level. Generated by default for all model autoselects.

Subclasses must override #query_class to specify the concrete Query class.

Direct Known Subclasses

Otu::Levels::Smart, TaxonName::Levels::Smart

Constant Summary collapse

RECENT_LIMIT =
10
RECENT_WINDOW =
1.week

Constants inherited from Autoselect::Level

Autoselect::Level::DEFAULT_FUSE_MS, Autoselect::Level::EXTERNAL_FUSE_MS, Autoselect::Level::MINIMUM_RESULTS

Instance Method Summary collapse

Methods inherited from Autoselect::Level

#external?, #fuse_ms, #metadata, #minimum_results, #model_key, #record_info, #record_info_html, #record_label, #record_label_html

Instance Method Details

#call(term:, operator: nil, project_id: nil, user_id: nil, **kwargs) ⇒ Array

Returns of ActiveRecord model instances.

Parameters:

  • term (String)
  • operator (Symbol, nil) (defaults to: nil)

    :recent, :recent_mine, :pinboard, :pinboard_top, or nil

  • project_id (Integer, nil) (defaults to: nil)
  • user_id (Integer, nil) (defaults to: nil)
  • kwargs (Hash)

    passed through to the query class

Returns:

  • (Array)

    of ActiveRecord model instances



37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/autoselect/levels/smart.rb', line 37

def call(term:, operator: nil, project_id: nil, user_id: nil, **kwargs)
  case operator
  when :recent
    recent_records(project_id:)
  when :recent_mine
    recent_records_by_user(project_id:, user_id:)
  when :pinboard
    pinboard_records(project_id:, user_id:)
  when :pinboard_top
    pinboard_top_record(project_id:, user_id:)
  else
    query_class.new(term, project_id:, **kwargs).autocomplete
  end
end

#descriptionObject



27
28
29
# File 'lib/autoselect/levels/smart.rb', line 27

def description
  'Multi-query results with fuzzy and pattern matching.'
end

#filter_classObject (private)

Derive the Filter class from the query_class namespace. e.g. Queries::TaxonName::Autocomplete -> Queries::TaxonName::Filter



104
105
106
107
108
# File 'lib/autoselect/levels/smart.rb', line 104

def filter_class
  parts = query_class.name.split('::')
  parts[-1] = 'Filter'
  parts.join('::').constantize
end

#keyObject



19
20
21
# File 'lib/autoselect/levels/smart.rb', line 19

def key
  :smart
end

#labelObject



23
24
25
# File 'lib/autoselect/levels/smart.rb', line 23

def label
  'Smart'
end

#pinboard_model_nameObject (private)

Derive the AR model name from the query class namespace. Queries::TaxonName::Autocomplete → 'TaxonName'



98
99
100
# File 'lib/autoselect/levels/smart.rb', line 98

def pinboard_model_name
  query_class.name.split('::')[-2]
end

#pinboard_records(project_id:, user_id:) ⇒ Object (private)

All pinboard items for this model type, ordered by pin position.



80
81
82
83
84
85
86
87
88
# File 'lib/autoselect/levels/smart.rb', line 80

def pinboard_records(project_id:, user_id:)
  return [] if user_id.blank?
  ::PinboardItem
    .where(pinned_object_type: pinboard_model_name, user_id:, project_id:)
    .order(:position)
    .includes(:pinned_object)
    .map(&:pinned_object)
    .compact
end

#pinboard_top_record(project_id:, user_id:) ⇒ Object (private)

The topmost pinboard item for this model type (0 or 1 records).



91
92
93
94
# File 'lib/autoselect/levels/smart.rb', line 91

def pinboard_top_record(project_id:, user_id:)
  rec = pinboard_records(project_id:, user_id:).first
  rec ? [rec] : []
end

#query_classClass

Returns the Queries::::Autocomplete class to delegate to.

Returns:

  • (Class)

    the Queries::::Autocomplete class to delegate to

Raises:

  • (NotImplementedError)


15
16
17
# File 'lib/autoselect/levels/smart.rb', line 15

def query_class
  raise NotImplementedError, "#{self.class} must implement #query_class"
end

#recent_records(project_id:) ⇒ Object (private)

TODO: abstract to a recent concern if it doesn't already exist

Records updated in the last week by anyone in the project, most recent first. Delegates to the model Filter so project_id scoping is handled correctly for models that may not have a project_id column.



59
60
61
62
63
64
65
# File 'lib/autoselect/levels/smart.rb', line 59

def recent_records(project_id:)
  return [] if project_id.blank?
  filter_class.new(
    project_id:,
    updated_since: RECENT_WINDOW.ago.to_date.iso8601
  ).all.order(updated_at: :desc).limit(RECENT_LIMIT).to_a
end

#recent_records_by_user(project_id:, user_id:) ⇒ Object (private)

TODO: See existing recent records, or abstract this to a Recent concern Records updated in the last week by the given user, most recent first.



69
70
71
72
73
74
75
76
77
# File 'lib/autoselect/levels/smart.rb', line 69

def recent_records_by_user(project_id:, user_id:)
  return [] if project_id.blank? || user_id.blank?
  filter_class.new(
    project_id:,
    updated_since: RECENT_WINDOW.ago.to_date.iso8601,
    user_id:,
    user_target: 'updated'
  ).all.order(updated_at: :desc).limit(RECENT_LIMIT).to_a
end