active_scaffold 3.6.0.rc1 → 3.6.2

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.rdoc +26 -0
  3. data/README.md +10 -9
  4. data/app/assets/javascripts/jquery/active_scaffold.js +48 -14
  5. data/app/assets/stylesheets/active_scaffold_layout.css +1 -1
  6. data/app/views/active_scaffold_overrides/_form_association.html.erb +2 -1
  7. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +22 -6
  8. data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +3 -3
  9. data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +2 -1
  10. data/app/views/active_scaffold_overrides/_vertical_subform.html.erb +2 -2
  11. data/app/views/active_scaffold_overrides/update_column.js.erb +1 -1
  12. data/lib/active_scaffold/actions/core.rb +5 -2
  13. data/lib/active_scaffold/actions/list.rb +1 -1
  14. data/lib/active_scaffold/actions/nested.rb +1 -1
  15. data/lib/active_scaffold/actions/subform.rb +12 -6
  16. data/lib/active_scaffold/attribute_params.rb +6 -16
  17. data/lib/active_scaffold/bridges/active_storage/active_storage_bridge.rb +1 -0
  18. data/lib/active_scaffold/bridges/active_storage/list_ui.rb +4 -4
  19. data/lib/active_scaffold/bridges/bitfields.rb +1 -1
  20. data/lib/active_scaffold/bridges/bitfields/list_ui.rb +19 -0
  21. data/lib/active_scaffold/bridges/paper_trail/actions.rb +3 -1
  22. data/lib/active_scaffold/bridges/record_select/helpers.rb +3 -1
  23. data/lib/active_scaffold/config/list.rb +1 -1
  24. data/lib/active_scaffold/data_structures/action_columns.rb +1 -1
  25. data/lib/active_scaffold/data_structures/association/abstract.rb +1 -4
  26. data/lib/active_scaffold/data_structures/nested_info.rb +14 -2
  27. data/lib/active_scaffold/extensions/action_view_rendering.rb +66 -25
  28. data/lib/active_scaffold/extensions/localize.rb +1 -1
  29. data/lib/active_scaffold/finder.rb +7 -5
  30. data/lib/active_scaffold/helpers/controller_helpers.rb +11 -0
  31. data/lib/active_scaffold/helpers/form_column_helpers.rb +52 -15
  32. data/lib/active_scaffold/helpers/list_column_helpers.rb +10 -6
  33. data/lib/active_scaffold/helpers/search_column_helpers.rb +14 -7
  34. data/lib/active_scaffold/helpers/view_helpers.rb +1 -1
  35. data/lib/active_scaffold/tableless.rb +16 -2
  36. data/lib/active_scaffold/version.rb +1 -1
  37. data/lib/generators/active_scaffold/install_generator.rb +51 -3
  38. data/test/data_structures/action_columns_test.rb +1 -1
  39. data/test/extensions/action_view_rendering_test.rb +20 -0
  40. data/test/misc/constraints_test.rb +1 -1
  41. data/test/misc/tableless_test.rb +8 -0
  42. data/test/mock_app/app/controllers/people_controller.rb +2 -0
  43. data/test/mock_app/app/controllers/roles_controller.rb +4 -0
  44. data/test/mock_app/app/views/active_scaffold_overrides/_form.html.erb +2 -0
  45. data/test/mock_app/app/views/active_scaffold_overrides/list.html.erb +2 -0
  46. data/test/mock_app/app/views/people/_first_name_form_column.html.erb +2 -0
  47. data/test/mock_app/app/views/people/_form.html.erb +2 -0
  48. data/test/mock_app/app/views/people/list.html.erb +2 -0
  49. data/test/test_helper.rb +2 -2
  50. metadata +25 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c9ea6700cdf564c8c6712df6f538251a00ab77d708a1cb6ddbaf1522f7f3c82
4
- data.tar.gz: c71eb0579b0671fedf08104b51237f260b43ff5d6aa090c98a3ffffde943f31d
3
+ metadata.gz: d35f441c2847444fd7e591e529085d3613774e19b0dc2b87a6a7e046e39eb95a
4
+ data.tar.gz: 5028894d44f4ed52a7e3cf7f4f92d38d86c48221815ccbb2f28396ecbda447ec
5
5
  SHA512:
6
- metadata.gz: dd0cb52f16d6a75545d491388cbde13f99db60cf0c951db73df00ce77dac5fdd09573331b510fcd2e9a2f637c539e754c8fab0838d5709e22fd8abb11128d9ae
7
- data.tar.gz: b0b4558cf821b84701e42f730eb6699c49a82e3c1e70a6f570d6dd99abbb599f783dded394b94bd7aa96db89d4cd4a23e848480239d4256a5e3f596812ba4e17
6
+ metadata.gz: 0d92dc0e4e6933a0849269191d4b273083e6914606a3198ccd132754f1ef4607434d7ef5cf6e51268aa34c7c926613f75214aa5b1ac961a0784ca5b8a34133c3
7
+ data.tar.gz: b87a086b26a98a148a485fe9af2c55e483dbbb82a1ccc4231d7e468a4f5265022bef3899e05ae6e6af1fef63295456f43f2456ba17043f42e42a7a796bcdffde
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,29 @@
1
+ = 3.6.2
2
+ - Fix count query when association's primary key is string
3
+ - Fix unauthorized_columns and constraint_columns with threadsafe enabled
4
+ - Fix changing list.sorting and column.sort_by per request when threadsafe is enabled
5
+
6
+ = 3.6.1
7
+ - Display group cols vertically when subform layout is vertical
8
+ - Fix html attributes for input datetime on field search, when jquery ui is not used
9
+ - Fix constraint columns for nested list on through assocaitions
10
+ - Support rails 6.1
11
+
12
+ = 3.6.0
13
+ - Fix i18n at ruby 3.0.0
14
+ - Add list helper for bitfield column, so it display labels of selected checkboxes in list
15
+ - Support rails 6.0
16
+
17
+ = 3.6.0.rc2
18
+ - Fix subform crud in subform subgroup when controller is embedded
19
+ - Fix sorting for mongoid models, broken in 3.6.0.rc1
20
+ - Improve add_new option, allow to change subform columns (with helper override calling super and add columns to locals argument)
21
+ - Support add_new option for record_select or radio form_ui
22
+ - 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)
23
+ - Support description for columns displayed as subform
24
+ - Don't mess with history if current page is not using activescaffold when is loaded
25
+ - Fix changing sort_by per request when threadsafe is enabled
26
+
1
27
  = 3.6.0.rc1
2
28
  - Cleanup: deprecate ActiveScaffold.set_defaults for ActiveScaffold.defaults, rename some setters
3
29
  - Fix adding new action links on request with threadsafety enabled
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
+
1
2
  Overview
2
3
  ========
3
- [![Build status](https://travis-ci.org/activescaffold/active_scaffold.svg?branch=master)](https://travis-ci.org/activescaffold/active_scaffold)
4
+ [![Build status](https://travis-ci.com/activescaffold/active_scaffold.svg?branch=master)](https://travis-ci.com/activescaffold/active_scaffold)
4
5
  [![Code Climate](https://codeclimate.com/github/activescaffold/active_scaffold/badges/gpa.svg)](https://codeclimate.com/github/activescaffold/active_scaffold)
5
6
  [![Test Coverage](https://codeclimate.com/github/activescaffold/active_scaffold/badges/coverage.svg)](https://codeclimate.com/github/activescaffold/active_scaffold)
6
7
  [![Dependency Status](https://gemnasium.com/activescaffold/active_scaffold.svg)](https://gemnasium.com/activescaffold/active_scaffold)
@@ -8,13 +9,13 @@ Overview
8
9
  [![Inline docs](https://inch-ci.org/github/activescaffold/active_scaffold.svg?branch=master)](https://inch-ci.org/github/activescaffold/active_scaffold)
9
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
10
11
 
11
- ActiveScaffold provides a quick and powerful user interfaces for CRUD (create, read, update, delete) operations for Rails applications. It offers additonal features including searching, pagination & layout control. Rails >= 4.2.0 is supported, ruby >= 2.3 required.
12
+ ActiveScaffold provides a quick and powerful user interfaces for CRUD (create, read, update, delete) operations for Rails applications. It offers additonal features including searching, pagination & layout control. Rails >= 4.2.0 and Rails <= 6.1 is supported, ruby >= 2.3 required.
12
13
 
13
14
  Branch Details
14
15
  --------------
15
- 3-5-stable supports rails >= 4.0.x and ruby >= 2.0.0
16
- 3-4-stable supports rails >= 3.2.x and ruby >= 1.9.3
17
- 3-3-stable supports rails >= 3.2.x and ruby >= 1.8
16
+ 3-5-stable supports rails >= 4.0.x and <= 5.1.x, and ruby >= 2.0.0
17
+ 3-4-stable supports rails >= 3.2.x and <= 4.2.x, and ruby >= 1.9.3
18
+ 3-3-stable supports rails 3.2.x and ruby >= 1.8
18
19
  rails-3.2 supports Rails 3.1 & 3.2, and is the current source of the 3.2.x line of gems.
19
20
 
20
21
  Quick Start
@@ -25,12 +26,12 @@ Added to Gemfile
25
26
 
26
27
  gem 'active_scaffold'
27
28
 
28
- For rails >= 5.1, add jquery to application.js before rails-ujs (with jquery-rails), or load jquery in your layout before application.js using CDN (e.g. jquery-rails-cdn). You can replace rails-ujs with jquery_ujs, although rails-ujs should work (never load both).
29
-
30
- //= require jquery
29
+ For rails >= 5.1, add jquery-rails to Gemfile, and install generator will jquery to application.js before rails-ujs. Also it's possible to load jquery in your layout before application.js using CDN (e.g. jquery-rails-cdn). You can replace rails-ujs with jquery_ujs, although rails-ujs should work (never load both).
31
30
 
32
31
  gem 'jquery-rails'
33
32
 
33
+ For rails >= 6.0, installer generator will create app/assets/javascripts/application.js, add it to assets.precompile array and add javascript_include_tag in layout, as ActiveScaffold doesn't work with webpack yet. Jquery may be loaded by packs or assets pipeline.
34
+
34
35
  Run the following commands, for rails 4.2
35
36
 
36
37
  bundle install
@@ -39,7 +40,7 @@ Run the following commands, for rails 4.2
39
40
  rails g active_scaffold:resource Model [attrs]
40
41
  bundle exec rake db:migrate
41
42
 
42
- Or run the following commands, for rails 5
43
+ Or run the following commands, for rails >= 5
43
44
 
44
45
  bundle install
45
46
  rails g active_scaffold:install
@@ -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
- select = line.find('#' + $this.data('select-id')),
330
- subform = line.find('#' + $this.data('subform-id'));
331
- if (select.is(':visible')) {
332
- select.hide().prop('disabled', true);
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
- $this.html($this.data('select-text'));
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('.form-element select + .sub-form').each(function() {
540
- jQuery("input:enabled,select:enabled,textarea:enabled", this).prop('disabled', true);
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) {
@@ -1430,7 +1464,7 @@ ActiveScaffold.ActionLink.Table = ActiveScaffold.ActionLink.Abstract.extend({
1430
1464
  else {
1431
1465
  throw 'Unknown position "' + this.position + '"'
1432
1466
  }
1433
- ActiveScaffold.highlight(this.adapter.find('td').first().children());
1467
+ ActiveScaffold.highlight(this.adapter.find('td').first().children().not('script'));
1434
1468
  ActiveScaffold.focus_first_element_of_form(this.adapter);
1435
1469
  }
1436
1470
  });
@@ -841,7 +841,7 @@ clear: left;
841
841
  padding: 5px 0;
842
842
  padding-left: 5px;
843
843
  }
844
- .active-scaffold .form-element select + .sub-form {
844
+ .active-scaffold .form-element .sub-form.optional {
845
845
  float: none;
846
846
  }
847
847
  .active-scaffold .form-element .show-new-subform {
@@ -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, {:default_visible => !column.collapsed}) -%>
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 config.subform.layout == :vertical
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
- <% config.subform.columns.each_column(for: record.class, crud_type: :read, flatten: flatten) do |column| %>
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
@@ -82,10 +84,24 @@
82
84
 
83
85
  <% columns_groups.each do |columns_group| %>
84
86
  <%= content_tag row_tag, :class => 'associated-record' do %>
85
- <%= content_tag column_tag, :colspan => (columns_length if column_tag == :td) do %>
86
- <% columns_group.each_column(for: record.class, crud_type: :read, flatten: true) do |col| %>
87
- <%= active_scaffold_render_subform_column(col, scope, crud_type, readonly, true, record) %>
88
- <% end %>
87
+ <% if layout == :vertical %>
88
+ <% columns_group.each_column(for: record.class, crud_type: :read, flatten: true) do |col| %>
89
+ <%
90
+ col_class = default_col_class.clone
91
+ col_class << 'required' if col.required?
92
+ col_class << col.css_class unless col.css_class.nil? || col.css_class.is_a?(Proc)
93
+ col_class << 'hidden' if column_renders_as(col) == :hidden
94
+ %>
95
+ <%= content_tag column_tag, :class => col_class, :colspan => (columns_length if column_tag == :td) do %>
96
+ <%= active_scaffold_render_subform_column(col, scope, crud_type, readonly, false, record) %>
97
+ <% end %>
98
+ <% end %>
99
+ <% else %>
100
+ <%= content_tag column_tag, :colspan => (columns_length if column_tag == :td) do %>
101
+ <% columns_group.each_column(for: record.class, crud_type: :read, flatten: true) do |col| %>
102
+ <%= active_scaffold_render_subform_column(col, scope, crud_type, readonly, true, record) %>
103
+ <% end %>
104
+ <% end %>
89
105
  <% end %>
90
106
  <% end %>
91
107
  <% end %>
@@ -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 :partial => 'horizontal_subform_header', :locals => {:parent_record => parent_record, :record_class => header_record_class, :parent_column => column} %>
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 :partial => 'form_association_record', :collection => associated, :locals => {:scope => scope, :parent_record => parent_record, :column => column} %>
8
- <%= render :partial => 'form_association_record', :object => show_blank_record, :locals => {:scope => scope, :parent_record => parent_record, :column => column, :locked => true, :index => associated.size} if show_blank_record %>
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.each_column(for: record_class, crud_type: :read) do |column|
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 :partial => 'form_association_record', :collection => associated, :locals => {:scope => scope, :parent_record => parent_record, :column => column} %>
3
- <%= render :partial => 'form_association_record', :object => show_blank_record, :locals => {:scope => scope, :parent_record => parent_record, :column => column, :locked => true, :index => associated.size} if show_blank_record %>
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
- setup_parent(@record) if main_form_controller && @scope
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
- build_options = sti_nested_build_options(relation.klass) if nested? && nested.plural_association?
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
 
@@ -161,7 +161,7 @@ module ActiveScaffold::Actions
161
161
 
162
162
  def count_query_on_association_class(column)
163
163
  key = column.association.primary_key || :id
164
- query = column.association.klass.where(column.association.foreign_key => @records.map(&key))
164
+ query = column.association.klass.where(column.association.foreign_key => @records.map(&key.to_sym))
165
165
  if column.association.as
166
166
  query.where!(column.association.reverse_association.foreign_type => active_scaffold_config.model.name)
167
167
  end
@@ -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.association && nested.association.klass == active_scaffold_config.model
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 do_edit_associated
13
- @parent_record = params[:id].nil? ? new_model : find_if_allowed(params[:id], :update)
14
- if @parent_record.new_record?
15
- apply_constraints_to_record @parent_record
16
- create_association_with_parent @parent_record if nested?
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(column.association.klass).subform.columns
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
- klass = column.association.klass
246
- (column.association.collection? && !column.show_blank_record?(current)) || !attributes_hash_is_empty?(params, klass)
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 = association.klass.new
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