active_scaffold_batch_vho 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 vhochstein
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ require './lib/active_scaffold_batch/version.rb'
14
+
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "active_scaffold_batch_vho"
18
+ gem.version = ActiveScaffoldBatch::Version::STRING
19
+ gem.homepage = "http://github.com/vhochstein/active_scaffold_batch"
20
+ gem.license = "MIT"
21
+ gem.summary = %Q{Batch Processing for ActiveScaffold}
22
+ gem.description = %Q{You want to destroy/update many records at once with activescaffold?}
23
+ gem.email = "activescaffold@googlegroups.com"
24
+ gem.authors = ["Volker Hochstein"]
25
+ gem.add_runtime_dependency 'active_scaffold_vho', '~> 3.0'
26
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
27
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
28
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
29
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
30
+ end
31
+ Jeweler::RubygemsDotOrgTasks.new
32
+
33
+ require 'rake/testtask'
34
+ Rake::TestTask.new(:test) do |test|
35
+ test.libs << 'lib' << 'test'
36
+ test.pattern = 'test/**/test_*.rb'
37
+ test.verbose = true
38
+ end
39
+
40
+ require 'rcov/rcovtask'
41
+ Rcov::RcovTask.new do |test|
42
+ test.libs << 'test'
43
+ test.pattern = 'test/**/test_*.rb'
44
+ test.verbose = true
45
+ end
46
+
47
+ task :default => :test
48
+
49
+ require 'rake/rdoctask'
50
+ Rake::RDocTask.new do |rdoc|
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "active_scaffold_batch #{ActiveScaffoldBatch::Version::STRING}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
@@ -0,0 +1,7 @@
1
+ <%= render :partial => "base_form", :locals => {:xhr => xhr ||= nil,
2
+ :form_action => form_action ||= :batch_update,
3
+ :method => method ||= :post,
4
+ :cancel_link => cancel_link ||= true,
5
+ :body_partial => 'batch_update_form_body',
6
+ :headline => headline ||= active_scaffold_config.batch_update.label} %>
7
+
@@ -0,0 +1,12 @@
1
+ <% scope ||= nil %>
2
+ <dl>
3
+ <dt>
4
+ <label for="<%= active_scaffold_input_options(column, scope)[:id] %>"><%= column.label %></label>
5
+ </dt>
6
+ <dd>
7
+ <%= active_scaffold_update_for column, scope %>
8
+ <% if column.description -%>
9
+ <span class="description"><%= column.description %></span>
10
+ <% end -%>
11
+ </dd>
12
+ </dl>
@@ -0,0 +1,9 @@
1
+ <% scope ||= nil %>
2
+ <dl>
3
+ <dt>
4
+ <label for="record_batch_scope"><%= as_(:records) %></label>
5
+ </dt>
6
+ <dd>
7
+ <%= active_scaffold_update_scope_select %>
8
+ </dd>
9
+ </dl>
@@ -0,0 +1,25 @@
1
+ <% subsection_id ||= nil %>
2
+ <ol class="form" <%= "id=#{subsection_id}" unless subsection_id.nil? %> <%= 'style="display: none;"' if columns.collapsed -%>>
3
+ <li class="form-element">
4
+ <%= render :partial => 'batch_update_form_attribute_scope' -%>
5
+ </li>
6
+ <% columns.each :for => @record do |column| %>
7
+ <% next if column.plural_association? || (column.association && [:has_one].include?(column.association.macro)) %>
8
+ <% renders_as = column_renders_as(column) %>
9
+ <% if renders_as == :subsection -%>
10
+ <% subsection_id = sub_section_id(:sub_section => column.label) %>
11
+ <li class="sub-section">
12
+ <h5><%= column.label %></h5>
13
+ <%= render :partial => 'form', :locals => { :columns => column, :subsection_id => subsection_id} %>
14
+ <%= link_to_visibility_toggle(subsection_id, {:default_visible => !column.collapsed}) -%>
15
+ </li>
16
+ <% elsif column.readonly_association?
17
+ next %>
18
+ <% else
19
+ renders_as = :field if renders_as == :subform -%>
20
+ <li class="form-element <%= column.css_class unless column.css_class.nil? %>">
21
+ <%= render :partial => 'batch_update_form_attribute', :locals => { :column => column } -%>
22
+ </li>
23
+ <% end -%>
24
+ <% end -%>
25
+ </ol>
@@ -0,0 +1,5 @@
1
+ <div class="active-scaffold">
2
+ <div class="batch-update-view <%= "#{params[:controller]}-view" %> view">
3
+ <%= render :partial => 'batch_update_form' -%>
4
+ </div>
5
+ </div>
@@ -0,0 +1,6 @@
1
+ unless @error_records.empty?
2
+ flash[:error] = @error_records.collect do |record|
3
+ active_scaffold_error_messages_for(record, :object_name => "#{record.class.model_name.human.downcase}#{record.new_record? ? '' : ": #{record.to_label}"}", :header_message => '', :message => "#{record.class.model_name.human.downcase}#{record.new_record? ? '' : ": #{record.to_label}"}", :container_tag => nil, :list_type => :br)
4
+ end.join.html_safe
5
+ end
6
+ page.call 'ActiveScaffold.replace_html', active_scaffold_content_id, render(:partial => 'list', :layout => false)
@@ -0,0 +1,10 @@
1
+ form_selector = "#{element_form_id(:action => :batch_update)}"
2
+
3
+ if controller.send :batch_successful?
4
+ page.call 'ActiveScaffold.replace_html', active_scaffold_content_id, render(:partial => 'list', :layout => false)
5
+ page << "ActiveScaffold.find_action_link('#{form_selector}').close();"
6
+ else
7
+ page << "ActiveScaffold.find_action_link('#{form_selector}').update_flash_messages('#{escape_javascript(render(:partial => 'messages').strip)}');"
8
+ page.call 'ActiveScaffold.replace', form_selector, render(:partial => 'batch_update_form', :locals => {:xhr => true})
9
+ page.call 'ActiveScaffold.scroll_to', form_selector
10
+ end
data/init.rb ADDED
@@ -0,0 +1,9 @@
1
+ ACTIVE_SCAFFOLD_BATCH_INSTALLED = :plugin
2
+
3
+ require 'active_scaffold_batch'
4
+
5
+ begin
6
+ ActiveScaffoldAssets.copy_to_public(ActiveScaffoldBatch.root)
7
+ rescue
8
+ raise $! unless Rails.env == 'production'
9
+ end
@@ -0,0 +1,118 @@
1
+ module ActiveScaffold::Actions
2
+ module BatchBase
3
+
4
+ def self.included(base)
5
+ base.add_active_scaffold_path File.join(ActiveScaffold::Config::BatchBase.plugin_directory, 'frontends', 'default' , 'views')
6
+ base.helper_method :batch_scope
7
+ end
8
+
9
+ protected
10
+
11
+ def batch_action(batch_action = :batch_base)
12
+ process_action_link_action(batch_action) do
13
+ process_batch
14
+ end
15
+ end
16
+
17
+ def process_batch
18
+ do_batch
19
+ do_search if respond_to? :do_search
20
+ do_list
21
+ end
22
+
23
+ def batch_scope
24
+ if params[:batch_scope]
25
+ @batch_scope = params[:batch_scope] if ['LISTED', 'MARKED'].include?(params[:batch_scope])
26
+ params.delete :batch_scope
27
+ end if @batch_scope.nil?
28
+ @batch_scope
29
+ end
30
+
31
+ def error_records
32
+ @error_records ||= []
33
+ end
34
+
35
+ # in case of an error we have to prepare @record object to have assigned all
36
+ # defined batch_update values, however, do not set those ones with an override
37
+ # these ones will manage on their own
38
+ def prepare_error_record
39
+ end
40
+
41
+ def batch_successful?
42
+ error_records.empty?
43
+ end
44
+
45
+ def do_batch
46
+ send("before_do_#{action_name}") if respond_to?("before_do_#{action_name}")
47
+ send("#{action_name}_#{batch_scope.downcase}") if !batch_scope.nil? && respond_to?("#{action_name}_#{batch_scope.downcase}")
48
+ prepare_error_record unless batch_successful?
49
+ end
50
+
51
+ def authorized_for_job?(record)
52
+ if record.authorized_for?(:crud_type => active_scaffold_config.send(action_name).crud_type)
53
+ true
54
+ else
55
+ record.errors.add(:base, as_(:no_authorization_for_action, :action => action_name))
56
+ error_records << record
57
+ false
58
+ end
59
+ end
60
+
61
+ def batch_base_respond_to_html
62
+ if respond_to? "#{action_name}_respond_to_html"
63
+ send("#{action_name}_respond_to_html")
64
+ else
65
+ if params[:iframe]=='true' # was this an iframe post ?
66
+ responds_to_parent do
67
+ render :action => 'on_batch_base.js', :layout => false
68
+ end
69
+ else # just a regular post
70
+ if batch_successful?
71
+ flash[:info] = as_(:batch_processing_successful)
72
+ end
73
+ return_to_main
74
+ end
75
+ end
76
+ end
77
+
78
+ def batch_base_respond_to_js
79
+ if respond_to? "#{action_name}_respond_to_js"
80
+ send("#{action_name}_respond_to_js")
81
+ else
82
+ render :action => "on_batch_base"
83
+ end
84
+ end
85
+
86
+ def batch_base_respond_to_xml
87
+ if respond_to? "#{action_name}_respond_to_xml"
88
+ send("#{action_name}_respond_to_xml")
89
+ else
90
+ render :xml => response_object.to_xml(:only => active_scaffold_config.send(action_name).columns.names), :content_type => Mime::XML, :status => response_status
91
+ end
92
+ end
93
+
94
+ def batch_base_respond_to_json
95
+ if respond_to? "#{action_name}_respond_to_json"
96
+ send("#{action_name}_respond_to_json")
97
+ else
98
+ render :text => response_object.to_json(:only => active_scaffold_config.send(action_name).columns.names), :content_type => Mime::JSON, :status => response_status
99
+ end
100
+ end
101
+
102
+ def batch_base_respond_to_yaml
103
+ if respond_to? "#{action_name}_respond_to_yaml"
104
+ send("#{action_name}_respond_to_yaml")
105
+ else
106
+ render :text => Hash.from_xml(response_object.to_xml(:only => active_scaffold_config.send(action_name).columns.names)).to_yaml, :content_type => Mime::YAML, :status => response_status
107
+ end
108
+ end
109
+
110
+ def batch_base_formats
111
+ if respond_to? "#{action_name}_formats"
112
+ send("#{action_name}_formats")
113
+ else
114
+ (default_formats + active_scaffold_config.formats + active_scaffold_config.send(action_name).formats).uniq
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,72 @@
1
+ module ActiveScaffold::Actions
2
+ module BatchDestroy
3
+
4
+ def self.included(base)
5
+ base.before_filter :batch_destroy_authorized_filter, :only => [:batch_destroy]
6
+ end
7
+
8
+ def batch_destroy
9
+ batch_action
10
+ end
11
+
12
+ protected
13
+
14
+ def batch_destroy_listed
15
+ case active_scaffold_config.batch_destroy.process_mode
16
+ when :delete then
17
+ each_record_in_scope do |record|
18
+ destroy_record(record) if authorized_for_job?(record)
19
+ end
20
+ when :delete_all then
21
+ do_search if respond_to? :do_search
22
+ active_scaffold_config.model.delete_all(all_conditions)
23
+ else
24
+ Rails.logger.error("Unknown process_mode: #{active_scaffold_config.batch_destroy.process_mode} for action batch_destroy")
25
+ end
26
+
27
+ end
28
+
29
+ def batch_destroy_marked
30
+ case active_scaffold_config.batch_destroy.process_mode
31
+ when :delete then
32
+ active_scaffold_config.model.marked.each do |record|
33
+ destroy_record(record) if authorized_for_job?(record)
34
+ end
35
+ when :delete_all then
36
+ active_scaffold_config.model.marked.delete_all
37
+ do_demark_all
38
+ else
39
+ Rails.logger.error("Unknown process_mode: #{active_scaffold_config.batch_destroy.process_mode} for action batch_destroy")
40
+ end
41
+ end
42
+
43
+ def destroy_record(record)
44
+ @successful = nil
45
+ @record = record
46
+
47
+ do_destroy
48
+ if successful?
49
+ @record.marked = false if batch_scope == 'MARKED'
50
+ else
51
+ error_records << @record
52
+ end
53
+ end
54
+
55
+ # The default security delegates to ActiveRecordPermissions.
56
+ # You may override the method to customize.
57
+ def batch_destroy_authorized?(record = nil)
58
+ authorized_for?(:crud_type => :delete)
59
+ end
60
+
61
+ def batch_destroy_marked_ignore?(record = nil)
62
+ !active_scaffold_config.list.columns.include? :marked
63
+ end
64
+
65
+ private
66
+
67
+ def batch_destroy_authorized_filter
68
+ link = active_scaffold_config.batch_destroy.link || active_scaffold_config.batch_destroy.class.link
69
+ raise ActiveScaffold::ActionNotAllowed unless self.send(link.first.security_method)
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,320 @@
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.before_filter :batch_update_authorized_filter, :only => [:batch_edit, :batch_update]
26
+ base.verify :method => [:post, :put],
27
+ :only => :batch_update,
28
+ :redirect_to => { :action => :index }
29
+ base.helper_method :batch_update_values
30
+ end
31
+
32
+ def batch_edit
33
+ do_batch_edit
34
+ respond_to_action(:batch_edit)
35
+ end
36
+
37
+ def batch_update
38
+ batch_action
39
+ end
40
+
41
+
42
+ protected
43
+ def batch_edit_respond_to_html
44
+ if batch_successful?
45
+ render(:action => 'batch_update')
46
+ else
47
+ return_to_main
48
+ end
49
+ end
50
+
51
+ def batch_edit_respond_to_js
52
+ render(:partial => 'batch_update_form')
53
+ end
54
+
55
+ def selected_columns
56
+ if @selected_columns.nil?
57
+ @selected_columns = []
58
+ if params[:record] && params[:record].is_a?(Hash)
59
+ params[:record].each do |key, value|
60
+ @selected_columns << key.to_sym if value[:operator] != 'NO_UPDATE'
61
+ end
62
+ end
63
+ end
64
+ @selected_columns
65
+ end
66
+
67
+
68
+ def batch_update_values
69
+ @batch_update_values || {}
70
+ end
71
+
72
+ def batch_update_respond_to_html
73
+ if params[:iframe]=='true' # was this an iframe post ?
74
+ responds_to_parent do
75
+ render :action => 'on_batch_update.js', :layout => false
76
+ end
77
+ else # just a regular post
78
+ if batch_successful?
79
+ flash[:info] = as_(:updated_model, :model => @record.to_label)
80
+ return_to_main
81
+ else
82
+ render(:action => 'batch_update')
83
+ end
84
+ end
85
+ end
86
+
87
+ def batch_update_respond_to_js
88
+ render :action => 'on_batch_update'
89
+ end
90
+
91
+ def do_batch_edit
92
+ self.successful = true
93
+ do_new
94
+ end
95
+
96
+ def before_do_batch_update
97
+ update_columns = active_scaffold_config.batch_update.columns
98
+ @batch_update_values = attribute_values_from_params(update_columns, params[:record])
99
+ end
100
+
101
+ # in case of an error we have to prepare @record object to have assigned all
102
+ # defined batch_update values, however, do not set those ones with an override
103
+ # these ones will manage on their own
104
+ def prepare_error_record
105
+ do_new
106
+ batch_update_values.each do |attribute, value|
107
+ form_ui = colunm_form_ui(value[:column])
108
+ set_record_attribute(value[:column], attribute, value[:value]) unless form_ui && override_batch_update_value?(form_ui)
109
+ end
110
+ end
111
+
112
+ def batch_update_listed
113
+ case active_scaffold_config.batch_update.process_mode
114
+ when :update then
115
+ each_record_in_scope {|record| update_record(record) if authorized_for_job?(record)}
116
+ when :update_all then
117
+ updates = updates_for_update_all
118
+ unless updates.first.empty?
119
+ do_search if respond_to? :do_search
120
+ # all_conditions might fail cause joins are not working in update_all
121
+ active_scaffold_config.model.update_all(updates, all_conditions)
122
+ end
123
+ else
124
+ Rails.logger.error("Unknown process_mode: #{active_scaffold_config.batch_update.process_mode} for action batch_update")
125
+ end
126
+
127
+ end
128
+
129
+ def batch_update_marked
130
+ case active_scaffold_config.batch_update.process_mode
131
+ when :update then
132
+ active_scaffold_config.model.marked.each {|record| update_record(record) if authorized_for_job?(record)}
133
+ when :update_all then
134
+ updates = updates_for_update_all
135
+ unless updates.first.empty?
136
+ active_scaffold_config.model.marked.update_all(updates)
137
+ do_demark_all
138
+ end
139
+ else
140
+ Rails.logger.error("Unknown process_mode: #{active_scaffold_config.batch_update.process_mode} for action batch_update")
141
+ end
142
+ end
143
+
144
+ def updates_for_update_all()
145
+ update_all = [[]]
146
+ batch_update_values.each do |attribute, value|
147
+ sql_set, value = get_update_all_attribute(value[:column], attribute, value[:value])
148
+ unless sql_set.nil?
149
+ update_all.first << sql_set
150
+ update_all << value if sql_set.include?('?')
151
+ end
152
+ end
153
+ update_all[0] = update_all.first.join(',')
154
+ update_all
155
+ end
156
+
157
+ def update_record(record)
158
+ @successful = nil
159
+ @record = record
160
+
161
+ batch_update_values.each do |attribute, value|
162
+ set_record_attribute(value[:column], attribute, value[:value])
163
+ end
164
+
165
+ update_save
166
+ if successful?
167
+ @record.marked = false if batch_scope == 'MARKED'
168
+ else
169
+ error_records << @record
170
+ end
171
+ end
172
+
173
+ def set_record_attribute(column, attribute, value)
174
+ form_ui = colunm_form_ui(column)
175
+ if form_ui && override_batch_update_value?(form_ui)
176
+ @record.send("#{attribute}=", send(override_batch_update_value(form_ui), column, @record, value))
177
+ else
178
+ @record.send("#{attribute}=", value[:operator] == 'NULL' ? nil : value[:value])
179
+ end
180
+ end
181
+
182
+ def colunm_form_ui(column)
183
+ form_ui = column.form_ui
184
+ form_ui = column.column.type if form_ui.nil? && column.column
185
+ end
186
+
187
+ def get_update_all_attribute(column, attribute, value)
188
+ form_ui = column.form_ui
189
+ form_ui = column.column.type if form_ui.nil? && column.column
190
+
191
+ if form_ui && override_batch_update_all_value?(form_ui)
192
+ update_value = send(override_batch_update_all_value(form_ui), column, value)
193
+ if update_value.nil?
194
+ sql_set = nil
195
+ else
196
+ sql_set = "#{attribute} = #{update_value}"
197
+ update_value = nil
198
+ end
199
+ else
200
+ sql_set = "#{attribute} = ?"
201
+ update_value = value[:operator] == 'NULL' ? nil : value[:value]
202
+ end
203
+
204
+ return sql_set, update_value
205
+ end
206
+
207
+ def attribute_values_from_params(columns, attributes)
208
+ values = {}
209
+ columns.each :for => active_scaffold_config.model.new, :crud_type => :update, :flatten => true do |column|
210
+ values[column.name] = {:column => column, :value => attributes[column.name].merge(:value => column_value_from_param_value(nil, column, attributes[column.name][:value]))} if selected_columns.include? column.name
211
+ end
212
+ values
213
+ end
214
+
215
+
216
+ # The default security delegates to ActiveRecordPermissions.
217
+ # You may override the method to customize.
218
+ def batch_update_authorized?(record = nil)
219
+ authorized_for?(:crud_type => :update)
220
+ end
221
+
222
+ def batch_update_value_for_numeric(column, record, calculation_info)
223
+ current_value = record.send(column.name)
224
+ if ActiveScaffold::Actions::BatchUpdate::GenericOperators.include?(calculation_info[:operator]) || ActiveScaffold::Actions::BatchUpdate::NumericOperators.include?(calculation_info[:operator])
225
+ operand = self.class.condition_value_for_numeric(column, calculation_info[:value])
226
+ operand = current_value / 100 * operand if calculation_info[:opt] == 'PERCENT'
227
+ case calculation_info[:operator]
228
+ when 'REPLACE' then operand
229
+ when 'NULL' then nil
230
+ when 'PLUS' then current_value.present? ? current_value + operand : nil
231
+ when 'MINUS' then current_value.present? ? current_value - operand : nil
232
+ when 'TIMES' then current_value.present? ? current_value * operand : nil
233
+ when 'DIVISION' then current_value.present? ? current_value / operand : nil
234
+ else
235
+ current_value
236
+ end
237
+ else
238
+ current_value
239
+ end
240
+ end
241
+ alias_method :batch_update_value_for_integer, :batch_update_value_for_numeric
242
+ alias_method :batch_update_value_for_decimal, :batch_update_value_for_numeric
243
+ alias_method :batch_update_value_for_float, :batch_update_value_for_numeric
244
+
245
+ def batch_update_all_value_for_numeric(column, calculation_info)
246
+ if ActiveScaffold::Actions::BatchUpdate::GenericOperators.include?(calculation_info[:operator]) || ActiveScaffold::Actions::BatchUpdate::NumericOperators.include?(calculation_info[:operator])
247
+ operand = active_scaffold_config.model.quote_value(self.class.condition_value_for_numeric(column, calculation_info[:value]))
248
+ if calculation_info[:opt] == 'PERCENT'#
249
+ operand = "#{active_scaffold_config.model.connection.quote_column_name(column.name)} / 100.0 * #{operand}"
250
+ end
251
+ case calculation_info[:operator]
252
+ when 'REPLACE' then operand
253
+ when 'NULL' then active_scaffold_config.model.quote_value(nil)
254
+ when 'PLUS' then "#{active_scaffold_config.model.connection.quote_column_name(column.name)} + #{operand}"
255
+ when 'MINUS' then "#{active_scaffold_config.model.connection.quote_column_name(column.name)} - #{operand}"
256
+ when 'TIMES' then "#{active_scaffold_config.model.connection.quote_column_name(column.name)} * #{operand}"
257
+ when 'DIVISION' then "#{active_scaffold_config.model.connection.quote_column_name(column.name)} / #{operand}"
258
+ else
259
+ nil
260
+ end
261
+ else
262
+ nil
263
+ end
264
+ end
265
+ alias_method :batch_update_all_value_for_integer, :batch_update_all_value_for_numeric
266
+ alias_method :batch_update_all_value_for_decimal, :batch_update_all_value_for_numeric
267
+ alias_method :batch_update_all_value_for_float, :batch_update_all_value_for_numeric
268
+
269
+ def batch_update_value_for_date_picker(column, record, calculation_info)
270
+ current_value = record.send(column.name)
271
+ {"number"=>"", "unit"=>"DAYS", "value"=>"November 16, 2010", "operator"=>"REPLACE"}
272
+ if ActiveScaffold::Actions::BatchUpdate::GenericOperators.include?(calculation_info[:operator]) || ActiveScaffold::Actions::BatchUpdate::DateOperators.include?(calculation_info[:operator])
273
+ operand = self.class.condition_value_for_datetime(calculation_info[:value], column.column.type == :date ? :to_date : :to_time)
274
+ case calculation_info[:operator]
275
+ when 'REPLACE' then operand
276
+ when 'NULL' then nil
277
+ when 'PLUS' then
278
+ trend_number = [calculation_info['number'].to_i, 1].max
279
+ current_value.in((trend_number).send(calculation_info['unit'].downcase.singularize.to_sym))
280
+ when 'MINUS' then
281
+ trend_number = [calculation_info['number'].to_i, 1].max
282
+ current_value.ago((trend_number).send(calculation_info['unit'].downcase.singularize.to_sym))
283
+ else
284
+ current_value
285
+ end
286
+ else
287
+ current_value
288
+ end
289
+ end
290
+ alias_method :batch_update_value_for_calendar_date_select, :batch_update_value_for_date_picker
291
+
292
+
293
+
294
+ def override_batch_update_value?(form_ui)
295
+ respond_to?(override_batch_update_value(form_ui))
296
+ end
297
+
298
+ def override_batch_update_value(form_ui)
299
+ "batch_update_value_for_#{form_ui}"
300
+ end
301
+
302
+ def override_batch_update_all_value?(form_ui)
303
+ respond_to?(override_batch_update_all_value(form_ui))
304
+ end
305
+
306
+ def override_batch_update_all_value(form_ui)
307
+ "batch_update_all_value_for_#{form_ui}"
308
+ end
309
+
310
+ private
311
+
312
+ def batch_update_authorized_filter
313
+ link = active_scaffold_config.batch_update.link || active_scaffold_config.batch_update.class.link
314
+ raise ActiveScaffold::ActionNotAllowed unless self.send(link.security_method)
315
+ end
316
+ def batch_edit_formats
317
+ (default_formats + active_scaffold_config.formats).uniq
318
+ end
319
+ end
320
+ end
@@ -0,0 +1,11 @@
1
+ module ActiveScaffold::Config
2
+ class BatchBase < ActiveScaffold::Config::Base
3
+ def initialize(core_config)
4
+ @core = core_config
5
+ end
6
+
7
+ # configures where the plugin itself is located. there is no instance version of this.
8
+ cattr_accessor :plugin_directory
9
+ @@plugin_directory = File.expand_path(__FILE__).match(%{(^.*)/lib/active_scaffold/config/batch_base.rb})[1]
10
+ end
11
+ end
@@ -0,0 +1,54 @@
1
+ module ActiveScaffold::Config
2
+ class BatchDestroy < ActiveScaffold::Config::Base
3
+ self.crud_type = :delete
4
+
5
+ def initialize(core_config)
6
+ @core = core_config
7
+
8
+ # start with the ActionLink defined globally
9
+ @link = self.class.link
10
+ @action_group = self.class.action_group.clone if self.class.action_group
11
+ @action_group ||= 'collection.batch.destroy'
12
+ @process_mode = self.class.process_mode
13
+ end
14
+
15
+ # global level configuration
16
+ # --------------------------
17
+ # the ActionLink for this action
18
+ def self.link
19
+ @@link
20
+ end
21
+ def self.link=(val)
22
+ @@link = val
23
+ end
24
+ @@link = [ ActiveScaffold::DataStructures::ActionLink.new('batch_destroy', :label => :listed, :type => :collection, :method => :delete, :position => false, :crud_type => :delete, :confirm => :are_you_sure_to_delete, :parameters => {:batch_scope => 'LISTED'},:security_method => :batch_destroy_authorized?),
25
+ ActiveScaffold::DataStructures::ActionLink.new('batch_destroy', :label => :marked, :type => :collection, :method => :delete, :position => false, :crud_type => :delete, :confirm => :are_you_sure_to_delete, :parameters => {:batch_scope => 'MARKED'}, :security_method => :batch_destroy_authorized?, :ignore_method => :batch_destroy_marked_ignore?)]
26
+
27
+ # configures where the plugin itself is located. there is no instance version of this.
28
+ cattr_accessor :plugin_directory
29
+ @@plugin_directory = File.expand_path(__FILE__).match(/vendor\/plugins\/([^\/]*)/)[1]
30
+
31
+ # configures how batch updates should be processed
32
+ # :delete => standard activerecord delete including validations
33
+ # :delete_all => updating in one sql call without activerecord instantiation and validation
34
+ cattr_accessor :process_mode
35
+ @@process_mode = :delete
36
+
37
+
38
+ # instance-level configuration
39
+ # ----------------------------
40
+
41
+ # see class accessor
42
+ attr_accessor :process_mode
43
+
44
+ # the ActionLink for this action
45
+ attr_accessor :link
46
+
47
+ # the label= method already exists in the Form base class
48
+ def label(model = nil)
49
+ model ||= @core.label(:count => 2)
50
+ @label ? as_(@label) : as_(:deleted_model, :model => model)
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,45 @@
1
+ module ActiveScaffold::Config
2
+ class BatchUpdate < ActiveScaffold::Config::Form
3
+ self.crud_type = :update
4
+ def initialize(*args)
5
+ super
6
+ @process_mode = self.class.process_mode
7
+ @action_group ||= 'collection.batch'
8
+ end
9
+
10
+ # global level configuration
11
+ # --------------------------
12
+ # the ActionLink for this action
13
+ def self.link
14
+ @@link
15
+ end
16
+ def self.link=(val)
17
+ @@link = val
18
+ end
19
+ @@link = ActiveScaffold::DataStructures::ActionLink.new('batch_edit', :label => :edit, :type => :collection, :security_method => :batch_update_authorized?)
20
+
21
+ # configures where the plugin itself is located. there is no instance version of this.
22
+ cattr_accessor :plugin_directory
23
+ @@plugin_directory = File.expand_path(__FILE__).match(/vendor\/plugins\/([^\/]*)/)[1]
24
+
25
+ # configures how batch updates should be processed
26
+ # :update => standard activerecord update including validations
27
+ # :update_all => updating in one sql call without activerecord instantiation and validation
28
+ cattr_accessor :process_mode
29
+ @@process_mode = :update
30
+
31
+
32
+ # instance-level configuration
33
+ # ----------------------------
34
+
35
+ # see class accessor
36
+ attr_accessor :process_mode
37
+
38
+
39
+ # the label= method already exists in the Form base class
40
+ def label(model = nil)
41
+ model ||= @core.label(:count => 2)
42
+ @label ? as_(@label) : as_(:update_model, :model => model)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,33 @@
1
+ module ActiveScaffold
2
+ module Helpers
3
+ module CalendarDateSelectUpdateColumnHelpers
4
+ def active_scaffold_update_calendar_date_select(column, options)
5
+ current_params = {:value => nil, :number => nil, :unit => nil, :operator => 'NO_UPDATE'}
6
+ current_params.merge!(batch_update_values[column.name][:value].symbolize_keys) if batch_update_values[column.name] && batch_update_values[column.name][:value]
7
+ Rails.logger.info("update_date column: #{column.name}: #{current_params[:value].inspect}, class: #{current_params[:value].class}")
8
+ Rails.logger.info("update_date column: #{column.name}: options #{options.inspect}")
9
+ current_params[:value] = nil if current_params[:value].is_a?(String)
10
+ Rails.logger.info("update_date2 column: #{column.name}: #{current_params[:value].inspect}, class: #{current_params[:value].class}")
11
+ operator_options = active_scaffold_update_generic_operators(column)
12
+ operator_options.concat(ActiveScaffold::Actions::BatchUpdate::DateOperators.collect {|comp| [as_(comp.downcase.to_sym), comp]}) if active_scaffold_config.batch_update.process_mode == :update
13
+ options = options.merge(:show => ['PLUS', 'MINUS'].exclude?(current_params[:operator]))
14
+ tags = []
15
+ tags << select_tag("[record][#{column.name}][operator]",
16
+ options_for_select(operator_options, current_params[:operator]),
17
+ :id => "#{options[:id]}_operator",
18
+ :class => "text-input as_update_date_operator")
19
+ tags << active_scaffold_search_date_bridge_calendar_control(column, options, current_params[:value], 'value')
20
+ tags << active_scaffold_update_date_bridge_trend_tag(column, current_params, options)
21
+ tags.join("&nbsp;").html_safe
22
+ end
23
+
24
+ def active_scaffold_update_date_bridge_trend_tag(column, current_params, options)
25
+ active_scaffold_date_bridge_trend_tag(column, options,
26
+ {:name_prefix => '[record]',
27
+ :number_value => current_params[:number],
28
+ :unit_value => current_params[:unit],
29
+ :show => ['PLUS','MINUS'].include?(current_params[:operator])})
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ module ActiveScaffold
2
+ module Helpers
3
+ module DatepickerUpdateColumnHelpers
4
+ def active_scaffold_update_date_picker(column, options)
5
+ current_params = {:value => nil, :number => nil, :unit => nil, :operator => 'NO_UPDATE'}
6
+ current_params.merge!(batch_update_values[column.name][:value].symbolize_keys) if batch_update_values[column.name] && batch_update_values[column.name][:value]
7
+ operator_options = active_scaffold_update_generic_operators(column)
8
+ operator_options.concat(ActiveScaffold::Actions::BatchUpdate::DateOperators.collect {|comp| [as_(comp.downcase.to_sym), comp]}) if active_scaffold_config.batch_update.process_mode == :update
9
+ options = options.merge(:show => ['PLUS', 'MINUS'].exclude?(current_params[:operator]))
10
+ tags = []
11
+ tags << select_tag("[record][#{column.name}][operator]",
12
+ options_for_select(operator_options, current_params[:operator]),
13
+ :id => "#{options[:id]}_operator",
14
+ :class => "text-input as_update_date_operator")
15
+ tags << active_scaffold_search_date_bridge_calendar_control(column, options, current_params[:value], 'value')
16
+ tags << active_scaffold_update_date_bridge_trend_tag(column, current_params, options)
17
+ tags.join("&nbsp;").html_safe
18
+ end
19
+
20
+ def active_scaffold_update_date_bridge_trend_tag(column, current_params, options)
21
+ active_scaffold_date_bridge_trend_tag(column, options,
22
+ {:name_prefix => '[record]',
23
+ :number_value => current_params[:number],
24
+ :unit_value => current_params[:unit],
25
+ :show => ['PLUS','MINUS'].include?(current_params[:operator])})
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,91 @@
1
+ module ActiveScaffold
2
+ module Helpers
3
+ # Helpers that assist with the rendering of a Form Column
4
+ module UpdateColumnHelpers
5
+ # This method decides which input to use for the given column.
6
+ # It does not do any rendering. It only decides which method is responsible for rendering.
7
+ def active_scaffold_update_for(column, scope = nil, options = {})
8
+ options = active_scaffold_input_options(column, scope, options)
9
+
10
+ # first, check if the dev has created an override for this specific field for search
11
+ if override_update_field?(column)
12
+ send(override_update_field(column), @record, options)
13
+ # second, check if the dev has specified a valid form_ui for this column, using specific ui for searches
14
+ elsif column.form_ui and override_update?(column.form_ui)
15
+ send(override_update(column.form_ui), column, options)
16
+ elsif column.column and override_update?(column.column.type)
17
+ send(override_update(column.column.type), column, options)
18
+ else
19
+ active_scaffold_update_generic_operators_select(column, options)<< ' ' << active_scaffold_render_input(column, options.merge(:name => "record[#{column.name}][value]"))
20
+ end
21
+ end
22
+
23
+ def active_scaffold_update_generic_operators(column)
24
+ operators = ActiveScaffold::Actions::BatchUpdate::GenericOperators.collect {|comp| [as_(comp.downcase.to_sym), comp]}
25
+ if column.column.nil? || column.column.null
26
+ operators << [as_(:null), 'NULL']
27
+ end
28
+ operators
29
+ end
30
+
31
+ def active_scaffold_update_generic_operators_select(column, options)
32
+ current = {:operator => 'NO_UPDATE'}
33
+ current.merge!(batch_update_values[column.name][:value].symbolize_keys) if batch_update_values[column.name] && batch_update_values[column.name][:value]
34
+ select_tag("[record][#{column.name}][operator]",
35
+ options_for_select(active_scaffold_update_generic_operators(column), current[:operator]),
36
+ :id => "#{options[:id]}_operator",
37
+ :class => "as_batch_update_operator text_input")
38
+ end
39
+
40
+ def active_scaffold_update_numeric(column, options)
41
+ current = {:value => nil, :opt => 'ABSOLUTE', :operator => 'NO_UPDATE'}
42
+ current.merge!(batch_update_values[column.name][:value].symbolize_keys) if batch_update_values[column.name] && batch_update_values[column.name][:value]
43
+ operator_options = active_scaffold_update_generic_operators(column) + ActiveScaffold::Actions::BatchUpdate::NumericOperators.collect {|comp| [as_(comp.downcase.to_sym), comp]}
44
+ select_options = ActiveScaffold::Actions::BatchUpdate::NumericOptions.collect {|comp| [as_(comp.downcase.to_sym), comp]}
45
+ html = select_tag("[record][#{column.name}][operator]",
46
+ options_for_select(operator_options, current[:operator]),
47
+ :id => "#{options[:id]}_operator",
48
+ :class => "as_update_numeric_option")
49
+ html << ' ' << text_field_tag("[record][#{column.name}][value]", current[:value], active_scaffold_input_text_options)
50
+ html << ' ' << select_tag("[record][#{column.name}][opt]",
51
+ options_for_select(select_options, current[:opt]),
52
+ :id => "#{options[:id]}_opt",
53
+ :class => "as_update_numeric_option")
54
+ html
55
+ end
56
+ alias_method :active_scaffold_update_integer, :active_scaffold_update_numeric
57
+ alias_method :active_scaffold_update_decimal, :active_scaffold_update_numeric
58
+ alias_method :active_scaffold_update_float, :active_scaffold_update_numeric
59
+
60
+ def active_scaffold_update_scope_select
61
+ select_options = [[as_(:listed), 'LISTED']]
62
+ select_options << [as_(:marked), 'MARKED'] if active_scaffold_config.actions.include?(:mark)
63
+ select_tag("batch_scope",
64
+ options_for_select(select_options, batch_scope || select_options.last[1]),
65
+ :class => "text_input")
66
+ end
67
+
68
+ ##
69
+ ## Search column override signatures
70
+ ##
71
+
72
+ def override_update_field?(column)
73
+ respond_to?(override_update_field(column))
74
+ end
75
+
76
+ # the naming convention for overriding form fields with helpers
77
+ def override_update_field(column)
78
+ "#{column.name}_update_column"
79
+ end
80
+
81
+ def override_update?(update_ui)
82
+ respond_to?(override_update(update_ui))
83
+ end
84
+
85
+ # the naming convention for overriding search input types with helpers
86
+ def override_update(update_ui)
87
+ "active_scaffold_update_#{update_ui}"
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,8 @@
1
+ ActionView::Base.class_eval do
2
+ include ActiveScaffold::Helpers::UpdateColumnHelpers
3
+ if ActiveScaffold.js_framework == :jquery
4
+ include ActiveScaffold::Helpers::DatepickerUpdateColumnHelpers
5
+ elsif ActiveScaffold.js_framework == :prototype
6
+ include ActiveScaffold::Helpers::CalendarDateSelectUpdateColumnHelpers
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ # Need to open the AS module carefully due to Rails 2.3 lazy loading
2
+ ActiveScaffold::Config::Core.class_eval do
3
+ ActionDispatch::Routing::ACTIVE_SCAFFOLD_CORE_ROUTING[:collection][:batch_edit] = :get
4
+ ActionDispatch::Routing::ACTIVE_SCAFFOLD_CORE_ROUTING[:collection][:batch_update] = :post
5
+ #not working because routing picks show route instead
6
+ #ActionDispatch::Routing::ACTIVE_SCAFFOLD_CORE_ROUTING[:collection][:batch_destroy] = :get
7
+ #you may define a route for your controller before resource routes
8
+ #match 'players/batch_destroy' => 'players#batch_destroy', :via => [:get]
9
+ ActionDispatch::Routing::ACTIVE_SCAFFOLD_CORE_ROUTING[:collection][:batch_destroy] = :delete
10
+ end
@@ -0,0 +1,9 @@
1
+ module ActiveScaffoldBatch
2
+ module Version
3
+ MAJOR = 3
4
+ MINOR = 0
5
+ PATCH = 0
6
+
7
+ STRING = [MAJOR, MINOR, PATCH].compact.join('.')
8
+ end
9
+ end
@@ -0,0 +1,27 @@
1
+ # Make sure that ActiveScaffold has already been included
2
+ ActiveScaffold rescue throw "should have included ActiveScaffold plug in first. Please make sure that this overwrite plugging comes alphabetically after the ActiveScaffold plug in"
3
+
4
+ # Load our overrides
5
+ require "#{File.dirname(__FILE__)}/active_scaffold_batch/config/core.rb"
6
+ require "#{File.dirname(__FILE__)}/active_scaffold/config/batch_update.rb"
7
+ require "#{File.dirname(__FILE__)}/active_scaffold/actions/batch_update.rb"
8
+ require "#{File.dirname(__FILE__)}/active_scaffold/helpers/view_helpers_override.rb"
9
+
10
+ module ActiveScaffoldBatch
11
+ def self.root
12
+ File.dirname(__FILE__) + "/.."
13
+ end
14
+ end
15
+
16
+
17
+ ##
18
+ ## Run the install assets script, too, just to make sure
19
+ ## But at least rescue the action in production
20
+ ##
21
+ Rails::Application.initializer("active_scaffold_batch.install_assets") do
22
+ begin
23
+ ActiveScaffoldAssets.copy_to_public(ActiveScaffoldBatch.root)
24
+ rescue
25
+ raise $! unless Rails.env == 'production'
26
+ end
27
+ end unless defined?(ACTIVE_SCAFFOLD_BATCH_INSTALLED) && ACTIVE_SCAFFOLD_BATCH_INSTALLED == :plugin
@@ -0,0 +1,2 @@
1
+ ACTIVE_SCAFFOLD_BATCH_INSTALLED = :gem
2
+ require 'active_scaffold_batch'
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # see active_scaffold/uninstall.rb
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_scaffold_batch_vho
3
+ version: !ruby/object:Gem::Version
4
+ hash: 7
5
+ prerelease: false
6
+ segments:
7
+ - 3
8
+ - 0
9
+ - 0
10
+ version: 3.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Volker Hochstein
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-26 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ prerelease: false
23
+ name: shoulda
24
+ version_requirements: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ requirement: *id001
34
+ type: :development
35
+ - !ruby/object:Gem::Dependency
36
+ prerelease: false
37
+ name: bundler
38
+ version_requirements: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ hash: 23
44
+ segments:
45
+ - 1
46
+ - 0
47
+ - 0
48
+ version: 1.0.0
49
+ requirement: *id002
50
+ type: :development
51
+ - !ruby/object:Gem::Dependency
52
+ prerelease: false
53
+ name: jeweler
54
+ version_requirements: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ~>
58
+ - !ruby/object:Gem::Version
59
+ hash: 7
60
+ segments:
61
+ - 1
62
+ - 5
63
+ - 2
64
+ version: 1.5.2
65
+ requirement: *id003
66
+ type: :development
67
+ - !ruby/object:Gem::Dependency
68
+ prerelease: false
69
+ name: rcov
70
+ version_requirements: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ requirement: *id004
80
+ type: :development
81
+ - !ruby/object:Gem::Dependency
82
+ prerelease: false
83
+ name: active_scaffold_vho
84
+ version_requirements: &id005 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ hash: 7
90
+ segments:
91
+ - 3
92
+ - 0
93
+ version: "3.0"
94
+ requirement: *id005
95
+ type: :runtime
96
+ description: You want to destroy/update many records at once with activescaffold?
97
+ email: activescaffold@googlegroups.com
98
+ executables: []
99
+
100
+ extensions: []
101
+
102
+ extra_rdoc_files:
103
+ - LICENSE.txt
104
+ - README
105
+ files:
106
+ - .document
107
+ - LICENSE.txt
108
+ - README
109
+ - Rakefile
110
+ - frontends/default/views/_batch_update_form.html.erb
111
+ - frontends/default/views/_batch_update_form_attribute.html.erb
112
+ - frontends/default/views/_batch_update_form_attribute_scope.html.erb
113
+ - frontends/default/views/_batch_update_form_body.html.erb
114
+ - frontends/default/views/batch_update.html.erb
115
+ - frontends/default/views/on_batch_base.js.rjs
116
+ - frontends/default/views/on_batch_update.js.rjs
117
+ - init.rb
118
+ - lib/active_scaffold/actions/batch_base.rb
119
+ - lib/active_scaffold/actions/batch_destroy.rb
120
+ - lib/active_scaffold/actions/batch_update.rb
121
+ - lib/active_scaffold/config/batch_base.rb
122
+ - lib/active_scaffold/config/batch_destroy.rb
123
+ - lib/active_scaffold/config/batch_update.rb
124
+ - lib/active_scaffold/helpers/calendar_date_select_update_column_helpers.rb
125
+ - lib/active_scaffold/helpers/datepicker_update_column_helpers.rb
126
+ - lib/active_scaffold/helpers/update_column_helpers.rb
127
+ - lib/active_scaffold/helpers/view_helpers_override.rb
128
+ - lib/active_scaffold_batch.rb
129
+ - lib/active_scaffold_batch/config/core.rb
130
+ - lib/active_scaffold_batch/version.rb
131
+ - lib/active_scaffold_batch_vho.rb
132
+ - uninstall.rb
133
+ has_rdoc: true
134
+ homepage: http://github.com/vhochstein/active_scaffold_batch
135
+ licenses:
136
+ - MIT
137
+ post_install_message:
138
+ rdoc_options: []
139
+
140
+ require_paths:
141
+ - lib
142
+ required_ruby_version: !ruby/object:Gem::Requirement
143
+ none: false
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ hash: 3
148
+ segments:
149
+ - 0
150
+ version: "0"
151
+ required_rubygems_version: !ruby/object:Gem::Requirement
152
+ none: false
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ hash: 3
157
+ segments:
158
+ - 0
159
+ version: "0"
160
+ requirements: []
161
+
162
+ rubyforge_project:
163
+ rubygems_version: 1.3.7
164
+ signing_key:
165
+ specification_version: 3
166
+ summary: Batch Processing for ActiveScaffold
167
+ test_files: []
168
+