active_scaffold 3.4.17 → 3.4.18
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 +12 -1
- data/README.md +8 -4
- data/app/assets/javascripts/jquery/active_scaffold.js +82 -67
- data/app/assets/stylesheets/active_scaffold.scss +1 -1
- data/app/assets/stylesheets/active_scaffold_colors.scss +1 -1
- data/app/assets/stylesheets/blue-theme.css +1 -1
- data/app/views/active_scaffold_overrides/_form_association.html.erb +3 -3
- data/app/views/active_scaffold_overrides/_form_association_record.html.erb +3 -3
- data/app/views/active_scaffold_overrides/_show_columns.html.erb +1 -1
- data/lib/active_scaffold.rb +16 -16
- data/lib/active_scaffold/actions/common_search.rb +13 -11
- data/lib/active_scaffold/actions/core.rb +85 -78
- data/lib/active_scaffold/actions/create.rb +29 -28
- data/lib/active_scaffold/actions/delete.rb +17 -17
- data/lib/active_scaffold/actions/field_search.rb +18 -19
- data/lib/active_scaffold/actions/list.rb +30 -22
- data/lib/active_scaffold/actions/mark.rb +1 -1
- data/lib/active_scaffold/actions/nested.rb +78 -65
- data/lib/active_scaffold/actions/search.rb +13 -10
- data/lib/active_scaffold/actions/show.rb +10 -6
- data/lib/active_scaffold/actions/subform.rb +1 -2
- data/lib/active_scaffold/actions/update.rb +39 -31
- data/lib/active_scaffold/active_record_permissions.rb +14 -15
- data/lib/active_scaffold/attribute_params.rb +42 -43
- data/lib/active_scaffold/bridges.rb +22 -12
- data/lib/active_scaffold/bridges/ancestry.rb +1 -1
- data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +6 -6
- data/lib/active_scaffold/bridges/bitfields.rb +1 -1
- data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +12 -13
- data/lib/active_scaffold/bridges/calendar_date_select.rb +5 -5
- data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +17 -20
- data/lib/active_scaffold/bridges/cancan.rb +1 -1
- data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +8 -9
- data/lib/active_scaffold/bridges/carrierwave.rb +4 -4
- data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +9 -8
- data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +11 -10
- data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +7 -6
- data/lib/active_scaffold/bridges/chosen.rb +1 -1
- data/lib/active_scaffold/bridges/chosen/helpers.rb +4 -4
- data/lib/active_scaffold/bridges/country_helper.rb +1 -1
- data/lib/active_scaffold/bridges/country_helper/country_helper_bridge.rb +259 -260
- data/lib/active_scaffold/bridges/date_picker.rb +2 -2
- data/lib/active_scaffold/bridges/date_picker/ext.rb +9 -11
- data/lib/active_scaffold/bridges/date_picker/helper.rb +61 -67
- data/lib/active_scaffold/bridges/dragonfly.rb +4 -4
- data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge.rb +9 -8
- data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +11 -10
- data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +6 -5
- data/lib/active_scaffold/bridges/file_column.rb +5 -5
- data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +20 -23
- data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +20 -23
- data/lib/active_scaffold/bridges/file_column/form_ui.rb +13 -14
- data/lib/active_scaffold/bridges/file_column/list_ui.rb +7 -8
- data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +18 -22
- data/lib/active_scaffold/bridges/file_column/test/mock_model.rb +5 -4
- data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +2 -10
- data/lib/active_scaffold/bridges/paper_trail.rb +7 -5
- data/lib/active_scaffold/bridges/paper_trail/paper_trail_bridge.rb +4 -3
- data/lib/active_scaffold/bridges/paperclip.rb +5 -5
- data/lib/active_scaffold/bridges/paperclip/form_ui.rb +11 -10
- data/lib/active_scaffold/bridges/paperclip/list_ui.rb +6 -5
- data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +10 -9
- data/lib/active_scaffold/bridges/record_select.rb +1 -1
- data/lib/active_scaffold/bridges/record_select/helpers.rb +28 -28
- data/lib/active_scaffold/bridges/semantic_attributes.rb +1 -1
- data/lib/active_scaffold/bridges/semantic_attributes/column.rb +1 -1
- data/lib/active_scaffold/bridges/shared/date_bridge.rb +58 -52
- data/lib/active_scaffold/bridges/tiny_mce.rb +2 -2
- data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +3 -3
- data/lib/active_scaffold/config/base.rb +9 -10
- data/lib/active_scaffold/config/core.rb +24 -29
- data/lib/active_scaffold/config/create.rb +0 -1
- data/lib/active_scaffold/config/field_search.rb +8 -10
- data/lib/active_scaffold/config/form.rb +5 -5
- data/lib/active_scaffold/config/list.rb +21 -20
- data/lib/active_scaffold/config/mark.rb +3 -3
- data/lib/active_scaffold/config/nested.rb +11 -10
- data/lib/active_scaffold/config/search.rb +2 -3
- data/lib/active_scaffold/config/show.rb +1 -1
- data/lib/active_scaffold/config/update.rb +1 -2
- data/lib/active_scaffold/configurable.rb +9 -11
- data/lib/active_scaffold/constraints.rb +9 -8
- data/lib/active_scaffold/core.rb +72 -84
- data/lib/active_scaffold/data_structures/action_columns.rb +26 -25
- data/lib/active_scaffold/data_structures/action_link.rb +43 -43
- data/lib/active_scaffold/data_structures/action_links.rb +17 -15
- data/lib/active_scaffold/data_structures/actions.rb +5 -5
- data/lib/active_scaffold/data_structures/bridge.rb +6 -3
- data/lib/active_scaffold/data_structures/column.rb +110 -89
- data/lib/active_scaffold/data_structures/columns.rb +3 -3
- data/lib/active_scaffold/data_structures/error_message.rb +4 -6
- data/lib/active_scaffold/data_structures/nested_info.rb +43 -48
- data/lib/active_scaffold/data_structures/set.rb +7 -8
- data/lib/active_scaffold/data_structures/sorting.rb +38 -33
- data/lib/active_scaffold/delayed_setup.rb +5 -6
- data/lib/active_scaffold/engine.rb +4 -4
- data/lib/active_scaffold/extensions/action_controller_rendering.rb +3 -4
- data/lib/active_scaffold/extensions/action_controller_rescueing.rb +1 -1
- data/lib/active_scaffold/extensions/action_view_rendering.rb +5 -6
- data/lib/active_scaffold/extensions/left_outer_joins.rb +11 -11
- data/lib/active_scaffold/extensions/localize.rb +1 -1
- data/lib/active_scaffold/extensions/name_option_for_datetime.rb +1 -1
- data/lib/active_scaffold/extensions/paginator_extensions.rb +2 -5
- data/lib/active_scaffold/extensions/reverse_associations.rb +13 -13
- data/lib/active_scaffold/extensions/routing_mapper.rb +9 -9
- data/lib/active_scaffold/extensions/unsaved_associated.rb +9 -9
- data/lib/active_scaffold/finder.rb +90 -93
- data/lib/active_scaffold/helpers/association_helpers.rb +5 -5
- data/lib/active_scaffold/helpers/controller_helpers.rb +22 -19
- data/lib/active_scaffold/helpers/form_column_helpers.rb +115 -105
- data/lib/active_scaffold/helpers/human_condition_helpers.rb +62 -35
- data/lib/active_scaffold/helpers/id_helpers.rb +6 -6
- data/lib/active_scaffold/helpers/list_column_helpers.rb +89 -94
- data/lib/active_scaffold/helpers/pagination_helpers.rb +9 -9
- data/lib/active_scaffold/helpers/search_column_helpers.rb +47 -44
- data/lib/active_scaffold/helpers/show_column_helpers.rb +2 -2
- data/lib/active_scaffold/helpers/view_helpers.rb +86 -91
- data/lib/active_scaffold/marked_model.rb +10 -10
- data/lib/active_scaffold/paginator.rb +30 -34
- data/lib/active_scaffold/responds_to_parent.rb +27 -28
- data/lib/active_scaffold/tableless.rb +20 -15
- data/lib/active_scaffold/version.rb +1 -1
- data/lib/generators/active_scaffold/active_scaffold_generator.rb +8 -8
- data/lib/generators/active_scaffold_controller/active_scaffold_controller_generator.rb +9 -9
- data/shoulda_macros/macros.rb +27 -22
- data/test/bridges/bridge_test.rb +38 -29
- data/test/bridges/date_picker_test.rb +1 -1
- data/test/bridges/paper_trail_test.rb +17 -0
- data/test/bridges/paperclip_test.rb +3 -2
- data/test/bridges/tiny_mce_test.rb +5 -2
- data/test/company.rb +25 -30
- data/test/config/base_test.rb +1 -1
- data/test/config/core_test.rb +9 -9
- data/test/config/create_test.rb +14 -8
- data/test/config/delete_test.rb +4 -4
- data/test/config/field_search_test.rb +6 -6
- data/test/config/list_test.rb +16 -16
- data/test/config/nested_test.rb +4 -4
- data/test/config/search_test.rb +8 -8
- data/test/config/show_test.rb +6 -6
- data/test/config/subform_test.rb +1 -1
- data/test/config/update_test.rb +5 -5
- data/test/const_mocker.rb +4 -4
- data/test/data_structures/action_columns_test.rb +4 -5
- data/test/data_structures/action_link_test.rb +1 -0
- data/test/data_structures/action_links_test.rb +5 -5
- data/test/data_structures/column_test.rb +9 -9
- data/test/data_structures/columns_test.rb +2 -2
- data/test/data_structures/error_message_test.rb +4 -5
- data/test/data_structures/set_test.rb +1 -2
- data/test/data_structures/sorting_test.rb +10 -10
- data/test/data_structures/validation_reflection_test.rb +8 -0
- data/test/extensions/routing_mapper_test.rb +2 -2
- data/test/helpers/list_column_helpers_test.rb +3 -2
- data/test/helpers/pagination_helpers_test.rb +5 -4
- data/test/helpers/search_column_helpers_test.rb +1 -1
- data/test/misc/active_record_permissions_test.rb +63 -50
- data/test/misc/attribute_params_test.rb +28 -26
- data/test/misc/calculation_test.rb +10 -3
- data/test/misc/configurable_test.rb +12 -13
- data/test/misc/constraints_test.rb +6 -6
- data/test/misc/convert_numbers_format_test.rb +7 -6
- data/test/misc/finder_test.rb +17 -12
- data/test/misc/lang_test.rb +3 -4
- data/test/misc/tableless_test.rb +2 -3
- data/test/mock_app/app/controllers/addresses_controller.rb +1 -1
- data/test/mock_app/app/controllers/buildings_controller.rb +1 -1
- data/test/mock_app/app/controllers/cars_controller.rb +1 -1
- data/test/mock_app/app/controllers/contacts_controller.rb +1 -1
- data/test/mock_app/app/controllers/people_controller.rb +1 -1
- data/test/mock_app/app/models/file_model.rb +2 -2
- data/test/mock_app/app/models/person.rb +1 -1
- data/test/mock_app/config/application.rb +3 -3
- data/test/mock_app/config/boot.rb +1 -1
- data/test/mock_app/config/environment.rb +1 -0
- data/test/mock_app/config/environments/development.rb +0 -1
- data/test/mock_app/config/environments/production.rb +1 -1
- data/test/mock_app/db/schema.rb +14 -15
- data/test/model_stub.rb +13 -16
- data/test/run_all.rb +5 -7
- data/test/test_helper.rb +12 -9
- metadata +19 -3
|
@@ -4,16 +4,18 @@ module ActiveScaffold::Actions
|
|
|
4
4
|
base.send :include, ActiveScaffold::Actions::CommonSearch
|
|
5
5
|
base.send :include, InstanceMethods
|
|
6
6
|
end
|
|
7
|
-
|
|
8
|
-
module InstanceMethods
|
|
9
7
|
|
|
8
|
+
module InstanceMethods
|
|
10
9
|
protected
|
|
10
|
+
|
|
11
11
|
def search_respond_to_html
|
|
12
|
-
render(:action =>
|
|
12
|
+
render(:action => 'search')
|
|
13
13
|
end
|
|
14
|
+
|
|
14
15
|
def search_respond_to_js
|
|
15
|
-
render(:partial =>
|
|
16
|
+
render(:partial => 'search')
|
|
16
17
|
end
|
|
18
|
+
|
|
17
19
|
def do_search
|
|
18
20
|
if search_params.is_a?(String) && search_params.present?
|
|
19
21
|
query = search_params.to_s.strip
|
|
@@ -22,13 +24,13 @@ module ActiveScaffold::Actions
|
|
|
22
24
|
query = query.split(active_scaffold_config.search.split_terms) if active_scaffold_config.search.split_terms
|
|
23
25
|
search_conditions = self.class.create_conditions_for_columns(query, columns, text_search)
|
|
24
26
|
@filtered = !search_conditions.blank?
|
|
25
|
-
|
|
27
|
+
active_scaffold_conditions.concat search_conditions if @filtered
|
|
26
28
|
|
|
27
|
-
references, outer_joins = columns.partition{ |column| column.includes.present? && list_columns.include?(column)}
|
|
28
|
-
outer_joins.collect!
|
|
29
|
-
references.collect!
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
references, outer_joins = columns.partition { |column| column.includes.present? && list_columns.include?(column) }
|
|
30
|
+
outer_joins.collect!(&:search_joins)
|
|
31
|
+
references.collect!(&:includes)
|
|
32
|
+
active_scaffold_outer_joins.concat outer_joins.flatten.uniq.compact
|
|
33
|
+
active_scaffold_references.concat references.flatten.uniq.compact
|
|
32
34
|
|
|
33
35
|
active_scaffold_config.list.user.page = nil
|
|
34
36
|
else
|
|
@@ -41,6 +43,7 @@ module ActiveScaffold::Actions
|
|
|
41
43
|
end
|
|
42
44
|
|
|
43
45
|
private
|
|
46
|
+
|
|
44
47
|
def search_formats
|
|
45
48
|
(default_formats + active_scaffold_config.formats + active_scaffold_config.search.formats).uniq
|
|
46
49
|
end
|
|
@@ -7,12 +7,12 @@ module ActiveScaffold::Actions
|
|
|
7
7
|
def show
|
|
8
8
|
# rest destroy falls back to rest show in case of disabled javascript
|
|
9
9
|
# just render action_confirmation message for destroy
|
|
10
|
-
|
|
11
|
-
do_show
|
|
12
|
-
respond_to_action(:show)
|
|
13
|
-
else
|
|
10
|
+
if params.delete :destroy_action
|
|
14
11
|
@record = find_if_allowed(params[:id], :read) if params[:id]
|
|
15
12
|
action_confirmation_respond_to_html(:destroy)
|
|
13
|
+
else
|
|
14
|
+
do_show
|
|
15
|
+
respond_to_action(:show)
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
|
|
@@ -55,14 +55,18 @@ module ActiveScaffold::Actions
|
|
|
55
55
|
def show_authorized?(record = nil)
|
|
56
56
|
(record || self).send(:authorized_for?, :crud_type => :read)
|
|
57
57
|
end
|
|
58
|
+
|
|
58
59
|
def show_ignore?(record = nil)
|
|
59
|
-
!
|
|
60
|
+
!send(:authorized_for?, :crud_type => :read)
|
|
60
61
|
end
|
|
62
|
+
|
|
61
63
|
private
|
|
64
|
+
|
|
62
65
|
def show_authorized_filter
|
|
63
66
|
link = active_scaffold_config.show.link || active_scaffold_config.show.class.link
|
|
64
|
-
raise ActiveScaffold::ActionNotAllowed unless
|
|
67
|
+
raise ActiveScaffold::ActionNotAllowed unless send(link.security_method)
|
|
65
68
|
end
|
|
69
|
+
|
|
66
70
|
def show_formats
|
|
67
71
|
(default_formats + active_scaffold_config.formats + active_scaffold_config.show.formats).uniq
|
|
68
72
|
end
|
|
@@ -20,7 +20,7 @@ module ActiveScaffold::Actions
|
|
|
20
20
|
# NOTE: we don't check whether the user is allowed to update this record, because if not, we'll still let them associate the record. we'll just refuse to do more than associate, is all.
|
|
21
21
|
@record = @column.association.klass.find(params[:associated_id]) if params[:associated_id]
|
|
22
22
|
if @record
|
|
23
|
-
if association = active_scaffold_config.columns[params[:child_association]].association.reverse
|
|
23
|
+
if (association = active_scaffold_config.columns[params[:child_association]].association.reverse)
|
|
24
24
|
if @record.class.reflect_on_association(association).collection?
|
|
25
25
|
@record.send(association) << @parent_record
|
|
26
26
|
else
|
|
@@ -32,6 +32,5 @@ module ActiveScaffold::Actions
|
|
|
32
32
|
end
|
|
33
33
|
@scope = params[:scope]
|
|
34
34
|
end
|
|
35
|
-
|
|
36
35
|
end
|
|
37
36
|
end
|
|
@@ -22,6 +22,7 @@ module ActiveScaffold::Actions
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
protected
|
|
25
|
+
|
|
25
26
|
def edit_respond_to_html
|
|
26
27
|
if successful?
|
|
27
28
|
render(:action => 'update')
|
|
@@ -29,12 +30,13 @@ module ActiveScaffold::Actions
|
|
|
29
30
|
return_to_main
|
|
30
31
|
end
|
|
31
32
|
end
|
|
33
|
+
|
|
32
34
|
def edit_respond_to_js
|
|
33
35
|
render(:partial => 'update_form')
|
|
34
36
|
end
|
|
35
|
-
|
|
37
|
+
|
|
36
38
|
def update_respond_to_html
|
|
37
|
-
if params[:iframe]=='true' # was this an iframe post ?
|
|
39
|
+
if params[:iframe] == 'true' # was this an iframe post ?
|
|
38
40
|
do_refresh_list if successful? && active_scaffold_config.update.refresh_list && !render_parent?
|
|
39
41
|
responds_to_parent do
|
|
40
42
|
render :action => 'on_update', :formats => [:js], :layout => false
|
|
@@ -54,7 +56,7 @@ module ActiveScaffold::Actions
|
|
|
54
56
|
end
|
|
55
57
|
end
|
|
56
58
|
end
|
|
57
|
-
|
|
59
|
+
|
|
58
60
|
def update_respond_to_js
|
|
59
61
|
if successful?
|
|
60
62
|
if !render_parent? && active_scaffold_config.actions.include?(:list)
|
|
@@ -70,15 +72,15 @@ module ActiveScaffold::Actions
|
|
|
70
72
|
end
|
|
71
73
|
render :action => 'on_update'
|
|
72
74
|
end
|
|
73
|
-
|
|
75
|
+
|
|
74
76
|
def update_respond_to_xml
|
|
75
77
|
render :xml => response_object.to_xml(:only => update_columns_names + [active_scaffold_config.model.primary_key], :include => association_columns(update_columns_names), :methods => virtual_columns(update_columns_names)), :content_type => Mime::XML, :status => response_status
|
|
76
78
|
end
|
|
77
|
-
|
|
79
|
+
|
|
78
80
|
def update_respond_to_json
|
|
79
81
|
render :text => response_object.to_json(:only => update_columns_names + [active_scaffold_config.model.primary_key], :include => association_columns(update_columns_names), :methods => virtual_columns(update_columns_names)), :content_type => Mime::JSON, :status => response_status
|
|
80
82
|
end
|
|
81
|
-
|
|
83
|
+
|
|
82
84
|
def update_respond_to_yaml
|
|
83
85
|
render :text => Hash.from_xml(response_object.to_xml(:only => update_columns_names + [active_scaffold_config.model.primary_key], :include => association_columns(update_columns_names), :methods => virtual_columns(update_columns_names))).to_yaml, :content_type => Mime::YAML, :status => response_status
|
|
84
86
|
end
|
|
@@ -109,7 +111,7 @@ module ActiveScaffold::Actions
|
|
|
109
111
|
# errors to @record can be added by update_record_from_params when association fails to set and ActiveRecord::RecordNotSaved is raised
|
|
110
112
|
self.successful = [@record.errors.empty? && @record.valid?, @record.associated_valid?].all? # this syntax avoids a short-circuit
|
|
111
113
|
if successful?
|
|
112
|
-
@record.save!
|
|
114
|
+
@record.save! && @record.save_associated!
|
|
113
115
|
after_update_save(@record)
|
|
114
116
|
else
|
|
115
117
|
# some associations such as habtm are saved before saved is called on parent object
|
|
@@ -121,11 +123,11 @@ module ActiveScaffold::Actions
|
|
|
121
123
|
@record.errors.add(:base, as_(:version_inconsistency))
|
|
122
124
|
self.successful = false
|
|
123
125
|
rescue ActiveRecord::RecordNotSaved => exception
|
|
124
|
-
logger.warn
|
|
126
|
+
logger.warn do
|
|
125
127
|
"\n\n#{exception.class} (#{exception.message}):\n " +
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
128
|
+
Rails.backtrace_cleaner.clean(exception.backtrace).join("\n ") +
|
|
129
|
+
"\n\n"
|
|
130
|
+
end
|
|
129
131
|
@record.errors.add(:base, as_(:record_not_saved)) if @record.errors.empty?
|
|
130
132
|
self.successful = false
|
|
131
133
|
rescue ActiveRecord::ActiveRecordError => ex
|
|
@@ -140,30 +142,31 @@ module ActiveScaffold::Actions
|
|
|
140
142
|
column = params.delete(:column).to_sym
|
|
141
143
|
params.delete(:original_html)
|
|
142
144
|
params.delete(:original_value)
|
|
143
|
-
|
|
144
145
|
@record = find_if_allowed(params[:id], :read)
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
return unless @record.authorized_for?(:crud_type => :update, :column => column)
|
|
147
|
+
|
|
148
|
+
@column = active_scaffold_config.columns[column]
|
|
149
|
+
value ||=
|
|
150
|
+
unless @column.column.nil? || @column.column.null
|
|
148
151
|
@column.column.default == true ? false : @column.column.default
|
|
149
152
|
end
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
153
|
+
unless @column.nil?
|
|
154
|
+
value = column_value_from_param_value(@record, @column, value)
|
|
155
|
+
value = [] if value.nil? && @column.form_ui && @column.plural_association?
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
@record.send("#{@column.name}=", value)
|
|
159
|
+
before_update_save(@record)
|
|
160
|
+
self.successful = @record.save
|
|
161
|
+
if self.successful? && active_scaffold_config.actions.include?(:list)
|
|
162
|
+
if @column.inplace_edit_update == :table
|
|
163
|
+
params.delete(:id)
|
|
164
|
+
do_list
|
|
165
|
+
elsif @column.inplace_edit_update
|
|
166
|
+
get_row
|
|
164
167
|
end
|
|
165
|
-
after_update_save(@record)
|
|
166
168
|
end
|
|
169
|
+
after_update_save(@record)
|
|
167
170
|
end
|
|
168
171
|
|
|
169
172
|
# override this method if you want to inject data in the record (or its associated objects) before the save
|
|
@@ -182,17 +185,22 @@ module ActiveScaffold::Actions
|
|
|
182
185
|
def update_authorized?(record = nil)
|
|
183
186
|
(!nested? || !nested.readonly?) && (record || self).authorized_for?(:crud_type => :update)
|
|
184
187
|
end
|
|
188
|
+
|
|
185
189
|
def update_ignore?(record = nil)
|
|
186
190
|
!self.authorized_for?(:crud_type => :update)
|
|
187
191
|
end
|
|
192
|
+
|
|
188
193
|
private
|
|
194
|
+
|
|
189
195
|
def update_authorized_filter
|
|
190
196
|
link = active_scaffold_config.update.link || active_scaffold_config.update.class.link
|
|
191
|
-
raise ActiveScaffold::ActionNotAllowed unless
|
|
197
|
+
raise ActiveScaffold::ActionNotAllowed unless send(link.security_method)
|
|
192
198
|
end
|
|
199
|
+
|
|
193
200
|
def edit_formats
|
|
194
201
|
(default_formats + active_scaffold_config.formats).uniq
|
|
195
202
|
end
|
|
203
|
+
|
|
196
204
|
def update_formats
|
|
197
205
|
(default_formats + active_scaffold_config.formats + active_scaffold_config.update.formats).uniq
|
|
198
206
|
end
|
|
@@ -14,14 +14,12 @@ module ActiveScaffold
|
|
|
14
14
|
# ActiveRecordPermissions needs to know what method on your ApplicationController will return the current user,
|
|
15
15
|
# if available. This defaults to the :current_user method. You may configure this in your environment.rb if you
|
|
16
16
|
# have a different setup.
|
|
17
|
-
|
|
18
|
-
def self.current_user_method; @@current_user_method; end
|
|
17
|
+
mattr_accessor :current_user_method
|
|
19
18
|
@@current_user_method = :current_user
|
|
20
19
|
|
|
21
20
|
# Whether the default permission is permissive or not
|
|
22
21
|
# If set to true, then everything's allowed until configured otherwise
|
|
23
|
-
|
|
24
|
-
def self.default_permission; @@default_permission; end
|
|
22
|
+
mattr_accessor :default_permission
|
|
25
23
|
@@default_permission = true
|
|
26
24
|
|
|
27
25
|
# This is a module aimed at making the current_user available to ActiveRecord models for permissions.
|
|
@@ -35,7 +33,7 @@ module ActiveScaffold
|
|
|
35
33
|
# because the object may change (someone may log in or out). So we give ActiveRecord a proc that ties to the
|
|
36
34
|
# current_user_method on this ApplicationController.
|
|
37
35
|
def assign_current_user_to_models
|
|
38
|
-
ActiveRecord::Base.current_user_proc = proc {send(ActiveRecordPermissions.current_user_method)}
|
|
36
|
+
ActiveRecord::Base.current_user_proc = proc { send(ActiveRecordPermissions.current_user_method) }
|
|
39
37
|
end
|
|
40
38
|
end
|
|
41
39
|
|
|
@@ -50,6 +48,7 @@ module ActiveScaffold
|
|
|
50
48
|
def current_user_proc
|
|
51
49
|
Thread.current[:current_user_proc]
|
|
52
50
|
end
|
|
51
|
+
|
|
53
52
|
def current_user_proc=(proc_value)
|
|
54
53
|
Thread.current[:current_user_proc] = proc_value
|
|
55
54
|
end
|
|
@@ -93,7 +92,7 @@ module ActiveScaffold
|
|
|
93
92
|
# options[:column] should be the name of a model attribute
|
|
94
93
|
# options[:action] is the name of a method
|
|
95
94
|
def authorized_for?(options = {})
|
|
96
|
-
raise ArgumentError, "unknown crud type #{options[:crud_type]}" if options[:crud_type]
|
|
95
|
+
raise ArgumentError, "unknown crud type #{options[:crud_type]}" if options[:crud_type] && ![:create, :read, :update, :delete].include?(options[:crud_type])
|
|
97
96
|
|
|
98
97
|
# collect other possibly-related methods that actually exist
|
|
99
98
|
methods = cached_authorized_for_methods(options)
|
|
@@ -101,10 +100,10 @@ module ActiveScaffold
|
|
|
101
100
|
return send(methods.first) if methods.one?
|
|
102
101
|
|
|
103
102
|
# if any method returns false, then return false
|
|
104
|
-
return false if methods.any? {|m| !send(m)}
|
|
103
|
+
return false if methods.any? { |m| !send(m) }
|
|
105
104
|
true
|
|
106
105
|
end
|
|
107
|
-
|
|
106
|
+
|
|
108
107
|
def cached_authorized_for_methods(options)
|
|
109
108
|
key = "#{options[:crud_type]}##{options[:column]}##{options[:action]}"
|
|
110
109
|
if self.is_a? Class
|
|
@@ -121,21 +120,21 @@ module ActiveScaffold
|
|
|
121
120
|
# you can disable a crud verb and enable that verb for a column
|
|
122
121
|
# (for example, disable update and enable inplace_edit in a column)
|
|
123
122
|
method = column_and_crud_type_security_method(options[:column], options[:crud_type])
|
|
124
|
-
return [method] if method
|
|
123
|
+
return [method] if method && respond_to?(method)
|
|
125
124
|
|
|
126
125
|
# authorized_for_action? has higher priority than other methods,
|
|
127
126
|
# you can disable a crud verb and enable an action with that crud verb
|
|
128
127
|
# (for example, disable update and enable an action with update as crud type)
|
|
129
128
|
method = action_security_method(options[:action])
|
|
130
|
-
return [method] if method
|
|
129
|
+
return [method] if method && respond_to?(method)
|
|
131
130
|
|
|
132
131
|
# collect other possibly-related methods that actually exist
|
|
133
|
-
|
|
132
|
+
[
|
|
134
133
|
column_security_method(options[:column]),
|
|
135
|
-
crud_type_security_method(options[:crud_type])
|
|
136
|
-
].compact.select {|m| respond_to?(m)}
|
|
134
|
+
crud_type_security_method(options[:crud_type])
|
|
135
|
+
].compact.select { |m| respond_to?(m) }
|
|
137
136
|
end
|
|
138
|
-
|
|
137
|
+
|
|
139
138
|
private
|
|
140
139
|
|
|
141
140
|
def column_security_method(column)
|
|
@@ -151,7 +150,7 @@ module ActiveScaffold
|
|
|
151
150
|
end
|
|
152
151
|
|
|
153
152
|
def column_and_crud_type_security_method(column, crud_type)
|
|
154
|
-
"#{column}_authorized_for_#{crud_type}?" if column
|
|
153
|
+
"#{column}_authorized_for_#{crud_type}?" if column && crud_type
|
|
155
154
|
end
|
|
156
155
|
end
|
|
157
156
|
end
|
|
@@ -32,10 +32,11 @@ module ActiveScaffold
|
|
|
32
32
|
# }
|
|
33
33
|
module AttributeParams
|
|
34
34
|
protected
|
|
35
|
+
|
|
35
36
|
# workaround to update counters when belongs_to changes on persisted record on Rails 3
|
|
36
37
|
# workaround to update counters when polymorphic has_many changes on persisted record
|
|
37
|
-
# TODO remove when rails3 support is removed and counter cache for polymorphic has_many association works on rails4 (works on rails4.2)
|
|
38
|
-
def
|
|
38
|
+
# TODO: remove when rails3 support is removed and counter cache for polymorphic has_many association works on rails4 (works on rails4.2)
|
|
39
|
+
def hack_for_has_many_counter_cache(parent_record, column, value)
|
|
39
40
|
association = parent_record.association(column.name)
|
|
40
41
|
counter_attr = association.send(:cached_counter_attribute_name)
|
|
41
42
|
difference = value.select(&:persisted?).size - parent_record.send(counter_attr)
|
|
@@ -61,24 +62,22 @@ module ActiveScaffold
|
|
|
61
62
|
end
|
|
62
63
|
parent_record.send "#{column.name}=", value if parent_record.persisted?
|
|
63
64
|
end
|
|
64
|
-
|
|
65
|
-
# TODO remove when
|
|
66
|
-
def
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
end
|
|
65
|
+
|
|
66
|
+
# TODO: remove when hack_for_has_many_counter_cache is not needed
|
|
67
|
+
def hack_for_has_many_counter_cache?(parent_record, column)
|
|
68
|
+
return unless column.association.try(:macro) == :has_many && parent_record.association(column.name).send(:has_cached_counter?)
|
|
69
|
+
if Rails.version < '4.0' # rails 3 needs this hack always
|
|
70
|
+
true
|
|
71
|
+
else # rails 4 needs this hack for polymorphic has_many
|
|
72
|
+
column.association.options[:as]
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
# workaround for updating counters twice bug on rails4 (https://github.com/rails/rails/pull/14849)
|
|
77
|
-
# TODO remove when pull request is merged and no version with bug is supported
|
|
77
|
+
# TODO: remove when pull request is merged and no version with bug is supported
|
|
78
78
|
def counter_cache_hack?(column, value)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
end
|
|
79
|
+
return unless Rails.version >= '4.0' && !value.is_a?(Hash)
|
|
80
|
+
column.association.try(:belongs_to?) && column.association.options[:counter_cache] && !column.association.options[:polymorphic]
|
|
82
81
|
end
|
|
83
82
|
|
|
84
83
|
# Takes attributes (as from params[:record]) and applies them to the parent_record. Also looks for
|
|
@@ -102,16 +101,16 @@ module ActiveScaffold
|
|
|
102
101
|
begin
|
|
103
102
|
# Set any passthrough parameters that may be associated with this column (ie, file column "keep" and "temp" attributes)
|
|
104
103
|
unless column.params.empty?
|
|
105
|
-
column.params.each{|p| parent_record.send("#{p}=", attributes[p]) if attributes.
|
|
104
|
+
column.params.each { |p| parent_record.send("#{p}=", attributes[p]) if attributes.key? p }
|
|
106
105
|
end
|
|
107
106
|
|
|
108
|
-
if multi_parameter_attributes.
|
|
107
|
+
if multi_parameter_attributes.key? column.name.to_s
|
|
109
108
|
parent_record.send(:assign_multiparameter_attributes, multi_parameter_attributes[column.name.to_s])
|
|
110
|
-
elsif attributes.
|
|
109
|
+
elsif attributes.key? column.name
|
|
111
110
|
value = update_column_from_params(parent_record, column, attributes[column.name], avoid_changes)
|
|
112
111
|
end
|
|
113
|
-
rescue
|
|
114
|
-
logger.error "#{
|
|
112
|
+
rescue StandardError => e
|
|
113
|
+
logger.error "#{e.class.name}: #{e.message} -- on the ActiveScaffold column = :#{column.name} for #{parent_record.inspect}#{" with value #{value}" if value}"
|
|
115
114
|
raise
|
|
116
115
|
end
|
|
117
116
|
end
|
|
@@ -119,7 +118,7 @@ module ActiveScaffold
|
|
|
119
118
|
flash[:warning] = parent_record.errors.to_a.join("\n") if parent_record.errors.present?
|
|
120
119
|
parent_record
|
|
121
120
|
end
|
|
122
|
-
|
|
121
|
+
|
|
123
122
|
def update_column_from_params(parent_record, column, attribute, avoid_changes = false)
|
|
124
123
|
value = column_value_from_param_value(parent_record, column, attribute, avoid_changes)
|
|
125
124
|
if avoid_changes && column.plural_association?
|
|
@@ -129,8 +128,8 @@ module ActiveScaffold
|
|
|
129
128
|
parent_record.association(column.name).target = value
|
|
130
129
|
else
|
|
131
130
|
begin
|
|
132
|
-
if
|
|
133
|
-
|
|
131
|
+
if hack_for_has_many_counter_cache?(parent_record, column)
|
|
132
|
+
hack_for_has_many_counter_cache(parent_record, column, value)
|
|
134
133
|
else
|
|
135
134
|
parent_record.send "#{column.name}=", value
|
|
136
135
|
end
|
|
@@ -149,14 +148,14 @@ module ActiveScaffold
|
|
|
149
148
|
# convert the value, possibly by instantiating associated objects
|
|
150
149
|
form_ui = column.form_ui || column.column.try(:type)
|
|
151
150
|
if form_ui && self.respond_to?("column_value_for_#{form_ui}_type", true)
|
|
152
|
-
|
|
151
|
+
send("column_value_for_#{form_ui}_type", parent_record, column, value)
|
|
153
152
|
elsif value.is_a?(Hash)
|
|
154
153
|
column_value_from_param_hash_value(parent_record, column, value, avoid_changes)
|
|
155
154
|
else
|
|
156
155
|
column_value_from_param_simple_value(parent_record, column, value)
|
|
157
156
|
end
|
|
158
157
|
end
|
|
159
|
-
|
|
158
|
+
|
|
160
159
|
def datetime_conversion_for_value(column)
|
|
161
160
|
if column.column
|
|
162
161
|
column.column.type == :date ? :to_date : :to_time
|
|
@@ -164,9 +163,9 @@ module ActiveScaffold
|
|
|
164
163
|
:to_time
|
|
165
164
|
end
|
|
166
165
|
end
|
|
167
|
-
|
|
166
|
+
|
|
168
167
|
def column_value_for_datetime_type(parent_record, column, value)
|
|
169
|
-
new_value = self.class.condition_value_for_datetime(column, value,
|
|
168
|
+
new_value = self.class.condition_value_for_datetime(column, value, datetime_conversion_for_value(column))
|
|
170
169
|
if new_value.nil? && value.present?
|
|
171
170
|
parent_record.errors.add column.name, :invalid
|
|
172
171
|
end
|
|
@@ -192,15 +191,15 @@ module ActiveScaffold
|
|
|
192
191
|
# convert empty strings into nil. this works better with 'null => true' columns (and validations),
|
|
193
192
|
# and 'null => false' columns should just convert back to an empty string.
|
|
194
193
|
# ... but we can at least check the ConnectionAdapter::Column object to see if nulls are allowed
|
|
195
|
-
value = nil if value.is_a?
|
|
194
|
+
value = nil if value.is_a?(String) && value.empty? && !column.column.nil? && column.column.null
|
|
196
195
|
value
|
|
197
196
|
end
|
|
198
197
|
end
|
|
199
198
|
|
|
200
199
|
def column_plural_assocation_value_from_value(column, value)
|
|
201
200
|
# it's an array of ids
|
|
202
|
-
if value
|
|
203
|
-
ids = value.select
|
|
201
|
+
if value && !value.empty?
|
|
202
|
+
ids = value.select(&:present?)
|
|
204
203
|
ids.empty? ? [] : column.association.klass.find(ids)
|
|
205
204
|
else
|
|
206
205
|
[]
|
|
@@ -211,13 +210,13 @@ module ActiveScaffold
|
|
|
211
210
|
if column.singular_association?
|
|
212
211
|
manage_nested_record_from_params(parent_record, column, value, avoid_changes)
|
|
213
212
|
elsif column.plural_association?
|
|
214
|
-
# HACK to be able to delete all associated records, hash will include "0" => ""
|
|
215
|
-
value.collect {|
|
|
213
|
+
# HACK: to be able to delete all associated records, hash will include "0" => ""
|
|
214
|
+
value.collect { |_, val| manage_nested_record_from_params(parent_record, column, val, avoid_changes) unless val.blank? }.compact
|
|
216
215
|
else
|
|
217
216
|
value
|
|
218
217
|
end
|
|
219
218
|
end
|
|
220
|
-
|
|
219
|
+
|
|
221
220
|
def manage_nested_record_from_params(parent_record, column, attributes, avoid_changes = false)
|
|
222
221
|
return nil unless build_record_from_params(attributes, column, parent_record)
|
|
223
222
|
record = find_or_create_for_params(attributes, column, parent_record)
|
|
@@ -242,7 +241,7 @@ module ActiveScaffold
|
|
|
242
241
|
def find_or_create_for_params(params, parent_column, parent_record)
|
|
243
242
|
current = parent_record.send(parent_column.name)
|
|
244
243
|
klass = parent_column.association.klass
|
|
245
|
-
if params.
|
|
244
|
+
if params.key? klass.primary_key
|
|
246
245
|
record_from_current_or_find(klass, params[klass.primary_key], current)
|
|
247
246
|
elsif klass.authorized_for?(:crud_type => :create)
|
|
248
247
|
parent_column.association.klass.new
|
|
@@ -252,12 +251,12 @@ module ActiveScaffold
|
|
|
252
251
|
# Attempts to find an instance of klass (which must be an ActiveRecord object) with id primary key
|
|
253
252
|
# Returns record from current if it's included or find from DB
|
|
254
253
|
def record_from_current_or_find(klass, id, current)
|
|
255
|
-
if current
|
|
256
|
-
|
|
254
|
+
if current && current.is_a?(ActiveRecord::Base) && current.id.to_s == id
|
|
255
|
+
# modifying the current object of a singular association
|
|
257
256
|
current
|
|
258
|
-
elsif current
|
|
259
|
-
|
|
260
|
-
current.detect {|o| o.id.to_s == id}
|
|
257
|
+
elsif current && current.respond_to?(:any?) && current.any? { |o| o.id.to_s == id }
|
|
258
|
+
# modifying one of the current objects in a plural association
|
|
259
|
+
current.detect { |o| o.id.to_s == id }
|
|
261
260
|
else # attaching an existing but not-current object
|
|
262
261
|
klass.find(id)
|
|
263
262
|
end
|
|
@@ -276,17 +275,17 @@ module ActiveScaffold
|
|
|
276
275
|
# This isn't a literal emptiness - it's an attempt to discern whether the user intended it to be empty or not.
|
|
277
276
|
def attributes_hash_is_empty?(hash, klass)
|
|
278
277
|
ignore_column_types = [:boolean]
|
|
279
|
-
hash.all? do |key,value|
|
|
278
|
+
hash.all? do |key, value|
|
|
280
279
|
# convert any possible multi-parameter attributes like 'created_at(5i)' to simply 'created_at'
|
|
281
280
|
parts = key.to_s.split('(')
|
|
282
|
-
#old style date form management... ignore them too
|
|
281
|
+
# old style date form management... ignore them too
|
|
283
282
|
ignore_column_types = [:boolean, :datetime, :date, :time] if parts.length > 1
|
|
284
283
|
column_name = parts.first
|
|
285
284
|
column = klass.columns_hash[column_name]
|
|
286
285
|
|
|
287
286
|
# booleans and datetimes will always have a value. so we ignore them when checking whether the hash is empty.
|
|
288
287
|
# this could be a bad idea. but the current situation (excess record entry) seems worse.
|
|
289
|
-
next true if column
|
|
288
|
+
next true if column && ignore_column_types.include?(column.type)
|
|
290
289
|
|
|
291
290
|
# defaults are pre-filled on the form. we can't use them to determine if the user intends a new row.
|
|
292
291
|
next true if value == column_default_value(column_name, klass, column)
|
|
@@ -300,7 +299,7 @@ module ActiveScaffold
|
|
|
300
299
|
end
|
|
301
300
|
end
|
|
302
301
|
end
|
|
303
|
-
|
|
302
|
+
|
|
304
303
|
def column_default_value(column_name, klass, column)
|
|
305
304
|
column.default.to_s if column
|
|
306
305
|
end
|