active_scaffold_batch 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE.txt +20 -0
- data/README +4 -0
- data/app/assets/javascripts/jquery/active_scaffold_batch.js +13 -0
- data/app/assets/javascripts/prototype/active_scaffold_batch.js +13 -0
- data/app/assets/stylesshets/active_scaffold_batch.css +36 -0
- data/app/views/active_scaffold_overrides/_batch_create_form.html.erb +9 -0
- data/app/views/active_scaffold_overrides/_batch_create_form_attribute.html.erb +19 -0
- data/app/views/active_scaffold_overrides/_batch_create_form_body.html.erb +25 -0
- data/app/views/active_scaffold_overrides/_batch_create_form_footer.html.erb +4 -0
- data/app/views/active_scaffold_overrides/_batch_create_form_horizontal.html.erb +14 -0
- data/app/views/active_scaffold_overrides/_batch_create_form_horizontal_header.html.erb +8 -0
- data/app/views/active_scaffold_overrides/_batch_create_form_horizontal_record.html.erb +26 -0
- data/app/views/active_scaffold_overrides/_batch_create_form_multiple.html.erb +8 -0
- data/app/views/active_scaffold_overrides/_batch_create_form_vertical.html.erb +7 -0
- data/app/views/active_scaffold_overrides/_batch_create_form_vertical_record.html.erb +6 -0
- data/app/views/active_scaffold_overrides/_batch_update_form.html.erb +7 -0
- data/app/views/active_scaffold_overrides/_batch_update_form_attribute.html.erb +12 -0
- data/app/views/active_scaffold_overrides/_batch_update_form_attribute_scope.html.erb +14 -0
- data/app/views/active_scaffold_overrides/_batch_update_form_body.html.erb +25 -0
- data/app/views/active_scaffold_overrides/_form_messages.html.erb +9 -0
- data/app/views/active_scaffold_overrides/batch_add.js.erb +5 -0
- data/app/views/active_scaffold_overrides/batch_create.html.erb +5 -0
- data/app/views/active_scaffold_overrides/batch_update.html.erb +5 -0
- data/app/views/active_scaffold_overrides/on_batch_base.js.erb +10 -0
- data/app/views/active_scaffold_overrides/on_batch_create.js.erb +15 -0
- data/app/views/active_scaffold_overrides/on_batch_update.js.erb +10 -0
- data/config/locales/de.yml +22 -0
- data/config/locales/en.yml +21 -0
- data/config/locales/es.yml +21 -0
- data/lib/active_scaffold/actions/batch_base.rb +135 -0
- data/lib/active_scaffold/actions/batch_create.rb +247 -0
- data/lib/active_scaffold/actions/batch_destroy.rb +77 -0
- data/lib/active_scaffold/actions/batch_update.rb +281 -0
- data/lib/active_scaffold/config/batch_create.rb +79 -0
- data/lib/active_scaffold/config/batch_destroy.rb +54 -0
- data/lib/active_scaffold/config/batch_update.rb +52 -0
- data/lib/active_scaffold/helpers/batch_create_column_helpers.rb +38 -0
- data/lib/active_scaffold/helpers/calendar_date_select_update_column_helpers.rb +33 -0
- data/lib/active_scaffold/helpers/datepicker_update_column_helpers.rb +29 -0
- data/lib/active_scaffold/helpers/update_column_helpers.rb +93 -0
- data/lib/active_scaffold_batch/config/core.rb +13 -0
- data/lib/active_scaffold_batch/engine.rb +23 -0
- data/lib/active_scaffold_batch/version.rb +9 -0
- data/lib/active_scaffold_batch.rb +25 -0
- metadata +125 -0
@@ -0,0 +1,247 @@
|
|
1
|
+
module ActiveScaffold::Actions
|
2
|
+
module BatchCreate
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.send :include, ActiveScaffold::Actions::BatchBase unless base < ActiveScaffold::Actions::BatchBase
|
6
|
+
base.before_filter :batch_create_authorized_filter, :only => [:batch_new, :batch_create]
|
7
|
+
base.helper_method :batch_create_values
|
8
|
+
base.helper_method :batch_create_by_column
|
9
|
+
base.helper_method :batch_create_by_records
|
10
|
+
end
|
11
|
+
|
12
|
+
def batch_new
|
13
|
+
do_batch_new
|
14
|
+
respond_to_action(:batch_new)
|
15
|
+
end
|
16
|
+
|
17
|
+
def batch_add
|
18
|
+
do_batch_add
|
19
|
+
respond_to_action(:batch_add)
|
20
|
+
end
|
21
|
+
|
22
|
+
def batch_create
|
23
|
+
batch_action
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
protected
|
28
|
+
def batch_new_respond_to_html
|
29
|
+
if batch_successful?
|
30
|
+
render(:action => 'batch_create')
|
31
|
+
else
|
32
|
+
return_to_main
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def batch_new_respond_to_js
|
37
|
+
render(:partial => 'batch_create_form')
|
38
|
+
end
|
39
|
+
|
40
|
+
def batch_add_respond_to_js
|
41
|
+
render
|
42
|
+
end
|
43
|
+
|
44
|
+
def batch_create_values
|
45
|
+
@batch_create_values || {}
|
46
|
+
end
|
47
|
+
|
48
|
+
def batch_create_by_records
|
49
|
+
if @batch_create_by_records.nil?
|
50
|
+
if marked_records_parent
|
51
|
+
column = active_scaffold_config.columns[batch_create_by_column.to_sym]
|
52
|
+
@batch_create_by_records = if column.polymorphic_association?
|
53
|
+
active_scaffold_config_for(params[:batch_create_by].singularize).model.find(marked_records_parent.to_a)
|
54
|
+
else
|
55
|
+
column_plural_assocation_value_from_value(column, marked_records_parent)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
@batch_create_by_records || []
|
60
|
+
end
|
61
|
+
|
62
|
+
def batch_create_respond_to_html
|
63
|
+
if params[:iframe]=='true' # was this an iframe post ?
|
64
|
+
do_refresh_list
|
65
|
+
responds_to_parent do
|
66
|
+
render :action => 'on_batch_create.js', :layout => false
|
67
|
+
end
|
68
|
+
else # just a regular post
|
69
|
+
if batch_successful?
|
70
|
+
return_to_main
|
71
|
+
else
|
72
|
+
render(:action => 'batch_create')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def batch_create_respond_to_js
|
78
|
+
do_refresh_list
|
79
|
+
render :action => 'on_batch_create'
|
80
|
+
end
|
81
|
+
|
82
|
+
def do_batch_new
|
83
|
+
self.successful = true
|
84
|
+
do_new
|
85
|
+
if batch_create_by_column
|
86
|
+
batch_scope # that s a dummy call to remove batch_scope parameter
|
87
|
+
else
|
88
|
+
@scope = temporary_id
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def do_batch_add
|
93
|
+
@records = {}
|
94
|
+
t = temporary_id
|
95
|
+
params[:num_records].to_i.times do
|
96
|
+
@records[t.succ!] = do_new
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def marked_records_parent
|
101
|
+
if @marked_records_parent.nil?
|
102
|
+
@marked_records_parent = if params[:batch_create_by]
|
103
|
+
session_parent = active_scaffold_session_storage(params[:batch_create_by])
|
104
|
+
session_parent[:marked_records] || Set.new
|
105
|
+
else
|
106
|
+
false
|
107
|
+
end
|
108
|
+
end
|
109
|
+
@marked_records_parent
|
110
|
+
end
|
111
|
+
|
112
|
+
def before_do_batch_create
|
113
|
+
if batch_create_by_column
|
114
|
+
create_columns = active_scaffold_config.batch_create.columns
|
115
|
+
@batch_create_values = create_attribute_values_from_params(create_columns, params[:record])
|
116
|
+
else
|
117
|
+
@batch_scope = 'multiple'
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def run_in_transaction?
|
122
|
+
active_scaffold_config.batch_create.run_in_transaction
|
123
|
+
end
|
124
|
+
|
125
|
+
def validate_first?
|
126
|
+
active_scaffold_config.batch_create.run_in_transaction == :validate_first
|
127
|
+
end
|
128
|
+
|
129
|
+
def run_in_transaction_if_enabled
|
130
|
+
processed_records, created_records = 0
|
131
|
+
if run_in_transaction?
|
132
|
+
active_scaffold_config.model.transaction do
|
133
|
+
processed_records, created_records = yield
|
134
|
+
if processed_records == created_records
|
135
|
+
@error_records.each { |_, record| create_save(record) } if validate_first?
|
136
|
+
@error_records = []
|
137
|
+
else
|
138
|
+
created_records = 0
|
139
|
+
raise ActiveRecord::Rollback
|
140
|
+
end
|
141
|
+
end
|
142
|
+
else
|
143
|
+
processed_records, created_records = yield
|
144
|
+
end
|
145
|
+
flash[:info] = as_(:some_records_created, :count => created_records, :model => active_scaffold_config.label(:count => created_records)) if batch_successful? || created_records > 0
|
146
|
+
end
|
147
|
+
|
148
|
+
def batch_create_listed
|
149
|
+
run_in_transaction_if_enabled do
|
150
|
+
processed_records = created_records = 0
|
151
|
+
case active_scaffold_config.batch_create.process_mode
|
152
|
+
when :create then
|
153
|
+
batch_create_by_records.each do |batch_record|
|
154
|
+
create_record_in_batch(batch_record)
|
155
|
+
created_records += 1 if successful?
|
156
|
+
processed_records += 1
|
157
|
+
end
|
158
|
+
else
|
159
|
+
Rails.logger.error("Unknown process_mode: #{active_scaffold_config.batch_create.process_mode} for action batch_create")
|
160
|
+
end
|
161
|
+
[processed_records, created_records]
|
162
|
+
end
|
163
|
+
end
|
164
|
+
alias_method :batch_create_marked, :batch_create_listed
|
165
|
+
|
166
|
+
def batch_create_multiple
|
167
|
+
run_in_transaction_if_enabled do
|
168
|
+
@error_records = {}
|
169
|
+
processed_records = created_records = 0
|
170
|
+
params[:record].each do |scope, record_hash|
|
171
|
+
do_create(:attributes => record_hash, :skip_save => validate_first?)
|
172
|
+
error_records[scope] = @record unless successful? && !run_in_transaction?
|
173
|
+
created_records += 1 if successful?
|
174
|
+
processed_records += 1
|
175
|
+
end
|
176
|
+
[processed_records, created_records]
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def new_batch_create_record(created_by)
|
181
|
+
new_model
|
182
|
+
end
|
183
|
+
|
184
|
+
def create_record_in_batch(created_by)
|
185
|
+
@successful = nil
|
186
|
+
@record = new_batch_create_record(created_by)
|
187
|
+
@record.send("#{batch_create_by_column.to_s}=", created_by)
|
188
|
+
batch_create_values.each do |attribute, value|
|
189
|
+
set_record_attribute(value[:column], attribute, value[:value])
|
190
|
+
end
|
191
|
+
|
192
|
+
if authorized_for_job?(@record)
|
193
|
+
create_save(@record)
|
194
|
+
if successful?
|
195
|
+
marked_records_parent.delete(created_by.id) if batch_scope == 'MARKED' && marked_records_parent
|
196
|
+
end
|
197
|
+
error_records << @record unless successful? && !run_in_transaction?
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def batch_create_by_column
|
202
|
+
active_scaffold_config.batch_create.default_batch_by_column
|
203
|
+
end
|
204
|
+
|
205
|
+
def create_attribute_values_from_params(columns, attributes)
|
206
|
+
values = {}
|
207
|
+
columns.each :for => active_scaffold_config.model, :crud_type => :create, :flatten => true do |column|
|
208
|
+
next unless attributes.has_key?(column.name)
|
209
|
+
if column == batch_create_by_column.to_sym
|
210
|
+
@batch_create_by_records = column_plural_assocation_value_from_value(column, attributes[column.name])
|
211
|
+
else
|
212
|
+
values[column.name] = {:column => column, :value => column_value_from_param_value(nil, column, attributes[column.name])}
|
213
|
+
end
|
214
|
+
end
|
215
|
+
values
|
216
|
+
end
|
217
|
+
|
218
|
+
# The default security delegates to ActiveRecordPermissions.
|
219
|
+
# You may override the method to customize.
|
220
|
+
def batch_create_authorized?(record = nil)
|
221
|
+
authorized_for?(:crud_type => :create)
|
222
|
+
end
|
223
|
+
|
224
|
+
def batch_create_ignore?(record = nil)
|
225
|
+
false
|
226
|
+
end
|
227
|
+
|
228
|
+
def override_batch_create_value(form_ui)
|
229
|
+
method = "batch_create_value_for_#{form_ui}"
|
230
|
+
method if respond_to? method
|
231
|
+
end
|
232
|
+
|
233
|
+
def create_ignore?
|
234
|
+
super || batch_create_by_column.blank?
|
235
|
+
end
|
236
|
+
|
237
|
+
private
|
238
|
+
|
239
|
+
def batch_create_authorized_filter
|
240
|
+
link = active_scaffold_config.batch_create.link || active_scaffold_config.batch_create.class.link
|
241
|
+
raise ActiveScaffold::ActionNotAllowed unless self.send(link.security_method)
|
242
|
+
end
|
243
|
+
def batch_new_formats
|
244
|
+
(default_formats + active_scaffold_config.formats).uniq
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module ActiveScaffold::Actions
|
2
|
+
module BatchDestroy
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.send :include, ActiveScaffold::Actions::BatchBase unless base < ActiveScaffold::Actions::BatchBase
|
6
|
+
base.before_filter :batch_destroy_authorized_filter, :only => [:batch_destroy]
|
7
|
+
end
|
8
|
+
|
9
|
+
def batch_destroy
|
10
|
+
batch_action
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def before_do_batch_destroy
|
16
|
+
end
|
17
|
+
|
18
|
+
def batch_destroy_listed
|
19
|
+
case active_scaffold_config.batch_destroy.process_mode
|
20
|
+
when :delete then
|
21
|
+
each_record_in_scope do |record|
|
22
|
+
destroy_record(record) if authorized_for_job?(record)
|
23
|
+
end
|
24
|
+
when :delete_all then
|
25
|
+
do_search if respond_to? :do_search
|
26
|
+
# dummy condition cause we have to call delete_all on relation not on association
|
27
|
+
beginning_of_chain.where('1=1').delete_all(all_conditions)
|
28
|
+
else
|
29
|
+
Rails.logger.error("Unknown process_mode: #{active_scaffold_config.batch_destroy.process_mode} for action batch_destroy")
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def batch_destroy_marked
|
35
|
+
case active_scaffold_config.batch_destroy.process_mode
|
36
|
+
when :delete then
|
37
|
+
each_marked_record do |record|
|
38
|
+
destroy_record(record) if authorized_for_job?(record)
|
39
|
+
end
|
40
|
+
when :delete_all then
|
41
|
+
active_scaffold_config.model.where(active_scaffold_config.model.primary_key => marked_records.to_a).delete_all
|
42
|
+
do_demark_all
|
43
|
+
else
|
44
|
+
Rails.logger.error("Unknown process_mode: #{active_scaffold_config.batch_destroy.process_mode} for action batch_destroy")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def destroy_record(record)
|
49
|
+
@successful = nil
|
50
|
+
@record = record
|
51
|
+
|
52
|
+
do_destroy
|
53
|
+
if successful?
|
54
|
+
@record.as_marked = false if batch_scope == 'MARKED'
|
55
|
+
else
|
56
|
+
error_records << @record
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# The default security delegates to ActiveRecordPermissions.
|
61
|
+
# You may override the method to customize.
|
62
|
+
def batch_destroy_authorized?(record = nil)
|
63
|
+
authorized_for?(:crud_type => :delete)
|
64
|
+
end
|
65
|
+
|
66
|
+
def batch_destroy_marked_ignore?(record = nil)
|
67
|
+
!active_scaffold_config.actions.include? :mark
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def batch_destroy_authorized_filter
|
73
|
+
link = active_scaffold_config.batch_destroy.link || active_scaffold_config.batch_destroy.class.link
|
74
|
+
raise ActiveScaffold::ActionNotAllowed unless self.send(link.first.security_method)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,281 @@
|
|
1
|
+
module ActiveScaffold::Actions
|
2
|
+
module BatchUpdate
|
3
|
+
|
4
|
+
GenericOperators = [
|
5
|
+
'NO_UPDATE',
|
6
|
+
'REPLACE'
|
7
|
+
]
|
8
|
+
NumericOperators = [
|
9
|
+
'PLUS',
|
10
|
+
'MINUS',
|
11
|
+
'TIMES',
|
12
|
+
'DIVISION'
|
13
|
+
]
|
14
|
+
NumericOptions = [
|
15
|
+
'ABSOLUTE',
|
16
|
+
'PERCENT'
|
17
|
+
]
|
18
|
+
|
19
|
+
DateOperators = [
|
20
|
+
'PLUS',
|
21
|
+
'MINUS'
|
22
|
+
]
|
23
|
+
|
24
|
+
def self.included(base)
|
25
|
+
base.send :include, ActiveScaffold::Actions::BatchBase unless base < ActiveScaffold::Actions::BatchBase
|
26
|
+
base.before_filter :batch_update_authorized_filter, :only => [:batch_edit, :batch_update]
|
27
|
+
base.helper_method :batch_update_values
|
28
|
+
end
|
29
|
+
|
30
|
+
def batch_edit
|
31
|
+
do_batch_edit
|
32
|
+
respond_to_action(:batch_edit)
|
33
|
+
end
|
34
|
+
|
35
|
+
def batch_update
|
36
|
+
batch_action
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
protected
|
41
|
+
def batch_edit_respond_to_html
|
42
|
+
if batch_successful?
|
43
|
+
render(:action => 'batch_update')
|
44
|
+
else
|
45
|
+
return_to_main
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def batch_edit_respond_to_js
|
50
|
+
render(:partial => 'batch_update_form')
|
51
|
+
end
|
52
|
+
|
53
|
+
def batch_update_values
|
54
|
+
@batch_update_values || {}
|
55
|
+
end
|
56
|
+
|
57
|
+
def batch_update_respond_to_html
|
58
|
+
if params[:iframe]=='true' # was this an iframe post ?
|
59
|
+
flash[:info] = as_(:batch_processing_successful) if batch_successful?
|
60
|
+
do_refresh_list
|
61
|
+
responds_to_parent do
|
62
|
+
render :action => 'on_batch_update.js', :layout => false
|
63
|
+
end
|
64
|
+
else # just a regular post
|
65
|
+
if batch_successful?
|
66
|
+
flash[:info] = as_(:updated_model, :model => @record.to_label)
|
67
|
+
return_to_main
|
68
|
+
else
|
69
|
+
render(:action => 'batch_update')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def batch_update_respond_to_js
|
75
|
+
flash[:info] = as_(:batch_processing_successful) if batch_successful?
|
76
|
+
do_refresh_list
|
77
|
+
render :action => 'on_batch_update'
|
78
|
+
end
|
79
|
+
|
80
|
+
def do_batch_edit
|
81
|
+
self.successful = true
|
82
|
+
do_new
|
83
|
+
end
|
84
|
+
|
85
|
+
def before_do_batch_update
|
86
|
+
@batch_update_values = update_attribute_values_from_params(active_scaffold_config.batch_update.columns, params[:record])
|
87
|
+
end
|
88
|
+
|
89
|
+
def batch_update_listed
|
90
|
+
case active_scaffold_config.batch_update.process_mode
|
91
|
+
when :update then
|
92
|
+
each_record_in_scope {|record| update_record_in_batch(record) if authorized_for_job?(record)}
|
93
|
+
when :update_all then
|
94
|
+
updates = updates_for_update_all
|
95
|
+
unless updates.first.empty?
|
96
|
+
do_search if respond_to? :do_search
|
97
|
+
# all_conditions might fail cause joins are not working in update_all
|
98
|
+
active_scaffold_config.model.update_all(updates, all_conditions)
|
99
|
+
end
|
100
|
+
else
|
101
|
+
Rails.logger.error("Unknown process_mode: #{active_scaffold_config.batch_update.process_mode} for action batch_update")
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
def batch_update_marked
|
107
|
+
case active_scaffold_config.batch_update.process_mode
|
108
|
+
when :update then
|
109
|
+
each_marked_record {|record| update_record_in_batch(record) if authorized_for_job?(record)}
|
110
|
+
when :update_all then
|
111
|
+
updates = updates_for_update_all
|
112
|
+
unless updates.first.empty?
|
113
|
+
active_scaffold_config.model.where(active_scaffold_config.model.primary_key => marked_records.to_a).update_all(updates)
|
114
|
+
do_demark_all
|
115
|
+
end
|
116
|
+
else
|
117
|
+
Rails.logger.error("Unknown process_mode: #{active_scaffold_config.batch_update.process_mode} for action batch_update")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def updates_for_update_all()
|
122
|
+
update_all = [[]]
|
123
|
+
batch_update_values.each do |attribute, value|
|
124
|
+
sql_set, value = get_update_all_attribute(value[:column], attribute, value[:value])
|
125
|
+
unless sql_set.nil?
|
126
|
+
update_all.first << sql_set
|
127
|
+
update_all << value if value.present?
|
128
|
+
end
|
129
|
+
end
|
130
|
+
update_all[0] = update_all.first.join(',')
|
131
|
+
update_all
|
132
|
+
end
|
133
|
+
|
134
|
+
def update_record_in_batch(record)
|
135
|
+
@successful = nil
|
136
|
+
@record = record
|
137
|
+
|
138
|
+
batch_update_values.each do |attribute, value|
|
139
|
+
set_record_attribute(value[:column], attribute, value[:value])
|
140
|
+
end
|
141
|
+
|
142
|
+
update_save(:no_record_param_update => true)
|
143
|
+
if successful?
|
144
|
+
@record.as_marked = false if batch_scope == 'MARKED'
|
145
|
+
else
|
146
|
+
error_records << @record
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def get_update_all_attribute(column, attribute, value)
|
151
|
+
form_ui = column_form_ui(column)
|
152
|
+
|
153
|
+
if form_ui && (method = override_batch_update_all_value(form_ui))
|
154
|
+
update_value = send(method, column, value)
|
155
|
+
if update_value.nil?
|
156
|
+
sql_set = nil
|
157
|
+
else
|
158
|
+
sql_set = "#{attribute} = #{update_value}"
|
159
|
+
update_value = nil
|
160
|
+
end
|
161
|
+
else
|
162
|
+
sql_set = "#{attribute} = ?"
|
163
|
+
update_value = value[:value]
|
164
|
+
end
|
165
|
+
|
166
|
+
return sql_set, update_value
|
167
|
+
end
|
168
|
+
|
169
|
+
def update_attribute_values_from_params(columns, attributes)
|
170
|
+
values = {}
|
171
|
+
attributes = {} unless attributes.is_a?(Hash)
|
172
|
+
columns.each :for => new_model, :crud_type => :update, :flatten => true do |column|
|
173
|
+
next unless attributes[column.name].is_a?(Hash) && params[:record][column.name][:operator] != 'NO_UPDATE'
|
174
|
+
value = attributes[column.name]
|
175
|
+
value = value.merge(:value => (value[:operator] == 'NULL') ? nil : column_value_from_param_value(nil, column, value[:value]))
|
176
|
+
values[column.name] = {:column => column, :value => value}
|
177
|
+
end
|
178
|
+
values
|
179
|
+
end
|
180
|
+
|
181
|
+
# The default security delegates to ActiveRecordPermissions.
|
182
|
+
# You may override the method to customize.
|
183
|
+
def batch_update_authorized?(record = nil)
|
184
|
+
authorized_for?(:crud_type => :update)
|
185
|
+
end
|
186
|
+
|
187
|
+
def batch_update_ignore?(record = nil)
|
188
|
+
false
|
189
|
+
end
|
190
|
+
|
191
|
+
def batch_update_value_for_numeric(column, record, calculation_info)
|
192
|
+
current_value = record.send(column.name)
|
193
|
+
if ActiveScaffold::Actions::BatchUpdate::GenericOperators.include?(calculation_info[:operator]) || ActiveScaffold::Actions::BatchUpdate::NumericOperators.include?(calculation_info[:operator])
|
194
|
+
operand = self.class.condition_value_for_numeric(column, calculation_info[:value])
|
195
|
+
operand = current_value / 100 * operand if calculation_info[:opt] == 'PERCENT'
|
196
|
+
case calculation_info[:operator]
|
197
|
+
when 'REPLACE' then operand
|
198
|
+
when 'NULL' then nil
|
199
|
+
when 'PLUS' then current_value.present? ? current_value + operand : nil
|
200
|
+
when 'MINUS' then current_value.present? ? current_value - operand : nil
|
201
|
+
when 'TIMES' then current_value.present? ? current_value * operand : nil
|
202
|
+
when 'DIVISION' then current_value.present? ? current_value / operand : nil
|
203
|
+
else
|
204
|
+
current_value
|
205
|
+
end
|
206
|
+
else
|
207
|
+
current_value
|
208
|
+
end
|
209
|
+
end
|
210
|
+
alias_method :batch_update_value_for_integer, :batch_update_value_for_numeric
|
211
|
+
alias_method :batch_update_value_for_decimal, :batch_update_value_for_numeric
|
212
|
+
alias_method :batch_update_value_for_float, :batch_update_value_for_numeric
|
213
|
+
|
214
|
+
def batch_update_all_value_for_numeric(column, calculation_info)
|
215
|
+
if ActiveScaffold::Actions::BatchUpdate::GenericOperators.include?(calculation_info[:operator]) || ActiveScaffold::Actions::BatchUpdate::NumericOperators.include?(calculation_info[:operator])
|
216
|
+
operand = active_scaffold_config.model.quote_value(self.class.condition_value_for_numeric(column, calculation_info[:value]))
|
217
|
+
if calculation_info[:opt] == 'PERCENT'
|
218
|
+
operand = "#{active_scaffold_config.model.connection.quote_column_name(column.name)} / 100.0 * #{operand}"
|
219
|
+
end
|
220
|
+
case calculation_info[:operator]
|
221
|
+
when 'REPLACE' then operand
|
222
|
+
when 'NULL' then active_scaffold_config.model.quote_value(nil)
|
223
|
+
when 'PLUS' then "#{active_scaffold_config.model.connection.quote_column_name(column.name)} + #{operand}"
|
224
|
+
when 'MINUS' then "#{active_scaffold_config.model.connection.quote_column_name(column.name)} - #{operand}"
|
225
|
+
when 'TIMES' then "#{active_scaffold_config.model.connection.quote_column_name(column.name)} * #{operand}"
|
226
|
+
when 'DIVISION' then "#{active_scaffold_config.model.connection.quote_column_name(column.name)} / #{operand}"
|
227
|
+
else
|
228
|
+
nil
|
229
|
+
end
|
230
|
+
else
|
231
|
+
nil
|
232
|
+
end
|
233
|
+
end
|
234
|
+
alias_method :batch_update_all_value_for_integer, :batch_update_all_value_for_numeric
|
235
|
+
alias_method :batch_update_all_value_for_decimal, :batch_update_all_value_for_numeric
|
236
|
+
alias_method :batch_update_all_value_for_float, :batch_update_all_value_for_numeric
|
237
|
+
|
238
|
+
def batch_update_value_for_date_picker(column, record, calculation_info)
|
239
|
+
current_value = record.send(column.name)
|
240
|
+
{"number"=>"", "unit"=>"DAYS", "value"=>"November 16, 2010", "operator"=>"REPLACE"}
|
241
|
+
if ActiveScaffold::Actions::BatchUpdate::GenericOperators.include?(calculation_info[:operator]) || ActiveScaffold::Actions::BatchUpdate::DateOperators.include?(calculation_info[:operator])
|
242
|
+
operand = self.class.condition_value_for_datetime(calculation_info[:value], column.column.type == :date ? :to_date : :to_time)
|
243
|
+
case calculation_info[:operator]
|
244
|
+
when 'REPLACE' then operand
|
245
|
+
when 'NULL' then nil
|
246
|
+
when 'PLUS' then
|
247
|
+
trend_number = [calculation_info['number'].to_i, 1].max
|
248
|
+
current_value.in((trend_number).send(calculation_info['unit'].downcase.singularize.to_sym))
|
249
|
+
when 'MINUS' then
|
250
|
+
trend_number = [calculation_info['number'].to_i, 1].max
|
251
|
+
current_value.ago((trend_number).send(calculation_info['unit'].downcase.singularize.to_sym))
|
252
|
+
else
|
253
|
+
current_value
|
254
|
+
end
|
255
|
+
else
|
256
|
+
current_value
|
257
|
+
end
|
258
|
+
end
|
259
|
+
alias_method :batch_update_value_for_calendar_date_select, :batch_update_value_for_date_picker
|
260
|
+
|
261
|
+
def override_batch_update_value(form_ui)
|
262
|
+
method = "batch_update_value_for_#{form_ui}"
|
263
|
+
method if respond_to? method
|
264
|
+
end
|
265
|
+
|
266
|
+
def override_batch_update_all_value(form_ui)
|
267
|
+
method = "batch_update_all_value_for_#{form_ui}"
|
268
|
+
method if respond_to? method
|
269
|
+
end
|
270
|
+
|
271
|
+
private
|
272
|
+
|
273
|
+
def batch_update_authorized_filter
|
274
|
+
link = active_scaffold_config.batch_update.link || active_scaffold_config.batch_update.class.link
|
275
|
+
raise ActiveScaffold::ActionNotAllowed unless self.send(link.security_method)
|
276
|
+
end
|
277
|
+
def batch_edit_formats
|
278
|
+
(default_formats + active_scaffold_config.formats).uniq
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module ActiveScaffold::Config
|
2
|
+
class BatchCreate < ActiveScaffold::Config::Form
|
3
|
+
self.crud_type = :create
|
4
|
+
def initialize(*args)
|
5
|
+
super
|
6
|
+
@multipart = @core.create.multipart? if @core.actions.include? :create
|
7
|
+
@process_mode = self.class.process_mode
|
8
|
+
@list_mode_enabled = self.class.list_mode_enabled
|
9
|
+
@run_in_transaction = self.class.run_in_transaction
|
10
|
+
@layout = self.class.layout
|
11
|
+
end
|
12
|
+
|
13
|
+
# global level configuration
|
14
|
+
# --------------------------
|
15
|
+
# the ActionLink for this action
|
16
|
+
def self.link
|
17
|
+
@@link
|
18
|
+
end
|
19
|
+
def self.link=(val)
|
20
|
+
@@link = val
|
21
|
+
end
|
22
|
+
@@link = ActiveScaffold::DataStructures::ActionLink.new('batch_new', :label => :create, :type => :collection, :security_method => :batch_create_authorized?, :ignore_method => :batch_create_ignore?)
|
23
|
+
|
24
|
+
# configures where the plugin itself is located. there is no instance version of this.
|
25
|
+
cattr_accessor :plugin_directory
|
26
|
+
@@plugin_directory = File.expand_path(__FILE__).match(%{(^.*)/lib/active_scaffold/config/batch_create.rb})[1]
|
27
|
+
|
28
|
+
# configures how batch create should be processed
|
29
|
+
# :create => standard activerecord create including validations
|
30
|
+
cattr_accessor :process_mode
|
31
|
+
@@process_mode = :create
|
32
|
+
|
33
|
+
# you may update all records in list view or all marked records
|
34
|
+
# you might disable list mode with this switch if you think it is
|
35
|
+
# too "dangerous"
|
36
|
+
cattr_accessor :list_mode_enabled
|
37
|
+
@@list_mode_enabled = true
|
38
|
+
|
39
|
+
# run all create statements in a transaction, so no record is created
|
40
|
+
# if someone fails
|
41
|
+
cattr_accessor :run_in_transaction
|
42
|
+
@@run_in_transaction = true
|
43
|
+
|
44
|
+
# layout for create multiple records
|
45
|
+
cattr_accessor :layout
|
46
|
+
@@layout = :vertical
|
47
|
+
|
48
|
+
# instance-level configuration
|
49
|
+
# ----------------------------
|
50
|
+
|
51
|
+
# see class accessor
|
52
|
+
attr_accessor :process_mode
|
53
|
+
|
54
|
+
attr_accessor :list_mode_enabled
|
55
|
+
|
56
|
+
# you may use create_batch to create a record for each record
|
57
|
+
# of a belong_to association (reverse must be has_many)
|
58
|
+
# eg. player belongs to team
|
59
|
+
# you may batch create a player records for a list of teams
|
60
|
+
attr_accessor :default_batch_by_column
|
61
|
+
|
62
|
+
# run all create statements in a transaction, so no record is created
|
63
|
+
# if someone fails
|
64
|
+
attr_accessor :run_in_transaction
|
65
|
+
|
66
|
+
# layout for create multiple records
|
67
|
+
attr_accessor :layout
|
68
|
+
|
69
|
+
def action_group
|
70
|
+
@action_group || (default_batch_by_column ? 'collection.group' : 'collection')
|
71
|
+
end
|
72
|
+
|
73
|
+
# the label= method already exists in the Form base class
|
74
|
+
def label(model = nil)
|
75
|
+
model ||= @core.label(:count => 2)
|
76
|
+
@label ? as_(@label) : as_(:create_model, :model => model)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|