motor-admin 0.1.104 → 0.2.3
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 +5 -2
- data/app/controllers/concerns/motor/load_and_authorize_dynamic_resource.rb +3 -2
- data/app/controllers/motor/data_controller.rb +14 -2
- data/app/controllers/motor/ui_controller.rb +13 -1
- data/app/mailers/motor/alerts_mailer.rb +1 -1
- data/app/views/motor/ui/show.html.erb +1 -1
- data/config/locales/en.yml +5 -1
- data/config/locales/es.yml +5 -1
- data/config/locales/pt.yml +2 -2
- data/config/routes.rb +2 -1
- data/lib/generators/motor/templates/install.rb +9 -0
- data/lib/motor/active_record_utils/active_record_filter_patch.rb +12 -0
- data/lib/motor/api_query/build_json.rb +1 -1
- data/lib/motor/build_schema/load_from_rails.rb +7 -9
- data/lib/motor/build_schema/utils.rb +1 -0
- data/lib/motor/build_schema.rb +4 -0
- data/lib/motor/configs/build_ui_app_tag.rb +5 -3
- data/lib/motor/configs/sync_from_file.rb +1 -2
- data/lib/motor/configs/write_to_file.rb +1 -2
- data/lib/motor/configs.rb +13 -0
- data/lib/motor/queries/run_query.rb +8 -4
- data/lib/motor/resources/fetch_configured_model.rb +18 -9
- data/lib/motor/version.rb +1 -1
- data/lib/motor.rb +0 -1
- data/ui/dist/main-1e1b7c867f581bccfb2d.css.gz +0 -0
- data/ui/dist/main-1e1b7c867f581bccfb2d.js.gz +0 -0
- data/ui/dist/manifest.json +5 -5
- metadata +4 -18
- data/ui/dist/main-37390abd2976b4fd28f0.css.gz +0 -0
- data/ui/dist/main-37390abd2976b4fd28f0.js.gz +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45ba4c64d6749aa260a6a14f49a3f71484fe1e127f93f31e0adbba201bfe840f
|
4
|
+
data.tar.gz: 483590c08e2194dc9232ed29de69143167723836b05dab95a90cb0e997191590
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5171324efad5960ed06d800f7872d7b0fbe823486aff3dfe346e9032c8d0bc9667a5a0c77dc106b8c0bfea8a1a4f0d3654c0986976b32744e4c3178be63b2d0a
|
7
|
+
data.tar.gz: 28519dfb8c532d3d803325977a0f65d30bd74277f0826a610f2c7c527d0aa1fc74b1820f01f64a3cf444133f6f5c054651949d8d5cad92c86445bea333ce30e6
|
data/README.md
CHANGED
@@ -49,6 +49,8 @@ Everything in the admin panel can be configured using the intuitive settings UI,
|
|
49
49
|
|
50
50
|
Data displayed on the resource page can be completely customized via [SQL queries](#sql-queries) and [dashboards](#dashboards) attached to the resource as a tab. Usually, queries used to display resource data should contain `{{resource_name_id}}` [variable](#sql-queries).
|
51
51
|
|
52
|
+
[Learn more about resource customizations](https://github.com/omohokcoj/motor-admin/blob/master/guides/customizing_resource_table.md)
|
53
|
+
|
52
54
|
### Custom Actions
|
53
55
|
|
54
56
|

|
@@ -75,8 +77,9 @@ end
|
|
75
77
|
|
76
78
|

|
77
79
|
|
78
|
-
Values from the form fields can be used in API path via `{field_name}` syntax: `/api/some-endpoint/{resource_id}/apply
|
79
|
-
|
80
|
+
Values from the form fields can be used in API path via `{field_name}` syntax: `/api/some-endpoint/{resource_id}/apply`.
|
81
|
+
|
82
|
+
[Learn more about custom forms builder](https://github.com/omohokcoj/motor-admin/blob/master/guides/building_custom_forms.md)
|
80
83
|
|
81
84
|
### SQL Queries
|
82
85
|
|
@@ -5,6 +5,7 @@ module Motor
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
INSTANCE_VARIABLE_NAME = 'resource'
|
8
|
+
ASSOCIATION_INSTANCE_VARIABLE_NAME = 'associated_resource'
|
8
9
|
|
9
10
|
included do
|
10
11
|
before_action :load_and_authorize_resource
|
@@ -26,7 +27,7 @@ module Motor
|
|
26
27
|
def load_and_authorize_resource
|
27
28
|
options = {
|
28
29
|
class: resource_class,
|
29
|
-
parent:
|
30
|
+
parent: params[:association].present?,
|
30
31
|
instance_name: INSTANCE_VARIABLE_NAME
|
31
32
|
}
|
32
33
|
|
@@ -57,7 +58,7 @@ module Motor
|
|
57
58
|
parent: false,
|
58
59
|
through: :resource,
|
59
60
|
through_association: params[:association].to_sym,
|
60
|
-
instance_name: INSTANCE_VARIABLE_NAME
|
61
|
+
instance_name: params[:action] == 'create' ? ASSOCIATION_INSTANCE_VARIABLE_NAME : INSTANCE_VARIABLE_NAME
|
61
62
|
).load_and_authorize_resource
|
62
63
|
else
|
63
64
|
render json: { message: 'Unknown association' }, status: :not_found
|
@@ -21,7 +21,19 @@ module Motor
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def create
|
24
|
-
@
|
24
|
+
if @associated_resource
|
25
|
+
if @resource_class.reflections[params[:association]].through_reflection?
|
26
|
+
@associated_resource.save!
|
27
|
+
|
28
|
+
@resource = @associated_resource
|
29
|
+
else
|
30
|
+
@resource.public_send(params[:association].to_sym).create!(@associated_resource.attributes) do |resource|
|
31
|
+
@resource = resource
|
32
|
+
end
|
33
|
+
end
|
34
|
+
else
|
35
|
+
@resource.save!
|
36
|
+
end
|
25
37
|
|
26
38
|
render json: { data: Motor::ApiQuery::BuildJson.call(@resource, params, current_ability) }
|
27
39
|
rescue ActiveRecord::RecordInvalid
|
@@ -61,7 +73,7 @@ module Motor
|
|
61
73
|
|
62
74
|
def resource_params
|
63
75
|
if params[:data].present?
|
64
|
-
params.require(:data).
|
76
|
+
params.require(:data).permit!
|
65
77
|
else
|
66
78
|
{}
|
67
79
|
end
|
@@ -4,7 +4,9 @@ module Motor
|
|
4
4
|
class UiController < ApplicationController
|
5
5
|
layout 'motor/application'
|
6
6
|
|
7
|
-
helper_method :current_user, :current_ability
|
7
|
+
helper_method :current_user, :current_ability, :cache_keys
|
8
|
+
|
9
|
+
before_action :set_i18n_locale
|
8
10
|
|
9
11
|
def index
|
10
12
|
render_ui
|
@@ -27,5 +29,15 @@ module Motor
|
|
27
29
|
|
28
30
|
render :show
|
29
31
|
end
|
32
|
+
|
33
|
+
def set_i18n_locale
|
34
|
+
configs = Motor::Configs::LoadFromCache.load_configs(cache_key: cache_keys[:configs])
|
35
|
+
|
36
|
+
I18n.locale = configs.find { |c| c.key == 'language' }&.value || I18n.locale
|
37
|
+
end
|
38
|
+
|
39
|
+
def cache_keys
|
40
|
+
@cache_keys ||= Configs::LoadFromCache.load_cache_keys
|
41
|
+
end
|
30
42
|
end
|
31
43
|
end
|
@@ -26,7 +26,7 @@ module Motor
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def from_address
|
29
|
-
from = ENV['MOTOR_ALERTS_FROM_ADDRESS'].presence
|
29
|
+
from = ENV['MOTOR_ALERTS_FROM_ADDRESS'].presence || ENV['MOTOR_EMAIL_ADDRESS'].presence
|
30
30
|
|
31
31
|
from ||= application_mailer_default_from
|
32
32
|
from ||= mailer_config_from_address
|
@@ -1 +1 @@
|
|
1
|
-
<%= raw(Motor::Configs::BuildUiAppTag.call(current_user, current_ability)) %>
|
1
|
+
<%= raw(Motor::Configs::BuildUiAppTag.call(current_user, current_ability, cache_keys: cache_keys)) %>
|
data/config/locales/en.yml
CHANGED
@@ -87,6 +87,7 @@ en:
|
|
87
87
|
field_name: Field name
|
88
88
|
field_value_does_not_match_pattern: '%{field} value does not match %{pattern}'
|
89
89
|
file: File
|
90
|
+
filter: Filter
|
90
91
|
filters: Filters
|
91
92
|
form: Form
|
92
93
|
form_has_been_saved: Form has been saved!
|
@@ -110,7 +111,7 @@ en:
|
|
110
111
|
interval: Interval
|
111
112
|
is: Is
|
112
113
|
is_not: Is not
|
113
|
-
|
114
|
+
items_have_been_removed: items have been removed
|
114
115
|
items_will_be_removed: '%{count} items will be removed'
|
115
116
|
json: JSON
|
116
117
|
label: Currency
|
@@ -258,3 +259,6 @@ en:
|
|
258
259
|
add_text: Add Text
|
259
260
|
edit_text: Edit Text
|
260
261
|
open_in_markdown_editor: Open in markdown editor
|
262
|
+
activate: Activate
|
263
|
+
load_existing_options_from_database: Load existing options from the database
|
264
|
+
add_database: Add Database
|
data/config/locales/es.yml
CHANGED
@@ -59,6 +59,7 @@ es:
|
|
59
59
|
emails: Emails
|
60
60
|
every_day_at_hh_mm: todos los días a las HH:mm PM...
|
61
61
|
field_name: Nombre del campo
|
62
|
+
filter: Filtrar
|
62
63
|
filters: Filtros
|
63
64
|
form: Formulario
|
64
65
|
form_has_been_saved: ¡Formulario guardado!
|
@@ -73,7 +74,7 @@ es:
|
|
73
74
|
hello_admin: Hola Admin 👋
|
74
75
|
input_type: Tipo de campo
|
75
76
|
interval: Intervalo
|
76
|
-
|
77
|
+
items_have_been_removed: elementos fueron eliminados
|
77
78
|
label: Moneda
|
78
79
|
line_chart: Gráfico de líneas
|
79
80
|
link_name: Nombre del link
|
@@ -258,6 +259,9 @@ es:
|
|
258
259
|
add_text: Añadir Texto
|
259
260
|
edit_text: Editar Texto
|
260
261
|
open_in_markdown_editor: Abrir en el editor de markdown
|
262
|
+
activate: Activar
|
263
|
+
load_existing_options_from_database: Cargar las opciones existentes de la base de datos
|
264
|
+
add_database: Añadir base de datos
|
261
265
|
i:
|
262
266
|
locale: es
|
263
267
|
select:
|
data/config/locales/pt.yml
CHANGED
@@ -96,8 +96,8 @@ pt:
|
|
96
96
|
field_is_required: "%{field} é obrigatório"
|
97
97
|
field_list_cant_be_empty: "A lista %{field} não pode estar vazia"
|
98
98
|
field_must_be_exactly_in_length: "%{field} deve ter exatamente %{length} de comprimento"
|
99
|
-
field_must_be_less_in_length: '%{
|
100
|
-
field_must_be_more_in_length: '%{
|
99
|
+
field_must_be_less_in_length: '%{field} deve ser menor que %{length} em comprimento'
|
100
|
+
field_must_be_more_in_length: '%{field} deve ter mais do que %{length} de comprimento'
|
101
101
|
field_name: "Nome do campo"
|
102
102
|
field_value_does_not_match_pattern: "%{field} valor não corresponde %{pattern}"
|
103
103
|
file: "Arquivo"
|
data/config/routes.rb
CHANGED
@@ -21,7 +21,8 @@ Motor::Admin.routes.draw do
|
|
21
21
|
resources :audits, only: %i[index]
|
22
22
|
resources :resources, path: '/data/:resource',
|
23
23
|
only: %i[index show update create destroy],
|
24
|
-
controller: 'data'
|
24
|
+
controller: 'data',
|
25
|
+
constraints: { id: %r{[^/]+} } do
|
25
26
|
put '/:method', to: 'data#execute'
|
26
27
|
resources :association, path: '/:association',
|
27
28
|
only: %i[index create],
|
@@ -143,6 +143,15 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
|
|
143
143
|
add_index :motor_audits, %i[user_id user_type], name: 'motor_auditable_user_index'
|
144
144
|
add_index :motor_audits, :request_uuid
|
145
145
|
add_index :motor_audits, :created_at
|
146
|
+
|
147
|
+
model = Class.new(ApplicationRecord)
|
148
|
+
|
149
|
+
model.table_name = 'motor_configs'
|
150
|
+
|
151
|
+
model.create!(key: 'header.links', value: [{
|
152
|
+
name: '⭐ Star on GitHub',
|
153
|
+
path: 'https://github.com/omohokcoj/motor-admin'
|
154
|
+
}].to_json)
|
146
155
|
end
|
147
156
|
|
148
157
|
def self.down
|
@@ -14,5 +14,17 @@ if Rails::VERSION::MAJOR == 6
|
|
14
14
|
build_filters(arel, my_alias_tracker)
|
15
15
|
arel
|
16
16
|
end
|
17
|
+
|
18
|
+
def build_filters(manager, alias_tracker)
|
19
|
+
where_clause = nil
|
20
|
+
|
21
|
+
@filters.each do |filters|
|
22
|
+
where_clause = filter_clause_factory.build(filters, alias_tracker)
|
23
|
+
|
24
|
+
manager.where(where_clause.ast)
|
25
|
+
end
|
26
|
+
|
27
|
+
@values[:where] = where_clause if where_clause
|
28
|
+
end
|
17
29
|
end
|
18
30
|
end
|
@@ -22,9 +22,9 @@ module Motor
|
|
22
22
|
|
23
23
|
def call
|
24
24
|
models.map do |model|
|
25
|
-
Object.const_get(model.name)
|
25
|
+
model = Object.const_get(model.name)
|
26
26
|
|
27
|
-
next unless
|
27
|
+
next unless model.table_exists?
|
28
28
|
|
29
29
|
schema = build_model_schema(model)
|
30
30
|
|
@@ -37,7 +37,7 @@ module Motor
|
|
37
37
|
Rails.logger.error(e)
|
38
38
|
|
39
39
|
next
|
40
|
-
end.compact
|
40
|
+
end.compact.uniq
|
41
41
|
end
|
42
42
|
|
43
43
|
def models
|
@@ -225,8 +225,8 @@ module Motor
|
|
225
225
|
display_name: model.human_attribute_name(name),
|
226
226
|
model_name: reflection.polymorphic? ? nil : reflection.klass.name.underscore,
|
227
227
|
reference_type: reflection.belongs_to? ? 'belongs_to' : 'has_one',
|
228
|
-
foreign_key: reflection.
|
229
|
-
primary_key: reflection.polymorphic? ? 'id' : reflection.
|
228
|
+
foreign_key: reflection.join_foreign_key,
|
229
|
+
primary_key: reflection.polymorphic? ? 'id' : reflection.join_primary_key,
|
230
230
|
options: reflection.options.slice(:through, :source),
|
231
231
|
polymorphic: reflection.polymorphic?,
|
232
232
|
virtual: false
|
@@ -248,8 +248,8 @@ module Motor
|
|
248
248
|
display_name: model.human_attribute_name(name),
|
249
249
|
slug: name.underscore,
|
250
250
|
model_name: model_class.name.underscore,
|
251
|
-
foreign_key: ref.
|
252
|
-
primary_key: ref.
|
251
|
+
foreign_key: ref.join_primary_key,
|
252
|
+
primary_key: ref.join_foreign_key,
|
253
253
|
polymorphic: ref.options[:as].present?,
|
254
254
|
icon: Motor::FindIcon.call(name),
|
255
255
|
options: ref.options.slice(:through, :source),
|
@@ -287,8 +287,6 @@ module Motor
|
|
287
287
|
{ includes: validator.send(:delimiter) }
|
288
288
|
when ActiveRecord::Validations::PresenceValidator
|
289
289
|
{ required: true }
|
290
|
-
when ActiveModel::Validations::FormatValidator
|
291
|
-
{ format: JsRegex.new(options[:with]).to_h.slice(:source, :options) }
|
292
290
|
when ActiveRecord::Validations::LengthValidator
|
293
291
|
{ length: normalize_length_validation_options(options) }
|
294
292
|
when ActiveModel::Validations::NumericalityValidator
|
data/lib/motor/build_schema.rb
CHANGED
@@ -51,7 +51,11 @@ module Motor
|
|
51
51
|
COLUMN_NAME_ACCESS_TYPES = {
|
52
52
|
id: ColumnAccessTypes::READ_ONLY,
|
53
53
|
created_at: ColumnAccessTypes::READ_ONLY,
|
54
|
+
created_on: ColumnAccessTypes::READ_ONLY,
|
55
|
+
inserted_at: ColumnAccessTypes::READ_ONLY,
|
54
56
|
updated_at: ColumnAccessTypes::READ_ONLY,
|
57
|
+
updated_on: ColumnAccessTypes::READ_ONLY,
|
58
|
+
modified_at: ColumnAccessTypes::READ_ONLY,
|
55
59
|
deleted_at: ColumnAccessTypes::READ_ONLY
|
56
60
|
}.with_indifferent_access.freeze
|
57
61
|
|
@@ -12,9 +12,7 @@ module Motor
|
|
12
12
|
|
13
13
|
module_function
|
14
14
|
|
15
|
-
def call(current_user = nil, current_ability = nil)
|
16
|
-
cache_keys = LoadFromCache.load_cache_keys
|
17
|
-
|
15
|
+
def call(current_user = nil, current_ability = nil, cache_keys: LoadFromCache.load_cache_keys)
|
18
16
|
CACHE_STORE.fetch("#{I18n.locale}#{cache_keys.hash}#{current_user&.id}") do
|
19
17
|
CACHE_STORE.clear
|
20
18
|
|
@@ -23,16 +21,19 @@ module Motor
|
|
23
21
|
end
|
24
22
|
end
|
25
23
|
|
24
|
+
# rubocop:disable Metrics/AbcSize
|
26
25
|
# @return [Hash]
|
27
26
|
def build_data(cache_keys = {}, current_user = nil, current_ability = nil)
|
28
27
|
configs_cache_key = cache_keys[:configs]
|
29
28
|
|
30
29
|
{
|
30
|
+
version: Motor::VERSION,
|
31
31
|
current_user: current_user&.as_json(only: %i[id email]),
|
32
32
|
current_rules: current_ability.serialized_rules,
|
33
33
|
audits_count: Motor::Audit.count,
|
34
34
|
i18n: i18n_data,
|
35
35
|
base_path: Motor::Admin.routes.url_helpers.motor_path,
|
36
|
+
admin_settings_path: Rails.application.routes.url_helpers.try(:admin_settings_general_path),
|
36
37
|
schema: Motor::BuildSchema.call(cache_keys, current_ability),
|
37
38
|
header_links: header_links_data_hash(configs_cache_key),
|
38
39
|
homepage_layout: homepage_layout_data_hash(configs_cache_key),
|
@@ -45,6 +46,7 @@ module Motor
|
|
45
46
|
forms: forms_data_hash(build_cache_key(cache_keys, :forms, current_user, current_ability), current_ability)
|
46
47
|
}
|
47
48
|
end
|
49
|
+
# rubocop:enable Metrics/AbcSize
|
48
50
|
|
49
51
|
def i18n_data
|
50
52
|
I18n.t('motor', default: I18n.t('motor', locale: :en))
|
@@ -3,7 +3,6 @@
|
|
3
3
|
module Motor
|
4
4
|
module Configs
|
5
5
|
module SyncFromFile
|
6
|
-
FILE_PATH = Motor::Configs::FILE_PATH
|
7
6
|
MUTEXT = Mutex.new
|
8
7
|
FILE_TIMESTAMPS_STORE = ActiveSupport::Cache::MemoryStore.new(size: 1.megabyte)
|
9
8
|
|
@@ -11,7 +10,7 @@ module Motor
|
|
11
10
|
|
12
11
|
def call(with_exception: false)
|
13
12
|
MUTEXT.synchronize do
|
14
|
-
file =
|
13
|
+
file = Pathname.new(Motor::Configs.file_path)
|
15
14
|
|
16
15
|
file_timestamp =
|
17
16
|
begin
|
@@ -4,7 +4,6 @@ module Motor
|
|
4
4
|
module Configs
|
5
5
|
module WriteToFile
|
6
6
|
THREAD_POOL = Concurrent::FixedThreadPool.new(1)
|
7
|
-
FILE_PATH = Motor::Configs::FILE_PATH
|
8
7
|
|
9
8
|
module_function
|
10
9
|
|
@@ -22,7 +21,7 @@ module Motor
|
|
22
21
|
end
|
23
22
|
|
24
23
|
def write_with_lock
|
25
|
-
File.open(
|
24
|
+
File.open(Motor::Configs.file_path, 'w') do |file|
|
26
25
|
file.flock(File::LOCK_EX)
|
27
26
|
|
28
27
|
YAML.dump(Motor::Configs::BuildConfigsHash.call, file)
|
data/lib/motor/configs.rb
CHANGED
@@ -5,6 +5,19 @@ module Motor
|
|
5
5
|
FILE_PATH = 'config/motor.yml'
|
6
6
|
SYNC_API_PATH = '/motor_configs_sync'
|
7
7
|
SYNC_ACCESS_KEY = ENV.fetch('MOTOR_SYNC_API_KEY', '')
|
8
|
+
MEMFS_PATH = '/__enclose_io_memfs__/'
|
9
|
+
PWD_FILE_NAME = 'motor-admin.yml'
|
10
|
+
|
11
|
+
module_function
|
12
|
+
|
13
|
+
# @return [String]
|
14
|
+
def file_path
|
15
|
+
if Rails.root.to_s.start_with?(MEMFS_PATH)
|
16
|
+
[ENV['PWD'], PWD_FILE_NAME].join('/')
|
17
|
+
else
|
18
|
+
Rails.root.join(FILE_PATH).to_s
|
19
|
+
end
|
20
|
+
end
|
8
21
|
end
|
9
22
|
end
|
10
23
|
|
@@ -63,15 +63,15 @@ module Motor
|
|
63
63
|
result = nil
|
64
64
|
statement = prepare_sql_statement(query, limit, variables_hash, filters)
|
65
65
|
|
66
|
-
|
66
|
+
connection_class.transaction do
|
67
67
|
result =
|
68
|
-
case
|
68
|
+
case connection_class.connection.class.name
|
69
69
|
when 'ActiveRecord::ConnectionAdapters::PostgreSQLAdapter'
|
70
|
-
PostgresqlExecQuery.call(
|
70
|
+
PostgresqlExecQuery.call(connection_class.connection, statement)
|
71
71
|
else
|
72
72
|
statement = normalize_statement_for_sql(statement)
|
73
73
|
|
74
|
-
|
74
|
+
connection_class.connection.exec_query(*statement)
|
75
75
|
end
|
76
76
|
|
77
77
|
raise ActiveRecord::Rollback
|
@@ -172,6 +172,10 @@ module Motor
|
|
172
172
|
acc[variable[:name]] ||= variables_hash[variable[:name]] || variable[:default_value]
|
173
173
|
end
|
174
174
|
end
|
175
|
+
|
176
|
+
def connection_class
|
177
|
+
defined?(ResourceRecord) ? ResourceRecord : ActiveRecord::Base
|
178
|
+
end
|
175
179
|
end
|
176
180
|
end
|
177
181
|
end
|
@@ -117,7 +117,7 @@ module Motor
|
|
117
117
|
|
118
118
|
def define_belongs_to_reflection(klass, config)
|
119
119
|
klass.belongs_to(config[:name].to_sym,
|
120
|
-
class_name: config[:model_name]
|
120
|
+
class_name: config[:model_name]&.classify,
|
121
121
|
foreign_key: config[:foreign_key],
|
122
122
|
polymorphic: config[:polymorphic],
|
123
123
|
primary_key: config[:primary_key],
|
@@ -163,20 +163,29 @@ module Motor
|
|
163
163
|
|
164
164
|
def define_associations(klass, config)
|
165
165
|
config.fetch(:associations, []).each do |association|
|
166
|
-
|
166
|
+
next unless association[:virtual]
|
167
167
|
|
168
|
-
|
168
|
+
options = normalize_association_params(association)
|
169
169
|
|
170
|
-
|
171
|
-
options[:class_name] = association[:model_name].classify
|
172
|
-
options[:as] = association[:foreign_key].delete_suffix('_id') if is_polymorphic
|
170
|
+
filters = options.delete(:filters)
|
173
171
|
|
174
|
-
|
175
|
-
|
176
|
-
|
172
|
+
if filters.present?
|
173
|
+
klass.has_many(association[:name].to_sym, -> { filter(filters).tap(&:arel) }, **options.symbolize_keys)
|
174
|
+
else
|
175
|
+
klass.has_many(association[:name].to_sym, **options.symbolize_keys)
|
176
|
+
end
|
177
177
|
end
|
178
178
|
end
|
179
179
|
|
180
|
+
def normalize_association_params(params)
|
181
|
+
options = params.slice(:foreign_key, :primary_key).merge(dependent: :destroy)
|
182
|
+
|
183
|
+
options[:class_name] = params[:model_name].classify
|
184
|
+
options[:as] = params[:foreign_key].delete_suffix('_id') if params[:polymorphic]
|
185
|
+
|
186
|
+
options.merge(params[:options] || {})
|
187
|
+
end
|
188
|
+
|
180
189
|
def maybe_fetch_from_cache(model, cache_key, miss_cache_block, postprocess_block)
|
181
190
|
return miss_cache_block.call unless cache_key
|
182
191
|
|
data/lib/motor/version.rb
CHANGED
data/lib/motor.rb
CHANGED
Binary file
|
Binary file
|
data/ui/dist/manifest.json
CHANGED
@@ -2601,9 +2601,9 @@
|
|
2601
2601
|
"icons/zoom-out.svg.gz": "icons/zoom-out.svg.gz",
|
2602
2602
|
"icons/zoom-question.svg": "icons/zoom-question.svg",
|
2603
2603
|
"icons/zoom-question.svg.gz": "icons/zoom-question.svg.gz",
|
2604
|
-
"main-
|
2605
|
-
"main-
|
2606
|
-
"main-
|
2607
|
-
"main.css": "main-
|
2608
|
-
"main.js": "main-
|
2604
|
+
"main-1e1b7c867f581bccfb2d.css.gz": "main-1e1b7c867f581bccfb2d.css.gz",
|
2605
|
+
"main-1e1b7c867f581bccfb2d.js.LICENSE.txt": "main-1e1b7c867f581bccfb2d.js.LICENSE.txt",
|
2606
|
+
"main-1e1b7c867f581bccfb2d.js.gz": "main-1e1b7c867f581bccfb2d.js.gz",
|
2607
|
+
"main.css": "main-1e1b7c867f581bccfb2d.css",
|
2608
|
+
"main.js": "main-1e1b7c867f581bccfb2d.js"
|
2609
2609
|
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: motor-admin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pete Matsyburka
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-10-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord-filter
|
@@ -80,20 +80,6 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '1.0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: js_regex
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '3.0'
|
90
|
-
type: :runtime
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - "~>"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '3.0'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: rails
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -1537,8 +1523,8 @@ files:
|
|
1537
1523
|
- ui/dist/icons/zoom-money.svg.gz
|
1538
1524
|
- ui/dist/icons/zoom-out.svg.gz
|
1539
1525
|
- ui/dist/icons/zoom-question.svg.gz
|
1540
|
-
- ui/dist/main-
|
1541
|
-
- ui/dist/main-
|
1526
|
+
- ui/dist/main-1e1b7c867f581bccfb2d.css.gz
|
1527
|
+
- ui/dist/main-1e1b7c867f581bccfb2d.js.gz
|
1542
1528
|
- ui/dist/manifest.json
|
1543
1529
|
homepage:
|
1544
1530
|
licenses:
|
Binary file
|
Binary file
|