active_scaffold 3.6.0.pre → 3.6.0.rc1
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 → CHANGELOG.rdoc} +39 -0
- data/app/assets/javascripts/active_scaffold.js.erb +0 -1
- data/app/assets/javascripts/jquery/active_scaffold.js +35 -4
- data/app/assets/stylesheets/active_scaffold_colors.scss +1 -1
- data/app/assets/stylesheets/active_scaffold_layout.css +52 -29
- data/app/views/active_scaffold_overrides/_list_header.html.erb +5 -7
- data/app/views/active_scaffold_overrides/_list_record.html.erb +4 -5
- data/app/views/active_scaffold_overrides/_list_with_header.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_refresh_list.js.erb +4 -0
- data/config/locales/de.yml +2 -1
- data/config/locales/en.yml +1 -0
- data/config/locales/es.yml +1 -0
- data/config/locales/fr.yml +2 -1
- data/config/locales/hu.yml +1 -0
- data/config/locales/ja.yml +1 -0
- data/config/locales/ru.yml +1 -0
- data/lib/active_scaffold.rb +8 -3
- data/lib/active_scaffold/actions/common_search.rb +11 -8
- data/lib/active_scaffold/actions/core.rb +79 -51
- data/lib/active_scaffold/actions/create.rb +27 -27
- data/lib/active_scaffold/actions/delete.rb +1 -1
- data/lib/active_scaffold/actions/field_search.rb +52 -42
- data/lib/active_scaffold/actions/list.rb +106 -23
- data/lib/active_scaffold/actions/nested.rb +59 -42
- data/lib/active_scaffold/actions/show.rb +3 -3
- data/lib/active_scaffold/actions/subform.rb +9 -16
- data/lib/active_scaffold/actions/update.rb +95 -77
- data/lib/active_scaffold/attribute_params.rb +93 -68
- data/lib/active_scaffold/bridges/active_storage.rb +6 -0
- data/lib/active_scaffold/bridges/active_storage/active_storage_bridge.rb +33 -0
- data/lib/active_scaffold/bridges/active_storage/active_storage_helpers.rb +54 -0
- data/lib/active_scaffold/bridges/active_storage/form_ui.rb +22 -0
- data/lib/active_scaffold/bridges/active_storage/list_ui.rb +36 -0
- data/lib/active_scaffold/bridges/bitfields.rb +1 -0
- data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +12 -15
- data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +6 -0
- data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +2 -2
- data/lib/active_scaffold/bridges/date_picker/helper.rb +46 -41
- data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +1 -1
- data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +2 -2
- data/lib/active_scaffold/bridges/file_column/form_ui.rb +3 -3
- data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +3 -1
- data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +2 -2
- data/lib/active_scaffold/bridges/record_select/helpers.rb +3 -7
- data/lib/active_scaffold/bridges/shared/date_bridge.rb +19 -18
- data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +3 -1
- data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +20 -3
- data/lib/active_scaffold/config/base.rb +58 -34
- data/lib/active_scaffold/config/core.rb +31 -12
- data/lib/active_scaffold/config/delete.rb +12 -1
- data/lib/active_scaffold/config/list.rb +17 -7
- data/lib/active_scaffold/config/mark.rb +1 -1
- data/lib/active_scaffold/configurable.rb +5 -3
- data/lib/active_scaffold/constraints.rb +21 -19
- data/lib/active_scaffold/core.rb +35 -26
- data/lib/active_scaffold/data_structures/action_columns.rb +1 -1
- data/lib/active_scaffold/data_structures/action_link.rb +34 -16
- data/lib/active_scaffold/data_structures/action_links.rb +9 -11
- data/lib/active_scaffold/data_structures/association/abstract.rb +35 -13
- data/lib/active_scaffold/data_structures/association/active_mongoid.rb +2 -6
- data/lib/active_scaffold/data_structures/association/active_record.rb +5 -1
- data/lib/active_scaffold/data_structures/association/mongoid.rb +0 -3
- data/lib/active_scaffold/data_structures/column.rb +49 -58
- data/lib/active_scaffold/data_structures/columns.rb +3 -2
- data/lib/active_scaffold/data_structures/nested_info.rb +20 -18
- data/lib/active_scaffold/data_structures/sorting.rb +5 -0
- data/lib/active_scaffold/delayed_setup.rb +16 -6
- data/lib/active_scaffold/extensions/action_controller_rendering.rb +1 -1
- data/lib/active_scaffold/extensions/action_view_rendering.rb +34 -14
- data/lib/active_scaffold/extensions/cow_proxy.rb +50 -2
- data/lib/active_scaffold/extensions/localize.rb +3 -1
- data/lib/active_scaffold/extensions/routing_mapper.rb +2 -2
- data/lib/active_scaffold/extensions/to_label.rb +3 -2
- data/lib/active_scaffold/finder.rb +81 -46
- data/lib/active_scaffold/helpers/action_link_helpers.rb +47 -21
- data/lib/active_scaffold/helpers/association_helpers.rb +13 -11
- data/lib/active_scaffold/helpers/controller_helpers.rb +14 -11
- data/lib/active_scaffold/helpers/form_column_helpers.rb +133 -99
- data/lib/active_scaffold/helpers/human_condition_helpers.rb +1 -1
- data/lib/active_scaffold/helpers/id_helpers.rb +4 -0
- data/lib/active_scaffold/helpers/list_column_helpers.rb +76 -49
- data/lib/active_scaffold/helpers/pagination_helpers.rb +2 -2
- data/lib/active_scaffold/helpers/search_column_helpers.rb +25 -30
- data/lib/active_scaffold/helpers/show_column_helpers.rb +3 -5
- data/lib/active_scaffold/helpers/view_helpers.rb +31 -22
- data/lib/active_scaffold/orm_checks.rb +2 -2
- data/lib/active_scaffold/paginator.rb +1 -3
- data/lib/active_scaffold/registry.rb +11 -0
- data/lib/active_scaffold/responds_to_parent.rb +6 -5
- data/lib/active_scaffold/tableless.rb +6 -8
- data/lib/active_scaffold/version.rb +1 -1
- data/shoulda_macros/macros.rb +3 -1
- data/test/bridges/paperclip_test.rb +1 -1
- data/test/company.rb +2 -2
- data/test/data_structures/action_columns_test.rb +2 -2
- data/test/data_structures/column_test.rb +3 -6
- data/test/data_structures/columns_test.rb +2 -2
- data/test/extensions/active_record_test.rb +4 -4
- data/test/extensions/routing_mapper_test.rb +2 -2
- data/test/helpers/list_column_helpers_test.rb +3 -1
- data/test/misc/active_record_permissions_test.rb +2 -2
- data/test/misc/attribute_params_test.rb +4 -0
- data/test/misc/configurable_test.rb +10 -10
- data/test/misc/convert_numbers_format_test.rb +4 -0
- data/test/mock_app/app/assets/config/manifest.js +0 -0
- data/test/mock_app/app/controllers/cars_controller.rb +1 -0
- data/test/mock_app/app/controllers/people_controller.rb +3 -1
- data/test/mock_app/config/application.rb +1 -0
- data/test/mock_app/config/routes.rb +4 -1
- data/test/mock_app/db/schema.rb +2 -0
- data/test/performance/list_cars_performance_test.rb +34 -0
- data/test/performance/list_people_performance_test.rb +31 -0
- data/test/performance_test_help.rb +3 -0
- data/test/test_helper.rb +2 -1
- metadata +22 -12
- data/app/assets/javascripts/prototype/rico_corner.js +0 -370
- data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +0 -5
@@ -16,11 +16,8 @@ module ActiveScaffold
|
|
16
16
|
def association_options_find(association, conditions = nil, klass = nil, record = nil)
|
17
17
|
if klass.nil? && association.polymorphic?
|
18
18
|
class_name = record.send(association.foreign_type) if association.belongs_to?
|
19
|
-
if class_name.
|
20
|
-
|
21
|
-
else
|
22
|
-
return []
|
23
|
-
end
|
19
|
+
return [] if class_name.blank?
|
20
|
+
klass = class_name.constantize
|
24
21
|
cache = !block_given?
|
25
22
|
else
|
26
23
|
cache = !block_given? && klass.nil?
|
@@ -37,7 +34,9 @@ module ActiveScaffold
|
|
37
34
|
relation = relation.includes(include_assoc[association.name]) if include_assoc
|
38
35
|
end
|
39
36
|
if column&.sort && column.sort&.dig(:sql)
|
40
|
-
|
37
|
+
# with threasafe enabled, column.sort[:sql] returns proxied strings and
|
38
|
+
# regexp capture won't work, which rails uses internally, so to_s is needed
|
39
|
+
relation = relation.order(Array(column.sort[:sql]).map(&:to_s))
|
41
40
|
end
|
42
41
|
relation = yield(relation) if block_given?
|
43
42
|
relation.to_a
|
@@ -45,7 +44,11 @@ module ActiveScaffold
|
|
45
44
|
end
|
46
45
|
|
47
46
|
def column_for_association(association, record)
|
48
|
-
active_scaffold_config_for(record.class).columns[association.name]
|
47
|
+
active_scaffold_config_for(record.class).columns[association.name]
|
48
|
+
rescue StandardError => e
|
49
|
+
message = "Error on config for #{record.class.name}:"
|
50
|
+
Rails.logger.warn "#{message}\n#{e.message}\n#{e.backtrace.join("\n")}"
|
51
|
+
nil
|
49
52
|
end
|
50
53
|
|
51
54
|
def association_klass_scoped(association, klass, record)
|
@@ -86,10 +89,9 @@ module ActiveScaffold
|
|
86
89
|
# Check association.name to specialize the conditions per-column.
|
87
90
|
def options_for_association_conditions(association, record = nil)
|
88
91
|
return nil if association.through?
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
end
|
92
|
+
return nil unless association.has_one? || association.has_many?
|
93
|
+
# Find only orphaned objects
|
94
|
+
{association.foreign_key => nil}
|
93
95
|
end
|
94
96
|
|
95
97
|
def record_select_params_for_add_existing(association, edit_associated_url_options, record)
|
@@ -2,15 +2,14 @@ module ActiveScaffold
|
|
2
2
|
module Helpers
|
3
3
|
module ControllerHelpers
|
4
4
|
def self.included(controller)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
5
|
+
return unless controller.respond_to? :helper_method
|
6
|
+
controller.class_eval do
|
7
|
+
helper_method :params_for, :conditions_from_params, :render_parent?,
|
8
|
+
:main_path_to_return, :render_parent_options,
|
9
|
+
:render_parent_action, :nested_singular_association?,
|
10
|
+
:main_form_controller, :build_associated,
|
11
|
+
:generate_temporary_id, :generated_id,
|
12
|
+
:active_scaffold_config_for
|
14
13
|
end
|
15
14
|
end
|
16
15
|
|
@@ -27,10 +26,14 @@ module ActiveScaffold
|
|
27
26
|
|
28
27
|
def generate_temporary_id(record = nil, generated_id = nil)
|
29
28
|
(generated_id || (Time.now.to_f * 1000).to_i.to_s).tap do |id|
|
30
|
-
|
29
|
+
cache_generated_id record, id
|
31
30
|
end
|
32
31
|
end
|
33
32
|
|
33
|
+
def cache_generated_id(record, generated_id)
|
34
|
+
(@temporary_ids ||= {})[record.class.name] = generated_id if record && generated_id
|
35
|
+
end
|
36
|
+
|
34
37
|
def generated_id(record)
|
35
38
|
@temporary_ids[record.class.name] if record && @temporary_ids
|
36
39
|
end
|
@@ -101,7 +104,7 @@ module ActiveScaffold
|
|
101
104
|
else
|
102
105
|
exclude_parameters = %i[utf8 associated_id]
|
103
106
|
parameters = {}
|
104
|
-
if params[:parent_scaffold] &&
|
107
|
+
if params[:parent_scaffold] && nested_singular_association?
|
105
108
|
parameters[:controller] = params[:parent_scaffold]
|
106
109
|
exclude_parameters.concat [nested.param_name, :association, :parent_scaffold]
|
107
110
|
# parameters[:eid] = params[:parent_scaffold] # not neeeded anymore?
|
@@ -16,47 +16,43 @@ module ActiveScaffold
|
|
16
16
|
# first, check if the dev has created an override for this specific field
|
17
17
|
if (method = override_form_field(column))
|
18
18
|
send(method, record, options)
|
19
|
+
|
19
20
|
# second, check if the dev has specified a valid form_ui for this column
|
20
21
|
elsif column.form_ui && (method = override_input(column.form_ui))
|
21
22
|
send(method, column, options)
|
22
|
-
|
23
|
-
|
24
|
-
if column.
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
if column.column.type == :string && options[:maxlength].blank?
|
46
|
-
options[:maxlength] = column.column.limit
|
47
|
-
options[:size] ||= options[:maxlength].to_i > 30 ? 30 : options[:maxlength]
|
48
|
-
end
|
49
|
-
options[:value] = format_number_value(record.send(column.name), column.options) if column.number?
|
50
|
-
text_field(:record, column.name, options.merge(column.options).except(:format))
|
51
|
-
end
|
23
|
+
|
24
|
+
elsif column.association
|
25
|
+
# if we get here, it's because the column has a form_ui but not one ActiveScaffold knows about.
|
26
|
+
raise "Unknown form_ui `#{column.form_ui}' for column `#{column.name}'" if column.form_ui
|
27
|
+
|
28
|
+
# its an association and nothing is specified, we will assume form_ui :select
|
29
|
+
active_scaffold_input_select(column, options)
|
30
|
+
|
31
|
+
elsif column.virtual?
|
32
|
+
options[:value] = format_number_value(record.send(column.name), column.options) if column.number?
|
33
|
+
active_scaffold_input_virtual(column, options)
|
34
|
+
|
35
|
+
elsif (method = override_input(column.column.type)) # regular model attribute column
|
36
|
+
# if we (or someone else) have created a custom render option for the column type, use that
|
37
|
+
send(method, column, options)
|
38
|
+
|
39
|
+
else # final ultimate fallback: use rails' generic input method
|
40
|
+
# for textual fields we pass different options
|
41
|
+
text_types = %i[text string integer float decimal]
|
42
|
+
options = active_scaffold_input_text_options(options) if text_types.include?(column.column.type)
|
43
|
+
if column.column.type == :string && options[:maxlength].blank?
|
44
|
+
options[:maxlength] = column.column.limit
|
45
|
+
options[:size] ||= options[:maxlength].to_i > 30 ? 30 : options[:maxlength]
|
52
46
|
end
|
47
|
+
options[:value] = format_number_value(record.send(column.name), column.options) if column.number?
|
48
|
+
text_field(:record, column.name, options.merge(column.options).except(:format))
|
53
49
|
end
|
54
50
|
rescue StandardError => e
|
55
51
|
logger.error "#{e.class.name}: #{e.message} -- on the ActiveScaffold column = :#{column.name} in #{controller.class}"
|
56
52
|
raise e
|
57
53
|
end
|
58
54
|
|
59
|
-
def active_scaffold_render_subform_column(column, scope, crud_type, readonly, add_class = false, record = nil)
|
55
|
+
def active_scaffold_render_subform_column(column, scope, crud_type, readonly, add_class = false, record = nil) # rubocop:disable Metrics/ParameterLists
|
60
56
|
if add_class
|
61
57
|
col_class = []
|
62
58
|
col_class << 'required' if column.required?
|
@@ -134,7 +130,7 @@ module ActiveScaffold
|
|
134
130
|
url_params = url_params.except(:parent_scaffold, :association, nested.param_name)
|
135
131
|
end
|
136
132
|
if scope
|
137
|
-
url_params[:parent_controller] ||= url_params[:controller].gsub(%r{
|
133
|
+
url_params[:parent_controller] ||= url_params[:controller].gsub(%r{^/}, '')
|
138
134
|
url_params[:controller] = subform_controller.controller_path
|
139
135
|
url_params[:scope] = scope
|
140
136
|
url_params[:parent_id] = params[:parent_id] || params[:id]
|
@@ -152,8 +148,8 @@ module ActiveScaffold
|
|
152
148
|
{}
|
153
149
|
end
|
154
150
|
|
155
|
-
def render_column(column, record, renders_as, scope = nil, only_value = false, col_class = nil)
|
156
|
-
if partial = override_form_field_partial(column)
|
151
|
+
def render_column(column, record, renders_as, scope = nil, only_value = false, col_class = nil) # rubocop:disable Metrics/ParameterLists
|
152
|
+
if (partial = override_form_field_partial(column))
|
157
153
|
render :partial => partial, :locals => {:column => column, :only_value => only_value, :scope => scope, :col_class => col_class, :record => record}
|
158
154
|
elsif renders_as == :field || override_form_field?(column)
|
159
155
|
form_attribute(column, record, scope, only_value, col_class)
|
@@ -179,12 +175,14 @@ module ActiveScaffold
|
|
179
175
|
else
|
180
176
|
field = active_scaffold_input_for column, scope, column_options
|
181
177
|
end
|
178
|
+
if field
|
179
|
+
field << loading_indicator_tag(:action => :render_field, :id => params[:id]) if column.update_columns
|
180
|
+
field << content_tag(:span, column.description, :class => 'description') if column.description.present?
|
181
|
+
end
|
182
182
|
|
183
183
|
content_tag :dl, attributes do
|
184
|
-
|
185
|
-
|
186
|
-
#{content_tag :span, column.description, :class => 'description' if column.description.present?}
|
187
|
-
</dd>).html_safe
|
184
|
+
content_tag(:dt, label_tag(label_for(column, column_options), form_column_label(column))) <<
|
185
|
+
content_tag(:dd, field)
|
188
186
|
end
|
189
187
|
end
|
190
188
|
|
@@ -192,6 +190,10 @@ module ActiveScaffold
|
|
192
190
|
options[:id] unless column.form_ui == :select && column.association&.collection?
|
193
191
|
end
|
194
192
|
|
193
|
+
def form_column_label(column)
|
194
|
+
column.label
|
195
|
+
end
|
196
|
+
|
195
197
|
def subform_label(column, hidden)
|
196
198
|
column.label unless hidden
|
197
199
|
end
|
@@ -276,9 +278,8 @@ module ActiveScaffold
|
|
276
278
|
end
|
277
279
|
|
278
280
|
def active_scaffold_select_name_with_multiple(options)
|
279
|
-
if options[:multiple]
|
280
|
-
|
281
|
-
end
|
281
|
+
return if !options[:multiple] || options[:name].to_s.ends_with?('[]')
|
282
|
+
options[:name] = "#{options[:name]}[]"
|
282
283
|
end
|
283
284
|
|
284
285
|
def active_scaffold_input_singular_association(column, html_options, options = {})
|
@@ -303,10 +304,24 @@ module ActiveScaffold
|
|
303
304
|
collection_select(:record, method, select_options, :id, column.options[:label_method] || :to_label, options, html_options)
|
304
305
|
end
|
305
306
|
html << active_scaffold_refresh_link(column, html_options, record) if column.options[:refresh_link]
|
307
|
+
html << active_scaffold_new_record_subform(column, record, html_options) if column.options[:add_new]
|
306
308
|
html
|
307
309
|
end
|
308
310
|
|
309
|
-
def
|
311
|
+
def active_scaffold_new_record_subform(column, record, html_options)
|
312
|
+
subform_attrs = active_scaffold_subform_attributes(column).merge(style: 'display: none')
|
313
|
+
scope = html_options[:name].scan(/record(.*)\[#{column.name}\]/).dig(0, 0)
|
314
|
+
new_record = build_associated(column.association, record)
|
315
|
+
subform = render(partial: subform_partial_for_column(column), locals: {column: column, parent_record: record, associated: [], show_blank_record: new_record, scope: scope})
|
316
|
+
html = content_tag(:div, subform, subform_attrs)
|
317
|
+
html << active_scaffold_show_new_subform_link(column, record, html_options[:id], subform_attrs[:id])
|
318
|
+
end
|
319
|
+
|
320
|
+
def active_scaffold_show_new_subform_link(column, record, select_id, subform_id)
|
321
|
+
link_to(as_(:create_new), '#', data: {select_id: select_id, subform_id: subform_id, subform_text: as_(:add_existing)}, class: 'show-new-subform')
|
322
|
+
end
|
323
|
+
|
324
|
+
def active_scaffold_file_with_remove_link(column, options, content, remove_file_prefix, controls_class, &block) # rubocop:disable Metrics/ParameterLists
|
310
325
|
options = active_scaffold_input_text_options(options.merge(column.options))
|
311
326
|
if content
|
312
327
|
active_scaffold_file_with_content(column, content, options, remove_file_prefix, controls_class, &block)
|
@@ -329,12 +344,13 @@ module ActiveScaffold
|
|
329
344
|
object_name, method = options[:name].split(/\[(#{column.name})\]/)
|
330
345
|
method.sub!(/#{column.name}/, "#{remove_file_prefix}\\0")
|
331
346
|
fields = block_given? ? yield : ''
|
347
|
+
link_key = options[:multiple] ? :remove_files : :remove_file
|
332
348
|
input = file_field(:record, column.name, options.merge(:onchange => js_dont_remove_file_code))
|
333
349
|
content_tag(:div, class: controls_class) do
|
334
350
|
content_tag(:div) do
|
335
351
|
safe_join [content, ' | ', fields,
|
336
352
|
hidden_field(object_name, method, :value => 'false', class: 'remove_file'),
|
337
|
-
content_tag(:a, as_(
|
353
|
+
content_tag(:a, as_(link_key), :href => '#', :onclick => js_remove_file_code)]
|
338
354
|
end << content_tag(:div, input, :style => 'display: none')
|
339
355
|
end
|
340
356
|
end
|
@@ -385,11 +401,11 @@ module ActiveScaffold
|
|
385
401
|
label_method = column.options[:label_method] || :to_label
|
386
402
|
html = hidden_field_tag("#{options[:name]}[]", '', :id => nil)
|
387
403
|
html << content_tag(:ul, options.merge(:class => "#{options[:class]} checkbox-list#{' draggable-lists' if column.options[:draggable_lists]}")) do
|
388
|
-
content =
|
404
|
+
content = []
|
389
405
|
select_options.each_with_index do |option, i|
|
390
406
|
content << active_scaffold_checkbox_option(option, label_method, associated_ids, :name => "#{options[:name]}[]", :id => "#{options[:id]}_#{i}_id")
|
391
407
|
end
|
392
|
-
content
|
408
|
+
safe_join content
|
393
409
|
end
|
394
410
|
html
|
395
411
|
end
|
@@ -454,10 +470,20 @@ module ActiveScaffold
|
|
454
470
|
end
|
455
471
|
|
456
472
|
selected = record.send(column.association.name)&.id if column.association
|
457
|
-
|
458
|
-
|
473
|
+
if options.present?
|
474
|
+
radios = options.map do |option|
|
475
|
+
active_scaffold_radio_option(option, selected, column, html_options)
|
476
|
+
end
|
477
|
+
if column.options[:include_blank]
|
478
|
+
label = column.options[:include_blank]
|
479
|
+
label = as_(column.options[:include_blank]) if column.options[:include_blank].is_a?(Symbol)
|
480
|
+
radios.prepend content_tag(:label, radio_button(:record, column.name, '', html_options.merge(id: nil)) + label)
|
481
|
+
end
|
482
|
+
safe_join radios
|
483
|
+
else
|
484
|
+
content_tag(:span, as_(:no_options), :class => "#{html_options[:class]} no-options", :id => html_options[:id]) <<
|
485
|
+
hidden_field_tag(html_options[:name], '', :id => nil)
|
459
486
|
end
|
460
|
-
safe_join radios
|
461
487
|
end
|
462
488
|
|
463
489
|
def active_scaffold_input_checkbox(column, options)
|
@@ -519,16 +545,17 @@ module ActiveScaffold
|
|
519
545
|
|
520
546
|
# A color picker
|
521
547
|
def active_scaffold_input_color(column, options)
|
548
|
+
html = []
|
522
549
|
options = active_scaffold_input_text_options(options)
|
523
550
|
if column.column&.null
|
524
551
|
no_color = options[:object].send(column.name).nil?
|
525
552
|
method = no_color ? :hidden_field : :color_field
|
526
|
-
html
|
553
|
+
html << content_tag(:label, check_box_tag('disable', '1', no_color, id: nil, name: nil, class: 'no-color') << " #{as_ column.options[:no_color] || :no_color}")
|
527
554
|
else
|
528
555
|
method = :color_field
|
529
|
-
html = ''.html_safe
|
530
556
|
end
|
531
557
|
html << send(method, :record, column.name, options.merge(column.options).except(:format, :no_color))
|
558
|
+
safe_join html
|
532
559
|
end
|
533
560
|
|
534
561
|
#
|
@@ -539,8 +566,8 @@ module ActiveScaffold
|
|
539
566
|
record = options.delete(:object)
|
540
567
|
select_options = []
|
541
568
|
select_options << [as_(:_select_), nil] if !column.virtual? && column.column.null
|
542
|
-
select_options << [as_(:true), true]
|
543
|
-
select_options << [as_(:false), false]
|
569
|
+
select_options << [as_(:true), true] # rubocop:disable Lint/BooleanSymbol
|
570
|
+
select_options << [as_(:false), false] # rubocop:disable Lint/BooleanSymbol
|
544
571
|
|
545
572
|
select_tag(options[:name], options_for_select(select_options, record.send(column.name)), options)
|
546
573
|
end
|
@@ -636,12 +663,12 @@ module ActiveScaffold
|
|
636
663
|
remote_controller = active_scaffold_controller_for(record_select_config.model).controller_path
|
637
664
|
options[:controller] = remote_controller
|
638
665
|
options.merge!(active_scaffold_input_text_options)
|
639
|
-
record_select_field(options[:name],
|
666
|
+
record_select_field(options[:name], nil, options)
|
640
667
|
else
|
641
668
|
select_options = sorted_association_options_find(nested.association, nil, record)
|
642
669
|
select_options ||= active_scaffold_config.model.all
|
643
670
|
select_options = options_from_collection_for_select(select_options, :id, :to_label)
|
644
|
-
select_tag 'associated_id', (
|
671
|
+
select_tag 'associated_id', (content_tag(:option, as_(:_select_), value: '') + select_options) unless select_options.empty?
|
645
672
|
end
|
646
673
|
end
|
647
674
|
|
@@ -654,55 +681,62 @@ module ActiveScaffold
|
|
654
681
|
end
|
655
682
|
|
656
683
|
# Try to get numerical constraints from model's validators
|
657
|
-
def
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
684
|
+
def column_numerical_constraints(column, options)
|
685
|
+
validators = column.active_record_class.validators.select do |v|
|
686
|
+
v.is_a?(ActiveModel::Validations::NumericalityValidator) && v.attributes.include?(column.name)
|
687
|
+
end
|
688
|
+
|
689
|
+
equal_validator = validators.find { |v| v.options[:equal_to] }
|
690
|
+
# If there is equal_to constraint - use it (unless otherwise specified by user)
|
691
|
+
if equal_validator && !(options[:min] || options[:max])
|
692
|
+
equal_to = equal_validator.options[:equal_to]
|
693
|
+
return {min: equal_to, max: equal_to}
|
694
|
+
end
|
695
|
+
|
696
|
+
numerical_constraints = {}
|
697
|
+
|
698
|
+
# find minimum and maximum from validators
|
699
|
+
# we can safely modify :min and :max by 1 for :greater_tnan or :less_than value only for integer values
|
700
|
+
only_integer = column.column.type == :integer if column.column
|
701
|
+
only_integer ||= validators.find { |v| v.options[:only_integer] }.present?
|
702
|
+
margin = only_integer ? 1 : 0
|
703
|
+
|
704
|
+
# Minimum
|
705
|
+
unless options[:min]
|
706
|
+
min = validators.map { |v| v.options[:greater_than_or_equal] }.compact.max
|
707
|
+
greater_than = validators.map { |v| v.options[:greater_than] }.compact.max
|
708
|
+
numerical_constraints[:min] = [min, (greater_than + margin if greater_than)].compact.max
|
709
|
+
end
|
710
|
+
|
711
|
+
# Maximum
|
712
|
+
unless options[:max]
|
713
|
+
max = validators.map { |v| v.options[:less_than_or_equal] }.compact.min
|
714
|
+
less_than = validators.map { |v| v.options[:less_than] }.compact.min
|
715
|
+
numerical_constraints[:max] = [max, (less_than - margin if less_than)].compact.min
|
716
|
+
end
|
717
|
+
|
718
|
+
# Set step = 2 for column values restricted to be odd or even (but only if minimum is set)
|
719
|
+
unless options[:step]
|
720
|
+
only_odd_valid = validators.any? { |v| v.options[:odd] }
|
721
|
+
only_even_valid = validators.any? { |v| v.options[:even] } unless only_odd_valid
|
722
|
+
if !only_integer
|
723
|
+
numerical_constraints[:step] ||= "0.#{'0' * (column.column.scale - 1)}1" if column.column&.scale.to_i.positive?
|
724
|
+
elsif options[:min] && options[:min].respond_to?(:even?) && (only_odd_valid || only_even_valid)
|
725
|
+
numerical_constraints[:step] = 2
|
726
|
+
numerical_constraints[:min] += 1 if only_odd_valid && options[:min].even?
|
727
|
+
numerical_constraints[:min] += 1 if only_even_valid && options[:min].odd?
|
662
728
|
end
|
663
|
-
|
664
|
-
|
665
|
-
# If there is equal_to constraint - use it (unless otherwise specified by user)
|
666
|
-
if equal_to && !(options[:min] || options[:max])
|
667
|
-
numerical_constraints[:min] = numerical_constraints[:max] = equal_to
|
668
|
-
else # find minimum and maximum from validators
|
669
|
-
# we can safely modify :min and :max by 1 for :greater_tnan or :less_than value only for integer values
|
670
|
-
only_integer = column.column.type == :integer if column.column
|
671
|
-
only_integer ||= validators.find { |v| v.options[:only_integer] }.present?
|
672
|
-
margin = only_integer ? 1 : 0
|
673
|
-
|
674
|
-
# Minimum
|
675
|
-
unless options[:min]
|
676
|
-
min = validators.map { |v| v.options[:greater_than_or_equal] }.compact.max
|
677
|
-
greater_than = validators.map { |v| v.options[:greater_than] }.compact.max
|
678
|
-
numerical_constraints[:min] = [min, (greater_than + margin if greater_than)].compact.max
|
679
|
-
end
|
680
|
-
|
681
|
-
# Maximum
|
682
|
-
unless options[:max]
|
683
|
-
max = validators.map { |v| v.options[:less_than_or_equal] }.compact.min
|
684
|
-
less_than = validators.map { |v| v.options[:less_than] }.compact.min
|
685
|
-
numerical_constraints[:max] = [max, (less_than - margin if less_than)].compact.min
|
686
|
-
end
|
729
|
+
numerical_constraints[:step] ||= 'any' unless only_integer
|
730
|
+
end
|
687
731
|
|
688
|
-
|
689
|
-
|
690
|
-
only_odd_valid = validators.any? { |v| v.options[:odd] }
|
691
|
-
only_even_valid = validators.any? { |v| v.options[:even] } unless only_odd_valid
|
692
|
-
if !only_integer
|
693
|
-
numerical_constraints[:step] ||= "0.#{'0' * (column.column.scale - 1)}1" if column.column&.scale.to_i.positive?
|
694
|
-
elsif options[:min] && options[:min].respond_to?(:even?) && (only_odd_valid || only_even_valid)
|
695
|
-
numerical_constraints[:step] = 2
|
696
|
-
numerical_constraints[:min] += 1 if only_odd_valid && options[:min].even?
|
697
|
-
numerical_constraints[:min] += 1 if only_even_valid && options[:min].odd?
|
698
|
-
end
|
699
|
-
numerical_constraints[:step] ||= 'any' unless only_integer
|
700
|
-
end
|
701
|
-
end
|
732
|
+
numerical_constraints
|
733
|
+
end
|
702
734
|
|
703
|
-
|
735
|
+
def numerical_constraints_for_column(column, options)
|
736
|
+
constraints = Rails.cache.fetch("#{column.cache_key}#numerical_constarints") do
|
737
|
+
column_numerical_constraints(column, options)
|
704
738
|
end
|
705
|
-
|
739
|
+
constraints.merge(options)
|
706
740
|
end
|
707
741
|
end
|
708
742
|
end
|