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
@@ -65,7 +65,7 @@ module ActiveScaffold::Actions
|
|
65
65
|
private
|
66
66
|
|
67
67
|
def delete_authorized_filter
|
68
|
-
link = active_scaffold_config.delete.link || active_scaffold_config.delete.class.link
|
68
|
+
link = active_scaffold_config.delete.link || self.class.active_scaffold_config.delete.class.link
|
69
69
|
raise ActiveScaffold::ActionNotAllowed unless Array(send(link.security_method))[0]
|
70
70
|
end
|
71
71
|
|
@@ -23,11 +23,11 @@ module ActiveScaffold::Actions
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def store_search_params_into_session
|
26
|
-
|
26
|
+
init_field_search_params(active_scaffold_config.field_search.default_params) unless active_scaffold_config.field_search.default_params.nil?
|
27
27
|
super
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
30
|
+
def init_field_search_params(default_params)
|
31
31
|
return unless (params[:search].is_a?(String) || search_params.nil?) && params[:search].blank?
|
32
32
|
params[:search] = default_params.is_a?(Proc) ? instance_eval(&default_params) : default_params
|
33
33
|
end
|
@@ -57,23 +57,24 @@ module ActiveScaffold::Actions
|
|
57
57
|
def custom_finder_options
|
58
58
|
if grouped_search?
|
59
59
|
group_sql = calculation_for_group_by(search_group_column&.field || search_group_name)
|
60
|
-
|
61
|
-
|
62
|
-
select_query = quoted_select_columns(search_group_column&.select_columns)
|
60
|
+
select_query = grouped_search_select
|
63
61
|
select_query << group_sql.as(search_group_column.name.to_s) if search_group_column && group_sql.respond_to?(:to_sql)
|
64
|
-
|
65
|
-
select_query << active_scaffold_config.columns[active_scaffold_config.model.inheritance_column].field
|
66
|
-
end
|
67
|
-
grouped_columns_calculations.each do |name, part|
|
68
|
-
select_query << (part.respond_to?(:as) ? part : Arel::Nodes::SqlLiteral.new(part)).as(name.to_s)
|
69
|
-
end
|
70
|
-
|
71
|
-
{group: group_by, select: select_query}
|
62
|
+
{group: group_sql, select: select_query}
|
72
63
|
else
|
73
64
|
super
|
74
65
|
end
|
75
66
|
end
|
76
67
|
|
68
|
+
def grouped_search_select
|
69
|
+
select_query = quoted_select_columns(search_group_column&.select_columns || [search_group_name])
|
70
|
+
if active_scaffold_config.model.columns_hash.include?(active_scaffold_config.model.inheritance_column)
|
71
|
+
select_query << active_scaffold_config.columns[active_scaffold_config.model.inheritance_column].field
|
72
|
+
end
|
73
|
+
grouped_columns_calculations.each do |name, part|
|
74
|
+
select_query << (part.respond_to?(:as) ? part : Arel::Nodes::SqlLiteral.new(part)).as(name.to_s)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
77
78
|
def grouped_columns_calculations
|
78
79
|
@grouped_columns_calculations ||= list_columns[1..-1].each_with_object({}) do |c, h|
|
79
80
|
h[c.name] = calculation_for_group_search(c)
|
@@ -113,12 +114,13 @@ module ActiveScaffold::Actions
|
|
113
114
|
end
|
114
115
|
|
115
116
|
def list_columns
|
116
|
-
@list_columns ||=
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
117
|
+
@list_columns ||=
|
118
|
+
if grouped_search?
|
119
|
+
columns = grouped_columns || super.select(&:calculation?)
|
120
|
+
columns.unshift(search_group_column || search_group_name)
|
121
|
+
else
|
122
|
+
super
|
123
|
+
end
|
122
124
|
end
|
123
125
|
|
124
126
|
def grouped_columns
|
@@ -142,34 +144,42 @@ module ActiveScaffold::Actions
|
|
142
144
|
|
143
145
|
def do_search
|
144
146
|
if field_search_params.present?
|
145
|
-
|
146
|
-
text_search = active_scaffold_config.field_search.text_search
|
147
|
-
columns = active_scaffold_config.field_search.columns
|
148
|
-
count_includes = active_scaffold_config.list.user.count_includes
|
149
|
-
search_params.each do |key, value|
|
150
|
-
next unless columns.include? key
|
151
|
-
column = active_scaffold_config.columns[key]
|
152
|
-
search_condition = self.class.condition_for_column(column, value, text_search)
|
153
|
-
next if search_condition.blank?
|
154
|
-
|
155
|
-
if count_includes.nil? && column.includes.present? && list_columns.include?(column) && !grouped_search?
|
156
|
-
active_scaffold_references << column.includes
|
157
|
-
elsif column.search_joins.present?
|
158
|
-
active_scaffold_outer_joins << column.search_joins
|
159
|
-
end
|
160
|
-
active_scaffold_conditions << search_condition
|
161
|
-
filtered_columns << column
|
162
|
-
end
|
163
|
-
if filtered_columns.present? || grouped_search?
|
164
|
-
@filtered = active_scaffold_config.field_search.human_conditions ? filtered_columns : true
|
165
|
-
end
|
166
|
-
|
167
|
-
active_scaffold_config.list.user.page = nil
|
147
|
+
do_field_search
|
168
148
|
else
|
169
149
|
super
|
170
150
|
end
|
171
151
|
end
|
172
152
|
|
153
|
+
def do_field_search
|
154
|
+
filtered_columns = []
|
155
|
+
text_search = active_scaffold_config.field_search.text_search
|
156
|
+
columns = active_scaffold_config.field_search.columns
|
157
|
+
count_includes = active_scaffold_config.list.user.count_includes
|
158
|
+
search_params.each do |key, value|
|
159
|
+
next unless columns.include? key
|
160
|
+
column = active_scaffold_config.columns[key]
|
161
|
+
search_condition = self.class.condition_for_column(column, value, text_search)
|
162
|
+
next if search_condition.blank?
|
163
|
+
|
164
|
+
joins_for_search_on_column(column, count_includes)
|
165
|
+
active_scaffold_conditions << search_condition
|
166
|
+
filtered_columns << column
|
167
|
+
end
|
168
|
+
if filtered_columns.present? || grouped_search?
|
169
|
+
@filtered = active_scaffold_config.field_search.human_conditions ? filtered_columns : true
|
170
|
+
end
|
171
|
+
|
172
|
+
active_scaffold_config.list.user.page = nil
|
173
|
+
end
|
174
|
+
|
175
|
+
def joins_for_search_on_column(column, count_includes)
|
176
|
+
if count_includes.nil? && column.includes.present? && list_columns.include?(column) && !grouped_search?
|
177
|
+
active_scaffold_references << column.includes
|
178
|
+
elsif column.search_joins.present?
|
179
|
+
active_scaffold_outer_joins << column.search_joins
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
173
183
|
def field_search_ignore?
|
174
184
|
active_scaffold_config.list.always_show_search && active_scaffold_config.list.search_partial == 'field_search'
|
175
185
|
end
|
@@ -2,7 +2,7 @@ module ActiveScaffold::Actions
|
|
2
2
|
module List
|
3
3
|
def self.included(base)
|
4
4
|
base.before_action :list_authorized_filter, :only => :index
|
5
|
-
base.helper_method :list_columns
|
5
|
+
base.helper_method :list_columns, :count_on_association_class?
|
6
6
|
end
|
7
7
|
|
8
8
|
def index
|
@@ -49,11 +49,11 @@ module ActiveScaffold::Actions
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def list_respond_to_xml
|
52
|
-
|
52
|
+
response_to_api(:xml, list_columns_names)
|
53
53
|
end
|
54
54
|
|
55
55
|
def list_respond_to_json
|
56
|
-
|
56
|
+
response_to_api(:json, list_columns_names)
|
57
57
|
end
|
58
58
|
|
59
59
|
def row_respond_to_html
|
@@ -82,7 +82,7 @@ module ActiveScaffold::Actions
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def set_includes_for_sorting(columns, sorting)
|
85
|
-
sorting.
|
85
|
+
sorting.each_column do |col|
|
86
86
|
next unless col.includes.present? && !columns.include?(col)
|
87
87
|
if active_scaffold_config.model.connection.needs_order_expressions_in_select?
|
88
88
|
active_scaffold_references << col.includes
|
@@ -93,7 +93,7 @@ module ActiveScaffold::Actions
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def includes_need_join?(column, sorting = active_scaffold_config.list.user.sorting)
|
96
|
-
sorting.sorts_on?(column) || scoped_habtm?(column)
|
96
|
+
(sorting.sorts_by_sql? && sorting.sorts_on?(column)) || scoped_habtm?(column)
|
97
97
|
end
|
98
98
|
|
99
99
|
def scoped_habtm?(column)
|
@@ -106,34 +106,111 @@ module ActiveScaffold::Actions
|
|
106
106
|
super
|
107
107
|
end
|
108
108
|
|
109
|
+
def current_page
|
110
|
+
set_includes_for_columns
|
111
|
+
|
112
|
+
page = find_page(find_page_options)
|
113
|
+
total_pages = page.pager.number_of_pages
|
114
|
+
if !page.pager.infinite? && !total_pages.zero? && page.number > total_pages
|
115
|
+
page = page.pager.last
|
116
|
+
active_scaffold_config.list.user.page = page.number
|
117
|
+
end
|
118
|
+
page
|
119
|
+
end
|
120
|
+
|
109
121
|
# The actual algorithm to prepare for the list view
|
110
122
|
def do_list
|
111
123
|
# id: nil needed in params_for because rails reuse it even
|
112
124
|
# if it was deleted from params (like do_refresh_list does)
|
113
125
|
@remove_id_from_list_links = params[:id].blank?
|
114
|
-
|
126
|
+
@page = current_page
|
127
|
+
@records = @page.items
|
128
|
+
cache_column_counts
|
129
|
+
end
|
130
|
+
|
131
|
+
def columns_to_cache_counts
|
132
|
+
list_columns.select do |col|
|
133
|
+
col.association&.collection? && col.includes.blank? && col.associated_number? &&
|
134
|
+
!ActiveScaffold::OrmChecks.tableless?(col.association.klass) &&
|
135
|
+
!col.association.reverse_association&.counter_cache
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def cache_column_counts
|
140
|
+
@counts = columns_to_cache_counts.each_with_object({}) do |column, counts|
|
141
|
+
if ActiveScaffold::OrmChecks.active_record?(column.association.klass)
|
142
|
+
counts[column.name] = count_query_for_column(column).count
|
143
|
+
elsif ActiveScaffold::OrmChecks.mongoid?(column.association.klass)
|
144
|
+
counts[column.name] = mongoid_count_for_column(column)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def count_on_association_class?(column)
|
150
|
+
column.association.has_many? && !column.association.through? &&
|
151
|
+
(!column.association.as || column.association.reverse_association)
|
152
|
+
end
|
153
|
+
|
154
|
+
def count_query_for_column(column)
|
155
|
+
if count_on_association_class?(column)
|
156
|
+
count_query_on_association_class(column)
|
157
|
+
else
|
158
|
+
count_query_with_join(column)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def count_query_on_association_class(column)
|
163
|
+
key = column.association.primary_key || :id
|
164
|
+
query = column.association.klass.where(column.association.foreign_key => @records.map(&key))
|
165
|
+
if column.association.as
|
166
|
+
query.where!(column.association.reverse_association.foreign_type => active_scaffold_config.model.name)
|
167
|
+
end
|
168
|
+
if column.association.scope
|
169
|
+
query = query.instance_exec(&column.association.scope)
|
170
|
+
end
|
171
|
+
query.group(column.association.foreign_key)
|
172
|
+
end
|
173
|
+
|
174
|
+
def count_query_with_join(column)
|
175
|
+
klass = column.association.klass
|
176
|
+
query = active_scaffold_config.model.where(active_scaffold_config.primary_key => @records.map(&:id))
|
177
|
+
.joins(column.name).group(active_scaffold_config.primary_key)
|
178
|
+
.select("#{klass.quoted_table_name}.#{klass.quoted_primary_key}")
|
179
|
+
query = query.uniq if column.association.scope && klass.instance_exec(&column.association.scope).values[:distinct]
|
180
|
+
query
|
181
|
+
end
|
182
|
+
|
183
|
+
def mongoid_count_for_column(column)
|
184
|
+
matches = {column.association.foreign_key => {'$in': @records.map(&:id)}}
|
185
|
+
if column.association.as
|
186
|
+
matches[column.association.reverse_association.foreign_type] = {'$eq': active_scaffold_config.model.name}
|
187
|
+
end
|
188
|
+
group = {_id: "$#{column.association.foreign_key}", count: {'$sum' => 1}}
|
189
|
+
query = column.association.klass.collection.aggregate([{'$match' => matches}, {'$group' => group}])
|
190
|
+
query.each_with_object({}) do |row, hash|
|
191
|
+
hash[row['_id']] = row['count']
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def find_page_options
|
196
|
+
options = {
|
197
|
+
:sorting => active_scaffold_config.list.user.sorting,
|
198
|
+
:count_includes => active_scaffold_config.list.user.count_includes
|
199
|
+
}
|
115
200
|
|
116
|
-
|
117
|
-
:count_includes => active_scaffold_config.list.user.count_includes}
|
118
|
-
paginate = params[:format].nil? ? (accepts? :html, :js) : %w[html js].include?(params[:format])
|
201
|
+
paginate = params[:format].nil? ? accepts?(:html, :js) : %w[html js].include?(params[:format])
|
119
202
|
options[:pagination] = active_scaffold_config.list.pagination if paginate
|
120
203
|
if options[:pagination]
|
121
204
|
options[:per_page] = active_scaffold_config.list.user.per_page
|
122
205
|
options[:page] = active_scaffold_config.list.user.page
|
123
206
|
end
|
207
|
+
|
124
208
|
if active_scaffold_config.list.auto_select_columns
|
125
209
|
auto_select_columns = list_columns + [active_scaffold_config.columns[active_scaffold_config.model.primary_key]]
|
126
210
|
options[:select] = auto_select_columns.map { |c| quoted_select_columns(c.select_columns) }.compact.flatten
|
127
211
|
end
|
128
212
|
|
129
|
-
|
130
|
-
total_pages = page.pager.number_of_pages
|
131
|
-
if !page.pager.infinite? && !total_pages.zero? && page.number > total_pages
|
132
|
-
page = page.pager.last
|
133
|
-
active_scaffold_config.list.user.page = page.number
|
134
|
-
end
|
135
|
-
@page = page
|
136
|
-
@records = page.items
|
213
|
+
options
|
137
214
|
end
|
138
215
|
|
139
216
|
def quoted_select_columns(columns)
|
@@ -150,17 +227,23 @@ module ActiveScaffold::Actions
|
|
150
227
|
end
|
151
228
|
|
152
229
|
def each_record_in_page
|
153
|
-
|
154
|
-
do_search if respond_to? :do_search, true
|
155
|
-
active_scaffold_config.list.user.page = current_page
|
156
|
-
do_list
|
157
|
-
@page.items.each { |record| yield record }
|
230
|
+
page_items.each { |record| yield record }
|
158
231
|
end
|
159
232
|
|
160
233
|
def each_record_in_scope
|
161
234
|
scoped_query.each { |record| yield record }
|
162
235
|
end
|
163
236
|
|
237
|
+
def page_items
|
238
|
+
@page_items ||= begin
|
239
|
+
page_number = active_scaffold_config.list.user.page
|
240
|
+
do_search if respond_to? :do_search, true
|
241
|
+
active_scaffold_config.list.user.page = page_number
|
242
|
+
@page = current_page
|
243
|
+
@page.items
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
164
247
|
def scoped_query
|
165
248
|
@scoped_query ||= begin
|
166
249
|
do_search if respond_to? :do_search, true
|
@@ -190,7 +273,7 @@ module ActiveScaffold::Actions
|
|
190
273
|
{:etag => active_scaffold_config.list.user.sorting.clause}
|
191
274
|
end
|
192
275
|
end
|
193
|
-
objects.
|
276
|
+
objects.presence || super
|
194
277
|
end
|
195
278
|
|
196
279
|
private
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module ActiveScaffold::Actions
|
2
|
-
# The Nested module basically handles automatically linking controllers together.
|
2
|
+
# The Nested module basically handles automatically linking controllers together.
|
3
|
+
# It does this by creating column links with the right parameters, and by providing
|
4
|
+
# any supporting systems (like a /:controller/nested action for returning associated scaffolds).
|
3
5
|
module Nested
|
4
6
|
def self.included(base)
|
5
7
|
super
|
@@ -33,11 +35,11 @@ module ActiveScaffold::Actions
|
|
33
35
|
def configure_nested
|
34
36
|
return unless nested?
|
35
37
|
register_constraints_with_action_columns(nested.constrained_fields)
|
38
|
+
return unless active_scaffold_config.actions.include? :list
|
36
39
|
active_scaffold_config.list.user.label = nested_label
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
40
|
+
return if active_scaffold_config.nested.ignore_order_from_association
|
41
|
+
chain = beginning_of_chain
|
42
|
+
active_scaffold_config.list.user.nested_default_sorting = nested_default_sorting(chain) if nested.sorted?(chain)
|
41
43
|
end
|
42
44
|
|
43
45
|
def nested_label
|
@@ -57,41 +59,39 @@ module ActiveScaffold::Actions
|
|
57
59
|
end
|
58
60
|
|
59
61
|
def include_habtm_actions
|
60
|
-
if nested
|
62
|
+
if nested&.habtm?
|
61
63
|
# Production mode is ok with adding a link everytime the scaffold is nested - we are not ok with that.
|
62
|
-
|
63
|
-
|
64
|
-
active_scaffold_config.action_links.add('destroy_existing', :label => :remove, :type => :member, :confirm => :are_you_sure_to_delete, :method => :delete, :position => false, :security_method => :delete_existing_authorized?) unless active_scaffold_config.action_links['destroy_existing']
|
65
|
-
if active_scaffold_config.actions.include?(:delete)
|
66
|
-
active_scaffold_config.action_links.delete('destroy') if active_scaffold_config.action_links['destroy']
|
67
|
-
end
|
68
|
-
end
|
69
|
-
else
|
70
|
-
# Production mode is caching this link into a non nested scaffold
|
71
|
-
active_scaffold_config.action_links.delete('new_existing') if active_scaffold_config.action_links['new_existing']
|
72
|
-
|
73
|
-
if active_scaffold_config.nested.shallow_delete
|
74
|
-
active_scaffold_config.action_links.delete('destroy_existing') if active_scaffold_config.action_links['destroy_existing']
|
75
|
-
if active_scaffold_config.actions.include?(:delete) && active_scaffold_config.delete.link
|
76
|
-
active_scaffold_config.action_links.add(active_scaffold_config.delete.link) unless active_scaffold_config.action_links['destroy']
|
77
|
-
end
|
64
|
+
unless active_scaffold_config.action_links['new_existing']
|
65
|
+
active_scaffold_config.action_links.add('new_existing', :label => :add_existing, :type => :collection, :security_method => :add_existing_authorized?)
|
78
66
|
end
|
67
|
+
add_shallow_links if active_scaffold_config.nested.shallow_delete
|
68
|
+
elsif !ActiveScaffold.threadsafe
|
69
|
+
# Production mode is caching this link into a non nested scaffold, when threadsafe is disabled
|
70
|
+
active_scaffold_config.action_links.delete('new_existing')
|
71
|
+
restore_shallow_links if active_scaffold_config.nested.shallow_delete
|
79
72
|
end
|
80
73
|
end
|
81
74
|
|
75
|
+
def add_shallow_links
|
76
|
+
unless active_scaffold_config.action_links['destroy_existing']
|
77
|
+
link_options = {:label => :remove, :type => :member, :confirm => :are_you_sure_to_delete, :method => :delete, :position => false, :security_method => :delete_existing_authorized?}
|
78
|
+
active_scaffold_config.action_links.add('destroy_existing', link_options)
|
79
|
+
end
|
80
|
+
active_scaffold_config.action_links.delete('destroy') if active_scaffold_config.actions.include?(:delete)
|
81
|
+
end
|
82
|
+
|
83
|
+
def restore_shallow_links
|
84
|
+
if active_scaffold_config.actions.include?(:delete) && active_scaffold_config.delete.link
|
85
|
+
link = active_scaffold_config.delete.link
|
86
|
+
active_scaffold_config.action_links.add(link) unless active_scaffold_config.action_links[link.action]
|
87
|
+
end
|
88
|
+
active_scaffold_config.action_links.delete('destroy_existing')
|
89
|
+
end
|
90
|
+
|
82
91
|
def beginning_of_chain
|
83
|
-
if nested
|
84
|
-
|
85
|
-
|
86
|
-
elsif nested.association.through? # has_one :through
|
87
|
-
active_scaffold_config.model.where(active_scaffold_config.model.primary_key => nested_parent_record.send(nested.association.name)&.id)
|
88
|
-
elsif nested.association.has_one?
|
89
|
-
active_scaffold_config.model.where(nested.child_association.name => nested_parent_record)
|
90
|
-
elsif nested.association.belongs_to?
|
91
|
-
nested_belongs_to_chain
|
92
|
-
else # never should get here
|
93
|
-
raise 'missing condition for nested beginning_of_chain'
|
94
|
-
end
|
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
|
94
|
+
nested_chain_with_association
|
95
95
|
elsif nested? && nested.scope
|
96
96
|
nested_parent_record.send(nested.scope)
|
97
97
|
else
|
@@ -99,23 +99,40 @@ module ActiveScaffold::Actions
|
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
|
-
def
|
103
|
-
|
104
|
-
|
102
|
+
def nested_chain_with_association
|
103
|
+
if nested.association.collection?
|
104
|
+
nested_parent_record.send(nested.association.name)
|
105
|
+
elsif nested.association.through? # has_one :through
|
106
|
+
active_scaffold_config.model.where(active_scaffold_config.model.primary_key => nested_parent_record.send(nested.association.name)&.id)
|
107
|
+
elsif nested.association.has_one?
|
108
|
+
active_scaffold_config.model.where(nested.child_association.name => nested_parent_record)
|
109
|
+
elsif nested.association.belongs_to?
|
110
|
+
primary_key = active_scaffold_config.mongoid? ? '_id' : active_scaffold_config.model.primary_key
|
111
|
+
active_scaffold_config.model.where(primary_key => nested_parent_record.send(nested.association.name))
|
112
|
+
else # never should get here
|
113
|
+
raise 'missing condition for nested beginning_of_chain'
|
114
|
+
end
|
105
115
|
end
|
106
116
|
|
107
117
|
def nested_parent_record(crud = :read)
|
108
118
|
@nested_parent_record ||= find_if_allowed(nested.parent_id, crud, nested.parent_model)
|
109
119
|
end
|
110
120
|
|
121
|
+
def create_association_with_parent?
|
122
|
+
# has_many is done by beginning_of_chain and rails if direct association, not in through associations
|
123
|
+
return false if nested.has_many? && !nested.association.through?
|
124
|
+
nested.child_association && nested_parent_record
|
125
|
+
end
|
126
|
+
|
111
127
|
def create_association_with_parent(record)
|
112
|
-
|
113
|
-
return unless (nested.belongs_to? || nested.has_one? || nested.habtm?) && nested.child_association
|
114
|
-
return if (parent = nested_parent_record).nil?
|
128
|
+
return unless create_association_with_parent?
|
115
129
|
if nested.child_association.singular?
|
116
|
-
record.send("#{nested.child_association.name}=",
|
130
|
+
record.send("#{nested.child_association.name}=", nested_parent_record)
|
131
|
+
elsif nested.association.through_singular? && nested.child_association.through_singular?
|
132
|
+
through = nested_parent_record.send(nested.association.through_reflection.name)
|
133
|
+
record.send("#{nested.child_association.through_reflection.name}=", through)
|
117
134
|
else
|
118
|
-
record.send(nested.child_association.name) <<
|
135
|
+
record.send(nested.child_association.name) << nested_parent_record
|
119
136
|
end
|
120
137
|
end
|
121
138
|
|