active_scaffold 3.2.17 → 3.2.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.
- data/CHANGELOG +5 -1
- metadata +17 -261
- data/app/assets/images/active_scaffold/add.png +0 -0
- data/app/assets/images/active_scaffold/arrow_down.png +0 -0
- data/app/assets/images/active_scaffold/arrow_up.png +0 -0
- data/app/assets/images/active_scaffold/close.png +0 -0
- data/app/assets/images/active_scaffold/close_touch.png +0 -0
- data/app/assets/images/active_scaffold/config.png +0 -0
- data/app/assets/images/active_scaffold/cross.png +0 -0
- data/app/assets/images/active_scaffold/gears.png +0 -0
- data/app/assets/images/active_scaffold/indicator-small.gif +0 -0
- data/app/assets/images/active_scaffold/indicator.gif +0 -0
- data/app/assets/images/active_scaffold/magnifier.png +0 -0
- data/app/assets/javascripts/active_scaffold.js.erb +0 -19
- data/app/assets/javascripts/jquery/active_scaffold.js +0 -1113
- data/app/assets/javascripts/jquery/date_picker_bridge.js.erb +0 -24
- data/app/assets/javascripts/jquery/draggable_lists.js +0 -27
- data/app/assets/javascripts/jquery/jquery.editinplace.js +0 -743
- data/app/assets/javascripts/jquery/tiny_mce_bridge.js +0 -7
- data/app/assets/javascripts/prototype/active_scaffold.js +0 -1107
- data/app/assets/javascripts/prototype/dhtml_history.js +0 -870
- data/app/assets/javascripts/prototype/form_enhancements.js +0 -117
- data/app/assets/javascripts/prototype/rico_corner.js +0 -370
- data/app/assets/javascripts/prototype/tiny_mce_bridge.js +0 -7
- data/app/assets/stylesheets/active_scaffold-ie.css.scss +0 -54
- data/app/assets/stylesheets/active_scaffold.css.scss +0 -14
- data/app/assets/stylesheets/active_scaffold_colors.css.scss +0 -395
- data/app/assets/stylesheets/active_scaffold_extensions.css.erb +0 -2
- data/app/assets/stylesheets/active_scaffold_images.css.scss +0 -40
- data/app/assets/stylesheets/active_scaffold_layout.css +0 -936
- data/app/assets/stylesheets/blue-theme.css +0 -74
- data/config/locales/de.yml +0 -125
- data/config/locales/en.yml +0 -127
- data/config/locales/es.yml +0 -128
- data/config/locales/fr.yml +0 -131
- data/config/locales/hu.yml +0 -126
- data/config/locales/ja.yml +0 -126
- data/config/locales/ru.yml +0 -135
- data/frontends/default/views/_action_group.html.erb +0 -24
- data/frontends/default/views/_add_existing_form.html.erb +0 -30
- data/frontends/default/views/_base_form.html.erb +0 -53
- data/frontends/default/views/_create_form.html.erb +0 -8
- data/frontends/default/views/_create_form_on_list.html.erb +0 -6
- data/frontends/default/views/_field_search.html.erb +0 -32
- data/frontends/default/views/_form.html.erb +0 -28
- data/frontends/default/views/_form_association.html.erb +0 -17
- data/frontends/default/views/_form_association_footer.html.erb +0 -47
- data/frontends/default/views/_form_attribute.html.erb +0 -23
- data/frontends/default/views/_form_hidden_attribute.html.erb +0 -7
- data/frontends/default/views/_form_messages.html.erb +0 -5
- data/frontends/default/views/_horizontal_subform.html.erb +0 -22
- data/frontends/default/views/_horizontal_subform_footer.html.erb +0 -0
- data/frontends/default/views/_horizontal_subform_header.html.erb +0 -11
- data/frontends/default/views/_horizontal_subform_record.html.erb +0 -43
- data/frontends/default/views/_human_conditions.html.erb +0 -1
- data/frontends/default/views/_list.html.erb +0 -18
- data/frontends/default/views/_list_actions.html.erb +0 -15
- data/frontends/default/views/_list_calculations.html.erb +0 -16
- data/frontends/default/views/_list_column_headings.html.erb +0 -12
- data/frontends/default/views/_list_header.html.erb +0 -10
- data/frontends/default/views/_list_inline_adapter.html.erb +0 -21
- data/frontends/default/views/_list_messages.html.erb +0 -28
- data/frontends/default/views/_list_pagination.html.erb +0 -11
- data/frontends/default/views/_list_pagination_links.html.erb +0 -9
- data/frontends/default/views/_list_record.html.erb +0 -13
- data/frontends/default/views/_list_record_columns.html.erb +0 -8
- data/frontends/default/views/_list_with_header.html.erb +0 -36
- data/frontends/default/views/_messages.html.erb +0 -10
- data/frontends/default/views/_refresh_list.js.erb +0 -1
- data/frontends/default/views/_render_field.js.erb +0 -20
- data/frontends/default/views/_row.html.erb +0 -1
- data/frontends/default/views/_search.html.erb +0 -34
- data/frontends/default/views/_search_attribute.html.erb +0 -10
- data/frontends/default/views/_show.html.erb +0 -8
- data/frontends/default/views/_show_columns.html.erb +0 -15
- data/frontends/default/views/_update_actions.html.erb +0 -9
- data/frontends/default/views/_update_calculations.js.erb +0 -4
- data/frontends/default/views/_update_form.html.erb +0 -6
- data/frontends/default/views/_update_messages.js.erb +0 -2
- data/frontends/default/views/_vertical_subform.html.erb +0 -12
- data/frontends/default/views/_vertical_subform_record.html.erb +0 -43
- data/frontends/default/views/action_confirmation.html.erb +0 -13
- data/frontends/default/views/add_existing.js.erb +0 -14
- data/frontends/default/views/add_existing_form.html.erb +0 -5
- data/frontends/default/views/create.html.erb +0 -5
- data/frontends/default/views/delete.html.erb +0 -13
- data/frontends/default/views/destroy.js.erb +0 -26
- data/frontends/default/views/edit_associated.js.erb +0 -12
- data/frontends/default/views/field_search.html.erb +0 -5
- data/frontends/default/views/form_messages.js.erb +0 -1
- data/frontends/default/views/list.html.erb +0 -1
- data/frontends/default/views/on_action_update.js.erb +0 -22
- data/frontends/default/views/on_create.js.erb +0 -38
- data/frontends/default/views/on_mark.js.erb +0 -6
- data/frontends/default/views/on_update.js.erb +0 -29
- data/frontends/default/views/refresh_list.js.erb +0 -2
- data/frontends/default/views/render_field.js.erb +0 -1
- data/frontends/default/views/row.js.erb +0 -2
- data/frontends/default/views/search.html.erb +0 -5
- data/frontends/default/views/show.html.erb +0 -5
- data/frontends/default/views/update.html.erb +0 -8
- data/frontends/default/views/update_column.js.erb +0 -15
- data/frontends/default/views/update_row.js.erb +0 -1
- data/lib/active_scaffold.rb +0 -373
- data/lib/active_scaffold/actions/common_search.rb +0 -22
- data/lib/active_scaffold/actions/core.rb +0 -203
- data/lib/active_scaffold/actions/create.rb +0 -139
- data/lib/active_scaffold/actions/delete.rb +0 -74
- data/lib/active_scaffold/actions/field_search.rb +0 -78
- data/lib/active_scaffold/actions/list.rb +0 -208
- data/lib/active_scaffold/actions/mark.rb +0 -89
- data/lib/active_scaffold/actions/nested.rb +0 -244
- data/lib/active_scaffold/actions/search.rb +0 -48
- data/lib/active_scaffold/actions/show.rb +0 -61
- data/lib/active_scaffold/actions/subform.rb +0 -23
- data/lib/active_scaffold/actions/update.rb +0 -156
- data/lib/active_scaffold/active_record_permissions.rb +0 -135
- data/lib/active_scaffold/attribute_params.rb +0 -200
- data/lib/active_scaffold/bridges.rb +0 -61
- data/lib/active_scaffold/bridges/ancestry.rb +0 -5
- data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +0 -39
- data/lib/active_scaffold/bridges/bitfields.rb +0 -6
- data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +0 -37
- data/lib/active_scaffold/bridges/calendar_date_select.rb +0 -24
- data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +0 -66
- data/lib/active_scaffold/bridges/cancan.rb +0 -15
- data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +0 -127
- data/lib/active_scaffold/bridges/carrierwave.rb +0 -12
- data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +0 -31
- data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge_helpers.rb +0 -10
- data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +0 -45
- data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +0 -17
- data/lib/active_scaffold/bridges/country_helper.rb +0 -9
- data/lib/active_scaffold/bridges/country_helper/country_helper_bridge.rb +0 -358
- data/lib/active_scaffold/bridges/date_picker.rb +0 -23
- data/lib/active_scaffold/bridges/date_picker/ext.rb +0 -63
- data/lib/active_scaffold/bridges/date_picker/helper.rb +0 -180
- data/lib/active_scaffold/bridges/dragonfly.rb +0 -9
- data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge.rb +0 -34
- data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge_helpers.rb +0 -10
- data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +0 -27
- data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +0 -16
- data/lib/active_scaffold/bridges/file_column.rb +0 -11
- data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +0 -46
- data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +0 -57
- data/lib/active_scaffold/bridges/file_column/form_ui.rb +0 -34
- data/lib/active_scaffold/bridges/file_column/list_ui.rb +0 -26
- data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +0 -43
- data/lib/active_scaffold/bridges/file_column/test/mock_model.rb +0 -9
- data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +0 -15
- data/lib/active_scaffold/bridges/paperclip.rb +0 -12
- data/lib/active_scaffold/bridges/paperclip/form_ui.rb +0 -27
- data/lib/active_scaffold/bridges/paperclip/list_ui.rb +0 -16
- data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +0 -36
- data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +0 -24
- data/lib/active_scaffold/bridges/record_select.rb +0 -11
- data/lib/active_scaffold/bridges/record_select/helpers.rb +0 -92
- data/lib/active_scaffold/bridges/semantic_attributes.rb +0 -5
- data/lib/active_scaffold/bridges/semantic_attributes/column.rb +0 -20
- data/lib/active_scaffold/bridges/shared/date_bridge.rb +0 -209
- data/lib/active_scaffold/bridges/tiny_mce.rb +0 -17
- data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +0 -46
- data/lib/active_scaffold/config/base.rb +0 -75
- data/lib/active_scaffold/config/core.rb +0 -236
- data/lib/active_scaffold/config/create.rb +0 -32
- data/lib/active_scaffold/config/delete.rb +0 -32
- data/lib/active_scaffold/config/field_search.rb +0 -79
- data/lib/active_scaffold/config/form.rb +0 -64
- data/lib/active_scaffold/config/list.rb +0 -247
- data/lib/active_scaffold/config/mark.rb +0 -30
- data/lib/active_scaffold/config/nested.rb +0 -42
- data/lib/active_scaffold/config/search.rb +0 -73
- data/lib/active_scaffold/config/show.rb +0 -31
- data/lib/active_scaffold/config/subform.rb +0 -35
- data/lib/active_scaffold/config/update.rb +0 -33
- data/lib/active_scaffold/configurable.rb +0 -29
- data/lib/active_scaffold/constraints.rb +0 -171
- data/lib/active_scaffold/data_structures/action_columns.rb +0 -142
- data/lib/active_scaffold/data_structures/action_link.rb +0 -185
- data/lib/active_scaffold/data_structures/action_links.rb +0 -191
- data/lib/active_scaffold/data_structures/actions.rb +0 -45
- data/lib/active_scaffold/data_structures/bridge.rb +0 -22
- data/lib/active_scaffold/data_structures/column.rb +0 -401
- data/lib/active_scaffold/data_structures/columns.rb +0 -75
- data/lib/active_scaffold/data_structures/error_message.rb +0 -24
- data/lib/active_scaffold/data_structures/nested_info.rb +0 -171
- data/lib/active_scaffold/data_structures/set.rb +0 -61
- data/lib/active_scaffold/data_structures/sorting.rb +0 -167
- data/lib/active_scaffold/engine.rb +0 -4
- data/lib/active_scaffold/extensions/action_controller_rendering.rb +0 -20
- data/lib/active_scaffold/extensions/action_controller_rescueing.rb +0 -7
- data/lib/active_scaffold/extensions/action_view_rendering.rb +0 -115
- data/lib/active_scaffold/extensions/active_record_offset.rb +0 -12
- data/lib/active_scaffold/extensions/array.rb +0 -7
- data/lib/active_scaffold/extensions/cache_association.rb +0 -16
- data/lib/active_scaffold/extensions/localize.rb +0 -10
- data/lib/active_scaffold/extensions/name_option_for_datetime.rb +0 -12
- data/lib/active_scaffold/extensions/nil_id_in_url_params.rb +0 -7
- data/lib/active_scaffold/extensions/paginator_extensions.rb +0 -26
- data/lib/active_scaffold/extensions/reverse_associations.rb +0 -64
- data/lib/active_scaffold/extensions/routing_mapper.rb +0 -48
- data/lib/active_scaffold/extensions/to_label.rb +0 -8
- data/lib/active_scaffold/extensions/unsaved_associated.rb +0 -61
- data/lib/active_scaffold/extensions/unsaved_record.rb +0 -20
- data/lib/active_scaffold/extensions/usa_state.rb +0 -46
- data/lib/active_scaffold/finder.rb +0 -399
- data/lib/active_scaffold/helpers/association_helpers.rb +0 -42
- data/lib/active_scaffold/helpers/controller_helpers.rb +0 -94
- data/lib/active_scaffold/helpers/form_column_helpers.rb +0 -322
- data/lib/active_scaffold/helpers/human_condition_helpers.rb +0 -64
- data/lib/active_scaffold/helpers/id_helpers.rb +0 -131
- data/lib/active_scaffold/helpers/list_column_helpers.rb +0 -374
- data/lib/active_scaffold/helpers/pagination_helpers.rb +0 -62
- data/lib/active_scaffold/helpers/search_column_helpers.rb +0 -257
- data/lib/active_scaffold/helpers/show_column_helpers.rb +0 -44
- data/lib/active_scaffold/helpers/view_helpers.rb +0 -398
- data/lib/active_scaffold/marked_model.rb +0 -38
- data/lib/active_scaffold/paginator.rb +0 -136
- data/lib/active_scaffold/responds_to_parent.rb +0 -70
- data/lib/active_scaffold/tableless.rb +0 -83
- data/lib/active_scaffold/version.rb +0 -9
- data/lib/active_scaffold_env.rb +0 -13
- data/lib/generators/active_scaffold/USAGE +0 -29
- data/lib/generators/active_scaffold/active_scaffold_generator.rb +0 -21
- data/lib/generators/active_scaffold_controller/USAGE +0 -19
- data/lib/generators/active_scaffold_controller/active_scaffold_controller_generator.rb +0 -29
- data/lib/generators/active_scaffold_controller/templates/controller.rb +0 -4
- data/lib/generators/active_scaffold_controller/templates/helper.rb +0 -2
- data/public/blank.html +0 -33
- data/shoulda_macros/macros.rb +0 -136
- data/vendor/assets/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/vendor/assets/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/vendor/assets/images/ui-bg_flat_10_000000_40x100.png +0 -0
- data/vendor/assets/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/vendor/assets/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/vendor/assets/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/vendor/assets/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/vendor/assets/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/vendor/assets/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/vendor/assets/images/ui-icons_222222_256x240.png +0 -0
- data/vendor/assets/images/ui-icons_228ef1_256x240.png +0 -0
- data/vendor/assets/images/ui-icons_ef8c08_256x240.png +0 -0
- data/vendor/assets/images/ui-icons_ffd27a_256x240.png +0 -0
- data/vendor/assets/images/ui-icons_ffffff_256x240.png +0 -0
- data/vendor/assets/javascripts/jquery-ui-timepicker-addon.js +0 -1276
- data/vendor/assets/stylesheets/jquery-ui.css +0 -568
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
module ActiveScaffold::Actions
|
|
2
|
-
module Search
|
|
3
|
-
include ActiveScaffold::Actions::CommonSearch
|
|
4
|
-
def self.included(base)
|
|
5
|
-
base.before_filter :search_authorized_filter, :only => :show_search
|
|
6
|
-
base.before_filter :store_search_params_into_session, :only => [:index]
|
|
7
|
-
base.before_filter :do_search, :only => [:index]
|
|
8
|
-
base.helper_method :search_params
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def show_search
|
|
12
|
-
respond_to_action(:search)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
protected
|
|
16
|
-
def search_respond_to_html
|
|
17
|
-
render(:action => "search")
|
|
18
|
-
end
|
|
19
|
-
def search_respond_to_js
|
|
20
|
-
render(:partial => "search")
|
|
21
|
-
end
|
|
22
|
-
def do_search
|
|
23
|
-
query = search_params.to_s.strip rescue ''
|
|
24
|
-
unless query.empty?
|
|
25
|
-
columns = active_scaffold_config.search.columns
|
|
26
|
-
text_search = active_scaffold_config.search.text_search
|
|
27
|
-
query = query.split(active_scaffold_config.search.split_terms) if active_scaffold_config.search.split_terms
|
|
28
|
-
search_conditions = self.class.create_conditions_for_columns(query, columns, text_search)
|
|
29
|
-
@filtered = !search_conditions.blank?
|
|
30
|
-
self.active_scaffold_conditions.concat search_conditions if @filtered
|
|
31
|
-
|
|
32
|
-
includes_for_search_columns = columns.collect{ |column| column.includes}.flatten.uniq.compact
|
|
33
|
-
self.active_scaffold_includes.concat includes_for_search_columns
|
|
34
|
-
|
|
35
|
-
active_scaffold_config.list.user.page = nil
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
private
|
|
40
|
-
def search_authorized_filter
|
|
41
|
-
link = active_scaffold_config.search.link || active_scaffold_config.search.class.link
|
|
42
|
-
raise ActiveScaffold::ActionNotAllowed unless self.send(link.security_method)
|
|
43
|
-
end
|
|
44
|
-
def search_formats
|
|
45
|
-
(default_formats + active_scaffold_config.formats + active_scaffold_config.search.formats).uniq
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
module ActiveScaffold::Actions
|
|
2
|
-
module Show
|
|
3
|
-
def self.included(base)
|
|
4
|
-
base.before_filter :show_authorized_filter, :only => :show
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
def show
|
|
8
|
-
# rest destroy falls back to rest show in case of disabled javascript
|
|
9
|
-
# just render action_confirmation message for destroy
|
|
10
|
-
unless params.delete :destroy_action
|
|
11
|
-
do_show
|
|
12
|
-
successful?
|
|
13
|
-
respond_to_action(:show)
|
|
14
|
-
else
|
|
15
|
-
@record = find_if_allowed(params[:id], :read) if params[:id] && params[:id] && params[:id].to_i > 0
|
|
16
|
-
action_confirmation_respond_to_html(:destroy)
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
protected
|
|
21
|
-
|
|
22
|
-
def show_respond_to_json
|
|
23
|
-
render :text => response_object.to_json(:only => active_scaffold_config.show.columns.names), :content_type => Mime::JSON, :status => response_status
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def show_respond_to_yaml
|
|
27
|
-
render :text => Hash.from_xml(response_object.to_xml(:only => active_scaffold_config.show.columns.names)).to_yaml, :content_type => Mime::YAML, :status => response_status
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def show_respond_to_xml
|
|
31
|
-
render :xml => response_object.to_xml(:only => active_scaffold_config.show.columns.names), :content_type => Mime::XML, :status => response_status
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def show_respond_to_js
|
|
35
|
-
render :partial => 'show'
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def show_respond_to_html
|
|
39
|
-
render :action => 'show'
|
|
40
|
-
end
|
|
41
|
-
# A simple method to retrieve and prepare a record for showing.
|
|
42
|
-
# May be overridden to customize show routine
|
|
43
|
-
def do_show
|
|
44
|
-
@record = find_if_allowed(params[:id], :read)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# The default security delegates to ActiveRecordPermissions.
|
|
48
|
-
# You may override the method to customize.
|
|
49
|
-
def show_authorized?(record = nil)
|
|
50
|
-
(record || self).send(:authorized_for?, :crud_type => :read)
|
|
51
|
-
end
|
|
52
|
-
private
|
|
53
|
-
def show_authorized_filter
|
|
54
|
-
link = active_scaffold_config.show.link || active_scaffold_config.show.class.link
|
|
55
|
-
raise ActiveScaffold::ActionNotAllowed unless self.send(link.security_method)
|
|
56
|
-
end
|
|
57
|
-
def show_formats
|
|
58
|
-
(default_formats + active_scaffold_config.formats + active_scaffold_config.show.formats).uniq
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
module ActiveScaffold::Actions
|
|
2
|
-
module Subform
|
|
3
|
-
def edit_associated
|
|
4
|
-
do_edit_associated
|
|
5
|
-
render :action => 'edit_associated', :formats => [:js]
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
protected
|
|
9
|
-
|
|
10
|
-
def do_edit_associated
|
|
11
|
-
@parent_record = params[:id].nil? ? new_model : find_if_allowed(params[:id], :update)
|
|
12
|
-
@column = active_scaffold_config.columns[params[:child_association]]
|
|
13
|
-
|
|
14
|
-
# 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.
|
|
15
|
-
@record = @column.association.klass.find(params[:associated_id]) if params[:associated_id]
|
|
16
|
-
@record ||= build_associated(@column, @parent_record)
|
|
17
|
-
|
|
18
|
-
@scope = "#{params[:scope]}[#{@column.name}]"
|
|
19
|
-
@scope += (@record.new_record?) ? "[#{(Time.now.to_f*1000).to_i.to_s}]" : "[#{@record.id}]" if @column.plural_association?
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
end
|
|
23
|
-
end
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
module ActiveScaffold::Actions
|
|
2
|
-
module Update
|
|
3
|
-
def self.included(base)
|
|
4
|
-
base.before_filter :update_authorized_filter, :only => [:edit, :update]
|
|
5
|
-
base.helper_method :update_refresh_list?
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def edit
|
|
9
|
-
do_edit
|
|
10
|
-
respond_to_action(:edit)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def update
|
|
14
|
-
do_update
|
|
15
|
-
respond_to_action(:update)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# for inline (inlist) editing
|
|
19
|
-
def update_column
|
|
20
|
-
do_update_column
|
|
21
|
-
@column_span_id = params[:editor_id] || params[:editorId]
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
protected
|
|
25
|
-
def edit_respond_to_html
|
|
26
|
-
if successful?
|
|
27
|
-
render(:action => 'update')
|
|
28
|
-
else
|
|
29
|
-
return_to_main
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
def edit_respond_to_js
|
|
33
|
-
render(:partial => 'update_form')
|
|
34
|
-
end
|
|
35
|
-
def update_respond_to_html
|
|
36
|
-
if params[:iframe]=='true' # was this an iframe post ?
|
|
37
|
-
responds_to_parent do
|
|
38
|
-
render :action => 'on_update', :formats => [:js], :layout => false
|
|
39
|
-
end
|
|
40
|
-
else # just a regular post
|
|
41
|
-
if successful?
|
|
42
|
-
flash[:info] = as_(:updated_model, :model => @record.to_label)
|
|
43
|
-
return_to_main
|
|
44
|
-
else
|
|
45
|
-
render(:action => 'update')
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
def update_respond_to_js
|
|
50
|
-
if successful?
|
|
51
|
-
do_refresh_list if update_refresh_list? && !render_parent?
|
|
52
|
-
flash.now[:info] = as_(:updated_model, :model => @record.to_label) if active_scaffold_config.update.persistent
|
|
53
|
-
end
|
|
54
|
-
render :action => 'on_update'
|
|
55
|
-
end
|
|
56
|
-
def update_respond_to_xml
|
|
57
|
-
render :xml => response_object.to_xml(:only => active_scaffold_config.update.columns.names), :content_type => Mime::XML, :status => response_status
|
|
58
|
-
end
|
|
59
|
-
def update_respond_to_json
|
|
60
|
-
render :text => response_object.to_json(:only => active_scaffold_config.update.columns.names), :content_type => Mime::JSON, :status => response_status
|
|
61
|
-
end
|
|
62
|
-
def update_respond_to_yaml
|
|
63
|
-
render :text => Hash.from_xml(response_object.to_xml(:only => active_scaffold_config.update.columns.names)).to_yaml, :content_type => Mime::YAML, :status => response_status
|
|
64
|
-
end
|
|
65
|
-
# A simple method to find and prepare a record for editing
|
|
66
|
-
# May be overridden to customize the record (set default values, etc.)
|
|
67
|
-
def do_edit
|
|
68
|
-
@record = find_if_allowed(params[:id], :update)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
# A complex method to update a record. The complexity comes from the support for subforms, and saving associated records.
|
|
72
|
-
# If you want to customize this algorithm, consider using the +before_update_save+ callback
|
|
73
|
-
def do_update
|
|
74
|
-
do_edit
|
|
75
|
-
update_save
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def update_save(options = {})
|
|
79
|
-
attributes = options[:attributes] || params[:record]
|
|
80
|
-
begin
|
|
81
|
-
active_scaffold_config.model.transaction do
|
|
82
|
-
@record = update_record_from_params(@record, active_scaffold_config.update.columns, attributes) unless options[:no_record_param_update]
|
|
83
|
-
before_update_save(@record)
|
|
84
|
-
self.successful = [@record.valid?, @record.associated_valid?].all? {|v| v == true} # this syntax avoids a short-circuit
|
|
85
|
-
if successful?
|
|
86
|
-
@record.save! and @record.save_associated!
|
|
87
|
-
after_update_save(@record)
|
|
88
|
-
else
|
|
89
|
-
# some associations such as habtm are saved before saved is called on parent object
|
|
90
|
-
# we have to revert these changes if validation fails
|
|
91
|
-
raise ActiveRecord::Rollback, "don't save habtm associations unless record is valid"
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
rescue ActiveRecord::StaleObjectError
|
|
95
|
-
@record.errors.add(:base, as_(:version_inconsistency))
|
|
96
|
-
self.successful = false
|
|
97
|
-
rescue ActiveRecord::RecordNotSaved
|
|
98
|
-
@record.errors.add(:base, as_(:record_not_saved)) if @record.errors.empty?
|
|
99
|
-
self.successful = false
|
|
100
|
-
rescue ActiveRecord::ActiveRecordError => ex
|
|
101
|
-
flash[:error] = ex.message
|
|
102
|
-
self.successful = false
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def do_update_column
|
|
107
|
-
@record = active_scaffold_config.model.find(params[:id])
|
|
108
|
-
if @record.authorized_for?(:crud_type => :update, :column => params[:column])
|
|
109
|
-
column = active_scaffold_config.columns[params[:column].to_sym]
|
|
110
|
-
unless @record.column_for_attribute(params[:column]).nil? || @record.column_for_attribute(params[:column]).null
|
|
111
|
-
if @record.column_for_attribute(params[:column]).default == true
|
|
112
|
-
params[:value] ||= false
|
|
113
|
-
else
|
|
114
|
-
params[:value] ||= @record.column_for_attribute(params[:column]).default
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
unless column.nil?
|
|
118
|
-
params[:value] = column_value_from_param_value(@record, column, params[:value])
|
|
119
|
-
params[:value] = [] if params[:value].nil? && column.form_ui && column.plural_association?
|
|
120
|
-
end
|
|
121
|
-
@record.send("#{params[:column]}=", params[:value])
|
|
122
|
-
before_update_save(@record)
|
|
123
|
-
@record.save
|
|
124
|
-
after_update_save(@record)
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
# override this method if you want to inject data in the record (or its associated objects) before the save
|
|
129
|
-
def before_update_save(record); end
|
|
130
|
-
|
|
131
|
-
# override this method if you want to do something after the save
|
|
132
|
-
def after_update_save(record); end
|
|
133
|
-
|
|
134
|
-
# should we refresh whole list after update operation
|
|
135
|
-
def update_refresh_list?
|
|
136
|
-
active_scaffold_config.update.refresh_list
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
# The default security delegates to ActiveRecordPermissions.
|
|
140
|
-
# You may override the method to customize.
|
|
141
|
-
def update_authorized?(record = nil)
|
|
142
|
-
(!nested? || !nested.readonly?) && (record || self).send(:authorized_for?, :crud_type => :update)
|
|
143
|
-
end
|
|
144
|
-
private
|
|
145
|
-
def update_authorized_filter
|
|
146
|
-
link = active_scaffold_config.update.link || active_scaffold_config.update.class.link
|
|
147
|
-
raise ActiveScaffold::ActionNotAllowed unless self.send(link.security_method)
|
|
148
|
-
end
|
|
149
|
-
def edit_formats
|
|
150
|
-
(default_formats + active_scaffold_config.formats).uniq
|
|
151
|
-
end
|
|
152
|
-
def update_formats
|
|
153
|
-
(default_formats + active_scaffold_config.formats + active_scaffold_config.update.formats).uniq
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
end
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
# This module attempts to create permissions conventions for your ActiveRecord models. It supports english-based
|
|
2
|
-
# methods that let you restrict access per-model, per-record, per-column, per-action, and per-user. All at once.
|
|
3
|
-
#
|
|
4
|
-
# You may define instance methods in the following formats:
|
|
5
|
-
# def #{column}_authorized_for_#{action}?
|
|
6
|
-
# def #{column}_authorized?
|
|
7
|
-
# def authorized_for_#{action}?
|
|
8
|
-
#
|
|
9
|
-
# Your methods should allow for the following special cases:
|
|
10
|
-
# * cron scripts
|
|
11
|
-
# * guest users (or nil current_user objects)
|
|
12
|
-
module ActiveRecordPermissions
|
|
13
|
-
# ActiveRecordPermissions needs to know what method on your ApplicationController will return the current user,
|
|
14
|
-
# if available. This defaults to the :current_user method. You may configure this in your environment.rb if you
|
|
15
|
-
# have a different setup.
|
|
16
|
-
def self.current_user_method=(v); @@current_user_method = v; end
|
|
17
|
-
def self.current_user_method; @@current_user_method; end
|
|
18
|
-
@@current_user_method = :current_user
|
|
19
|
-
|
|
20
|
-
# Whether the default permission is permissive or not
|
|
21
|
-
# If set to true, then everything's allowed until configured otherwise
|
|
22
|
-
def self.default_permission=(v); @@default_permission = v; end
|
|
23
|
-
def self.default_permission; @@default_permission; end
|
|
24
|
-
@@default_permission = true
|
|
25
|
-
|
|
26
|
-
# This is a module aimed at making the current_user available to ActiveRecord models for permissions.
|
|
27
|
-
module ModelUserAccess
|
|
28
|
-
module Controller
|
|
29
|
-
def self.included(base)
|
|
30
|
-
base.prepend_before_filter :assign_current_user_to_models
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# We need to give the ActiveRecord classes a handle to the current user. We don't want to just pass the object,
|
|
34
|
-
# because the object may change (someone may log in or out). So we give ActiveRecord a proc that ties to the
|
|
35
|
-
# current_user_method on this ApplicationController.
|
|
36
|
-
def assign_current_user_to_models
|
|
37
|
-
ActiveRecord::Base.current_user_proc = proc {send(ActiveRecordPermissions.current_user_method)}
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
module Model
|
|
42
|
-
def self.included(base)
|
|
43
|
-
base.extend ClassMethods
|
|
44
|
-
base.send :include, ActiveRecordPermissions::Permissions
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
module ClassMethods
|
|
48
|
-
# The proc to call that retrieves the current_user from the ApplicationController.
|
|
49
|
-
attr_accessor :current_user_proc
|
|
50
|
-
|
|
51
|
-
# Class-level access to the current user
|
|
52
|
-
def current_user
|
|
53
|
-
ActiveRecord::Base.current_user_proc.call if ActiveRecord::Base.current_user_proc
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# Instance-level access to the current user
|
|
58
|
-
def current_user
|
|
59
|
-
self.class.current_user
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
module Permissions
|
|
65
|
-
def self.included(base)
|
|
66
|
-
base.extend SecurityMethods
|
|
67
|
-
base.send :include, SecurityMethods
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
# Because any class-level queries get delegated to the instance level via a new record,
|
|
71
|
-
# it's useful to know when the authorization query is meant for a specific record or not.
|
|
72
|
-
# But using new_record? is confusing, even though accurate. So this is basically just a wrapper.
|
|
73
|
-
def existing_record_check?
|
|
74
|
-
!new_record?
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
module SecurityMethods
|
|
78
|
-
# A generic authorization query. This is what will be called programatically, since
|
|
79
|
-
# the actual permission methods can't be guaranteed to exist. And because we want to
|
|
80
|
-
# intelligently combine multiple applicable methods.
|
|
81
|
-
#
|
|
82
|
-
# options[:crud_type] should be a CRUD verb (:create, :read, :update, :destroy)
|
|
83
|
-
# options[:column] should be the name of a model attribute
|
|
84
|
-
# options[:action] is the name of a method
|
|
85
|
-
def authorized_for?(options = {})
|
|
86
|
-
raise ArgumentError, "unknown crud type #{options[:crud_type]}" if options[:crud_type] and ![:create, :read, :update, :delete].include?(options[:crud_type])
|
|
87
|
-
|
|
88
|
-
# column_authorized_for_crud_type? has the highest priority over other methods,
|
|
89
|
-
# you can disable a crud verb and enable that verb for a column
|
|
90
|
-
# (for example, disable update and enable inplace_edit in a column)
|
|
91
|
-
method = column_and_crud_type_security_method(options[:column], options[:crud_type])
|
|
92
|
-
return send(method) if method and respond_to?(method)
|
|
93
|
-
|
|
94
|
-
# authorized_for_action? has higher priority than other methods,
|
|
95
|
-
# you can disable a crud verb and enable an action with that crud verb
|
|
96
|
-
# (for example, disable update and enable an action with update as crud type)
|
|
97
|
-
method = action_security_method(options[:action])
|
|
98
|
-
return send(method) if method and respond_to?(method)
|
|
99
|
-
|
|
100
|
-
# collect other possibly-related methods that actually exist
|
|
101
|
-
methods = [
|
|
102
|
-
column_security_method(options[:column]),
|
|
103
|
-
crud_type_security_method(options[:crud_type]),
|
|
104
|
-
].compact.select {|m| respond_to?(m)}
|
|
105
|
-
|
|
106
|
-
# if any method returns false, then return false
|
|
107
|
-
return false if methods.any? {|m| !send(m)}
|
|
108
|
-
|
|
109
|
-
# if any method actually exists then it must've returned true, so return true
|
|
110
|
-
return true unless methods.empty?
|
|
111
|
-
|
|
112
|
-
# if no method exists, return the default permission
|
|
113
|
-
return ActiveRecordPermissions.default_permission
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
private
|
|
117
|
-
|
|
118
|
-
def column_security_method(column)
|
|
119
|
-
"#{column}_authorized?" if column
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def crud_type_security_method(crud_type)
|
|
123
|
-
"authorized_for_#{crud_type}?" if crud_type
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def action_security_method(action)
|
|
127
|
-
"authorized_for_#{action}?" if action
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def column_and_crud_type_security_method(column, crud_type)
|
|
131
|
-
"#{column}_authorized_for_#{crud_type}?" if column and crud_type
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
end
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
module ActiveScaffold
|
|
2
|
-
# Provides support for param hashes assumed to be model attributes.
|
|
3
|
-
# Support is primarily needed for creating/editing associated records using a nested hash structure.
|
|
4
|
-
#
|
|
5
|
-
# Paradigm Params Hash (should write unit tests on this):
|
|
6
|
-
# params[:record] = {
|
|
7
|
-
# # a simple record attribute
|
|
8
|
-
# 'name' => 'John',
|
|
9
|
-
# # a plural association hash
|
|
10
|
-
# 'roles' => {
|
|
11
|
-
# # associate with an existing role
|
|
12
|
-
# '5' => {'id' => 5}
|
|
13
|
-
# # associate with an existing role and edit it
|
|
14
|
-
# '6' => {'id' => 6, 'name' => 'designer'}
|
|
15
|
-
# # create and associate a new role
|
|
16
|
-
# '124521' => {'name' => 'marketer'}
|
|
17
|
-
# }
|
|
18
|
-
# # a singular association hash
|
|
19
|
-
# 'location' => {'id' => 12, 'city' => 'New York'}
|
|
20
|
-
# }
|
|
21
|
-
#
|
|
22
|
-
# Simpler association structures are also supported, like:
|
|
23
|
-
# params[:record] = {
|
|
24
|
-
# # a simple record attribute
|
|
25
|
-
# 'name' => 'John',
|
|
26
|
-
# # a plural association ... all ids refer to existing records
|
|
27
|
-
# 'roles' => ['5', '6'],
|
|
28
|
-
# # a singular association ... all ids refer to existing records
|
|
29
|
-
# 'location' => '12'
|
|
30
|
-
# }
|
|
31
|
-
module AttributeParams
|
|
32
|
-
protected
|
|
33
|
-
# Takes attributes (as from params[:record]) and applies them to the parent_record. Also looks for
|
|
34
|
-
# association attributes and attempts to instantiate them as associated objects.
|
|
35
|
-
#
|
|
36
|
-
# This is a secure way to apply params to a record, because it's based on a loop over the columns
|
|
37
|
-
# set. The columns set will not yield unauthorized columns, and it will not yield unregistered columns.
|
|
38
|
-
def update_record_from_params(parent_record, columns, attributes)
|
|
39
|
-
crud_type = parent_record.new_record? ? :create : :update
|
|
40
|
-
return parent_record unless parent_record.authorized_for?(:crud_type => crud_type)
|
|
41
|
-
|
|
42
|
-
multi_parameter_attributes = {}
|
|
43
|
-
attributes.each do |k, v|
|
|
44
|
-
next unless k.include? '('
|
|
45
|
-
column_name = k.split('(').first.to_sym
|
|
46
|
-
multi_parameter_attributes[column_name] ||= []
|
|
47
|
-
multi_parameter_attributes[column_name] << [k, v]
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
columns.each :for => parent_record, :crud_type => crud_type, :flatten => true do |column|
|
|
51
|
-
# Set any passthrough parameters that may be associated with this column (ie, file column "keep" and "temp" attributes)
|
|
52
|
-
unless column.params.empty?
|
|
53
|
-
column.params.each{|p| parent_record.send("#{p}=", attributes[p]) if attributes.has_key? p}
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
if multi_parameter_attributes.has_key? column.name
|
|
57
|
-
parent_record.send(:assign_multiparameter_attributes, multi_parameter_attributes[column.name])
|
|
58
|
-
elsif attributes.has_key? column.name
|
|
59
|
-
value = column_value_from_param_value(parent_record, column, attributes[column.name])
|
|
60
|
-
|
|
61
|
-
# we avoid assigning a value that already exists because otherwise has_one associations will break (AR bug in has_one_association.rb#replace)
|
|
62
|
-
parent_record.send("#{column.name}=", value) unless parent_record.send(column.name) == value
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
if parent_record.new_record?
|
|
67
|
-
parent_record.class.reflect_on_all_associations.each do |a|
|
|
68
|
-
next unless [:has_one, :has_many].include?(a.macro) and not (a.options[:through] || a.options[:finder_sql])
|
|
69
|
-
next unless association_proxy = parent_record.send(a.name)
|
|
70
|
-
|
|
71
|
-
raise ActiveScaffold::ReverseAssociationRequired, "Association #{a.name} in class #{parent_record.class.name}: In order to support :has_one and :has_many where the parent record is new and the child record(s) validate the presence of the parent, ActiveScaffold requires the reverse association (the belongs_to)." unless a.reverse
|
|
72
|
-
|
|
73
|
-
association_proxy = [association_proxy] if a.macro == :has_one
|
|
74
|
-
association_proxy.each { |record| record.send("#{a.reverse}=", parent_record) }
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
parent_record
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def manage_nested_record_from_params(parent_record, column, attributes)
|
|
82
|
-
record = find_or_create_for_params(attributes, column, parent_record)
|
|
83
|
-
if record
|
|
84
|
-
record_columns = active_scaffold_config_for(column.association.klass).subform.columns
|
|
85
|
-
record_columns.constraint_columns = [column.association.reverse]
|
|
86
|
-
update_record_from_params(record, record_columns, attributes)
|
|
87
|
-
record.unsaved = true
|
|
88
|
-
end
|
|
89
|
-
record
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def column_value_from_param_value(parent_record, column, value)
|
|
93
|
-
# convert the value, possibly by instantiating associated objects
|
|
94
|
-
if value.is_a?(Hash)
|
|
95
|
-
column_value_from_param_hash_value(parent_record, column, value)
|
|
96
|
-
else
|
|
97
|
-
column_value_from_param_simple_value(parent_record, column, value)
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def column_value_from_param_simple_value(parent_record, column, value)
|
|
102
|
-
if column.singular_association?
|
|
103
|
-
# it's a single id
|
|
104
|
-
column.association.klass.find(value) if value and not value.empty?
|
|
105
|
-
elsif column.plural_association?
|
|
106
|
-
column_plural_assocation_value_from_value(column, Array(value))
|
|
107
|
-
elsif column.number? && [:i18n_number, :currency].include?(column.options[:format])
|
|
108
|
-
self.class.i18n_number_to_native_format(value)
|
|
109
|
-
else
|
|
110
|
-
# convert empty strings into nil. this works better with 'null => true' columns (and validations),
|
|
111
|
-
# and 'null => false' columns should just convert back to an empty string.
|
|
112
|
-
# ... but we can at least check the ConnectionAdapter::Column object to see if nulls are allowed
|
|
113
|
-
value = nil if value.is_a? String and value.empty? and !column.column.nil? and column.column.null
|
|
114
|
-
value
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def column_plural_assocation_value_from_value(column, value)
|
|
119
|
-
# it's an array of ids
|
|
120
|
-
if value and not value.empty?
|
|
121
|
-
ids = value.select {|id| id.respond_to?(:empty?) ? !id.empty? : true}
|
|
122
|
-
ids.empty? ? [] : column.association.klass.find(ids)
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def column_value_from_param_hash_value(parent_record, column, value)
|
|
127
|
-
# this is just for backwards compatibility. we should clean this up in 2.0.
|
|
128
|
-
if column.form_ui == :select
|
|
129
|
-
ids = if column.singular_association?
|
|
130
|
-
value[:id]
|
|
131
|
-
else
|
|
132
|
-
value.values.collect {|hash| hash[:id]}
|
|
133
|
-
end
|
|
134
|
-
(ids and not ids.empty?) ? column.association.klass.find(ids) : nil
|
|
135
|
-
|
|
136
|
-
elsif column.singular_association?
|
|
137
|
-
manage_nested_record_from_params(parent_record, column, value)
|
|
138
|
-
elsif column.plural_association?
|
|
139
|
-
# HACK to be able to delete all associated records, hash will include "0" => ""
|
|
140
|
-
value.collect {|key, value| manage_nested_record_from_params(parent_record, column, value) unless value == ""}.compact
|
|
141
|
-
else
|
|
142
|
-
value
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
# Attempts to create or find an instance of klass (which must be an ActiveRecord object) from the
|
|
147
|
-
# request parameters given. If params[:id] exists it will attempt to find an existing object
|
|
148
|
-
# otherwise it will build a new one.
|
|
149
|
-
def find_or_create_for_params(params, parent_column, parent_record)
|
|
150
|
-
current = parent_record.send(parent_column.name)
|
|
151
|
-
klass = parent_column.association.klass
|
|
152
|
-
pk = klass.primary_key.to_sym
|
|
153
|
-
return nil if parent_column.show_blank_record?(current) and attributes_hash_is_empty?(params, klass)
|
|
154
|
-
|
|
155
|
-
if params.has_key? pk
|
|
156
|
-
# modifying the current object of a singular association
|
|
157
|
-
pk_val = params[pk]
|
|
158
|
-
if current and current.is_a? ActiveRecord::Base and current.id.to_s == pk_val
|
|
159
|
-
current
|
|
160
|
-
# modifying one of the current objects in a plural association
|
|
161
|
-
elsif current and current.respond_to?(:any?) and current.any? {|o| o.id.to_s == pk_val}
|
|
162
|
-
current.detect {|o| o.id.to_s == pk_val}
|
|
163
|
-
# attaching an existing but not-current object
|
|
164
|
-
else
|
|
165
|
-
klass.find(pk_val)
|
|
166
|
-
end
|
|
167
|
-
else
|
|
168
|
-
build_associated(parent_column, parent_record) if klass.authorized_for?(:crud_type => :create)
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
# Determines whether the given attributes hash is "empty".
|
|
172
|
-
# This isn't a literal emptiness - it's an attempt to discern whether the user intended it to be empty or not.
|
|
173
|
-
def attributes_hash_is_empty?(hash, klass)
|
|
174
|
-
ignore_column_types = [:boolean]
|
|
175
|
-
hash.all? do |key,value|
|
|
176
|
-
# convert any possible multi-parameter attributes like 'created_at(5i)' to simply 'created_at'
|
|
177
|
-
parts = key.to_s.split('(')
|
|
178
|
-
#old style date form management... ignore them too
|
|
179
|
-
ignore_column_types = [:boolean, :datetime, :date, :time] if parts.length > 1
|
|
180
|
-
column_name = parts.first
|
|
181
|
-
column = klass.columns_hash[column_name]
|
|
182
|
-
|
|
183
|
-
# booleans and datetimes will always have a value. so we ignore them when checking whether the hash is empty.
|
|
184
|
-
# this could be a bad idea. but the current situation (excess record entry) seems worse.
|
|
185
|
-
next true if column and ignore_column_types.include?(column.type)
|
|
186
|
-
|
|
187
|
-
# defaults are pre-filled on the form. we can't use them to determine if the user intends a new row.
|
|
188
|
-
next true if column and value == column.default.to_s
|
|
189
|
-
|
|
190
|
-
if value.is_a?(Hash)
|
|
191
|
-
attributes_hash_is_empty?(value, klass)
|
|
192
|
-
elsif value.is_a?(Array)
|
|
193
|
-
value.any? {|id| id.respond_to?(:empty?) ? !id.empty? : true}
|
|
194
|
-
else
|
|
195
|
-
value.respond_to?(:empty?) ? value.empty? : false
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
end
|
|
200
|
-
end
|