active_scaffold 4.1.6 → 4.2.0
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 +27 -0
- data/README.md +6 -5
- data/app/assets/javascripts/jquery/active_scaffold.js +98 -47
- data/app/assets/javascripts/jquery/tiny_mce_bridge.js +15 -2
- data/app/assets/stylesheets/active_scaffold_images.scss +6 -0
- data/app/assets/stylesheets/{active_scaffold_layout.css → active_scaffold_layout.scss} +104 -4
- data/app/assets/stylesheets/tiny_mce_bridge.scss +11 -0
- data/app/views/active_scaffold_overrides/_base_form.html.erb +3 -2
- data/app/views/active_scaffold_overrides/_field_search.html.erb +2 -2
- data/app/views/active_scaffold_overrides/_form.html.erb +14 -4
- data/app/views/active_scaffold_overrides/_form_association.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_form_association_record.html.erb +5 -11
- data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +1 -3
- data/app/views/active_scaffold_overrides/_new_record.js.erb +3 -1
- data/app/views/active_scaffold_overrides/_refresh_list.js.erb +1 -1
- data/app/views/active_scaffold_overrides/_render_field.js.erb +67 -36
- data/app/views/active_scaffold_overrides/_update_field_on_create.js.erb +41 -6
- data/app/views/active_scaffold_overrides/action_links_menu.js.erb +1 -0
- data/config/locales/de.yml +9 -0
- data/config/locales/en.yml +11 -0
- data/config/locales/es.yml +8 -0
- data/config/locales/fr.yml +8 -0
- data/config/locales/hu.yml +8 -0
- data/config/locales/ja.yml +8 -0
- data/config/locales/ru.yml +8 -0
- data/lib/active_scaffold/actions/common_search.rb +2 -0
- data/lib/active_scaffold/actions/core.rb +47 -23
- data/lib/active_scaffold/actions/create.rb +2 -0
- data/lib/active_scaffold/actions/delete.rb +6 -0
- data/lib/active_scaffold/actions/field_search.rb +36 -11
- data/lib/active_scaffold/actions/list.rb +26 -8
- data/lib/active_scaffold/actions/mark.rb +6 -0
- data/lib/active_scaffold/actions/nested.rb +2 -0
- data/lib/active_scaffold/actions/search.rb +7 -0
- data/lib/active_scaffold/actions/show.rb +6 -0
- data/lib/active_scaffold/actions/subform.rb +2 -0
- data/lib/active_scaffold/actions/update.rb +8 -1
- data/lib/active_scaffold/active_record_permissions.rb +3 -3
- data/lib/active_scaffold/attribute_params.rb +35 -17
- data/lib/active_scaffold/bridges/active_storage/active_storage_bridge.rb +2 -0
- data/lib/active_scaffold/bridges/active_storage/active_storage_helpers.rb +10 -9
- data/lib/active_scaffold/bridges/active_storage/form_ui.rb +10 -3
- data/lib/active_scaffold/bridges/active_storage/list_ui.rb +2 -0
- data/lib/active_scaffold/bridges/active_storage.rb +2 -0
- data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +2 -0
- data/lib/active_scaffold/bridges/ancestry.rb +2 -0
- data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +2 -0
- data/lib/active_scaffold/bridges/bitfields/list_ui.rb +2 -0
- data/lib/active_scaffold/bridges/bitfields.rb +2 -0
- data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +9 -6
- data/lib/active_scaffold/bridges/cancan.rb +2 -0
- data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +2 -0
- data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge_helpers.rb +2 -0
- data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +3 -1
- data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +2 -0
- data/lib/active_scaffold/bridges/carrierwave.rb +2 -0
- data/lib/active_scaffold/bridges/chosen/helpers.rb +13 -4
- data/lib/active_scaffold/bridges/chosen.rb +2 -0
- data/lib/active_scaffold/bridges/country_select/country_select_bridge_helper.rb +2 -0
- data/lib/active_scaffold/bridges/country_select.rb +2 -0
- data/lib/active_scaffold/bridges/date_picker/ext.rb +6 -0
- data/lib/active_scaffold/bridges/date_picker/helper.rb +7 -3
- data/lib/active_scaffold/bridges/date_picker.rb +2 -0
- data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge.rb +2 -0
- data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge_helpers.rb +2 -0
- data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +3 -1
- data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +2 -0
- data/lib/active_scaffold/bridges/dragonfly.rb +2 -0
- data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +2 -0
- data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +10 -9
- data/lib/active_scaffold/bridges/file_column/form_ui.rb +2 -0
- data/lib/active_scaffold/bridges/file_column/list_ui.rb +2 -0
- data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +2 -0
- data/lib/active_scaffold/bridges/file_column/test/mock_model.rb +2 -0
- data/lib/active_scaffold/bridges/file_column.rb +2 -0
- data/lib/active_scaffold/bridges/logical_query_parser/tokens_grammar.rb +65 -0
- data/lib/active_scaffold/bridges/logical_query_parser/tokens_grammar.treetop +31 -0
- data/lib/active_scaffold/bridges/logical_query_parser.rb +9 -0
- data/lib/active_scaffold/bridges/paper_trail/actions.rb +2 -0
- data/lib/active_scaffold/bridges/paper_trail/config.rb +2 -0
- data/lib/active_scaffold/bridges/paper_trail/helper.rb +2 -0
- data/lib/active_scaffold/bridges/paper_trail/paper_trail_bridge.rb +2 -0
- data/lib/active_scaffold/bridges/paper_trail.rb +2 -0
- data/lib/active_scaffold/bridges/paperclip/form_ui.rb +3 -1
- data/lib/active_scaffold/bridges/paperclip/list_ui.rb +2 -0
- data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +2 -0
- data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +12 -12
- data/lib/active_scaffold/bridges/paperclip.rb +2 -0
- data/lib/active_scaffold/bridges/record_select/helpers.rb +19 -11
- data/lib/active_scaffold/bridges/record_select.rb +2 -0
- data/lib/active_scaffold/bridges/semantic_attributes/column.rb +2 -0
- data/lib/active_scaffold/bridges/semantic_attributes.rb +2 -0
- data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +3 -1
- data/lib/active_scaffold/bridges/tiny_mce.rb +6 -0
- data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +2 -0
- data/lib/active_scaffold/bridges/usa_state_select.rb +2 -0
- data/lib/active_scaffold/bridges.rb +2 -0
- data/lib/active_scaffold/config/base.rb +12 -7
- data/lib/active_scaffold/config/core.rb +26 -23
- data/lib/active_scaffold/config/create.rb +2 -0
- data/lib/active_scaffold/config/delete.rb +2 -0
- data/lib/active_scaffold/config/field_search.rb +2 -0
- data/lib/active_scaffold/config/form.rb +11 -1
- data/lib/active_scaffold/config/list.rb +7 -7
- data/lib/active_scaffold/config/mark.rb +2 -0
- data/lib/active_scaffold/config/nested.rb +28 -0
- data/lib/active_scaffold/config/search.rb +2 -0
- data/lib/active_scaffold/config/show.rb +2 -0
- data/lib/active_scaffold/config/subform.rb +2 -0
- data/lib/active_scaffold/config/update.rb +3 -1
- data/lib/active_scaffold/configurable.rb +4 -2
- data/lib/active_scaffold/constraints.rb +2 -0
- data/lib/active_scaffold/core.rb +14 -4
- data/lib/active_scaffold/data_structures/action_columns.rb +3 -1
- data/lib/active_scaffold/data_structures/action_link.rb +10 -0
- data/lib/active_scaffold/data_structures/action_link_separator.rb +2 -0
- data/lib/active_scaffold/data_structures/action_links.rb +32 -21
- data/lib/active_scaffold/data_structures/actions.rb +4 -2
- data/lib/active_scaffold/data_structures/association/abstract.rb +4 -2
- data/lib/active_scaffold/data_structures/association/active_mongoid.rb +4 -2
- data/lib/active_scaffold/data_structures/association/active_record.rb +3 -9
- data/lib/active_scaffold/data_structures/association/mongoid.rb +4 -2
- data/lib/active_scaffold/data_structures/association.rb +2 -0
- data/lib/active_scaffold/data_structures/bridge.rb +3 -1
- data/lib/active_scaffold/data_structures/column.rb +37 -3
- data/lib/active_scaffold/data_structures/columns.rb +4 -2
- data/lib/active_scaffold/data_structures/filter.rb +3 -3
- data/lib/active_scaffold/data_structures/filter_option.rb +2 -0
- data/lib/active_scaffold/data_structures/filters.rb +3 -3
- data/lib/active_scaffold/data_structures/nested_info.rb +4 -2
- data/lib/active_scaffold/data_structures/set.rb +8 -10
- data/lib/active_scaffold/data_structures/sorting.rb +5 -7
- data/lib/active_scaffold/engine.rb +3 -4
- data/lib/active_scaffold/extensions/action_controller_rendering.rb +2 -0
- data/lib/active_scaffold/extensions/action_controller_rescueing.rb +2 -0
- data/lib/active_scaffold/extensions/action_view_rendering.rb +2 -0
- data/lib/active_scaffold/extensions/connection_adapter.rb +2 -0
- data/lib/active_scaffold/extensions/ice_nine.rb +2 -0
- data/lib/active_scaffold/extensions/localize.rb +2 -0
- data/lib/active_scaffold/extensions/name_option_for_datetime.rb +2 -0
- data/lib/active_scaffold/extensions/paginator_extensions.rb +3 -1
- data/lib/active_scaffold/extensions/routing_mapper.rb +2 -0
- data/lib/active_scaffold/extensions/to_label.rb +2 -0
- data/lib/active_scaffold/extensions/unsaved_associated.rb +10 -8
- data/lib/active_scaffold/extensions/unsaved_record.rb +2 -0
- data/lib/active_scaffold/finder.rb +57 -18
- data/lib/active_scaffold/helpers/action_link_helpers.rb +112 -37
- data/lib/active_scaffold/helpers/association_helpers.rb +4 -2
- data/lib/active_scaffold/helpers/controller_helpers.rb +2 -0
- data/lib/active_scaffold/helpers/filter_helpers.rb +11 -3
- data/lib/active_scaffold/helpers/form_column_helpers.rb +98 -71
- data/lib/active_scaffold/helpers/human_condition_helpers.rb +2 -0
- data/lib/active_scaffold/helpers/id_helpers.rb +2 -0
- data/lib/active_scaffold/helpers/list_column_helpers.rb +9 -5
- data/lib/active_scaffold/helpers/pagination_helpers.rb +3 -1
- data/lib/active_scaffold/helpers/search_column_helpers.rb +19 -9
- data/lib/active_scaffold/helpers/show_column_helpers.rb +4 -2
- data/lib/active_scaffold/helpers/tabs_helpers.rb +5 -3
- data/lib/active_scaffold/helpers/view_helpers.rb +3 -3
- data/lib/active_scaffold/marked_model.rb +6 -5
- data/lib/active_scaffold/orm_checks.rb +2 -0
- data/lib/active_scaffold/paginator.rb +4 -1
- data/lib/active_scaffold/registry.rb +2 -0
- data/lib/active_scaffold/responds_to_parent.rb +2 -0
- data/lib/active_scaffold/tableless.rb +23 -13
- data/lib/active_scaffold/version.rb +4 -2
- data/lib/active_scaffold.rb +10 -2
- data/lib/generators/active_scaffold/controller/USAGE +19 -0
- data/lib/generators/active_scaffold/controller/controller_generator.rb +29 -0
- data/lib/generators/active_scaffold/install/USAGE +2 -0
- data/lib/generators/active_scaffold/{install_generator.rb → install/install_generator.rb} +10 -6
- data/lib/generators/active_scaffold/resource/USAGE +29 -0
- data/lib/generators/active_scaffold/resource/resource_generator.rb +30 -0
- data/lib/tasks/brakeman.rake +2 -0
- data/shoulda_macros/macros.rb +2 -0
- metadata +19 -11
- data/lib/generators/active_scaffold/controller_generator.rb +0 -49
- data/lib/generators/active_scaffold/resource_generator.rb +0 -56
- /data/lib/generators/{templates → active_scaffold/controller/templates}/controller.rb +0 -0
- /data/lib/generators/{templates → active_scaffold/controller/templates}/helper.rb +0 -0
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveScaffold::Actions
|
|
2
4
|
module FieldSearch
|
|
3
5
|
def self.included(base)
|
|
6
|
+
conf = base.active_scaffold_config
|
|
7
|
+
if conf.model.primary_key.nil? && conf.field_search.columns.any? { |col| conf.columns[col]&.association }
|
|
8
|
+
raise "#{base.active_scaffold_config.model.name} has no primary key, field_search with association columns won't work"
|
|
9
|
+
end
|
|
10
|
+
|
|
4
11
|
base.class_eval do
|
|
5
12
|
helper_method :field_search_params, :grouped_search?, :search_group_column, :search_group_function
|
|
6
13
|
include ActiveScaffold::Actions::CommonSearch
|
|
@@ -124,7 +131,7 @@ module ActiveScaffold::Actions
|
|
|
124
131
|
when 'year_quarter'
|
|
125
132
|
sql_operator(sql_operator(extract_sql_fn('year', group_sql), '*', 10), '+', extract_sql_fn('quarter', group_sql))
|
|
126
133
|
else
|
|
127
|
-
raise "#{group_function} unsupported, override calculation_for_group_by in #{self.class.name}"
|
|
134
|
+
raise ArgumentError, "#{group_function} unsupported, override calculation_for_group_by in #{self.class.name}"
|
|
128
135
|
end
|
|
129
136
|
end
|
|
130
137
|
|
|
@@ -184,27 +191,45 @@ module ActiveScaffold::Actions
|
|
|
184
191
|
end
|
|
185
192
|
|
|
186
193
|
def do_field_search
|
|
187
|
-
filtered_columns = []
|
|
188
194
|
text_search = active_scaffold_config.field_search.text_search
|
|
189
195
|
columns = active_scaffold_config.field_search.columns
|
|
190
|
-
|
|
196
|
+
|
|
197
|
+
search_conditions = search_params.filter_map do |key, value|
|
|
191
198
|
next unless columns.include? key
|
|
192
199
|
|
|
193
200
|
column = active_scaffold_config.columns[key]
|
|
194
201
|
search_condition = self.class.condition_for_column(column, value, text_search, session)
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
active_scaffold_conditions << search_condition
|
|
198
|
-
filtered_columns << column
|
|
199
|
-
end
|
|
200
|
-
setup_joins_for_filtered_columns(filtered_columns)
|
|
201
|
-
if filtered_columns.present? || grouped_search?
|
|
202
|
-
@filtered = active_scaffold_config.field_search.human_conditions ? filtered_columns : true
|
|
202
|
+
[column, search_condition] unless search_condition.nil?
|
|
203
203
|
end
|
|
204
204
|
|
|
205
|
+
process_search_conditions(search_conditions)
|
|
205
206
|
active_scaffold_config.list.user.page = nil
|
|
206
207
|
end
|
|
207
208
|
|
|
209
|
+
def process_search_conditions(search_conditions)
|
|
210
|
+
filtered_columns = []
|
|
211
|
+
filtered_columns_for_joins = []
|
|
212
|
+
search_conditions.each do |column, search_condition|
|
|
213
|
+
if search_condition.is_a? ActiveRecord::Relation
|
|
214
|
+
active_scaffold_relations << search_condition
|
|
215
|
+
filtered_columns << column
|
|
216
|
+
else
|
|
217
|
+
active_scaffold_conditions << search_condition
|
|
218
|
+
filtered_columns << column
|
|
219
|
+
filtered_columns_for_joins << column
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
setup_joins_for_filtered_columns(filtered_columns_for_joins)
|
|
224
|
+
setup_human_conditions(filtered_columns)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def setup_human_conditions(filtered_columns)
|
|
228
|
+
return unless filtered_columns.present? || grouped_search?
|
|
229
|
+
|
|
230
|
+
@filtered = active_scaffold_config.field_search.human_conditions ? filtered_columns : true
|
|
231
|
+
end
|
|
232
|
+
|
|
208
233
|
def field_search_ignore?
|
|
209
234
|
active_scaffold_config.list.always_show_search && active_scaffold_config.list.search_partial == 'field_search'
|
|
210
235
|
end
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveScaffold::Actions
|
|
2
4
|
module List
|
|
3
5
|
def self.included(base)
|
|
4
6
|
base.before_action :list_authorized_filter, only: :index
|
|
5
|
-
base.helper_method :list_columns, :count_on_association_class?
|
|
7
|
+
base.helper_method :list_columns, :count_on_association_class?, :filters_enabled?
|
|
6
8
|
end
|
|
7
9
|
|
|
8
10
|
def index
|
|
9
|
-
if params[:
|
|
11
|
+
if params[:action_links] && request.xhr?
|
|
12
|
+
action_links_menu
|
|
13
|
+
elsif params[:id] && !params[:id].is_a?(Array) && request.xhr?
|
|
10
14
|
row
|
|
11
15
|
else
|
|
12
16
|
list
|
|
@@ -15,6 +19,18 @@ module ActiveScaffold::Actions
|
|
|
15
19
|
|
|
16
20
|
protected
|
|
17
21
|
|
|
22
|
+
def action_links_menu
|
|
23
|
+
@record = find_if_allowed(params[:id], :read) if params[:id]
|
|
24
|
+
@action_links = params[:action_links].split('.').reduce(active_scaffold_config.action_links) do |links, submenu|
|
|
25
|
+
links.subgroup(submenu)
|
|
26
|
+
end
|
|
27
|
+
respond_to_action(:action_links_menu, action_links_menu_formats)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def action_links_menu_formats
|
|
31
|
+
%i[js]
|
|
32
|
+
end
|
|
33
|
+
|
|
18
34
|
# get just a single row
|
|
19
35
|
def row
|
|
20
36
|
get_row
|
|
@@ -64,15 +80,17 @@ module ActiveScaffold::Actions
|
|
|
64
80
|
render action: 'row'
|
|
65
81
|
end
|
|
66
82
|
|
|
83
|
+
def action_links_menu_respond_to_js
|
|
84
|
+
render action: 'action_links_menu'
|
|
85
|
+
end
|
|
86
|
+
|
|
67
87
|
# The actual algorithm to prepare for the list view
|
|
68
88
|
def set_includes_for_columns(action = :list, sorting = active_scaffold_config.list.user.sorting)
|
|
69
89
|
@cache_associations = true
|
|
70
90
|
columns = columns_for_action(action)
|
|
71
|
-
joins_cols
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
active_scaffold_references.concat joins_cols.map(&:includes).flatten.uniq
|
|
75
|
-
active_scaffold_preload.concat preload_cols.map(&:includes).flatten.uniq
|
|
91
|
+
joins_cols = columns.select { |col| col.sort_joins.present? && includes_need_join?(col, sorting) && !grouped_search? }
|
|
92
|
+
active_scaffold_references.concat joins_cols.map(&:sort_joins).flatten.uniq
|
|
93
|
+
active_scaffold_preload.concat columns.filter_map { |c| c.includes.presence }.flatten.uniq
|
|
76
94
|
set_includes_for_sorting(columns, sorting) if sorting.sorts_by_sql?
|
|
77
95
|
end
|
|
78
96
|
|
|
@@ -286,7 +304,7 @@ module ActiveScaffold::Actions
|
|
|
286
304
|
do_search if respond_to? :do_search, true
|
|
287
305
|
set_includes_for_columns
|
|
288
306
|
# where(nil) is needed because we need a relation
|
|
289
|
-
append_to_query(
|
|
307
|
+
append_to_query(filtered_query.where(nil), finder_options)
|
|
290
308
|
end
|
|
291
309
|
end
|
|
292
310
|
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveScaffold::Actions
|
|
2
4
|
module Mark
|
|
3
5
|
def self.included(base)
|
|
6
|
+
if base.active_scaffold_config.model.primary_key.nil?
|
|
7
|
+
raise "#{base.active_scaffold_config.model.name} has no primary key, mark won't work"
|
|
8
|
+
end
|
|
9
|
+
|
|
4
10
|
base.before_action :mark_authorized_filter, only: :mark
|
|
5
11
|
base.before_action :assign_marked_records_to_model
|
|
6
12
|
base.helper_method :marked_records
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveScaffold::Actions
|
|
2
4
|
module Search
|
|
3
5
|
def self.included(base)
|
|
6
|
+
conf = base.active_scaffold_config
|
|
7
|
+
if conf.model.primary_key.nil? && conf.search.columns.any? { |col| conf.columns[col]&.association }
|
|
8
|
+
raise "#{base.active_scaffold_config.model.name} has no primary key, search with association columns won't work"
|
|
9
|
+
end
|
|
10
|
+
|
|
4
11
|
base.send :include, ActiveScaffold::Actions::CommonSearch
|
|
5
12
|
base.send :include, InstanceMethods
|
|
6
13
|
end
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveScaffold::Actions
|
|
2
4
|
module Show
|
|
3
5
|
def self.included(base)
|
|
6
|
+
if base.active_scaffold_config.model.primary_key.nil?
|
|
7
|
+
raise "#{base.active_scaffold_config.model.name} has no primary key, show won't work"
|
|
8
|
+
end
|
|
9
|
+
|
|
4
10
|
base.before_action :show_authorized_filter, only: :show
|
|
5
11
|
end
|
|
6
12
|
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveScaffold::Actions
|
|
2
4
|
module Update
|
|
3
5
|
def self.included(base)
|
|
6
|
+
if base.active_scaffold_config.model.primary_key.nil?
|
|
7
|
+
raise "#{base.active_scaffold_config.model.name} has no primary key, update won't work"
|
|
8
|
+
end
|
|
9
|
+
|
|
4
10
|
base.before_action :update_authorized_filter, only: %i[edit update]
|
|
5
11
|
base.helper_method :update_refresh_list?
|
|
6
12
|
end
|
|
@@ -97,7 +103,8 @@ module ActiveScaffold::Actions
|
|
|
97
103
|
# A simple method to find and prepare a record for editing
|
|
98
104
|
# May be overridden to customize the record (set default values, etc.)
|
|
99
105
|
def do_edit
|
|
100
|
-
|
|
106
|
+
preload_values = preload_for_form(active_scaffold_config.update.columns)
|
|
107
|
+
@record = find_if_allowed(params[:id], :update, filtered_query.preload(preload_values))
|
|
101
108
|
end
|
|
102
109
|
|
|
103
110
|
# A complex method to update a record. The complexity comes from the support for subforms,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# This module attempts to create permissions conventions for your ActiveRecord models. It supports english-based
|
|
2
4
|
# methods that let you restrict access per-model, per-record, per-column, per-action, and per-user. All at once.
|
|
3
5
|
#
|
|
@@ -55,9 +57,7 @@ module ActiveScaffold
|
|
|
55
57
|
end
|
|
56
58
|
|
|
57
59
|
# Instance-level access to the current user
|
|
58
|
-
|
|
59
|
-
self.class.current_user
|
|
60
|
-
end
|
|
60
|
+
delegate :current_user, to: :class
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveScaffold
|
|
2
4
|
# Provides support for param hashes assumed to be model attributes.
|
|
3
5
|
# Support is primarily needed for creating/editing associated records using a nested hash structure.
|
|
@@ -80,8 +82,8 @@ module ActiveScaffold
|
|
|
80
82
|
rescue StandardError => e
|
|
81
83
|
message = "on the ActiveScaffold column = :#{column.name} for #{parent_record.inspect} " \
|
|
82
84
|
"(value from params #{attributes[column.name].inspect})"
|
|
83
|
-
|
|
84
|
-
raise e.class, "#{e.message} -- #{message}"
|
|
85
|
+
ActiveScaffold.log_exception(e, message)
|
|
86
|
+
raise e.class, "#{e.message} -- #{message}", e.backtrace
|
|
85
87
|
end
|
|
86
88
|
end
|
|
87
89
|
|
|
@@ -156,13 +158,9 @@ module ActiveScaffold
|
|
|
156
158
|
|
|
157
159
|
def association_value_from_param_simple_value(parent_record, column, value)
|
|
158
160
|
if column.association.singular?
|
|
159
|
-
|
|
160
|
-
klass = column.association.klass(parent_record)
|
|
161
|
-
# find_by needed when using update_columns in type foreign type key of polymorphic association,
|
|
162
|
-
# and foreign key had value, it will try to find record with id of previous type
|
|
163
|
-
klass&.find_by(klass&.primary_key => value) if value.present? && !value.is_a?(Array)
|
|
161
|
+
column_singular_assocation_value_from_value(parent_record, column, value)
|
|
164
162
|
else # column.association.collection?
|
|
165
|
-
column_plural_assocation_value_from_value(column, Array(value))
|
|
163
|
+
column_plural_assocation_value_from_value(parent_record, column, Array(value))
|
|
166
164
|
end
|
|
167
165
|
end
|
|
168
166
|
|
|
@@ -180,7 +178,21 @@ module ActiveScaffold
|
|
|
180
178
|
end
|
|
181
179
|
end
|
|
182
180
|
|
|
183
|
-
def
|
|
181
|
+
def column_singular_assocation_value_from_value(parent_record, column, value)
|
|
182
|
+
# value may be Array if using update_columns in field_search with multi-select
|
|
183
|
+
return if value.blank? || value.is_a?(Array)
|
|
184
|
+
|
|
185
|
+
if parent_record.association_cached?(column.name) && parent_record.send(column.name)&.id.to_s == value
|
|
186
|
+
parent_record.send(column.name)
|
|
187
|
+
else
|
|
188
|
+
klass = column.association.klass(parent_record)
|
|
189
|
+
# find_by needed when using update_columns in type foreign type key of polymorphic association,
|
|
190
|
+
# and foreign key had value, it will try to find record with id of previous type
|
|
191
|
+
klass&.find_by(klass.primary_key => value)
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def column_plural_assocation_value_from_value(parent_record, column, value)
|
|
184
196
|
# it's an array of ids
|
|
185
197
|
if value.present?
|
|
186
198
|
ids = value.compact_blank
|
|
@@ -213,9 +225,9 @@ module ActiveScaffold
|
|
|
213
225
|
end
|
|
214
226
|
|
|
215
227
|
def manage_nested_record_from_params(parent_record, column, attributes, avoid_changes = false)
|
|
216
|
-
return nil unless build_record_from_params?(attributes, column, parent_record)
|
|
228
|
+
return nil unless avoid_changes || build_record_from_params?(attributes, column, parent_record)
|
|
217
229
|
|
|
218
|
-
record = find_or_create_for_params(attributes, column, parent_record)
|
|
230
|
+
record = find_or_create_for_params(attributes, column, parent_record, avoid_changes)
|
|
219
231
|
if record
|
|
220
232
|
record_columns = active_scaffold_config_for(record.class).subform.columns
|
|
221
233
|
prev_constraints = record_columns.constraint_columns
|
|
@@ -238,11 +250,11 @@ module ActiveScaffold
|
|
|
238
250
|
# Attempts to create or find an instance of the klass of the association in parent_column from the
|
|
239
251
|
# request parameters given. If params[primary_key] exists it will attempt to find an existing object
|
|
240
252
|
# otherwise it will build a new one.
|
|
241
|
-
def find_or_create_for_params(params, parent_column, parent_record)
|
|
253
|
+
def find_or_create_for_params(params, parent_column, parent_record, avoid_changes = false)
|
|
242
254
|
current = parent_record.send(parent_column.name)
|
|
243
255
|
klass = parent_column.association.klass(parent_record)
|
|
244
256
|
if params.key? klass.primary_key
|
|
245
|
-
record_from_current_or_find(klass, params[klass.primary_key], current)
|
|
257
|
+
record_from_current_or_find(klass, params[klass.primary_key], current, avoid_changes)
|
|
246
258
|
elsif klass.authorized_for?(crud_type: :create)
|
|
247
259
|
association = parent_column.association
|
|
248
260
|
record = klass.new
|
|
@@ -255,15 +267,21 @@ module ActiveScaffold
|
|
|
255
267
|
|
|
256
268
|
# Attempts to find an instance of klass (which must be an ActiveRecord object) with id primary key
|
|
257
269
|
# Returns record from current if it's included or find from DB
|
|
258
|
-
def record_from_current_or_find(klass, id, current)
|
|
270
|
+
def record_from_current_or_find(klass, id, current, avoid_changes = false)
|
|
271
|
+
record = record_from_current(current, id)
|
|
272
|
+
record ||= klass.new(klass.primary_key => id) if avoid_changes
|
|
273
|
+
record ||= klass.find(id)
|
|
274
|
+
record = copy_attributes(record) if avoid_changes && record.persisted?
|
|
275
|
+
record
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def record_from_current(current, id)
|
|
259
279
|
if current.is_a?(ActiveRecord::Base) && current.id.to_s == id
|
|
260
280
|
# modifying the current object of a singular association
|
|
261
281
|
current
|
|
262
|
-
elsif current.respond_to?(:any?)
|
|
282
|
+
elsif current.respond_to?(:any?)
|
|
263
283
|
# modifying one of the current objects in a plural association
|
|
264
284
|
current.detect { |o| o.id.to_s == id }
|
|
265
|
-
else # attaching an existing but not-current object
|
|
266
|
-
klass.find(id)
|
|
267
285
|
end
|
|
268
286
|
end
|
|
269
287
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveScaffold
|
|
2
4
|
module Bridges
|
|
3
5
|
class ActiveStorage
|
|
@@ -23,17 +25,16 @@ module ActiveScaffold
|
|
|
23
25
|
|
|
24
26
|
def generate_delete_helpers(klass)
|
|
25
27
|
(active_storage_has_one_fields(klass) | active_storage_has_many_fields(klass)).each do |field|
|
|
26
|
-
|
|
27
|
-
attr_reader :delete_#{field}
|
|
28
|
+
next if klass.method_defined?(:"#{field}_with_delete=")
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
klass.attr_reader :"delete_#{field}"
|
|
31
|
+
klass.define_method "delete_#{field}=" do |value|
|
|
32
|
+
value = (value == 'true') if value.is_a?(String)
|
|
33
|
+
return unless value
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
CODE
|
|
35
|
+
# passing nil to the file column causes the file to be deleted.
|
|
36
|
+
send(field).purge
|
|
37
|
+
end
|
|
37
38
|
end
|
|
38
39
|
end
|
|
39
40
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveScaffold
|
|
2
4
|
module Helpers
|
|
3
5
|
# Helpers that assist with the rendering of a Form Column
|
|
@@ -6,16 +8,21 @@ module ActiveScaffold
|
|
|
6
8
|
record = options[:object]
|
|
7
9
|
active_storage = record.send(column.name.to_s)
|
|
8
10
|
content = active_scaffold_column_active_storage_has_one(record, column, ui_options: ui_options) if active_storage.attached?
|
|
9
|
-
|
|
11
|
+
active_scaffold_file_with_content(column, options, content, 'delete_', 'active_storage_controls', ui_options: ui_options)
|
|
10
12
|
end
|
|
11
13
|
|
|
12
14
|
def active_scaffold_input_active_storage_has_many(column, options, ui_options: column.options)
|
|
13
15
|
record = options[:object]
|
|
14
16
|
options[:multiple] = 'multiple'
|
|
17
|
+
options[:include_hidden] = false
|
|
15
18
|
options[:name] += '[]'
|
|
16
19
|
active_storage = record.send(column.name.to_s)
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
existing = active_storage.map do |file|
|
|
21
|
+
content = hidden_field_tag(options[:name], file.signed_id) <<
|
|
22
|
+
link_for_attachment(file, column, ui_options: ui_options) << h(' | ')
|
|
23
|
+
active_scaffold_file_with_remove_link(content, options, 'active_storage_controls', :remove)
|
|
24
|
+
end
|
|
25
|
+
safe_join existing << hidden_field_tag(options[:name]) << file_field(:record, column.name, options)
|
|
19
26
|
end
|
|
20
27
|
end
|
|
21
28
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Allow users to easily define aliases for AS actions.
|
|
2
4
|
# Ability#as_action_aliases should be called by the user in his ability class
|
|
3
5
|
#
|
|
@@ -58,6 +60,7 @@ module ActiveScaffold::Bridges
|
|
|
58
60
|
module ModelUserAccess
|
|
59
61
|
module Controller
|
|
60
62
|
extend ActiveSupport::Concern
|
|
63
|
+
|
|
61
64
|
included do
|
|
62
65
|
prepend_before_action :assign_current_ability_to_models
|
|
63
66
|
end
|
|
@@ -81,17 +84,17 @@ module ActiveScaffold::Bridges
|
|
|
81
84
|
end
|
|
82
85
|
|
|
83
86
|
# Instance-level access to the current ability
|
|
84
|
-
|
|
85
|
-
self.class.current_ability
|
|
86
|
-
end
|
|
87
|
+
delegate :current_ability, to: :class
|
|
87
88
|
end
|
|
88
89
|
end
|
|
89
90
|
|
|
90
91
|
# plug into AS#authorized_for calls
|
|
91
92
|
module ActiveRecord
|
|
92
93
|
extend ActiveSupport::Concern
|
|
94
|
+
|
|
93
95
|
included do
|
|
94
96
|
prepend SecurityMethods
|
|
97
|
+
|
|
95
98
|
class << self
|
|
96
99
|
prepend SecurityMethods
|
|
97
100
|
end
|
|
@@ -105,12 +108,12 @@ module ActiveScaffold::Bridges
|
|
|
105
108
|
# {action: 'edit'}
|
|
106
109
|
# to allow access cancan must allow both :crud_type and :action
|
|
107
110
|
# if cancan says "no", it delegates to default AS behavior
|
|
108
|
-
def authorized_for?(options = {})
|
|
111
|
+
def authorized_for?(options = {}) # rubocop:disable Naming/PredicateMethod
|
|
109
112
|
raise InvalidArgument if options[:crud_type].blank? && options[:action].blank?
|
|
110
113
|
|
|
111
114
|
if current_ability.present?
|
|
112
|
-
crud_type_result = options[:crud_type].nil?
|
|
113
|
-
action_result = options[:action].nil?
|
|
115
|
+
crud_type_result = options[:crud_type].nil? || current_ability.can?(options[:crud_type], self)
|
|
116
|
+
action_result = options[:action].nil? || current_ability.can?(options[:action].to_sym, self)
|
|
114
117
|
else
|
|
115
118
|
crud_type_result = action_result = false
|
|
116
119
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveScaffold
|
|
2
4
|
module Helpers
|
|
3
5
|
module FormColumnHelpers
|
|
@@ -5,7 +7,7 @@ module ActiveScaffold
|
|
|
5
7
|
record = options[:object]
|
|
6
8
|
carrierwave = record.send(column.name.to_s)
|
|
7
9
|
content = get_column_value(record, column) if carrierwave.file.present?
|
|
8
|
-
|
|
10
|
+
active_scaffold_file_with_content(column, options, content, 'remove_', 'carrierwave_controls', ui_options: ui_options) do
|
|
9
11
|
cache_field_options = {
|
|
10
12
|
name: options[:name].gsub(/\[#{column.name}\]$/, "[#{column.name}_cache]"),
|
|
11
13
|
id: "#{options[:id]}_cache"
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'active_support/concern'
|
|
2
4
|
|
|
3
5
|
class ActiveScaffold::Bridges::Chosen
|
|
4
6
|
module Helpers
|
|
5
7
|
extend ActiveSupport::Concern
|
|
8
|
+
|
|
6
9
|
included do
|
|
7
10
|
include FormColumnHelpers
|
|
8
11
|
include SearchColumnHelpers
|
|
@@ -21,11 +24,17 @@ class ActiveScaffold::Bridges::Chosen
|
|
|
21
24
|
options.update(ui_options)
|
|
22
25
|
active_scaffold_select_name_with_multiple html_options
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
html =
|
|
28
|
+
if (optgroup = options.delete(:optgroup))
|
|
29
|
+
select(:record, column.name, active_scaffold_grouped_options(column, select_options, optgroup), options, html_options)
|
|
30
|
+
else
|
|
31
|
+
collection_select(:record, column.name, select_options, :id, ui_options[:label_method] || :to_label, options, html_options)
|
|
32
|
+
end
|
|
33
|
+
if ui_options[:add_new]
|
|
34
|
+
html = content_tag(:div, html, class: 'select-field') <<
|
|
35
|
+
active_scaffold_add_new(column, record, html_options, ui_options: ui_options)
|
|
28
36
|
end
|
|
37
|
+
html
|
|
29
38
|
else
|
|
30
39
|
active_scaffold_input_select(column, html_options, ui_options: ui_options)
|
|
31
40
|
end
|