mat_views 0.1.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +10 -10
- data/app/assets/images/mat_views/android-chrome-192x192.png +0 -0
- data/app/assets/images/mat_views/android-chrome-512x512.png +0 -0
- data/app/assets/images/mat_views/apple-touch-icon.png +0 -0
- data/app/assets/images/mat_views/favicon-16x16.png +0 -0
- data/app/assets/images/mat_views/favicon-32x32.png +0 -0
- data/app/assets/images/mat_views/favicon-48x48.png +0 -0
- data/app/assets/images/mat_views/favicon.ico +0 -0
- data/app/assets/images/mat_views/favicon.svg +18 -0
- data/app/assets/images/mat_views/logo.svg +18 -0
- data/app/assets/images/mat_views/mask-icon.svg +5 -0
- data/app/assets/stylesheets/mat_views/application.css +323 -12
- data/app/controllers/mat_views/admin/application_controller.rb +135 -0
- data/app/controllers/mat_views/admin/dashboard_controller.rb +32 -0
- data/app/controllers/mat_views/admin/mat_view_definitions_controller.rb +248 -0
- data/app/controllers/mat_views/admin/preferences_controller.rb +91 -0
- data/app/controllers/mat_views/admin/runs_controller.rb +74 -0
- data/app/helpers/mat_views/admin/ui_helper.rb +385 -0
- data/app/javascript/mat_views/application.js +8 -0
- data/app/javascript/mat_views/controllers/application.js +10 -0
- data/app/javascript/mat_views/controllers/details_controller.js +122 -0
- data/app/javascript/mat_views/controllers/drawer_controller.js +252 -0
- data/app/javascript/mat_views/controllers/filter_controller.js +90 -0
- data/app/javascript/mat_views/controllers/flash_controller.js +13 -0
- data/app/javascript/mat_views/controllers/index.js +10 -0
- data/app/javascript/mat_views/controllers/mv_confirm_controller.js +281 -0
- data/app/javascript/mat_views/controllers/submitter_controller.js +15 -0
- data/app/javascript/mat_views/controllers/tabs_controller.js +67 -0
- data/app/javascript/mat_views/controllers/timezone_controller.js +16 -0
- data/app/javascript/mat_views/controllers/tooltip_controller.js +328 -0
- data/app/javascript/mat_views/controllers/turbo_frame_lifecycle_controller.js +49 -0
- data/app/jobs/mat_views/application_job.rb +107 -2
- data/app/jobs/mat_views/create_view_job.rb +21 -122
- data/app/jobs/mat_views/delete_view_job.rb +22 -129
- data/app/jobs/mat_views/refresh_view_job.rb +12 -133
- data/app/models/concerns/mat_views_i18n.rb +139 -0
- data/app/models/mat_views/application_record.rb +1 -0
- data/app/models/mat_views/mat_view_definition.rb +12 -7
- data/app/models/mat_views/mat_view_run.rb +34 -16
- data/app/views/layouts/mat_views/_footer.html.erb +41 -0
- data/app/views/layouts/mat_views/_header.html.erb +25 -0
- data/app/views/layouts/mat_views/admin.html.erb +47 -0
- data/app/views/layouts/mat_views/turbo_frame.html.erb +3 -0
- data/app/views/mat_views/admin/dashboard/index.html.erb +33 -0
- data/app/views/mat_views/admin/mat_view_definitions/_definition_actions.html.erb +94 -0
- data/app/views/mat_views/admin/mat_view_definitions/_table.html.erb +48 -0
- data/app/views/mat_views/admin/mat_view_definitions/empty.html.erb +1 -0
- data/app/views/mat_views/admin/mat_view_definitions/form.html.erb +79 -0
- data/app/views/mat_views/admin/mat_view_definitions/index.html.erb +10 -0
- data/app/views/mat_views/admin/mat_view_definitions/show.html.erb +40 -0
- data/app/views/mat_views/admin/preferences/show.html.erb +50 -0
- data/app/views/mat_views/admin/runs/_table.html.erb +61 -0
- data/app/views/mat_views/admin/runs/index.html.erb +38 -0
- data/app/views/mat_views/admin/runs/show.html.erb +64 -0
- data/app/views/mat_views/admin/ui/_card.html.erb +15 -0
- data/app/views/mat_views/admin/ui/_details.html.erb +10 -0
- data/app/views/mat_views/admin/ui/_flash.html.erb +6 -0
- data/app/views/mat_views/admin/ui/_table.html.erb +8 -0
- data/config/importmap.rb +9 -0
- data/config/locales/en-AU-ocker.yml +187 -0
- data/config/locales/en-AU.yml +187 -0
- data/config/locales/en-BB.yml +187 -0
- data/config/locales/en-BD.yml +187 -0
- data/config/locales/en-BE.yml +187 -0
- data/config/locales/en-BORK.yml +187 -0
- data/config/locales/en-BS.yml +187 -0
- data/config/locales/en-BZ.yml +187 -0
- data/config/locales/en-CA.yml +187 -0
- data/config/locales/en-CM.yml +187 -0
- data/config/locales/en-CY.yml +187 -0
- data/config/locales/en-EG.yml +187 -0
- data/config/locales/en-FJ.yml +187 -0
- data/config/locales/en-GB.yml +187 -0
- data/config/locales/en-GH.yml +187 -0
- data/config/locales/en-GI.yml +187 -0
- data/config/locales/en-GM.yml +187 -0
- data/config/locales/en-GY.yml +187 -0
- data/config/locales/en-HK.yml +187 -0
- data/config/locales/en-IE.yml +187 -0
- data/config/locales/en-IN.yml +187 -0
- data/config/locales/en-JM.yml +187 -0
- data/config/locales/en-KE.yml +187 -0
- data/config/locales/en-LK.yml +187 -0
- data/config/locales/en-LOL.yml +187 -0
- data/config/locales/en-LR.yml +187 -0
- data/config/locales/en-MS.yml +187 -0
- data/config/locales/en-MT.yml +187 -0
- data/config/locales/en-MW.yml +187 -0
- data/config/locales/en-MY.yml +187 -0
- data/config/locales/en-NG.yml +187 -0
- data/config/locales/en-NP.yml +187 -0
- data/config/locales/en-NZ.yml +187 -0
- data/config/locales/en-PG.yml +187 -0
- data/config/locales/en-PH.yml +187 -0
- data/config/locales/en-PK.yml +187 -0
- data/config/locales/en-RW.yml +187 -0
- data/config/locales/en-SCOT.yml +187 -0
- data/config/locales/en-SG.yml +187 -0
- data/config/locales/en-SHAKESPEARE.yml +187 -0
- data/config/locales/en-SL.yml +187 -0
- data/config/locales/en-SS.yml +187 -0
- data/config/locales/en-TH.yml +187 -0
- data/config/locales/en-TT.yml +187 -0
- data/config/locales/en-TZ.yml +187 -0
- data/config/locales/en-UG.yml +187 -0
- data/config/locales/en-US-pirate.yml +187 -0
- data/config/locales/en-US.yml +187 -0
- data/config/locales/en-YODA.yml +187 -0
- data/config/locales/en-ZA.yml +187 -0
- data/config/locales/en-ZW.yml +187 -0
- data/config/locales/en.yml +187 -0
- data/config/routes.rb +27 -3
- data/lib/ext/exception.rb +20 -0
- data/lib/generators/mat_views/install/templates/create_mat_view_definitions.rb +7 -7
- data/lib/generators/mat_views/install/templates/create_mat_view_runs.rb +7 -7
- data/lib/mat_views/admin/auth_bridge.rb +93 -0
- data/lib/mat_views/admin/default_auth.rb +61 -0
- data/lib/mat_views/configuration.rb +9 -0
- data/lib/mat_views/engine.rb +50 -2
- data/lib/mat_views/helpers/ui_test_ids.rb +43 -0
- data/lib/mat_views/jobs/adapter.rb +8 -5
- data/lib/mat_views/service_response.rb +30 -15
- data/lib/mat_views/services/base_service.rb +204 -41
- data/lib/mat_views/services/check_matview_exists.rb +76 -0
- data/lib/mat_views/services/concurrent_refresh.rb +38 -121
- data/lib/mat_views/services/create_view.rb +72 -55
- data/lib/mat_views/services/delete_view.rb +46 -95
- data/lib/mat_views/services/regular_refresh.rb +38 -94
- data/lib/mat_views/services/swap_refresh.rb +83 -123
- data/lib/mat_views/version.rb +1 -1
- data/lib/mat_views.rb +13 -6
- data/lib/tasks/helpers.rb +27 -27
- data/lib/tasks/mat_views_tasks.rake +48 -42
- metadata +131 -5
@@ -5,8 +5,8 @@
|
|
5
5
|
# This source code is licensed under the MIT license found in the
|
6
6
|
# LICENSE file in the root directory of this source tree.
|
7
7
|
|
8
|
-
# This migration creates the mat_view_runs table, which tracks the mutation runs(create,refresh,drop) of
|
9
|
-
# It includes references to the
|
8
|
+
# This migration creates the mat_view_runs table, which tracks the mutation runs(create,refresh,drop) of materialised views.
|
9
|
+
# It includes references to the materialised view definition, status, operation type, timestamps,
|
10
10
|
# duration, error messages, and additional metadata.
|
11
11
|
class CreateMatViewRuns < ActiveRecord::Migration[7.1]
|
12
12
|
def change
|
@@ -14,17 +14,17 @@ class CreateMatViewRuns < ActiveRecord::Migration[7.1]
|
|
14
14
|
t.references :mat_view_definition,
|
15
15
|
null: false,
|
16
16
|
foreign_key: true,
|
17
|
-
comment: 'Reference to the
|
17
|
+
comment: 'Reference to the materialised view definition'
|
18
18
|
|
19
|
-
# 0=
|
20
|
-
t.integer :status, null: false, default: 0, comment: '0=
|
19
|
+
# 0=running, 1=success, 2=failed
|
20
|
+
t.integer :status, null: false, default: 0, comment: '0=running,1=success,2=failed'
|
21
21
|
# 0=create, 1=refresh, 2=drop
|
22
22
|
t.integer :operation, null: false, default: 0, comment: '0=create,1=refresh,2=drop'
|
23
23
|
t.datetime :started_at, comment: 'Timestamp when the operation started'
|
24
24
|
t.datetime :finished_at, comment: 'Timestamp when the operation finished'
|
25
25
|
t.integer :duration_ms, comment: 'Duration of the operation in milliseconds'
|
26
|
-
t.
|
27
|
-
t.jsonb
|
26
|
+
t.jsonb :error, comment: 'Error details if the operation failed. :message, :class, :backtrace'
|
27
|
+
t.jsonb :meta, null: false, default: {}, comment: 'Additional metadata about the run, such as job ID, row count or parameters'
|
28
28
|
|
29
29
|
t.timestamps
|
30
30
|
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
4
|
+
#
|
5
|
+
# This source code is licensed under the MIT license found in the
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
7
|
+
|
8
|
+
module MatViews
|
9
|
+
module Admin
|
10
|
+
#
|
11
|
+
# MatViews::Admin::AuthBridge
|
12
|
+
# ---------------------------
|
13
|
+
# Bridge module that wires the MatViews admin engine to a **host-provided**
|
14
|
+
# authentication/authorization layer, while providing safe defaults.
|
15
|
+
#
|
16
|
+
# ### How it works
|
17
|
+
# - Includes {MatViews::Admin::DefaultAuth} first (fallback, no-op/hostable).
|
18
|
+
# - Then includes the **host auth module** returned by {.host_auth_module}.
|
19
|
+
# Because Ruby searches the most recently included module first, the host
|
20
|
+
# module cleanly **overrides** any defaults from `DefaultAuth`.
|
21
|
+
# - Registers a before_action `authenticate_mat_views!`.
|
22
|
+
# - Exposes helpers: `mat_views_current_user` and its alias {#user}.
|
23
|
+
#
|
24
|
+
# ### Host integration options (define one of these):
|
25
|
+
# 1) A top-level module:
|
26
|
+
# ```ruby
|
27
|
+
# # app/lib/mat_views_admin.rb (or any autoloaded path)
|
28
|
+
# module MatViewsAdmin
|
29
|
+
# def authenticate_mat_views!; end
|
30
|
+
# def authorize_mat_views!(*); end
|
31
|
+
# def mat_views_current_user; end
|
32
|
+
# end
|
33
|
+
# ```
|
34
|
+
# 2) A namespaced module:
|
35
|
+
# ```ruby
|
36
|
+
# # app/lib/mat_views/admin/host_auth.rb
|
37
|
+
# module MatViews
|
38
|
+
# module Admin
|
39
|
+
# module HostAuth
|
40
|
+
# def authenticate_mat_views!; end
|
41
|
+
# def authorize_mat_views!(*); end
|
42
|
+
# def mat_views_current_user; end
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
# end
|
46
|
+
# ```
|
47
|
+
#
|
48
|
+
# If neither module is present, a blank `Module.new` is included and the
|
49
|
+
# defaults in {MatViews::Admin::DefaultAuth} remain in effect.
|
50
|
+
#
|
51
|
+
# @see MatViews::Admin::DefaultAuth
|
52
|
+
#
|
53
|
+
module AuthBridge
|
54
|
+
extend ActiveSupport::Concern
|
55
|
+
|
56
|
+
included do
|
57
|
+
# Include defaults first, so the host module (included below) can override.
|
58
|
+
include MatViews::Admin::DefaultAuth
|
59
|
+
include host_auth_module
|
60
|
+
|
61
|
+
before_action :authenticate_mat_views!
|
62
|
+
helper_method :mat_views_current_user, :user
|
63
|
+
end
|
64
|
+
|
65
|
+
# Convenience alias for `mat_views_current_user` exposed to views.
|
66
|
+
#
|
67
|
+
# @return [Object, nil] the current user object as defined by host auth
|
68
|
+
def user = mat_views_current_user
|
69
|
+
|
70
|
+
class_methods do
|
71
|
+
# Resolves the host's auth module, if any.
|
72
|
+
#
|
73
|
+
# Lookup order:
|
74
|
+
# 1. `::MatViewsAdmin`
|
75
|
+
# 2. `::MatViews::Admin::HostAuth`
|
76
|
+
# 3. Fallback: a blank Module (no overrides)
|
77
|
+
#
|
78
|
+
# @return [Module] the module to include for host auth overrides
|
79
|
+
def host_auth_module
|
80
|
+
if Object.const_defined?('MatViewsAdmin')
|
81
|
+
::MatViewsAdmin
|
82
|
+
elsif Object.const_defined?('MatViews') &&
|
83
|
+
MatViews.const_defined?('Admin') &&
|
84
|
+
MatViews::Admin.const_defined?('HostAuth')
|
85
|
+
::MatViews::Admin::HostAuth
|
86
|
+
else
|
87
|
+
Module.new
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
4
|
+
#
|
5
|
+
# This source code is licensed under the MIT license found in the
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
7
|
+
|
8
|
+
module MatViews
|
9
|
+
module Admin
|
10
|
+
# MatViews::Admin::DefaultAuth
|
11
|
+
# ----------------------------
|
12
|
+
# Development-friendly **fallback** authentication/authorization for the MatViews
|
13
|
+
# admin UI. It is included first by {MatViews::Admin::AuthBridge}, and is meant
|
14
|
+
# to be overridden by a host-provided module (`MatViewsAdmin` or
|
15
|
+
# `MatViews::Admin::HostAuth`).
|
16
|
+
#
|
17
|
+
# ❗ **Not for production**: this module allows all access and returns a dummy user.
|
18
|
+
#
|
19
|
+
# @see MatViews::Admin::AuthBridge
|
20
|
+
#
|
21
|
+
module DefaultAuth
|
22
|
+
# Minimal stand-in user object used by the default auth.
|
23
|
+
#
|
24
|
+
# @!attribute [rw] email
|
25
|
+
# @return [String] the email address of the sample user
|
26
|
+
class SampleUser
|
27
|
+
attr_accessor :email
|
28
|
+
|
29
|
+
# @param email [String]
|
30
|
+
def initialize(email) = @email = email
|
31
|
+
|
32
|
+
# @return [String] the user's email
|
33
|
+
def to_s = email
|
34
|
+
end
|
35
|
+
|
36
|
+
# Authenticates the current request.
|
37
|
+
# Always returns true in the default implementation.
|
38
|
+
#
|
39
|
+
# @return [Boolean] true
|
40
|
+
# rubocop:disable Naming/PredicateMethod
|
41
|
+
def authenticate_mat_views! = true
|
42
|
+
# rubocop:enable Naming/PredicateMethod
|
43
|
+
|
44
|
+
# Returns the current user object.
|
45
|
+
# In the default implementation this is a {SampleUser}.
|
46
|
+
#
|
47
|
+
# @return [SampleUser]
|
48
|
+
def mat_views_current_user = SampleUser.new('sample-user@example.com')
|
49
|
+
|
50
|
+
# Authorizes an action on a record.
|
51
|
+
# Always returns true in the default implementation.
|
52
|
+
#
|
53
|
+
# @param _action [Symbol, String] the attempted action (ignored)
|
54
|
+
# @param _record [Object] the target record or symbol (ignored)
|
55
|
+
# @return [Boolean] true
|
56
|
+
# rubocop:disable Naming/PredicateMethod
|
57
|
+
def authorize_mat_views!(_action, _record) = true
|
58
|
+
# rubocop:enable Naming/PredicateMethod
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -17,6 +17,7 @@ module MatViews
|
|
17
17
|
# MatViews.configure do |config|
|
18
18
|
# config.job_adapter = :sidekiq
|
19
19
|
# config.job_queue = :low_priority
|
20
|
+
# config.admin_ui = { row_count_strategy: :estimated }
|
20
21
|
# end
|
21
22
|
#
|
22
23
|
# Supported job adapters:
|
@@ -37,6 +38,11 @@ module MatViews
|
|
37
38
|
# @return [Symbol, String]
|
38
39
|
attr_accessor :job_queue
|
39
40
|
|
41
|
+
##
|
42
|
+
# admin_ui configuration
|
43
|
+
# @return [Hash]
|
44
|
+
attr_accessor :admin_ui
|
45
|
+
|
40
46
|
##
|
41
47
|
# Initialize with defaults.
|
42
48
|
#
|
@@ -44,6 +50,9 @@ module MatViews
|
|
44
50
|
def initialize
|
45
51
|
@job_adapter = :active_job
|
46
52
|
@job_queue = :default
|
53
|
+
@admin_ui = {
|
54
|
+
row_count_strategy: :none
|
55
|
+
}
|
47
56
|
end
|
48
57
|
end
|
49
58
|
end
|
data/lib/mat_views/engine.rb
CHANGED
@@ -5,13 +5,19 @@
|
|
5
5
|
# This source code is licensed under the MIT license found in the
|
6
6
|
# LICENSE file in the root directory of this source tree.
|
7
7
|
|
8
|
+
##
|
9
|
+
# MatViews is a Rails engine that provides first-class support for
|
10
|
+
# PostgreSQL materialised views in Rails applications.
|
8
11
|
module MatViews
|
12
|
+
class << self
|
13
|
+
attr_accessor :importmap
|
14
|
+
end
|
9
15
|
##
|
10
16
|
# Rails Engine for MatViews.
|
11
17
|
#
|
12
18
|
# This engine encapsulates all functionality related to
|
13
|
-
#
|
14
|
-
# - Defining
|
19
|
+
# materialised views, including:
|
20
|
+
# - Defining materialised view definitions
|
15
21
|
# - Creating and refreshing views
|
16
22
|
# - Managing background jobs for refresh/create/delete
|
17
23
|
#
|
@@ -30,5 +36,47 @@ module MatViews
|
|
30
36
|
initializer 'mat_views.load_config' do
|
31
37
|
MatViews.configuration ||= MatViews::Configuration.new
|
32
38
|
end
|
39
|
+
|
40
|
+
initializer 'mat_views.javascript' do |app|
|
41
|
+
app.config.assets.paths << root.join('app/javascript')
|
42
|
+
end
|
43
|
+
|
44
|
+
initializer 'mat_views.importmap', before: 'importmap' do |_app|
|
45
|
+
next unless defined?(Importmap)
|
46
|
+
|
47
|
+
MatViews.importmap = Importmap::Map.new
|
48
|
+
MatViews.importmap.draw(root.join('config/importmap.rb'))
|
49
|
+
MatViews.importmap.cache_sweeper(watches: root.join('app/javascript'))
|
50
|
+
|
51
|
+
ActiveSupport.on_load(:action_controller_base) do
|
52
|
+
before_action { MatViews.importmap.cache_sweeper.execute_if_updated }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.locale_code_mapping
|
57
|
+
@locale_code_mapping ||= begin
|
58
|
+
mappings = Dir[root.join('config', 'locales', '*.yml')].map.to_h do |file|
|
59
|
+
code = File.basename(file, '.yml').to_sym
|
60
|
+
name = I18n.t('i18n.name', locale: code)
|
61
|
+
[code, name]
|
62
|
+
end
|
63
|
+
mappings.sort_by { |code, _name| code.to_s }.to_h
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.available_locales
|
68
|
+
@available_locales ||= locale_code_mapping.keys.freeze
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.default_locale = :en
|
72
|
+
def self.loaded_spec = Gem.loaded_specs['mat_views']
|
73
|
+
def self.project_name = loaded_spec&.name
|
74
|
+
def self.project_version = MatViews::VERSION
|
75
|
+
def self.project_homepage = loaded_spec&.homepage
|
76
|
+
def self.company_name = 'Codevedas Inc.'
|
77
|
+
def self.documentation_uri = loaded_spec&.metadata&.[]('documentation_uri')
|
78
|
+
def self.bug_tracker_uri = loaded_spec&.metadata&.[]('bug_tracker_uri')
|
79
|
+
def self.support_uri = loaded_spec&.metadata&.[]('support_uri')
|
80
|
+
def self.rubygems_uri = loaded_spec&.metadata&.[]('rubygems_uri')
|
33
81
|
end
|
34
82
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
4
|
+
#
|
5
|
+
# This source code is licensed under the MIT license found in the
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
7
|
+
|
8
|
+
module MatViews
|
9
|
+
module Helpers
|
10
|
+
module UiTestIds
|
11
|
+
GEM_LINK = 'gem_link'
|
12
|
+
PROJECT_HOMEPAGE_LINK = 'project_homepage_link'
|
13
|
+
OPEN_ISSUE_LINK = 'open_issue_link'
|
14
|
+
DOCUMENTATION_LINK = 'documentation_link'
|
15
|
+
SUPPORT_LINK = 'support_link'
|
16
|
+
|
17
|
+
DRAWER_REFRESH_LINK = 'drawer_refresh_link'
|
18
|
+
DRAWER_CLOSE_LINK = 'drawer_close_link'
|
19
|
+
|
20
|
+
HEADER_LINK = 'header_link'
|
21
|
+
PREFERENCES_LINK = 'preferences_link'
|
22
|
+
|
23
|
+
DEFINITIONS_TAB_LINK = 'definitions_tab_link'
|
24
|
+
RUNS_TAB_LINK = 'runs_tab_link'
|
25
|
+
|
26
|
+
NEW_DEFINITION_LINK = 'new_definition_link'
|
27
|
+
SUBMIT_BUTTON = 'submit_button'
|
28
|
+
CANCEL_BUTTON = 'cancel_button'
|
29
|
+
VIEW_HISTORY_LINK = 'view_history_link'
|
30
|
+
VIEW_LINK = 'view_link'
|
31
|
+
EDIT_LINK = 'edit_link'
|
32
|
+
DELETE_LINK = 'delete_link'
|
33
|
+
REFRESH_LINK = 'refresh_link'
|
34
|
+
DROP_LINK = 'drop_link'
|
35
|
+
DROP_CASCADE_LINK = 'drop_cascade_link'
|
36
|
+
CREATE_MV_LINK = 'create_mv_link'
|
37
|
+
RESET_FILTERS_LINK = 'reset_filters_link'
|
38
|
+
|
39
|
+
PREFERENCES_SAVE_BUTTON = 'preferences_save_button'
|
40
|
+
PREFERENCES_CANCEL_BUTTON = 'preferences_cancel_button'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -58,19 +58,22 @@ module MatViews
|
|
58
58
|
# @raise [ArgumentError] if the configured adapter is not recognized.
|
59
59
|
#
|
60
60
|
def self.enqueue(job_class, queue:, args: [])
|
61
|
-
|
61
|
+
queue_str = queue.to_s
|
62
|
+
job_adapter = MatViews.configuration.job_adapter
|
63
|
+
|
64
|
+
case job_adapter
|
62
65
|
when :active_job
|
63
|
-
job_class.set(queue:
|
66
|
+
job_class.set(queue: queue_str).perform_later(*args)
|
64
67
|
when :sidekiq
|
65
68
|
Sidekiq::Client.push(
|
66
69
|
'class' => job_class.name,
|
67
|
-
'queue' =>
|
70
|
+
'queue' => queue_str,
|
68
71
|
'args' => args
|
69
72
|
)
|
70
73
|
when :resque
|
71
|
-
Resque.enqueue_to(
|
74
|
+
Resque.enqueue_to(queue_str, job_class, *args)
|
72
75
|
else
|
73
|
-
raise ArgumentError, "Unknown job adapter: #{
|
76
|
+
raise ArgumentError, "Unknown job adapter: #{job_adapter.inspect}"
|
74
77
|
end
|
75
78
|
end
|
76
79
|
end
|
@@ -10,16 +10,19 @@ module MatViews
|
|
10
10
|
# Encapsulates the result of a service operation within MatViews.
|
11
11
|
#
|
12
12
|
# Provides a consistent contract for all services by standardizing:
|
13
|
-
# - `status`: Symbol representing outcome (`:ok`, `:created`, `:updated`,
|
13
|
+
# - `status`: Symbol representing outcome (`:ok`, `:created`, `:updated`,
|
14
14
|
# `:skipped`, `:deleted`, `:error`)
|
15
|
-
# - `
|
16
|
-
# - `
|
17
|
-
# - `
|
15
|
+
# - `request`: Request detailed that service was invoked with
|
16
|
+
# - `response`: Response detailed that service returned, nil with :error status
|
17
|
+
# - `error`: Exception or error message, with :error status
|
18
|
+
# - `message`: String description of the error
|
19
|
+
# - `class`: Exception class name
|
20
|
+
# - `backtrace`: Array of strings
|
18
21
|
#
|
19
22
|
# @example Successful response
|
20
23
|
# MatViews::ServiceResponse.new(
|
21
24
|
# status: :updated,
|
22
|
-
#
|
25
|
+
# response: { ... }
|
23
26
|
# )
|
24
27
|
#
|
25
28
|
# @example Error response
|
@@ -29,32 +32,44 @@ module MatViews
|
|
29
32
|
# )
|
30
33
|
#
|
31
34
|
class ServiceResponse
|
32
|
-
attr_reader :status, :
|
35
|
+
attr_reader :status, :request, :error, :response
|
36
|
+
|
37
|
+
# acceptable status values
|
38
|
+
ACCEPTABLE_STATES = %i[ok created updated skipped deleted error].freeze
|
39
|
+
|
40
|
+
# statuses indicating success
|
41
|
+
OK_STATES = %i[ok created updated skipped deleted].freeze
|
42
|
+
|
43
|
+
# statuses indicating error
|
44
|
+
ERROR_STATES = %i[error].freeze
|
33
45
|
|
34
46
|
# @param status [Symbol] the outcome status
|
35
|
-
# @param
|
47
|
+
# @param request [Hash] request details
|
48
|
+
# @param response [Hash] response details
|
36
49
|
# @param error [Exception, String, nil] error details if applicable
|
37
|
-
|
38
|
-
|
50
|
+
def initialize(status:, request: {}, response: {}, error: nil)
|
51
|
+
raise ArgumentError, 'status is required' unless ACCEPTABLE_STATES.include?(status&.to_sym)
|
52
|
+
raise ArgumentError, 'error must be an Exception object' if error && !error.is_a?(Exception)
|
53
|
+
|
39
54
|
@status = status.to_sym
|
40
|
-
@
|
41
|
-
@
|
42
|
-
@
|
55
|
+
@request = request
|
56
|
+
@response = response
|
57
|
+
@error = error&.mv_serialize_error
|
43
58
|
end
|
44
59
|
|
45
60
|
# @return [Boolean] whether the response represents a success
|
46
61
|
def success?
|
47
|
-
|
62
|
+
OK_STATES.include?(status)
|
48
63
|
end
|
49
64
|
|
50
65
|
# @return [Boolean] whether the response represents an error
|
51
66
|
def error?
|
52
|
-
|
67
|
+
ERROR_STATES.include?(status)
|
53
68
|
end
|
54
69
|
|
55
70
|
# @return [Hash] hash representation of the response
|
56
71
|
def to_h
|
57
|
-
{ status:,
|
72
|
+
{ status:, request:, response:, error: }.compact
|
58
73
|
end
|
59
74
|
end
|
60
75
|
end
|