active_scaffold_batch 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|