Class: RailsOmnibar

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_omnibar.rb,
lib/rails_omnibar/items.rb,
lib/rails_omnibar/config.rb,
lib/rails_omnibar/engine.rb,
lib/rails_omnibar/version.rb,
lib/rails_omnibar/commands.rb,
lib/rails_omnibar/item/base.rb,
lib/rails_omnibar/item/help.rb,
lib/rails_omnibar/rendering.rb,
lib/rails_omnibar/command/base.rb,
lib/rails_omnibar/item/webadmin.rb,
lib/rails_omnibar/command/search.rb

Defined Under Namespace

Modules: Command, Item Classes: BaseController, Engine, HtmlController, JsController, QueriesController

Constant Summary collapse

VERSION =
'1.6.0'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#authObject

Returns the value of attribute auth.



7
8
9
# File 'lib/rails_omnibar/config.rb', line 7

def auth
  @auth
end

#calculator=(value) ⇒ Object (writeonly)

Sets the attribute calculator

Parameters:

  • value

    the value to set the attribute calculator to.



34
35
36
# File 'lib/rails_omnibar/config.rb', line 34

def calculator=(value)
  @calculator = value
end

#modal=(value) ⇒ Object (writeonly)

Sets the attribute modal

Parameters:

  • value

    the value to set the attribute modal to.



29
30
31
# File 'lib/rails_omnibar/config.rb', line 29

def modal=(value)
  @modal = value
end

#placeholderObject



48
49
50
51
52
53
# File 'lib/rails_omnibar/config.rb', line 48

def placeholder
  return @placeholder.presence unless @placeholder.nil?

  help_item = items.find { |i| i.type == :help }
  help_item && "Hint: Type `#{help_item.title}` for help"
end

Class Method Details

.cast_to_command(arg) ⇒ Object



17
18
19
20
21
22
23
# File 'lib/rails_omnibar/commands.rb', line 17

def self.cast_to_command(arg)
  case arg
  when Command::Base then arg
  when Hash          then Command::Base.new(**arg)
  else raise(ArgumentError, "expected command, got #{arg.class}")
  end
end

.cast_to_item(arg) ⇒ Object



13
14
15
16
17
18
19
# File 'lib/rails_omnibar/items.rb', line 13

def self.cast_to_item(arg)
  case arg
  when Item::Base then arg
  when Hash       then Item::Base.new(**arg)
  else raise(ArgumentError, "expected Item, got #{arg.class}")
  end
end

.cast_to_proc(arg) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/rails_omnibar/commands.rb', line 25

def self.cast_to_proc(arg)
  arg = arg.method(:call).to_proc if arg.respond_to?(:call) && !arg.is_a?(Proc)
  arg.is_a?(Proc) && arg.parameters.count { |type, _| type == :req } == 1 ||
    raise(ArgumentError, "must be a proc that takes one positional argument")

  if arg.arity == 1
    # normalize for easier calling
    return ->(v, controller:, omnibar:) { arg.call(v) }
  end

  unsupported = arg.parameters.reject do |type, name|
    type == :req || type == :keyreq && name.in?(%i[controller omnibar])
  end
  unsupported.empty? ||
    raise(ArgumentError, "unsupported proc params: #{unsupported}")

  arg
end

.likeObject



72
73
74
# File 'lib/rails_omnibar/command/search.rb', line 72

def self.like
  @like ||= ActiveRecord::Base.connection.adapter_name =~ /^post|pg/i ? 'ILIKE' : 'LIKE'
end

Instance Method Details

#add_active_admin_items(icon: default_admin_item_icon, prefix: nil, suffix: nil, suggested: false) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/rails_omnibar/item/webadmin.rb', line 13

def add_active_admin_items(icon: default_admin_item_icon, prefix: nil, suffix: nil, suggested: false)
  ActiveAdmin.load!

  ActiveAdmin.application.namespaces.each do |namespace|
    namespace.fetch_menu(ActiveAdmin::DEFAULT_MENU) # ensure menu is loaded

    namespace.resources.each do |res|
      next unless (res.controller.action_methods & ['index', :index]).any?
      next unless index = res.route_collection_path rescue next
      next unless label = res.menu_item&.label.presence

      title = [prefix, label, suffix].compact.join(' ')
      add_item(title: title, url: index, icon: icon, suggested: suggested)
    end
  end
end

#add_command(command) ⇒ Object



11
12
13
14
15
# File 'lib/rails_omnibar/commands.rb', line 11

def add_command(command)
  check_const_and_clear_cache
  commands << RailsOmnibar.cast_to_command(command)
  self
end

#add_help(**kwargs) ⇒ Object



2
3
4
# File 'lib/rails_omnibar/item/help.rb', line 2

def add_help(**kwargs)
  add_item Item::Help.new(for_commands: commands, **kwargs)
end

#add_item(item) ⇒ Object



2
3
4
5
6
# File 'lib/rails_omnibar/items.rb', line 2

def add_item(item)
  check_const_and_clear_cache
  items << RailsOmnibar.cast_to_item(item)
  self
end

#add_items(*args) ⇒ Object



8
9
10
11
# File 'lib/rails_omnibar/items.rb', line 8

def add_items(*args)
  args.each { |arg| add_item(arg) }
  self
end

#add_rails_admin_items(icon: default_admin_item_icon, prefix: nil, suffix: nil, suggested: false) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
# File 'lib/rails_omnibar/item/webadmin.rb', line 30

def add_rails_admin_items(icon: default_admin_item_icon, prefix: nil, suffix: nil, suggested: false)
  admin_urls = RailsAdmin::Engine.routes.url_helpers

  RailsAdmin::Config.models.select(&:visible?).each do |model|
    next unless index = admin_urls.index_path(model.abstract_model.to_param)
    next unless label = model.label_plural # as used by rails_admin in sidebar

    title = [prefix, label, suffix].compact.join(' ')
    add_item(title: title, url: index, icon: icon, suggested: suggested)
  end
end

#add_record_search(**kwargs) ⇒ Object



6
7
8
# File 'lib/rails_omnibar/command/search.rb', line 6

def add_record_search(**kwargs)
  add_command Command::RecordSearch.new(**kwargs)
end

#add_search(**kwargs) ⇒ Object



2
3
4
# File 'lib/rails_omnibar/command/search.rb', line 2

def add_search(**kwargs)
  add_command Command::Search.new(**kwargs)
end

#add_webadmin_items(icon: default_admin_item_icon, prefix: nil, suffix: nil, suggested: false) ⇒ Object

adds fuzzy-searchable links to each defined resource index of ActiveAdmin etc.



3
4
5
6
7
8
9
10
11
# File 'lib/rails_omnibar/item/webadmin.rb', line 3

def add_webadmin_items(icon: default_admin_item_icon, prefix: nil, suffix: nil, suggested: false)
  if defined?(ActiveAdmin)
    add_active_admin_items(icon: icon, prefix: prefix, suffix: suffix, suggested: suggested)
  elsif defined?(RailsAdmin)
    add_rails_admin_items(icon: icon, prefix: prefix, suffix: suffix, suggested: suggested)
  else
    raise "#{__method__} currently only works with ActiveAdmin or RailsAdmin"
  end
end

#as_jsonObject



17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/rails_omnibar/rendering.rb', line 17

def as_json(*)
  {
    calculator:     calculator?,
    commandPattern: JsRegex.new!(command_pattern, target: 'ES2018'),
    hotkey:         hotkey,
    items:          items,
    maxResults:     max_results,
    modal:          modal?,
    placeholder:    placeholder,
    queryPath:      urls.query_path(omnibar_class: omnibar_class),
  }
end

#authorize(controller) ⇒ Object



11
12
13
14
15
16
17
18
19
# File 'lib/rails_omnibar/config.rb', line 11

def authorize(controller)
  if auth.nil?
    true
  elsif auth.arity == 0
    controller.instance_exec(&auth)
  else
    auth.call(controller, controller: controller, omnibar: self)
  end
end

#calculator?Boolean

Returns:

  • (Boolean)


35
36
37
# File 'lib/rails_omnibar/config.rb', line 35

def calculator?
  instance_variable_defined?(:@calculator) ? !!@calculator : true
end

#command_patternObject



7
8
9
# File 'lib/rails_omnibar/commands.rb', line 7

def command_pattern
  commands.any? ? Regexp.union(commands.map(&:pattern)) : /$NO_COMMANDS/
end

#configure(&block) ⇒ Object



2
3
4
5
# File 'lib/rails_omnibar/config.rb', line 2

def configure(&block)
  check_const_and_clear_cache
  tap(&block)
end

#default_admin_item_iconObject



42
43
44
# File 'lib/rails_omnibar/item/webadmin.rb', line 42

def default_admin_item_icon
  :document
end

#handle(input, controller) ⇒ Object



2
3
4
5
# File 'lib/rails_omnibar/commands.rb', line 2

def handle(input, controller)
  handler = commands.find { |h| h.pattern.match?(input) }
  handler&.call(input, controller: controller, omnibar: self) || []
end

#hotkeyObject



39
40
41
# File 'lib/rails_omnibar/config.rb', line 39

def hotkey
  @hotkey || 'k'
end

#hotkey=(arg) ⇒ Object



42
43
44
45
# File 'lib/rails_omnibar/config.rb', line 42

def hotkey=(arg)
  arg.to_s.size == 1 || raise(ArgumentError, 'hotkey must have length 1')
  @hotkey = arg.to_s.downcase
end

#html_urlObject



11
12
13
# File 'lib/rails_omnibar/rendering.rb', line 11

def html_url
  urls.html_path(omnibar_class: omnibar_class)
end

#max_resultsObject



25
26
27
# File 'lib/rails_omnibar/config.rb', line 25

def max_results
  @max_results || 10
end

#max_results=(arg) ⇒ Object



21
22
23
24
# File 'lib/rails_omnibar/config.rb', line 21

def max_results=(arg)
  arg.is_a?(Integer) && arg > 0 || raise(ArgumentError, 'max_results must be > 0')
  @max_results = arg
end

#modal?Boolean

Returns:

  • (Boolean)


30
31
32
# File 'lib/rails_omnibar/config.rb', line 30

def modal?
  instance_variable_defined?(:@modal) ? !!@modal : false
end

#renderObject



2
3
4
5
6
7
8
9
# File 'lib/rails_omnibar/rendering.rb', line 2

def render
  @cached_html ||= <<~HTML.html_safe
    <script src='#{urls.js_path}?v=#{RailsOmnibar::VERSION}' type='text/javascript'></script>
    <div id='mount-rails-omnibar'>
      <script type="application/json">#{to_json}</script>
    </div>
  HTML
end

#urlsObject



30
31
32
# File 'lib/rails_omnibar/rendering.rb', line 30

def urls
  @urls ||= RailsOmnibar::Engine.routes.url_helpers
end