avo 1.6.4.pre.1 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of avo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +2 -2
- data/app/components/avo/edit/field_wrapper_component.html.erb +1 -1
- data/app/components/avo/edit/field_wrapper_component.rb +6 -1
- data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +65 -15
- data/app/components/avo/fields/belongs_to_field/edit_component.rb +1 -1
- data/app/controllers/avo/base_controller.rb +5 -0
- data/app/packs/js/controllers/fields/belongs_to_field_controller.js +65 -0
- data/db/factories.rb +4 -0
- data/lib/avo/base_resource.rb +36 -41
- data/lib/avo/fields/base_field.rb +5 -3
- data/lib/avo/fields/belongs_to_field.rb +96 -12
- data/lib/avo/fields/boolean_group_field.rb +1 -1
- data/lib/avo/fields/date_time_field.rb +1 -1
- data/lib/avo/fields/files_field.rb +1 -1
- data/lib/avo/fields/has_one_field.rb +1 -1
- data/lib/avo/fields/key_value_field.rb +1 -1
- data/lib/avo/fields_collector.rb +0 -2
- data/lib/avo/version.rb +1 -1
- data/public/avo-packs/css/application-797341b7.css.map +1 -1
- data/public/avo-packs/css/application-797341b7.css.map.br +0 -0
- data/public/avo-packs/css/application-797341b7.css.map.gz +0 -0
- data/public/avo-packs/js/application-947ed727440d5b5d73ab.js +26 -0
- data/public/avo-packs/js/{application-b444cbf11135b4b23654.js.LICENSE.txt → application-947ed727440d5b5d73ab.js.LICENSE.txt} +0 -0
- data/public/avo-packs/js/application-947ed727440d5b5d73ab.js.br +0 -0
- data/public/avo-packs/js/application-947ed727440d5b5d73ab.js.gz +0 -0
- data/public/avo-packs/js/application-947ed727440d5b5d73ab.js.map +1 -0
- data/public/avo-packs/js/application-947ed727440d5b5d73ab.js.map.br +0 -0
- data/public/avo-packs/js/application-947ed727440d5b5d73ab.js.map.gz +0 -0
- data/public/avo-packs/manifest.json +8 -8
- metadata +11 -10
- data/public/avo-packs/js/application-b444cbf11135b4b23654.js +0 -26
- data/public/avo-packs/js/application-b444cbf11135b4b23654.js.br +0 -0
- data/public/avo-packs/js/application-b444cbf11135b4b23654.js.gz +0 -0
- data/public/avo-packs/js/application-b444cbf11135b4b23654.js.map +0 -1
- data/public/avo-packs/js/application-b444cbf11135b4b23654.js.map.br +0 -0
- data/public/avo-packs/js/application-b444cbf11135b4b23654.js.map.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: e58bf8c94a89819523d1ef5abf6390ea2fb754d589c434a5de0d9daef0a231d0
|
4
|
+
data.tar.gz: 4662ea67f1f2653a495617d02ea279ed919889d33c599642394ca3f35e726f1b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6743f19e795f59bed7ac32436e67a73a8bfbfdb7d267dd12de510d93d64bfe7f592cf400c1aef2e1cab4538ada6b614191aac596ecd3f19444b9ef0fb42e8518
|
7
|
+
data.tar.gz: 16360a9602b08cc7f973cddda9106546c6cded669ce9592d80b6b647a0e53ec1f3d74468f8d04c8db632610059e234552b3b5debfa444489af0b4090677e4e96
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
avo (1.
|
4
|
+
avo (1.7.0)
|
5
5
|
active_link_to
|
6
6
|
addressable
|
7
7
|
breadcrumbs_on_rails
|
@@ -333,7 +333,7 @@ GEM
|
|
333
333
|
thread_safe (~> 0.1)
|
334
334
|
unicode-display_width (2.0.0)
|
335
335
|
unicode_utils (1.4.0)
|
336
|
-
view_component (2.
|
336
|
+
view_component (2.32.0)
|
337
337
|
activesupport (>= 5.0.0, < 7.0)
|
338
338
|
warden (1.2.9)
|
339
339
|
rack (>= 2.0.9)
|
data/README.md
CHANGED
@@ -56,6 +56,6 @@ $ bundle install
|
|
56
56
|
|
57
57
|
Please read [CONTRIBUTING.MD](./CONTRIBUTING.MD)
|
58
58
|
|
59
|
-
# Upgrade
|
59
|
+
# Upgrade Guide
|
60
60
|
|
61
|
-
Please read the [UPGRADE_GUIDE.MD](https://docs.avohq.io/0
|
61
|
+
Please read the [UPGRADE_GUIDE.MD](https://docs.avohq.io/1.0/upgrade.html)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<div class="flex items-center py-0 leading-tight <%= @classes %> min-h-16" data-field-id="<%= @field.id %>" data-field-type="<%= @field.type %>">
|
2
2
|
<div class="h-16 flex self-start items-center text-blue-gray-800">
|
3
3
|
<div class="<% if @displayed_in_modal %> md:w-48 <% else %> md:w-64 <% end %> w-48 px-8 flex" data-slot="label">
|
4
|
-
<%= @form.label @field.id,
|
4
|
+
<%= @form.label @field.id, label %> <% if @field.required %> <span class="text-red-600">*</span> <% end %>
|
5
5
|
</div>
|
6
6
|
</div>
|
7
7
|
<div class="flex-1 flex flex-row min-h-inherit">
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Avo::Edit::FieldWrapperComponent < ViewComponent::Base
|
4
|
-
def initialize(field: nil, dash_if_blank: true, full_width: false, displayed_in_modal: false, form: nil, resource: {}, **args)
|
4
|
+
def initialize(field: nil, dash_if_blank: true, full_width: false, displayed_in_modal: false, form: nil, resource: {}, label: nil, **args)
|
5
5
|
@field = field
|
6
6
|
@dash_if_blank = dash_if_blank
|
7
7
|
@classes = args[:class].present? ? args[:class] : ""
|
@@ -11,9 +11,14 @@ class Avo::Edit::FieldWrapperComponent < ViewComponent::Base
|
|
11
11
|
@resource = resource
|
12
12
|
@model = resource.present? ? resource.model : nil
|
13
13
|
@full_width = full_width
|
14
|
+
@label = label
|
14
15
|
|
15
16
|
if (@index != 0) || @displayed_in_modal
|
16
17
|
@classes += " border-t"
|
17
18
|
end
|
18
19
|
end
|
20
|
+
|
21
|
+
def label
|
22
|
+
@label || @field.name
|
23
|
+
end
|
19
24
|
end
|
@@ -1,18 +1,68 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
1
|
+
<% if @field.types.present? %>
|
2
|
+
<div data-controller="belongs-to-field">
|
3
|
+
<%= edit_field_wrapper field: @field, index: @index, form: @form, resource: @resource, displayed_in_modal: @displayed_in_modal do %>
|
4
|
+
<%= @form.select "#{@field.foreign_key}_type", @field.types.map { |type| [type.to_s.underscore.humanize, type.to_s] },
|
5
|
+
{
|
6
|
+
include_blank: @field.placeholder,
|
7
|
+
},
|
8
|
+
{
|
9
|
+
class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
|
10
|
+
disabled: disabled,
|
11
|
+
'data-belongs-to-field-target': "select",
|
12
|
+
'data-action': 'change->belongs-to-field#changedType'
|
13
|
+
}
|
14
|
+
%>
|
15
|
+
<%
|
16
|
+
# If the select field is disabled, no value will be sent. It's how HTML works.
|
17
|
+
# Thus the extra hidden field to actually send the related id to the server.
|
18
|
+
if disabled
|
19
|
+
%>
|
20
|
+
<%= @form.hidden_field "#{@field.foreign_key}_type" %>
|
21
|
+
<% end %>
|
22
|
+
<% end %>
|
23
|
+
<% @field.types.each do |type| %>
|
24
|
+
<div class="hidden"
|
25
|
+
data-belongs-to-field-target="type"
|
26
|
+
data-type="<%= type %>"
|
27
|
+
>
|
28
|
+
<%= edit_field_wrapper field: @field, index: @index, form: @form, resource: @resource, displayed_in_modal: @displayed_in_modal, label: type.to_s.underscore.humanize do %>
|
29
|
+
<%= @form.select "#{@field.foreign_key}_id", @field.values_for_type(type),
|
30
|
+
{
|
31
|
+
include_blank: @field.placeholder,
|
32
|
+
},
|
33
|
+
{
|
34
|
+
class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
|
35
|
+
disabled: disabled
|
36
|
+
}
|
37
|
+
%>
|
38
|
+
<%
|
39
|
+
# If the select field is disabled, no value will be sent. It's how HTML works.
|
40
|
+
# Thus the extra hidden field to actually send the related id to the server.
|
41
|
+
if disabled
|
42
|
+
%>
|
43
|
+
<%= @form.hidden_field "#{@field.foreign_key}_id" %>
|
44
|
+
<% end %>
|
45
|
+
<% end %>
|
46
|
+
</div>
|
47
|
+
<% end %>
|
48
|
+
</div>
|
49
|
+
<% else %>
|
50
|
+
<%= edit_field_wrapper field: @field, index: @index, form: @form, resource: @resource, displayed_in_modal: @displayed_in_modal do %>
|
51
|
+
<%= @form.select @field.foreign_key, @field.options.map { |o| [o[:label], o[:value]] },
|
52
|
+
{
|
53
|
+
include_blank: @field.placeholder,
|
54
|
+
},
|
55
|
+
{
|
56
|
+
class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
|
57
|
+
disabled: disabled
|
58
|
+
}
|
59
|
+
%>
|
60
|
+
<%
|
61
|
+
# If the select field is disabled, no value will be sent. It's how HTML works.
|
62
|
+
# Thus the extra hidden field to actually send the related id to the server.
|
63
|
+
if disabled
|
10
64
|
%>
|
11
|
-
|
12
|
-
|
13
|
-
# Thus the extra hidden field to actually send the related id to the server.
|
14
|
-
if disabled
|
15
|
-
%>
|
16
|
-
<%= @form.hidden_field @field.foreign_key %>
|
65
|
+
<%= @form.hidden_field @field.foreign_key %>
|
66
|
+
<% end %>
|
17
67
|
<% end %>
|
18
68
|
<% end %>
|
@@ -3,7 +3,7 @@
|
|
3
3
|
class Avo::Fields::BelongsToField::EditComponent < Avo::Fields::EditComponent
|
4
4
|
def disabled
|
5
5
|
return true if @field.readonly
|
6
|
-
return true if @field.target_resource.model_class.name == params[:via_resource_class]
|
6
|
+
return true if @field.target_resource.present? && @field.target_resource.model_class.name == params[:via_resource_class]
|
7
7
|
return true if @field.id.to_s == params[:via_relation].to_s
|
8
8
|
|
9
9
|
false
|
@@ -21,6 +21,11 @@ module Avo
|
|
21
21
|
@query = @authorization.apply_policy @resource.model_class
|
22
22
|
end
|
23
23
|
|
24
|
+
# Remove default_scope for index view
|
25
|
+
if @resource.unscoped_queries_on_index
|
26
|
+
@query = @query.unscoped
|
27
|
+
end
|
28
|
+
|
24
29
|
# Eager load the relations
|
25
30
|
if @resource.includes.present?
|
26
31
|
@query = @query.includes(*@resource.includes)
|
@@ -0,0 +1,65 @@
|
|
1
|
+
import { Controller } from 'stimulus'
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static targets = ['select', 'type']
|
5
|
+
|
6
|
+
get selectedType() {
|
7
|
+
return this.selectTarget.value
|
8
|
+
}
|
9
|
+
|
10
|
+
connect() {
|
11
|
+
this.setValidNames()
|
12
|
+
this.changedType()
|
13
|
+
}
|
14
|
+
|
15
|
+
setValidNames() {
|
16
|
+
this.typeTargets.forEach((target) => {
|
17
|
+
const { type } = target.dataset
|
18
|
+
const select = target.querySelector('select')
|
19
|
+
const name = select.getAttribute('name')
|
20
|
+
|
21
|
+
select.setAttribute('valid-name', name)
|
22
|
+
if (this.selectedType !== type) {
|
23
|
+
select.selectedIndex = 0
|
24
|
+
}
|
25
|
+
})
|
26
|
+
}
|
27
|
+
|
28
|
+
changedType() {
|
29
|
+
this.hideAllTypeTargets()
|
30
|
+
this.enableType(this.selectTarget.value)
|
31
|
+
}
|
32
|
+
|
33
|
+
hideAllTypeTargets() {
|
34
|
+
this.typeTargets.forEach((target) => {
|
35
|
+
this.hideTarget(target)
|
36
|
+
this.invalidateTarget(target)
|
37
|
+
})
|
38
|
+
}
|
39
|
+
|
40
|
+
hideTarget(target) {
|
41
|
+
target.classList.add('hidden')
|
42
|
+
}
|
43
|
+
|
44
|
+
invalidateTarget(target) {
|
45
|
+
const select = target.querySelector('select')
|
46
|
+
|
47
|
+
select.setAttribute('name', '')
|
48
|
+
}
|
49
|
+
|
50
|
+
validateTarget(target) {
|
51
|
+
const select = target.querySelector('select')
|
52
|
+
const validName = select.getAttribute('valid-name')
|
53
|
+
|
54
|
+
select.setAttribute('name', validName)
|
55
|
+
}
|
56
|
+
|
57
|
+
enableType(type) {
|
58
|
+
const target = this.typeTargets.find((typeTarget) => typeTarget.dataset.type === type)
|
59
|
+
|
60
|
+
if (target) {
|
61
|
+
target.classList.remove('hidden')
|
62
|
+
this.validateTarget(target)
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
data/db/factories.rb
CHANGED
@@ -40,4 +40,8 @@ FactoryBot.define do
|
|
40
40
|
meta { [{foo: "bar", hey: "hi"}, {bar: "baz"}, {hoho: "hohoho"}].sample }
|
41
41
|
progress { Faker::Number.between(from: 0, to: 100) }
|
42
42
|
end
|
43
|
+
|
44
|
+
factory :comment do
|
45
|
+
body { Faker::Lorem.paragraphs(number: rand(4...10)).join("\n") }
|
46
|
+
end
|
43
47
|
end
|
data/lib/avo/base_resource.rb
CHANGED
@@ -22,6 +22,7 @@ module Avo
|
|
22
22
|
class_attribute :fields
|
23
23
|
class_attribute :grid_loader
|
24
24
|
class_attribute :visible_on_sidebar, default: true
|
25
|
+
class_attribute :unscoped_queries_on_index, default: false
|
25
26
|
|
26
27
|
class << self
|
27
28
|
def grid(&block)
|
@@ -87,20 +88,30 @@ module Avo
|
|
87
88
|
end
|
88
89
|
|
89
90
|
def get_fields(panel: nil, reflection: nil)
|
90
|
-
fields = get_field_definitions
|
91
|
-
field
|
92
|
-
|
91
|
+
fields = get_field_definitions
|
92
|
+
.select do |field|
|
93
|
+
field.send("show_on_#{@view}")
|
94
|
+
end
|
93
95
|
.select do |field|
|
94
|
-
|
95
|
-
|
96
|
+
field.visible?
|
97
|
+
end
|
96
98
|
.select do |field|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
99
|
+
# Strip out the reflection field in index queries with a parent association.
|
100
|
+
if reflection.present? &&
|
101
|
+
reflection.options.present? &&
|
102
|
+
field.respond_to?(:polymorphic_as) &&
|
103
|
+
field.polymorphic_as.to_s == reflection.options[:as].to_s
|
104
|
+
next
|
105
|
+
end
|
106
|
+
if field.respond_to?(:foreign_key) &&
|
107
|
+
reflection.present? &&
|
108
|
+
reflection.respond_to?(:foreign_key) &&
|
109
|
+
reflection.foreign_key != field.foreign_key
|
110
|
+
next
|
111
|
+
end
|
112
|
+
|
101
113
|
true
|
102
114
|
end
|
103
|
-
end
|
104
115
|
|
105
116
|
if panel.present?
|
106
117
|
fields = fields.select do |field|
|
@@ -216,28 +227,6 @@ module Avo
|
|
216
227
|
self.class.context
|
217
228
|
end
|
218
229
|
|
219
|
-
def query_search(via_resource_name:, via_resource_id:, user:, query: "")
|
220
|
-
# model_class = self.model
|
221
|
-
|
222
|
-
db_query = AuthorizationService.apply_policy(user, model_class)
|
223
|
-
|
224
|
-
if via_resource_name.present?
|
225
|
-
related_model = App.get_resource_by_name(via_resource_name).model
|
226
|
-
|
227
|
-
db_query = related_model.find(via_resource_id).public_send(plural_name.downcase)
|
228
|
-
end
|
229
|
-
|
230
|
-
new_query = []
|
231
|
-
|
232
|
-
[search].flatten.each_with_index do |search_by, index|
|
233
|
-
new_query.push "or" if index != 0
|
234
|
-
|
235
|
-
new_query.push "text(#{search_by}) ILIKE '%#{query}%'"
|
236
|
-
end
|
237
|
-
|
238
|
-
db_query.where(new_query.join(" "))
|
239
|
-
end
|
240
|
-
|
241
230
|
def attached_file_fields
|
242
231
|
get_field_definitions.select do |field|
|
243
232
|
[Avo::Fields::FileField, Avo::Fields::FilesField].include? field.class
|
@@ -250,14 +239,17 @@ module Avo
|
|
250
239
|
.reject do |field|
|
251
240
|
field.computed
|
252
241
|
end
|
253
|
-
.map
|
242
|
+
.map do |field|
|
243
|
+
[field.database_id(model).to_s, field]
|
244
|
+
end
|
245
|
+
.to_h
|
254
246
|
|
255
247
|
params.each do |key, value|
|
256
248
|
field = fields_by_database_id[key]
|
257
249
|
|
258
250
|
next unless field.present?
|
259
251
|
|
260
|
-
model = field.fill_field model, key, value
|
252
|
+
model = field.fill_field model, key, value, params
|
261
253
|
end
|
262
254
|
|
263
255
|
model
|
@@ -295,19 +287,22 @@ module Avo
|
|
295
287
|
|
296
288
|
# We will not overwrite any attributes that come pre-filled in the model.
|
297
289
|
def hydrate_model_with_default_values
|
298
|
-
default_values = get_fields
|
299
|
-
|
300
|
-
|
290
|
+
default_values = get_fields
|
291
|
+
.select do |field|
|
292
|
+
!field.computed
|
293
|
+
end
|
301
294
|
.map do |field|
|
302
295
|
id = field.id
|
303
296
|
value = field.value
|
304
297
|
|
305
|
-
if field.
|
298
|
+
if field.type == "belongs_to"
|
306
299
|
id = field.foreign_key.to_sym
|
307
300
|
|
308
301
|
reflection = @model._reflections[@params[:via_relation]]
|
309
302
|
|
310
|
-
if
|
303
|
+
if field.polymorphic_as.present? && field.types.map(&:to_s).include?(@params["via_relation_class"])
|
304
|
+
value = @params["via_relation_class"].safe_constantize.find(@params[:via_resource_id])
|
305
|
+
elsif reflection.present? && reflection.foreign_key.present? && field.id.to_s == @params[:via_relation].to_s
|
311
306
|
value = @params[:via_resource_id]
|
312
307
|
end
|
313
308
|
end
|
@@ -316,8 +311,8 @@ module Avo
|
|
316
311
|
end
|
317
312
|
.to_h
|
318
313
|
.select do |id, value|
|
319
|
-
|
320
|
-
|
314
|
+
value.present?
|
315
|
+
end
|
321
316
|
|
322
317
|
default_values.each do |id, value|
|
323
318
|
if @model.send(id).nil?
|
@@ -91,9 +91,11 @@ module Avo
|
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
-
def value
|
94
|
+
def value(property = nil)
|
95
|
+
property ||= id
|
96
|
+
|
95
97
|
# Get model value
|
96
|
-
final_value = @model.send(
|
98
|
+
final_value = @model.send(property) if (model_or_class(@model) == "model") && @model.respond_to?(property)
|
97
99
|
|
98
100
|
if (@view === :new) || @action.present?
|
99
101
|
final_value = if default.present? && default.respond_to?(:call)
|
@@ -114,7 +116,7 @@ module Avo
|
|
114
116
|
final_value
|
115
117
|
end
|
116
118
|
|
117
|
-
def fill_field(model, key, value)
|
119
|
+
def fill_field(model, key, value, params)
|
118
120
|
return model unless model.methods.include? key.to_sym
|
119
121
|
|
120
122
|
model.send("#{key}=", value)
|
@@ -2,7 +2,9 @@ module Avo
|
|
2
2
|
module Fields
|
3
3
|
class BelongsToField < BaseField
|
4
4
|
attr_reader :searchable
|
5
|
+
attr_reader :polymorphic_as
|
5
6
|
attr_reader :relation_method
|
7
|
+
attr_reader :types
|
6
8
|
|
7
9
|
def initialize(id, **args, &block)
|
8
10
|
args[:placeholder] ||= I18n.t("avo.choose_an_option")
|
@@ -10,11 +12,17 @@ module Avo
|
|
10
12
|
super(id, **args, &block)
|
11
13
|
|
12
14
|
@searchable = args[:searchable] == true
|
15
|
+
@polymorphic_as = args[:polymorphic_as]
|
16
|
+
@types = args[:types]
|
13
17
|
@relation_method = name.to_s.parameterize.underscore
|
14
18
|
end
|
15
19
|
|
20
|
+
def value
|
21
|
+
super(polymorphic_as)
|
22
|
+
end
|
23
|
+
|
16
24
|
def options
|
17
|
-
target_resource.model_class.all.map do |model|
|
25
|
+
::Avo::Services::AuthorizationService.apply_policy(user, target_resource.model_class).all.map do |model|
|
18
26
|
{
|
19
27
|
value: model.id,
|
20
28
|
label: model.send(target_resource.class.title)
|
@@ -22,22 +30,32 @@ module Avo
|
|
22
30
|
end
|
23
31
|
end
|
24
32
|
|
33
|
+
def values_for_type(type)
|
34
|
+
::Avo::Services::AuthorizationService.apply_policy(user, type).all.map do |model|
|
35
|
+
[model.send(App.get_resource_by_model_name(type).class.title), model.id]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
25
39
|
def database_value
|
26
40
|
target_resource.id
|
27
41
|
end
|
28
42
|
|
29
43
|
def foreign_key
|
44
|
+
return polymorphic_as if polymorphic_as.present?
|
45
|
+
|
30
46
|
if @model.present?
|
31
|
-
|
32
|
-
|
33
|
-
else
|
34
|
-
@model.class.reflections[@relation_method].foreign_key
|
35
|
-
end
|
36
|
-
elsif @resource.present?
|
47
|
+
get_model_class(@model).reflections[@relation_method].foreign_key
|
48
|
+
elsif @resource.present? && @resource.model_class.reflections[@relation_method].present?
|
37
49
|
@resource.model_class.reflections[@relation_method].foreign_key
|
38
50
|
end
|
39
51
|
end
|
40
52
|
|
53
|
+
def reflection_for_key(key)
|
54
|
+
get_model_class(get_model).reflections[key.to_s]
|
55
|
+
rescue
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
|
41
59
|
def relation_model_class
|
42
60
|
@resource.model_class
|
43
61
|
end
|
@@ -47,16 +65,82 @@ module Avo
|
|
47
65
|
end
|
48
66
|
|
49
67
|
def to_permitted_param
|
68
|
+
if polymorphic_as.present?
|
69
|
+
return ["#{polymorphic_as}_type".to_sym, "#{polymorphic_as}_id".to_sym]
|
70
|
+
end
|
71
|
+
|
50
72
|
foreign_key.to_sym
|
51
73
|
end
|
52
74
|
|
75
|
+
def fill_field(model, key, value, params)
|
76
|
+
return model unless model.methods.include? key.to_sym
|
77
|
+
|
78
|
+
if polymorphic_as.present?
|
79
|
+
model.send("#{polymorphic_as}_type=", params["#{polymorphic_as}_type"])
|
80
|
+
|
81
|
+
# If the type is blank, reset the id too.
|
82
|
+
if params["#{polymorphic_as}_type"].blank?
|
83
|
+
model.send("#{polymorphic_as}_id=", nil)
|
84
|
+
else
|
85
|
+
model.send("#{polymorphic_as}_id=", params["#{polymorphic_as}_id"])
|
86
|
+
end
|
87
|
+
else
|
88
|
+
model.send("#{key}=", value)
|
89
|
+
end
|
90
|
+
|
91
|
+
model
|
92
|
+
end
|
93
|
+
|
94
|
+
def database_id(model)
|
95
|
+
# If the field is a polymorphic value, return the polymorphic_type as key and pre-fill the _id in fill_field.
|
96
|
+
return "#{polymorphic_as}_type" if polymorphic_as.present?
|
97
|
+
|
98
|
+
foreign_key
|
99
|
+
rescue
|
100
|
+
id
|
101
|
+
end
|
102
|
+
|
53
103
|
def target_resource
|
54
|
-
if
|
55
|
-
|
56
|
-
|
57
|
-
|
104
|
+
if polymorphic_as.present?
|
105
|
+
if value.present?
|
106
|
+
return App.get_resource_by_model_name(value.class)
|
107
|
+
else
|
108
|
+
return nil
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
reflection_key = polymorphic_as || id
|
113
|
+
|
114
|
+
if @model._reflections[reflection_key.to_s].klass.present?
|
115
|
+
App.get_resource_by_model_name @model._reflections[reflection_key.to_s].klass.to_s
|
116
|
+
elsif @model._reflections[reflection_key.to_s].options[:class_name].present?
|
117
|
+
App.get_resource_by_model_name @model._reflections[reflection_key.to_s].options[:class_name]
|
118
|
+
else
|
119
|
+
App.get_resource_by_name reflection_key.to_s
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def get_model
|
124
|
+
return @model if @model.present?
|
125
|
+
|
126
|
+
@resource.model
|
127
|
+
rescue
|
128
|
+
nil
|
129
|
+
end
|
130
|
+
|
131
|
+
def name
|
132
|
+
return polymorphic_as.to_s.humanize if polymorphic_as.present? && view == :index
|
133
|
+
|
134
|
+
super
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
|
139
|
+
def get_model_class(model)
|
140
|
+
if model.instance_of?(Class)
|
141
|
+
model
|
58
142
|
else
|
59
|
-
|
143
|
+
model.class
|
60
144
|
end
|
61
145
|
end
|
62
146
|
end
|