active_scaffold 3.2.20 → 3.3.0.rc
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 +19 -13
- data/README +66 -0
- data/app/assets/javascripts/jquery/active_scaffold.js +156 -113
- data/app/assets/javascripts/jquery/active_scaffold_chosen.js +11 -0
- data/app/assets/javascripts/jquery/date_picker_bridge.js.erb +0 -1
- data/app/assets/javascripts/jquery/jquery.editinplace.js +132 -128
- data/app/assets/javascripts/prototype/active_scaffold.js +68 -25
- data/{frontends/default/views/_horizontal_subform_footer.html.erb → app/assets/javascripts/prototype/active_scaffold_chosen.js} +0 -0
- data/app/assets/stylesheets/active_scaffold_colors.css.scss +8 -1
- data/app/assets/stylesheets/active_scaffold_layout.css +14 -8
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_add_existing_form.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_base_form.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_create_form.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_create_form_on_list.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_field_search.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_form.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_form_association.html.erb +8 -3
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_form_association_footer.html.erb +5 -4
- data/app/views/active_scaffold_overrides/_form_association_record.html.erb +85 -0
- data/app/views/active_scaffold_overrides/_form_attribute.html.erb +23 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_form_hidden_attribute.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_form_messages.html.erb +0 -0
- data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +12 -0
- data/app/views/active_scaffold_overrides/_horizontal_subform_footer.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_horizontal_subform_header.html.erb +3 -2
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_human_conditions.html.erb +0 -0
- data/app/views/active_scaffold_overrides/_list.html.erb +35 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_calculations.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_column_headings.html.erb +0 -0
- data/app/views/active_scaffold_overrides/_list_header.html.erb +8 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_inline_adapter.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_messages.html.erb +4 -4
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_pagination.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_pagination_links.html.erb +0 -0
- data/app/views/active_scaffold_overrides/_list_record.html.erb +30 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_list_with_header.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_messages.html.erb +0 -0
- data/app/views/active_scaffold_overrides/_refresh_list.js.erb +1 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_render_field.js.erb +9 -1
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_row.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_search.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_search_attribute.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_show.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_show_columns.html.erb +0 -0
- data/app/views/active_scaffold_overrides/_update_actions.html.erb +9 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_update_calculations.js.erb +0 -0
- data/app/views/active_scaffold_overrides/_update_column.js.erb +16 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_update_form.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/_update_messages.js.erb +0 -0
- data/app/views/active_scaffold_overrides/_vertical_subform.html.erb +8 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/action_confirmation.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/add_existing.js.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/add_existing_form.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/create.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/delete.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/destroy.js.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/edit_associated.js.erb +1 -1
- data/{frontends/default/views → app/views/active_scaffold_overrides}/field_search.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/form_messages.js.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/list.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/on_action_update.js.erb +3 -3
- data/{frontends/default/views → app/views/active_scaffold_overrides}/on_create.js.erb +1 -1
- data/{frontends/default/views → app/views/active_scaffold_overrides}/on_mark.js.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/on_update.js.erb +4 -4
- data/{frontends/default/views → app/views/active_scaffold_overrides}/render_field.js.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/row.js.erb +1 -1
- data/{frontends/default/views → app/views/active_scaffold_overrides}/search.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/show.html.erb +0 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/update.html.erb +1 -1
- data/app/views/active_scaffold_overrides/update_column.js.erb +26 -0
- data/{frontends/default/views → app/views/active_scaffold_overrides}/update_row.js.erb +0 -0
- data/config/locales/de.yml +1 -0
- data/config/locales/en.yml +1 -0
- data/config/locales/es.yml +1 -0
- data/config/locales/fr.yml +1 -0
- 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 +14 -26
- data/lib/active_scaffold/actions/core.rb +14 -11
- data/lib/active_scaffold/actions/create.rb +3 -3
- data/lib/active_scaffold/actions/delete.rb +3 -0
- data/lib/active_scaffold/actions/list.rb +9 -6
- data/lib/active_scaffold/actions/mark.rb +1 -1
- data/lib/active_scaffold/actions/nested.rb +8 -6
- data/lib/active_scaffold/actions/show.rb +6 -1
- data/lib/active_scaffold/actions/update.rb +39 -19
- data/lib/active_scaffold/active_record_permissions.rb +29 -12
- data/lib/active_scaffold/attribute_params.rb +14 -7
- data/lib/active_scaffold/bridges/calendar_date_select.rb +1 -1
- data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +1 -2
- data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +1 -1
- data/lib/active_scaffold/bridges/chosen.rb +14 -0
- data/lib/active_scaffold/bridges/chosen/helpers.rb +48 -0
- data/lib/active_scaffold/bridges/date_picker/helper.rb +7 -6
- data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +1 -1
- data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +1 -1
- data/lib/active_scaffold/bridges/file_column.rb +1 -1
- data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +1 -1
- data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +2 -2
- data/lib/active_scaffold/bridges/file_column/list_ui.rb +4 -4
- data/lib/active_scaffold/bridges/paperclip.rb +1 -1
- data/lib/active_scaffold/bridges/paperclip/form_ui.rb +1 -1
- data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
- data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +1 -1
- data/lib/active_scaffold/bridges/shared/date_bridge.rb +1 -1
- data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +1 -1
- data/lib/active_scaffold/config/core.rb +9 -2
- data/lib/active_scaffold/config/list.rb +9 -13
- data/lib/active_scaffold/config/nested.rb +11 -2
- data/lib/active_scaffold/data_structures/action_columns.rb +19 -5
- data/lib/active_scaffold/data_structures/action_link.rb +9 -2
- data/lib/active_scaffold/data_structures/action_links.rb +5 -36
- data/lib/active_scaffold/data_structures/column.rb +21 -21
- data/lib/active_scaffold/data_structures/nested_info.rb +31 -44
- data/lib/active_scaffold/extensions/action_controller_rescueing.rb +1 -0
- data/lib/active_scaffold/extensions/action_view_rendering.rb +30 -36
- data/lib/active_scaffold/extensions/reverse_associations.rb +10 -6
- data/lib/active_scaffold/extensions/routing_mapper.rb +6 -5
- data/lib/active_scaffold/extensions/unsaved_associated.rb +1 -1
- data/lib/active_scaffold/finder.rb +18 -10
- data/lib/active_scaffold/helpers/association_helpers.rb +21 -2
- data/lib/active_scaffold/helpers/controller_helpers.rb +14 -16
- data/lib/active_scaffold/helpers/form_column_helpers.rb +161 -21
- data/lib/active_scaffold/helpers/id_helpers.rb +7 -7
- data/lib/active_scaffold/helpers/list_column_helpers.rb +42 -92
- data/lib/active_scaffold/helpers/search_column_helpers.rb +10 -3
- data/lib/active_scaffold/helpers/show_column_helpers.rb +4 -9
- data/lib/active_scaffold/helpers/view_helpers.rb +278 -78
- data/lib/active_scaffold/version.rb +2 -2
- data/lib/generators/active_scaffold_controller/templates/controller.rb +1 -1
- data/test/bridges/paperclip_test.rb +2 -2
- data/vendor/assets/javascripts/jquery-ui-timepicker-addon.js +1882 -1276
- metadata +79 -80
- data/README.md +0 -67
- data/frontends/default/views/_action_group.html.erb +0 -24
- data/frontends/default/views/_form_attribute.html.erb +0 -23
- data/frontends/default/views/_horizontal_subform.html.erb +0 -22
- data/frontends/default/views/_horizontal_subform_record.html.erb +0 -43
- data/frontends/default/views/_list.html.erb +0 -18
- data/frontends/default/views/_list_actions.html.erb +0 -15
- data/frontends/default/views/_list_header.html.erb +0 -10
- 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/_refresh_list.js.erb +0 -1
- data/frontends/default/views/_update_actions.html.erb +0 -9
- 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/refresh_list.js.erb +0 -2
- data/frontends/default/views/update_column.js.erb +0 -15
- data/lib/active_scaffold/extensions/active_record_offset.rb +0 -12
- data/lib/active_scaffold/extensions/nil_id_in_url_params.rb +0 -7
|
@@ -55,25 +55,25 @@ module ActiveScaffold::Actions
|
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def row_respond_to_js
|
|
58
|
-
render
|
|
58
|
+
render :action => 'row'
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
# The actual algorithm to prepare for the list view
|
|
62
|
-
def
|
|
62
|
+
def set_includes_for_columns(action = :list)
|
|
63
63
|
@cache_associations = true
|
|
64
|
-
includes_for_list_columns = active_scaffold_config.
|
|
64
|
+
includes_for_list_columns = active_scaffold_config.send(action).columns.collect{ |c| c.includes }.flatten.uniq.compact
|
|
65
65
|
self.active_scaffold_includes.concat includes_for_list_columns
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
def get_row
|
|
69
|
-
|
|
69
|
+
set_includes_for_columns
|
|
70
70
|
klass = beginning_of_chain.includes(active_scaffold_includes)
|
|
71
71
|
@record = find_if_allowed(params[:id], :read, klass)
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
# The actual algorithm to prepare for the list view
|
|
75
75
|
def do_list
|
|
76
|
-
|
|
76
|
+
set_includes_for_columns
|
|
77
77
|
|
|
78
78
|
options = { :sorting => active_scaffold_config.list.user.sorting,
|
|
79
79
|
:count_includes => active_scaffold_config.list.user.count_includes }
|
|
@@ -96,6 +96,7 @@ module ActiveScaffold::Actions
|
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
def do_refresh_list
|
|
99
|
+
params.delete(:id)
|
|
99
100
|
do_search if respond_to? :do_search
|
|
100
101
|
do_list
|
|
101
102
|
end
|
|
@@ -135,7 +136,9 @@ module ActiveScaffold::Actions
|
|
|
135
136
|
@action_link = active_scaffold_config.action_links[action_name]
|
|
136
137
|
if params[:id] && params[:id] && params[:id].to_i > 0
|
|
137
138
|
crud_type ||= (request.post? || request.put?) ? :update : :delete
|
|
138
|
-
|
|
139
|
+
set_includes_for_columns
|
|
140
|
+
klass = beginning_of_chain.includes(active_scaffold_includes)
|
|
141
|
+
@record = find_if_allowed(params[:id], crud_type, klass)
|
|
139
142
|
unless @record.nil?
|
|
140
143
|
yield @record
|
|
141
144
|
else
|
|
@@ -29,7 +29,7 @@ module ActiveScaffold::Actions
|
|
|
29
29
|
def mark_respond_to_js
|
|
30
30
|
if params[:id]
|
|
31
31
|
do_search if respond_to? :do_search
|
|
32
|
-
|
|
32
|
+
set_includes_for_columns if active_scaffold_config.actions.include? :list
|
|
33
33
|
@page = find_page(:pagination => active_scaffold_config.mark.mark_all_mode != :page)
|
|
34
34
|
render :action => 'on_mark'
|
|
35
35
|
else
|
|
@@ -37,7 +37,7 @@ module ActiveScaffold::Actions
|
|
|
37
37
|
else
|
|
38
38
|
as_(:nested_for_model, :nested_model => active_scaffold_config.list.label, :parent_model => nested_parent_record.to_label)
|
|
39
39
|
end
|
|
40
|
-
if nested.sorted?
|
|
40
|
+
if nested.sorted? && !active_scaffold_config.nested.ignore_order_from_association
|
|
41
41
|
active_scaffold_config.list.user.nested_default_sorting = {:table_name => active_scaffold_config.model.model_name, :default_sorting => nested.default_sorting}
|
|
42
42
|
end
|
|
43
43
|
end
|
|
@@ -73,16 +73,18 @@ module ActiveScaffold::Actions
|
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
def beginning_of_chain
|
|
76
|
-
if nested? && nested.association
|
|
76
|
+
if nested? && nested.association
|
|
77
77
|
if nested.association.collection?
|
|
78
|
-
|
|
79
|
-
elsif nested.association.options[:through] # has_one :through doesn't need conditions
|
|
78
|
+
nested_parent_record.send(nested.association.name)
|
|
79
|
+
elsif nested.association.options[:through] || nested.child_association.nil? # has_one :through doesn't need conditions, and without child_association is not possible to add them
|
|
80
80
|
active_scaffold_config.model
|
|
81
81
|
elsif nested.child_association.belongs_to?
|
|
82
|
-
active_scaffold_config.model.where(nested.child_association.foreign_key =>
|
|
82
|
+
active_scaffold_config.model.where(nested.child_association.foreign_key => nested_parent_record)
|
|
83
|
+
elsif nested.association.belongs_to?
|
|
84
|
+
active_scaffold_config.model.joins(nested.child_association.name).where(nested.association.active_record.table_name => {nested.association.active_record.primary_key => nested_parent_record}).readonly(false)
|
|
83
85
|
end
|
|
84
86
|
elsif nested? && nested.scope
|
|
85
|
-
|
|
87
|
+
nested_parent_record.send(nested.scope)
|
|
86
88
|
else
|
|
87
89
|
active_scaffold_config.model
|
|
88
90
|
end
|
|
@@ -41,7 +41,9 @@ module ActiveScaffold::Actions
|
|
|
41
41
|
# A simple method to retrieve and prepare a record for showing.
|
|
42
42
|
# May be overridden to customize show routine
|
|
43
43
|
def do_show
|
|
44
|
-
|
|
44
|
+
set_includes_for_columns(:show) if active_scaffold_config.actions.include? :list
|
|
45
|
+
klass = beginning_of_chain.includes(active_scaffold_includes)
|
|
46
|
+
@record = find_if_allowed(params[:id], :read, klass)
|
|
45
47
|
end
|
|
46
48
|
|
|
47
49
|
# The default security delegates to ActiveRecordPermissions.
|
|
@@ -49,6 +51,9 @@ module ActiveScaffold::Actions
|
|
|
49
51
|
def show_authorized?(record = nil)
|
|
50
52
|
(record || self).send(:authorized_for?, :crud_type => :read)
|
|
51
53
|
end
|
|
54
|
+
def show_ignore?(record = nil)
|
|
55
|
+
!self.send(:authorized_for?, :crud_type => :read)
|
|
56
|
+
end
|
|
52
57
|
private
|
|
53
58
|
def show_authorized_filter
|
|
54
59
|
link = active_scaffold_config.show.link || active_scaffold_config.show.class.link
|
|
@@ -18,7 +18,7 @@ module ActiveScaffold::Actions
|
|
|
18
18
|
# for inline (inlist) editing
|
|
19
19
|
def update_column
|
|
20
20
|
do_update_column
|
|
21
|
-
@column_span_id = params
|
|
21
|
+
@column_span_id = params.delete(:editor_id) || params.delete(:editorId)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
protected
|
|
@@ -35,7 +35,7 @@ module ActiveScaffold::Actions
|
|
|
35
35
|
def update_respond_to_html
|
|
36
36
|
if params[:iframe]=='true' # was this an iframe post ?
|
|
37
37
|
responds_to_parent do
|
|
38
|
-
render :action => 'on_update
|
|
38
|
+
render :action => 'on_update', :formats => [:js], :layout => false
|
|
39
39
|
end
|
|
40
40
|
else # just a regular post
|
|
41
41
|
if successful?
|
|
@@ -48,7 +48,13 @@ module ActiveScaffold::Actions
|
|
|
48
48
|
end
|
|
49
49
|
def update_respond_to_js
|
|
50
50
|
if successful?
|
|
51
|
-
|
|
51
|
+
if !render_parent? && active_scaffold_config.actions.include?(:list)
|
|
52
|
+
if update_refresh_list?
|
|
53
|
+
do_refresh_list
|
|
54
|
+
else
|
|
55
|
+
get_row
|
|
56
|
+
end
|
|
57
|
+
end
|
|
52
58
|
flash.now[:info] = as_(:updated_model, :model => @record.to_label) if active_scaffold_config.update.persistent
|
|
53
59
|
end
|
|
54
60
|
render :action => 'on_update'
|
|
@@ -62,6 +68,7 @@ module ActiveScaffold::Actions
|
|
|
62
68
|
def update_respond_to_yaml
|
|
63
69
|
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
70
|
end
|
|
71
|
+
|
|
65
72
|
# A simple method to find and prepare a record for editing
|
|
66
73
|
# May be overridden to customize the record (set default values, etc.)
|
|
67
74
|
def do_edit
|
|
@@ -81,7 +88,7 @@ module ActiveScaffold::Actions
|
|
|
81
88
|
active_scaffold_config.model.transaction do
|
|
82
89
|
@record = update_record_from_params(@record, active_scaffold_config.update.columns, attributes) unless options[:no_record_param_update]
|
|
83
90
|
before_update_save(@record)
|
|
84
|
-
self.successful = [@record.valid?, @record.associated_valid?].all?
|
|
91
|
+
self.successful = [@record.valid?, @record.associated_valid?].all? # this syntax avoids a short-circuit
|
|
85
92
|
if successful?
|
|
86
93
|
@record.save! and @record.save_associated!
|
|
87
94
|
after_update_save(@record)
|
|
@@ -104,23 +111,33 @@ module ActiveScaffold::Actions
|
|
|
104
111
|
end
|
|
105
112
|
|
|
106
113
|
def do_update_column
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
# delete from params so update :table won't break urls, also they shouldn't be used in sort links too
|
|
115
|
+
value = params.delete(:value)
|
|
116
|
+
column = params.delete(:column).to_sym
|
|
117
|
+
params.delete(:original_html)
|
|
118
|
+
params.delete(:original_value)
|
|
119
|
+
|
|
120
|
+
@record = find_if_allowed(params[:id], :read)
|
|
121
|
+
if @record.authorized_for?(:crud_type => :update, :column => column)
|
|
122
|
+
@column = active_scaffold_config.columns[column]
|
|
123
|
+
value ||= unless @column.column.nil? || @column.column.null
|
|
124
|
+
@column.column.default == true ? false : @column.column.default
|
|
116
125
|
end
|
|
117
|
-
unless column.nil?
|
|
118
|
-
|
|
119
|
-
|
|
126
|
+
unless @column.nil?
|
|
127
|
+
value = column_value_from_param_value(@record, @column, value)
|
|
128
|
+
value = [] if value.nil? && @column.form_ui && @column.plural_association?
|
|
120
129
|
end
|
|
121
|
-
@record.send("#{
|
|
130
|
+
@record.send("#{@column.name}=", value)
|
|
122
131
|
before_update_save(@record)
|
|
123
|
-
@record.save
|
|
132
|
+
self.successful = @record.save
|
|
133
|
+
if self.successful? && active_scaffold_config.actions.include?(:list)
|
|
134
|
+
if @column.inplace_edit_update == :table
|
|
135
|
+
params.delete(:id)
|
|
136
|
+
do_list
|
|
137
|
+
elsif @column.inplace_edit_update
|
|
138
|
+
get_row
|
|
139
|
+
end
|
|
140
|
+
end
|
|
124
141
|
after_update_save(@record)
|
|
125
142
|
end
|
|
126
143
|
end
|
|
@@ -139,7 +156,10 @@ module ActiveScaffold::Actions
|
|
|
139
156
|
# The default security delegates to ActiveRecordPermissions.
|
|
140
157
|
# You may override the method to customize.
|
|
141
158
|
def update_authorized?(record = nil)
|
|
142
|
-
(!nested? || !nested.readonly?) && (record || self).
|
|
159
|
+
(!nested? || !nested.readonly?) && (record || self).authorized_for?(:crud_type => :update)
|
|
160
|
+
end
|
|
161
|
+
def update_ignore?(record = nil)
|
|
162
|
+
!self.authorized_for?(:crud_type => :update)
|
|
143
163
|
end
|
|
144
164
|
private
|
|
145
165
|
def update_authorized_filter
|
|
@@ -65,6 +65,10 @@ module ActiveRecordPermissions
|
|
|
65
65
|
def self.included(base)
|
|
66
66
|
base.extend SecurityMethods
|
|
67
67
|
base.send :include, SecurityMethods
|
|
68
|
+
class << base
|
|
69
|
+
attr_accessor :class_security_methods
|
|
70
|
+
attr_accessor :instance_security_methods
|
|
71
|
+
end
|
|
68
72
|
end
|
|
69
73
|
|
|
70
74
|
# Because any class-level queries get delegated to the instance level via a new record,
|
|
@@ -85,34 +89,47 @@ module ActiveRecordPermissions
|
|
|
85
89
|
def authorized_for?(options = {})
|
|
86
90
|
raise ArgumentError, "unknown crud type #{options[:crud_type]}" if options[:crud_type] and ![:create, :read, :update, :delete].include?(options[:crud_type])
|
|
87
91
|
|
|
92
|
+
# collect other possibly-related methods that actually exist
|
|
93
|
+
methods = cached_authorized_for_methods(options)
|
|
94
|
+
return ActiveRecordPermissions.default_permission if methods.empty?
|
|
95
|
+
return send(methods.first) if methods.one?
|
|
96
|
+
|
|
97
|
+
# if any method returns false, then return false
|
|
98
|
+
return false if methods.any? {|m| !send(m)}
|
|
99
|
+
true
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def cached_authorized_for_methods(options)
|
|
103
|
+
key = "#{options[:crud_type]}##{options[:column]}##{options[:action]}"
|
|
104
|
+
if self.is_a? Class
|
|
105
|
+
self.class_security_methods ||= {}
|
|
106
|
+
self.class_security_methods[key] ||= authorized_for_methods(options)
|
|
107
|
+
else
|
|
108
|
+
self.class.instance_security_methods ||= {}
|
|
109
|
+
self.class.instance_security_methods[key] ||= authorized_for_methods(options)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def authorized_for_methods(options)
|
|
88
114
|
# column_authorized_for_crud_type? has the highest priority over other methods,
|
|
89
115
|
# you can disable a crud verb and enable that verb for a column
|
|
90
116
|
# (for example, disable update and enable inplace_edit in a column)
|
|
91
117
|
method = column_and_crud_type_security_method(options[:column], options[:crud_type])
|
|
92
|
-
return
|
|
118
|
+
return [method] if method and respond_to?(method)
|
|
93
119
|
|
|
94
120
|
# authorized_for_action? has higher priority than other methods,
|
|
95
121
|
# you can disable a crud verb and enable an action with that crud verb
|
|
96
122
|
# (for example, disable update and enable an action with update as crud type)
|
|
97
123
|
method = action_security_method(options[:action])
|
|
98
|
-
return
|
|
124
|
+
return [method] if method and respond_to?(method)
|
|
99
125
|
|
|
100
126
|
# collect other possibly-related methods that actually exist
|
|
101
127
|
methods = [
|
|
102
128
|
column_security_method(options[:column]),
|
|
103
129
|
crud_type_security_method(options[:crud_type]),
|
|
104
130
|
].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
131
|
end
|
|
115
|
-
|
|
132
|
+
|
|
116
133
|
private
|
|
117
134
|
|
|
118
135
|
def column_security_method(column)
|
|
@@ -66,7 +66,7 @@ module ActiveScaffold
|
|
|
66
66
|
if parent_record.new_record?
|
|
67
67
|
parent_record.class.reflect_on_all_associations.each do |a|
|
|
68
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)
|
|
69
|
+
next unless (association_proxy = parent_record.send(a.name)).present?
|
|
70
70
|
|
|
71
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
72
|
|
|
@@ -100,11 +100,18 @@ module ActiveScaffold
|
|
|
100
100
|
|
|
101
101
|
def column_value_from_param_simple_value(parent_record, column, value)
|
|
102
102
|
if column.singular_association?
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
if value.present?
|
|
104
|
+
if column.polymorphic_association?
|
|
105
|
+
class_name = parent_record.send(column.association.foreign_type)
|
|
106
|
+
class_name.constantize.find(value) if class_name
|
|
107
|
+
else
|
|
108
|
+
# it's a single id
|
|
109
|
+
column.association.klass.find(value)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
105
112
|
elsif column.plural_association?
|
|
106
113
|
column_plural_assocation_value_from_value(column, Array(value))
|
|
107
|
-
elsif column.number? && [:i18n_number, :currency].include?(column.options[:format])
|
|
114
|
+
elsif column.number? && [:i18n_number, :currency].include?(column.options[:format]) && column.form_ui != :number
|
|
108
115
|
self.class.i18n_number_to_native_format(value)
|
|
109
116
|
else
|
|
110
117
|
# convert empty strings into nil. this works better with 'null => true' columns (and validations),
|
|
@@ -118,7 +125,7 @@ module ActiveScaffold
|
|
|
118
125
|
def column_plural_assocation_value_from_value(column, value)
|
|
119
126
|
# it's an array of ids
|
|
120
127
|
if value and not value.empty?
|
|
121
|
-
ids = value.select {|id| id.
|
|
128
|
+
ids = value.select {|id| id.present?}
|
|
122
129
|
ids.empty? ? [] : column.association.klass.find(ids)
|
|
123
130
|
end
|
|
124
131
|
end
|
|
@@ -137,7 +144,7 @@ module ActiveScaffold
|
|
|
137
144
|
manage_nested_record_from_params(parent_record, column, value)
|
|
138
145
|
elsif column.plural_association?
|
|
139
146
|
# 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
|
|
147
|
+
value.sort.collect {|key, value| manage_nested_record_from_params(parent_record, column, value) unless value == ""}.compact
|
|
141
148
|
else
|
|
142
149
|
value
|
|
143
150
|
end
|
|
@@ -190,7 +197,7 @@ module ActiveScaffold
|
|
|
190
197
|
if value.is_a?(Hash)
|
|
191
198
|
attributes_hash_is_empty?(value, klass)
|
|
192
199
|
elsif value.is_a?(Array)
|
|
193
|
-
value.
|
|
200
|
+
value.any? {|id| id.respond_to?(:empty?) ? !id.empty? : true}
|
|
194
201
|
else
|
|
195
202
|
value.respond_to?(:empty?) ? value.empty? : false
|
|
196
203
|
end
|
|
@@ -3,7 +3,7 @@ class ActiveScaffold::Bridges::CalendarDateSelect < ActiveScaffold::DataStructur
|
|
|
3
3
|
# check to see if the old bridge was installed. If so, warn them
|
|
4
4
|
# we can detect this by checking to see if the bridge was installed before calling this code
|
|
5
5
|
|
|
6
|
-
if ActiveScaffold::Config::Core.instance_methods.include?("initialize_with_calendar_date_select"
|
|
6
|
+
if ActiveScaffold::Config::Core.instance_methods.include?("initialize_with_calendar_date_select")
|
|
7
7
|
raise RuntimeError, "We've detected that you have active_scaffold_calendar_date_select_bridge installed. This plugin has been moved to core. Please remove active_scaffold_calendar_date_select_bridge to prevent any conflicts"
|
|
8
8
|
end
|
|
9
9
|
|
|
@@ -11,8 +11,7 @@ module CanCan
|
|
|
11
11
|
module Ability
|
|
12
12
|
def as_action_aliases
|
|
13
13
|
alias_action :list, :row, :show_search, :render_field, :to => :read
|
|
14
|
-
alias_action :update_column, :
|
|
15
|
-
:edit_associated, :new_existing, :add_existing, :to => :update
|
|
14
|
+
alias_action :update_column, :edit_associated, :new_existing, :add_existing, :to => :update
|
|
16
15
|
alias_action :delete, :destroy_existing, :to => :destroy
|
|
17
16
|
end
|
|
18
17
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module ActiveScaffold
|
|
2
2
|
module Helpers
|
|
3
3
|
module ListColumnHelpers
|
|
4
|
-
def active_scaffold_column_carrierwave(
|
|
4
|
+
def active_scaffold_column_carrierwave(record, column)
|
|
5
5
|
carrierwave = record.send("#{column.name}")
|
|
6
6
|
return nil unless !carrierwave.file.blank?
|
|
7
7
|
thumbnail_style = ActiveScaffold::Bridges::Carrierwave::CarrierwaveBridgeHelpers.thumbnail_style
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class ActiveScaffold::Bridges::Chosen < ActiveScaffold::DataStructures::Bridge
|
|
2
|
+
def self.install
|
|
3
|
+
require File.join(File.dirname(__FILE__), "chosen/helpers.rb")
|
|
4
|
+
end
|
|
5
|
+
def self.install?
|
|
6
|
+
super && [:jquery, :prototype].include?(ActiveScaffold.js_framework)
|
|
7
|
+
end
|
|
8
|
+
def self.stylesheets
|
|
9
|
+
'chosen'
|
|
10
|
+
end
|
|
11
|
+
def self.javascripts
|
|
12
|
+
["chosen-#{ActiveScaffold.js_framework}", "#{ActiveScaffold.js_framework}/active_scaffold_chosen"]
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
class ActiveScaffold::Bridges::Chosen
|
|
2
|
+
module Helpers
|
|
3
|
+
def self.included(base)
|
|
4
|
+
base.class_eval do
|
|
5
|
+
include FormColumnHelpers
|
|
6
|
+
include SearchColumnHelpers
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module FormColumnHelpers
|
|
11
|
+
# requires RecordSelect plugin to be installed and configured.
|
|
12
|
+
def active_scaffold_input_chosen(column, html_options)
|
|
13
|
+
html_options[:class] << ' chosen'
|
|
14
|
+
if column.plural_association?
|
|
15
|
+
associated_options, select_options = active_scaffold_plural_association_options(column)
|
|
16
|
+
options = {:selected => associated_options.collect {|a| a[1]}, :include_blank => as_(:_select_)}
|
|
17
|
+
|
|
18
|
+
html_options.update(:multiple => true).update(column.options[:html_options] || {})
|
|
19
|
+
options.update(column.options)
|
|
20
|
+
html_options[:name] = "#{html_options[:name]}[]" if html_options[:multiple] == true && !html_options[:name].to_s.ends_with?("[]")
|
|
21
|
+
|
|
22
|
+
if optgroup = options.delete(:optgroup)
|
|
23
|
+
select(:record, column.name, grouped_options_for_select(column, select_options, optgroup), options, html_options)
|
|
24
|
+
else
|
|
25
|
+
collection_select(:record, column.name, select_options, :id, :to_label, options, html_options)
|
|
26
|
+
end
|
|
27
|
+
else
|
|
28
|
+
active_scaffold_input_select(column, html_options)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
module SearchColumnHelpers
|
|
34
|
+
def active_scaffold_search_chosen(column, options)
|
|
35
|
+
options[:class] << ' chosen'
|
|
36
|
+
active_scaffold_search_select(column, options)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def active_scaffold_search_multi_chosen(column, options)
|
|
40
|
+
options[:class] << ' chosen'
|
|
41
|
+
options[:multiple] = true
|
|
42
|
+
active_scaffold_search_select(column, options)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
ActionView::Base.class_eval { include ActiveScaffold::Bridges::Chosen::Helpers }
|