active_scaffold 3.6.0.rc1 → 3.6.0.rc2
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/CHANGELOG.rdoc +10 -0
- data/app/assets/javascripts/jquery/active_scaffold.js +47 -13
- data/app/assets/stylesheets/active_scaffold_layout.css +1 -1
- data/app/views/active_scaffold_overrides/_form_association.html.erb +2 -1
- data/app/views/active_scaffold_overrides/_form_association_record.html.erb +4 -2
- data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +3 -3
- data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +2 -1
- data/app/views/active_scaffold_overrides/_vertical_subform.html.erb +2 -2
- data/app/views/active_scaffold_overrides/update_column.js.erb +1 -1
- data/lib/active_scaffold/actions/core.rb +5 -2
- data/lib/active_scaffold/actions/nested.rb +1 -1
- data/lib/active_scaffold/actions/subform.rb +12 -6
- data/lib/active_scaffold/attribute_params.rb +6 -16
- data/lib/active_scaffold/bridges/active_storage/active_storage_bridge.rb +1 -0
- data/lib/active_scaffold/bridges/active_storage/list_ui.rb +4 -4
- data/lib/active_scaffold/bridges/paper_trail/actions.rb +3 -1
- data/lib/active_scaffold/bridges/record_select/helpers.rb +3 -1
- data/lib/active_scaffold/data_structures/association/abstract.rb +1 -4
- data/lib/active_scaffold/data_structures/nested_info.rb +12 -0
- data/lib/active_scaffold/extensions/cow_proxy.rb +4 -0
- data/lib/active_scaffold/finder.rb +7 -5
- data/lib/active_scaffold/helpers/controller_helpers.rb +11 -0
- data/lib/active_scaffold/helpers/form_column_helpers.rb +50 -13
- data/lib/active_scaffold/helpers/list_column_helpers.rb +4 -4
- data/lib/active_scaffold/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 482104397cc4bcba59938371add5a7d584a23c3f42aa4b8f3f4ba44f0ffa6114
|
4
|
+
data.tar.gz: a140af6343b7a3002740fa8a5af20ddd5da09a0c7a3f384ef31c85a697918cb4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 89556a2bbb6664fb22291e21bba6108d21c0195788cf5e3fdb6b5d471aab24e7bdef1d40d764f68bb9ecb6e94dfc5c728ac4742b3034a7e74d7e11688933d835
|
7
|
+
data.tar.gz: 2606b28e771d97eb6600fb380c34cace3adfbce11cc7baa470de3821dd2bd82e3acec4e66b1bcef14ff7fa17755e2255d7b977a43e85aea893d70d83c2d0f133
|
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
= 3.6.0.rc2
|
2
|
+
- Fix subform crud in subform subgroup when controller is embedded
|
3
|
+
- Fix sorting for mongoid models, broken in 3.6.0.rc1
|
4
|
+
- Improve add_new option, allow to change subform columns (with helper override calling super and add columns to locals argument)
|
5
|
+
- Support add_new option for record_select or radio form_ui
|
6
|
+
- Support add_new option for polymorphic associations (add_new may be array with class names to allow add new, or true to allow add new for any model)
|
7
|
+
- Support description for columns displayed as subform
|
8
|
+
- Don't mess with history if current page is not using activescaffold when is loaded
|
9
|
+
- Fix changing sort_by per request when threadsafe is enabled
|
10
|
+
|
1
11
|
= 3.6.0.rc1
|
2
12
|
- Cleanup: deprecate ActiveScaffold.set_defaults for ActiveScaffold.defaults, rename some setters
|
3
13
|
- Fix adding new action links on request with threadsafety enabled
|
@@ -323,20 +323,34 @@ jQuery(document).ready(function($) {
|
|
323
323
|
if (jQuery(this).prop('checked')) color_field.val('');
|
324
324
|
});
|
325
325
|
|
326
|
-
jQuery(document).on('click', '.show-new-subform', function(e) {
|
327
|
-
e.preventDefault();
|
326
|
+
jQuery(document).on('click', '.hide-new-subform, .show-new-subform', function(e) {
|
328
327
|
var $this = jQuery(this), line = $this.closest('.form-element'),
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
subform.show().find("input:disabled,select:disabled,textarea:disabled").prop('disabled', false);
|
334
|
-
$this.data('select-text', $this.html());
|
335
|
-
$this.html($this.data('subform-text'));
|
328
|
+
subform = line.find('#' + $this.data('subform-id')), radio = false, hide, select;
|
329
|
+
if ($this.is('[type=radio]')) {
|
330
|
+
radio = true;
|
331
|
+
hide = $this.is('.hide-new-subform');
|
336
332
|
} else {
|
333
|
+
e.preventDefault();
|
334
|
+
hide = subform.is(':visible');
|
335
|
+
}
|
336
|
+
if ($this.data('select-id')) {
|
337
|
+
select = line.find('#' + $this.data('select-id'));
|
338
|
+
if (select.hasClass('recordselect') || select.is('.no-options')) select = select.next(':hidden').andSelf();
|
339
|
+
}
|
340
|
+
if (hide) {
|
337
341
|
subform.hide().find("input:enabled,select:enabled,textarea:enabled").prop('disabled', true);
|
338
|
-
select.show().prop('disabled', false);
|
339
|
-
|
342
|
+
if (select) select.show().prop('disabled', false);
|
343
|
+
if (radio) {
|
344
|
+
$this.closest('.form-element').find('[name="' + $this.attr('name') + '"].show-new-subform').prop('disabled', false);
|
345
|
+
} else $this.html($this.data('select-text'));
|
346
|
+
} else {
|
347
|
+
if (select) select.hide().prop('disabled', true);
|
348
|
+
subform.show().find("input:disabled,select:disabled,textarea:disabled").prop('disabled', false);
|
349
|
+
if (radio) $this.prop('disabled', true);
|
350
|
+
else {
|
351
|
+
$this.data('select-text', $this.html());
|
352
|
+
$this.html($this.data('subform-text'));
|
353
|
+
}
|
340
354
|
}
|
341
355
|
});
|
342
356
|
|
@@ -500,6 +514,7 @@ var ActiveScaffold = {
|
|
500
514
|
ActiveScaffold.disable_optional_subforms(container);
|
501
515
|
},
|
502
516
|
setup_history_state: function() {
|
517
|
+
if (!jQuery('.active-scaffold').length) return;
|
503
518
|
var data = {}, current_search_item = jQuery('.active-scaffold .filtered-message[data-search]');
|
504
519
|
if (current_search_item.length) {
|
505
520
|
// store user settings enabled, update state with current page, search and sorting
|
@@ -536,8 +551,27 @@ var ActiveScaffold = {
|
|
536
551
|
jQuery('.as-js-button', element).show();
|
537
552
|
},
|
538
553
|
disable_optional_subforms: function(element) {
|
539
|
-
jQuery('.
|
540
|
-
jQuery(
|
554
|
+
jQuery('.sub-form.optional', element).each(function () {
|
555
|
+
var $this = jQuery(this), toggle = $this.find('>.visibility-toggle');
|
556
|
+
if (toggle.length) {
|
557
|
+
var hide = toggle.text() == toggle.data('show');
|
558
|
+
$this.find('> [id] > .sub-form-record > .associated-record dl:first').each(function (i) {
|
559
|
+
var parent = jQuery(this).parent(), div_id = toggle.data('toggable') + i;
|
560
|
+
parent.children().wrapAll('<div id="' + div_id + '">');
|
561
|
+
if (hide) parent.find('> div').hide();
|
562
|
+
parent.prepend(toggle.clone().data('toggable', div_id));
|
563
|
+
});
|
564
|
+
toggle.remove();
|
565
|
+
}
|
566
|
+
if ($this.is(':visible')) {
|
567
|
+
var line = $this.closest('.form-element'), toggle = line.find('.show-new-subform[data-subform-id="' + $this.attr('id') + '"]').first();
|
568
|
+
if (toggle.is('[type=radio]')) toggle.prop('disabled', true);
|
569
|
+
else if (toggle.data('select-id')) {
|
570
|
+
select = line.find('#' + toggle.data('select-id'));
|
571
|
+
if (select.hasClass('recordselect') || select.is('.no-options')) select = select.next(':hidden').andSelf();
|
572
|
+
select.hide().prop('disabled', true);
|
573
|
+
}
|
574
|
+
} else $this.find("input:enabled,select:enabled,textarea:enabled").prop('disabled', true);
|
541
575
|
});
|
542
576
|
},
|
543
577
|
sliders: function(element) {
|
@@ -13,8 +13,9 @@ footer = render(:partial => 'form_association_footer', :locals => {:parent_recor
|
|
13
13
|
-%>
|
14
14
|
<h5>
|
15
15
|
<%= column.label -%>
|
16
|
-
<%= link_to_visibility_toggle(subform_div_id,
|
16
|
+
<%= link_to_visibility_toggle(subform_div_id, default_visible: !column.collapsed) -%>
|
17
17
|
</h5>
|
18
|
+
<%= content_tag :span, column.description, class: 'description' if column.description.present? %>
|
18
19
|
<div id ="<%= subform_div_id %>" <%= 'style="display: none;"'.html_safe if column.collapsed -%>>
|
19
20
|
<%# HACK: to be able to delete all associated records %>
|
20
21
|
<%= hidden_field_tag "#{(opts = active_scaffold_input_options(column, scope, :object => parent_record))[:name]}[0]", '', :id => "#{opts[:id]}_0" if column.association.collection? %>
|
@@ -6,11 +6,13 @@
|
|
6
6
|
show_actions = false
|
7
7
|
locked ||= false
|
8
8
|
config = active_scaffold_config_for(record.class)
|
9
|
+
columns ||= config.subform.columns
|
9
10
|
scope = column_scope(record_column, scope, record)
|
10
11
|
options = active_scaffold_input_options(config.columns[record.class.primary_key], scope, :object => record)
|
11
12
|
tr_id = "association-#{options[:id]}"
|
13
|
+
layout ||= config.subform.layout
|
12
14
|
|
13
|
-
if
|
15
|
+
if layout == :vertical
|
14
16
|
record_tag ||= :div
|
15
17
|
row_tag ||= :ol
|
16
18
|
column_tag ||= :li
|
@@ -40,7 +42,7 @@
|
|
40
42
|
<% end %>
|
41
43
|
<% end %>
|
42
44
|
<%= content_tag row_tag, :id => tr_id, :class => "association-record#{' association-record-new' if record.new_record?}#{' locked' if locked}" do %>
|
43
|
-
<%
|
45
|
+
<% columns.each_column(for: record.class, crud_type: :read, flatten: flatten) do |column| %>
|
44
46
|
<%
|
45
47
|
if column.respond_to? :each_column
|
46
48
|
columns_groups << column
|
@@ -2,10 +2,10 @@
|
|
2
2
|
<%
|
3
3
|
header_record_class = (show_blank_record && show_blank_record.class) || column.association.klass
|
4
4
|
-%>
|
5
|
-
<%= render :
|
5
|
+
<%= render partial: 'horizontal_subform_header', :locals => {parent_record: parent_record, record_class: header_record_class, parent_column: column, columns: local_assigns[:columns]} %>
|
6
6
|
|
7
|
-
<%= render :
|
8
|
-
<%= render :
|
7
|
+
<%= render partial: 'form_association_record', collection: associated, locals: {scope: scope, parent_record: parent_record, column: column, columns: local_assigns[:columns], layout: :horizontal} %>
|
8
|
+
<%= render partial: 'form_association_record', object: show_blank_record, locals: {scope: scope, parent_record: parent_record, column: column, columns: local_assigns[:columns], layout: :horizontal, locked: true, index: associated.size} if show_blank_record %>
|
9
9
|
<tfoot>
|
10
10
|
<%= render :partial => 'horizontal_subform_footer', :locals => {:scope => scope, :parent_record => parent_record, :column => column} %>
|
11
11
|
</tfoot>
|
@@ -1,7 +1,8 @@
|
|
1
1
|
<thead>
|
2
2
|
<tr>
|
3
3
|
<%
|
4
|
-
active_scaffold_config_for(record_class).subform.columns
|
4
|
+
columns ||= active_scaffold_config_for(record_class).subform.columns
|
5
|
+
columns.each_column(for: record_class, crud_type: :read) do |column|
|
5
6
|
next unless column.is_a? ActiveScaffold::DataStructures::Column
|
6
7
|
next unless in_subform?(column, parent_record, parent_column)
|
7
8
|
hidden = column_renders_as(column) == :hidden
|
@@ -1,4 +1,4 @@
|
|
1
1
|
<div id="<%= sub_form_list_id(:association => column.name, :id => parent_record.id || generated_id(parent_record) || 99999999999) %>">
|
2
|
-
<%= render :
|
3
|
-
<%= render :
|
2
|
+
<%= render partial: 'form_association_record', collection: associated, locals: {scope: scope, parent_record: parent_record, column: column, columns: local_assigns[:columns], layout: :vertical} %>
|
3
|
+
<%= render partial: 'form_association_record', object: show_blank_record, locals: {scope: scope, parent_record: parent_record, column: column, columns: local_assigns[:columns], layout: :vertical, locked: true, index: associated.size} if show_blank_record %>
|
4
4
|
</div>
|
@@ -22,5 +22,5 @@
|
|
22
22
|
ActiveScaffold.replace_html('<%= @column_span_id %>','<%= escape_javascript(get_column_value(@record, @column)) %>');
|
23
23
|
<% end -%>
|
24
24
|
<% if @column.calculation? -%>
|
25
|
-
ActiveScaffold.replace_html('<%= active_scaffold_calculations_id(:column => @column) %>', '<%= escape_javascript(render_column_calculation(@column)) %>');
|
25
|
+
ActiveScaffold.replace_html('<%= active_scaffold_calculations_id(:column => @column) %>', '<%= escape_javascript(render_column_calculation(@column, id_condition: false)) %>');
|
26
26
|
<% end -%>
|
@@ -72,7 +72,8 @@ module ActiveScaffold::Actions
|
|
72
72
|
else
|
73
73
|
updated_record_with_column(@column, params.delete(:value), @scope)
|
74
74
|
end
|
75
|
-
|
75
|
+
# if @scope has more than 2 ] then it's subform inside subform, and assign parent would fail (found associotion may be through association)
|
76
|
+
setup_parent(@record) if main_form_controller && @scope && @scope.scan(']').size == 2
|
76
77
|
after_render_field(@record, @column)
|
77
78
|
end
|
78
79
|
|
@@ -277,7 +278,9 @@ module ActiveScaffold::Actions
|
|
277
278
|
|
278
279
|
def new_model
|
279
280
|
relation = beginning_of_chain
|
280
|
-
|
281
|
+
if nested? && nested.plural_association? && nested.match_model?(active_scaffold_config.model)
|
282
|
+
build_options = sti_nested_build_options(relation.klass)
|
283
|
+
end
|
281
284
|
relation.respond_to?(:build) ? relation.build(build_options || {}) : relation.new
|
282
285
|
end
|
283
286
|
|
@@ -90,7 +90,7 @@ module ActiveScaffold::Actions
|
|
90
90
|
|
91
91
|
def beginning_of_chain
|
92
92
|
# only if nested is related to current controller, e.g. not when adding record in subform inside subform
|
93
|
-
if nested? && nested.
|
93
|
+
if nested? && nested.match_model?(active_scaffold_config.model)
|
94
94
|
nested_chain_with_association
|
95
95
|
elsif nested? && nested.scope
|
96
96
|
nested_parent_record.send(nested.scope)
|
@@ -9,19 +9,25 @@ module ActiveScaffold::Actions
|
|
9
9
|
|
10
10
|
protected
|
11
11
|
|
12
|
-
def
|
13
|
-
|
14
|
-
if
|
15
|
-
|
16
|
-
|
12
|
+
def new_parent_record
|
13
|
+
parent_record = new_model
|
14
|
+
# don't apply if scope, subform inside subform, because constraints won't apply to parent_record
|
15
|
+
apply_constraints_to_record parent_record unless @scope
|
16
|
+
if nested? && nested.match_model?(active_scaffold_config.model)
|
17
|
+
create_association_with_parent parent_record
|
17
18
|
end
|
19
|
+
parent_record
|
20
|
+
end
|
21
|
+
|
22
|
+
def do_edit_associated
|
23
|
+
@scope = params[:scope]
|
24
|
+
@parent_record = params[:id].nil? ? new_parent_record : find_if_allowed(params[:id], :update)
|
18
25
|
|
19
26
|
cache_generated_id(@parent_record, params[:generated_id]) if @parent_record.new_record?
|
20
27
|
@column = active_scaffold_config.columns[params[:child_association]]
|
21
28
|
|
22
29
|
@record = find_associated_record if params[:associated_id]
|
23
30
|
@record ||= build_associated(@column.association, @parent_record)
|
24
|
-
@scope = params[:scope]
|
25
31
|
end
|
26
32
|
|
27
33
|
def find_associated_record
|
@@ -230,7 +230,7 @@ module ActiveScaffold
|
|
230
230
|
return nil unless build_record_from_params?(attributes, column, parent_record)
|
231
231
|
record = find_or_create_for_params(attributes, column, parent_record)
|
232
232
|
if record
|
233
|
-
record_columns = active_scaffold_config_for(
|
233
|
+
record_columns = active_scaffold_config_for(record.class).subform.columns
|
234
234
|
prev_constraints = record_columns.constraint_columns
|
235
235
|
record_columns.constraint_columns = [column.association.reverse].compact
|
236
236
|
update_record_from_params(record, record_columns, attributes, avoid_changes)
|
@@ -242,8 +242,9 @@ module ActiveScaffold
|
|
242
242
|
|
243
243
|
def build_record_from_params?(params, column, record)
|
244
244
|
current = record.send(column.name)
|
245
|
-
|
246
|
-
|
245
|
+
return true if column.association.collection? && !column.show_blank_record?(current)
|
246
|
+
klass = column.association.klass(record)
|
247
|
+
klass && !attributes_hash_is_empty?(params, klass)
|
247
248
|
end
|
248
249
|
|
249
250
|
# Attempts to create or find an instance of the klass of the association in parent_column from the
|
@@ -251,12 +252,12 @@ module ActiveScaffold
|
|
251
252
|
# otherwise it will build a new one.
|
252
253
|
def find_or_create_for_params(params, parent_column, parent_record)
|
253
254
|
current = parent_record.send(parent_column.name)
|
254
|
-
klass = parent_column.association.klass
|
255
|
+
klass = parent_column.association.klass(parent_record)
|
255
256
|
if params.key? klass.primary_key
|
256
257
|
record_from_current_or_find(klass, params[klass.primary_key], current)
|
257
258
|
elsif klass.authorized_for?(:crud_type => :create)
|
258
259
|
association = parent_column.association
|
259
|
-
record =
|
260
|
+
record = klass.new
|
260
261
|
if association.reverse_association&.belongs_to? && (association.collection? || current.nil?)
|
261
262
|
record.send("#{parent_column.association.reverse}=", parent_record)
|
262
263
|
end
|
@@ -278,17 +279,6 @@ module ActiveScaffold
|
|
278
279
|
end
|
279
280
|
end
|
280
281
|
|
281
|
-
def save_record_to_association(record, association, value, reverse = nil)
|
282
|
-
return unless association
|
283
|
-
if association.collection?
|
284
|
-
record.send(association.name) << value
|
285
|
-
elsif reverse&.belongs_to?
|
286
|
-
value.send("#{reverse.name}=", record)
|
287
|
-
else
|
288
|
-
record.send("#{association.name}=", value)
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
282
|
# Determines whether the given attributes hash is "empty".
|
293
283
|
# This isn't a literal emptiness - it's an attempt to discern whether the user intended it to be empty or not.
|
294
284
|
def attributes_hash_is_empty?(hash, klass)
|
@@ -24,6 +24,7 @@ module ActiveScaffold
|
|
24
24
|
columns << field
|
25
25
|
columns.exclude "#{field}_attachment#{'s' if field_type == :has_many}".to_sym
|
26
26
|
columns.exclude "#{field}_blob#{'s' if field_type == :has_many}".to_sym
|
27
|
+
columns[field].includes ||= ["#{field}_attachment#{'s' if field_type == :has_many}".to_sym, "#{field}_blob#{'s' if field_type == :has_many}".to_sym]
|
27
28
|
columns[field].form_ui ||= "active_storage_#{field_type}".to_sym
|
28
29
|
columns[field].params.add "delete_#{field}"
|
29
30
|
end
|
@@ -3,7 +3,7 @@ module ActiveScaffold
|
|
3
3
|
module ListColumnHelpers
|
4
4
|
def active_scaffold_column_active_storage_has_one(record, column)
|
5
5
|
attachment = record.send(column.name.to_s)
|
6
|
-
attachment.attached? ? link_for_attachment(attachment) : nil
|
6
|
+
attachment.attached? ? link_for_attachment(attachment, column) : nil
|
7
7
|
end
|
8
8
|
|
9
9
|
def active_scaffold_column_active_storage_has_many(record, column)
|
@@ -12,7 +12,7 @@ module ActiveScaffold
|
|
12
12
|
|
13
13
|
attachments = active_storage_files.attachments
|
14
14
|
if attachments.size <= 3 # Lets display up to three links, otherwise just show the count.
|
15
|
-
links = attachments.map { |attachment| link_for_attachment(attachment) }
|
15
|
+
links = attachments.map { |attachment| link_for_attachment(attachment, column) }
|
16
16
|
safe_join links, association_join_text(column)
|
17
17
|
else
|
18
18
|
pluralize attachments.size, column.name.to_s
|
@@ -21,10 +21,10 @@ module ActiveScaffold
|
|
21
21
|
|
22
22
|
private
|
23
23
|
|
24
|
-
def link_for_attachment(attachment)
|
24
|
+
def link_for_attachment(attachment, column)
|
25
25
|
variant = column.options[:thumb] || ActiveScaffold::Bridges::ActiveStorage::ActiveStorageBridgeHelpers.thumbnail_variant
|
26
26
|
content =
|
27
|
-
if variant && attachment.variable?
|
27
|
+
if variant && attachment.variable? && column.options[:thumb] != false
|
28
28
|
image_tag(attachment.variant(variant))
|
29
29
|
else
|
30
30
|
attachment.filename
|
@@ -11,7 +11,9 @@ module ActiveScaffold::Actions
|
|
11
11
|
|
12
12
|
def deleted
|
13
13
|
query = PaperTrail::Version.destroys.where(:item_type => active_scaffold_config.model)
|
14
|
-
|
14
|
+
if nested? && nested.child_association&.belongs_to? && PaperTrail::Version.respond_to?(:where_object)
|
15
|
+
query = query.where_object(nested.child_association.foreign_key => nested.parent_id)
|
16
|
+
end
|
15
17
|
pager = Paginator.new(query.count, active_scaffold_config.list.per_page) do |offset, per_page|
|
16
18
|
query.offset(offset).limit(per_page).map(&:reify)
|
17
19
|
end
|
@@ -14,7 +14,9 @@ class ActiveScaffold::Bridges::RecordSelect
|
|
14
14
|
record = options.delete(:object)
|
15
15
|
if column.association&.singular?
|
16
16
|
multiple = column.options.dig(:html_options, :multiple)
|
17
|
-
active_scaffold_record_select(record, column, options, record.send(column.name), multiple)
|
17
|
+
html = active_scaffold_record_select(record, column, options, record.send(column.name), multiple)
|
18
|
+
html << active_scaffold_new_record_subform(column, record, options) if column.options[:add_new]
|
19
|
+
html
|
18
20
|
elsif column.association&.collection?
|
19
21
|
active_scaffold_record_select(record, column, options, record.send(column.name), true)
|
20
22
|
else
|
@@ -12,13 +12,10 @@ module ActiveScaffold::DataStructures::Association
|
|
12
12
|
|
13
13
|
def klass(record = nil)
|
14
14
|
if polymorphic?
|
15
|
-
record&.send(foreign_type)&.
|
15
|
+
record&.send(foreign_type)&.safe_constantize
|
16
16
|
else
|
17
17
|
@association.klass
|
18
18
|
end
|
19
|
-
rescue NameError => e
|
20
|
-
Rails.logger.warn "#{e.message}\n#{e.backtrace.join("\n")}"
|
21
|
-
nil
|
22
19
|
end
|
23
20
|
|
24
21
|
def belongs_to?
|
@@ -66,6 +66,10 @@ module ActiveScaffold::DataStructures
|
|
66
66
|
def sorted?(*)
|
67
67
|
false
|
68
68
|
end
|
69
|
+
|
70
|
+
def match_model?(model)
|
71
|
+
false
|
72
|
+
end
|
69
73
|
end
|
70
74
|
|
71
75
|
class NestedInfoAssociation < NestedInfo
|
@@ -100,6 +104,14 @@ module ActiveScaffold::DataStructures
|
|
100
104
|
association.through?
|
101
105
|
end
|
102
106
|
|
107
|
+
def match_model?(model)
|
108
|
+
if association.polymorphic?
|
109
|
+
child_association&.inverse_klass == model
|
110
|
+
else
|
111
|
+
association.klass == model
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
103
115
|
def sorted?(chain)
|
104
116
|
default_sorting(chain).present?
|
105
117
|
end
|
@@ -409,9 +409,9 @@ module ActiveScaffold
|
|
409
409
|
params_hash active_scaffold_embedded_params[:conditions]
|
410
410
|
end
|
411
411
|
|
412
|
-
def all_conditions
|
412
|
+
def all_conditions(include_id_condition = true)
|
413
413
|
[
|
414
|
-
id_condition,
|
414
|
+
(id_condition if include_id_condition), # for list with id (e.g. /users/:id/index)
|
415
415
|
active_scaffold_conditions, # from the search modules
|
416
416
|
conditions_for_collection, # from the dev
|
417
417
|
conditions_from_params, # from the parameters (e.g. /users/list?first_name=Fred)
|
@@ -444,9 +444,11 @@ module ActiveScaffold
|
|
444
444
|
def finder_options(options = {})
|
445
445
|
search_conditions = all_conditions
|
446
446
|
|
447
|
+
sorting = options[:sorting]&.clause((grouped_columns_calculations if grouped_search?))
|
448
|
+
sorting = sorting.map(&Arel.method(:sql)) if sorting && active_scaffold_config.active_record?
|
447
449
|
# create a general-use options array that's compatible with Rails finders
|
448
450
|
finder_options = {
|
449
|
-
:reorder =>
|
451
|
+
:reorder => sorting,
|
450
452
|
:conditions => search_conditions
|
451
453
|
}
|
452
454
|
if active_scaffold_config.mongoid?
|
@@ -519,8 +521,8 @@ module ActiveScaffold
|
|
519
521
|
@last_modified = query.maximum(:updated_at)
|
520
522
|
end
|
521
523
|
|
522
|
-
def calculate_query
|
523
|
-
conditions = all_conditions
|
524
|
+
def calculate_query(id_condition = true)
|
525
|
+
conditions = all_conditions(id_condition)
|
524
526
|
includes = active_scaffold_config.list.count_includes
|
525
527
|
includes ||= active_scaffold_references if conditions.present?
|
526
528
|
left_joins = active_scaffold_outer_joins
|
@@ -180,6 +180,17 @@ module ActiveScaffold
|
|
180
180
|
end
|
181
181
|
end
|
182
182
|
end
|
183
|
+
|
184
|
+
def save_record_to_association(record, association, value, reverse = nil)
|
185
|
+
return unless association
|
186
|
+
if association.collection?
|
187
|
+
record.association(association.name).target << value
|
188
|
+
elsif reverse&.belongs_to?
|
189
|
+
value.send("#{reverse.name}=", record)
|
190
|
+
else
|
191
|
+
record.send("#{association.name}=", value)
|
192
|
+
end
|
193
|
+
end
|
183
194
|
end
|
184
195
|
end
|
185
196
|
end
|
@@ -71,9 +71,9 @@ module ActiveScaffold
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
def active_scaffold_subform_attributes(column, column_css_class = nil)
|
74
|
+
def active_scaffold_subform_attributes(column, column_css_class = nil, klass = nil)
|
75
75
|
{
|
76
|
-
:class => "sub-form #{active_scaffold_config_for(column.association.klass).subform.layout}-sub-form #{column_css_class} #{column.name}-sub-form",
|
76
|
+
:class => "sub-form #{active_scaffold_config_for(klass || column.association.klass).subform.layout}-sub-form #{column_css_class} #{column.name}-sub-form",
|
77
77
|
:id => sub_form_id(:association => column.name)
|
78
78
|
}
|
79
79
|
end
|
@@ -308,17 +308,39 @@ module ActiveScaffold
|
|
308
308
|
html
|
309
309
|
end
|
310
310
|
|
311
|
-
def active_scaffold_new_record_subform(column, record, html_options)
|
312
|
-
|
311
|
+
def active_scaffold_new_record_subform(column, record, html_options, new_record_attributes: nil, locals: {}, skip_link: false) # rubocop:disable Metrics/ParameterLists
|
312
|
+
klass =
|
313
|
+
if column.association.polymorphic? && column.association.belongs_to?
|
314
|
+
type = record.send(column.association.foreign_type)
|
315
|
+
column.association.klass(record) if type.present? && (column.options[:add_new] == true || type.in?(column.options[:add_new]))
|
316
|
+
else
|
317
|
+
column.association.klass
|
318
|
+
end
|
319
|
+
return content_tag(:div, '') unless klass
|
320
|
+
subform_attrs = active_scaffold_subform_attributes(column, nil, klass)
|
321
|
+
if record.send(column.name)&.new_record?
|
322
|
+
new_record = record.send(column.name)
|
323
|
+
else
|
324
|
+
subform_attrs[:style] = 'display: none'
|
325
|
+
end
|
326
|
+
subform_attrs[:class] << ' optional'
|
313
327
|
scope = html_options[:name].scan(/record(.*)\[#{column.name}\]/).dig(0, 0)
|
314
|
-
new_record
|
315
|
-
|
328
|
+
new_record ||= klass.new(new_record_attributes)
|
329
|
+
locals = locals.reverse_merge(column: column, parent_record: record, associated: [], show_blank_record: new_record, scope: scope)
|
330
|
+
subform = render(partial: subform_partial_for_column(column, klass), locals: locals)
|
331
|
+
if column.options[:hide_subgroups]
|
332
|
+
toggable_id = "#{sub_form_id(association: column.name, id: record.id || generated_id(record) || 99_999_999_999)}-div"
|
333
|
+
subform << link_to_visibility_toggle(toggable_id, default_visible: false)
|
334
|
+
end
|
316
335
|
html = content_tag(:div, subform, subform_attrs)
|
336
|
+
return html if skip_link
|
317
337
|
html << active_scaffold_show_new_subform_link(column, record, html_options[:id], subform_attrs[:id])
|
318
338
|
end
|
319
339
|
|
320
340
|
def active_scaffold_show_new_subform_link(column, record, select_id, subform_id)
|
321
|
-
|
341
|
+
data = {select_id: select_id, subform_id: subform_id, subform_text: as_(:add_existing), select_text: as_(:create_new)}
|
342
|
+
label = data[record.send(column.name)&.new_record? ? :subform_text : :select_text]
|
343
|
+
link_to(label, '#', data: data, class: 'show-new-subform')
|
322
344
|
end
|
323
345
|
|
324
346
|
def active_scaffold_file_with_remove_link(column, options, content, remove_file_prefix, controls_class, &block) # rubocop:disable Metrics/ParameterLists
|
@@ -469,20 +491,35 @@ module ActiveScaffold
|
|
469
491
|
active_scaffold_enum_options(column, record)
|
470
492
|
end
|
471
493
|
|
472
|
-
selected = record.send(column.association.name)
|
494
|
+
selected = record.send(column.association.name) if column.association
|
495
|
+
selected_id = selected&.id
|
473
496
|
if options.present?
|
497
|
+
if column.options[:add_new]
|
498
|
+
html_options[:data] ||= {}
|
499
|
+
html_options[:data][:subform_id] = active_scaffold_subform_attributes(column)[:id]
|
500
|
+
radio_html_options = html_options.merge(class: html_options[:class] + ' hide-new-subform')
|
501
|
+
else
|
502
|
+
radio_html_options = html_options
|
503
|
+
end
|
474
504
|
radios = options.map do |option|
|
475
|
-
active_scaffold_radio_option(option,
|
505
|
+
active_scaffold_radio_option(option, selected_id, column, radio_html_options)
|
476
506
|
end
|
477
507
|
if column.options[:include_blank]
|
478
508
|
label = column.options[:include_blank]
|
479
509
|
label = as_(column.options[:include_blank]) if column.options[:include_blank].is_a?(Symbol)
|
480
510
|
radios.prepend content_tag(:label, radio_button(:record, column.name, '', html_options.merge(id: nil)) + label)
|
481
511
|
end
|
512
|
+
if column.options[:add_new]
|
513
|
+
create_new_button = radio_button_tag(html_options[:name], '', selected&.new_record?, html_options.merge(id: nil, class: html_options[:class] + ' show-new-subform'))
|
514
|
+
radios << content_tag(:label, create_new_button << as_(:create_new)) <<
|
515
|
+
active_scaffold_new_record_subform(column, record, html_options, skip_link: true)
|
516
|
+
end
|
482
517
|
safe_join radios
|
483
518
|
else
|
484
|
-
content_tag(:span, as_(:no_options), :class => "#{html_options[:class]} no-options", :id => html_options[:id])
|
485
|
-
|
519
|
+
html = content_tag(:span, as_(:no_options), :class => "#{html_options[:class]} no-options", :id => html_options[:id])
|
520
|
+
html << hidden_field_tag(html_options[:name], '', :id => nil)
|
521
|
+
html << active_scaffold_new_record_subform(column, record, html_options) if column.options[:add_new]
|
522
|
+
html
|
486
523
|
end
|
487
524
|
end
|
488
525
|
|
@@ -628,8 +665,8 @@ module ActiveScaffold
|
|
628
665
|
end
|
629
666
|
alias override_input? override_input
|
630
667
|
|
631
|
-
def subform_partial_for_column(column)
|
632
|
-
subform_partial = "#{active_scaffold_config_for(column.association.klass).subform.layout}_subform"
|
668
|
+
def subform_partial_for_column(column, klass = nil)
|
669
|
+
subform_partial = "#{column.options[:layout] || active_scaffold_config_for(klass || column.association.klass).subform.layout}_subform"
|
633
670
|
override_subform_partial(column, subform_partial) || subform_partial
|
634
671
|
end
|
635
672
|
|
@@ -427,16 +427,16 @@ module ActiveScaffold
|
|
427
427
|
|
428
428
|
# CALCULATIONS
|
429
429
|
|
430
|
-
def column_calculation(column)
|
430
|
+
def column_calculation(column, id_condition: true)
|
431
431
|
if column.calculate.instance_of? Proc
|
432
432
|
column.calculate.call(@records)
|
433
433
|
else
|
434
|
-
calculate_query.calculate(column.calculate, column.name)
|
434
|
+
calculate_query(id_condition).calculate(column.calculate, column.name)
|
435
435
|
end
|
436
436
|
end
|
437
437
|
|
438
|
-
def render_column_calculation(column)
|
439
|
-
calculation = column_calculation(column)
|
438
|
+
def render_column_calculation(column, id_condition: true)
|
439
|
+
calculation = column_calculation(column, id_condition: id_condition)
|
440
440
|
override_formatter = "render_#{column.name}_#{column.calculate.is_a?(Proc) ? :calculate : column.calculate}"
|
441
441
|
calculation = send(override_formatter, calculation) if respond_to? override_formatter
|
442
442
|
format_column_calculation(column, calculation)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_scaffold
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.6.0.
|
4
|
+
version: 3.6.0.rc2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Many, see README
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|