active_scaffold_vho 3.1.4 → 3.1.5

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.
@@ -181,6 +181,16 @@ module ActiveScaffold::DataStructures
181
181
  # to modify the default order of columns
182
182
  attr_accessor :weight
183
183
 
184
+ # whether the field should be stripped when search values or form values are read for this value
185
+ attr_writer :stripable
186
+ def stripable?
187
+ @stripable
188
+ end
189
+
190
+ def stripped_value(value)
191
+ stripable? ? value.strip : value
192
+ end
193
+
184
194
  # to set how many associated records a column with plural association must show in list
185
195
  cattr_accessor :associated_limit
186
196
  @@associated_limit = 3
@@ -228,6 +238,9 @@ module ActiveScaffold::DataStructures
228
238
  def plural_association?
229
239
  self.association and [:has_many, :has_and_belongs_to_many].include? self.association.macro
230
240
  end
241
+ def belongs_to_association?
242
+ self.association && self.association.macro == :belongs_to
243
+ end
231
244
  def through_association?
232
245
  self.association and self.association.options[:through]
233
246
  end
@@ -278,6 +291,7 @@ module ActiveScaffold::DataStructures
278
291
  @options = {:format => :i18n_number} if @column.try(:number?)
279
292
  @form_ui = :checkbox if @column and @column.type == :boolean
280
293
  @form_ui = :textarea if @column and @column.type == :text
294
+ @stripable = true if @column and @column.text?
281
295
  @allow_add_existing = true
282
296
  @form_ui = self.class.association_form_ui if @association && self.class.association_form_ui
283
297
 
@@ -311,7 +325,7 @@ module ActiveScaffold::DataStructures
311
325
  self.sort = false
312
326
  else
313
327
  if self.singular_association?
314
- self.sort = {:method => "#{self.name}.to_label"}
328
+ self.sort = {:method => "#{self.name}.nil? ? '' : #{self.name}.to_label"}
315
329
  elsif self.plural_association?
316
330
  self.sort = {:method => "#{self.name}.join(',')"}
317
331
  else
@@ -322,7 +336,7 @@ module ActiveScaffold::DataStructures
322
336
 
323
337
  def initialize_search_sql
324
338
  self.search_sql = unless self.virtual?
325
- if association.nil?
339
+ if association.nil? || self.belongs_to_association?
326
340
  self.field.to_s
327
341
  elsif !self.polymorphic_association?
328
342
  [association.klass.table_name, association.klass.primary_key].collect! do |str|
@@ -86,18 +86,24 @@ module ActiveScaffold
86
86
  def condition_for_range(column, value, like_pattern = nil)
87
87
  if !value.is_a?(Hash)
88
88
  if column.column.nil? || column.column.text?
89
- ["#{column.search_sql} #{ActiveScaffold::Finder.like_operator} ?", like_pattern.sub('?', value)]
89
+ ["#{column.search_sql} #{ActiveScaffold::Finder.like_operator} ?", like_pattern.sub('?', column.stripped_value(value))]
90
90
  else
91
91
  ["#{column.search_sql} = ?", column.column.type_cast(value)]
92
92
  end
93
93
  elsif value[:from].blank?
94
94
  nil
95
95
  elsif ActiveScaffold::Finder::StringComparators.values.include?(value[:opt])
96
- ["#{column.search_sql} #{ActiveScaffold::Finder.like_operator} ?", value[:opt].sub('?', value[:from])]
96
+ if(active_scaffold_config.field_search.or_columns.include? column.name)
97
+ search_values = column.stripped_value(value[:from]).split(active_scaffold_config.field_search.or_delimiter).compact
98
+ sql_prepared_statement = search_values.collect {|search_value| "#{column.search_sql} #{ActiveScaffold::Finder.like_operator} ?"}.join(' OR ')
99
+ [sql_prepared_statement] + search_values.collect{|search_value| value[:opt].sub('?', column.stripped_value(search_value))}
100
+ else
101
+ ["#{column.search_sql} #{ActiveScaffold::Finder.like_operator} ?", value[:opt].sub('?', column.stripped_value(value[:from]))]
102
+ end
97
103
  elsif value[:opt] == 'BETWEEN'
98
- ["#{column.search_sql} BETWEEN ? AND ?", value[:from], value[:to]]
104
+ ["#{column.search_sql} BETWEEN ? AND ?", column.stripped_value(value[:from]), column.stripped_value(value[:to])]
99
105
  elsif ActiveScaffold::Finder::NumericComparators.include?(value[:opt])
100
- ["#{column.search_sql} #{value[:opt]} ?", value[:from]]
106
+ ["#{column.search_sql} #{value[:opt]} ?", column.stripped_value(value[:from])]
101
107
  else
102
108
  nil
103
109
  end
@@ -256,6 +262,7 @@ module ActiveScaffold
256
262
  full_includes = (active_scaffold_includes.blank? ? nil : active_scaffold_includes)
257
263
  options[:per_page] ||= 999999999
258
264
  options[:page] ||= 1
265
+ #TODO not supported by kaminary
259
266
  options[:count_includes] ||= full_includes unless search_conditions.nil?
260
267
 
261
268
  klass = beginning_of_chain
@@ -264,35 +271,18 @@ module ActiveScaffold
264
271
  finder_options = { :order => options[:sorting].try(:clause),
265
272
  :where => search_conditions,
266
273
  :joins => joins_for_finder,
267
- :includes => options[:count_includes]}
274
+ :includes => add_association_to_includes_for_sorting(options[:sorting], full_includes)}
268
275
 
269
276
  finder_options.merge! custom_finder_options
270
-
271
- # NOTE: we must use :include in the count query, because some conditions may reference other tables
272
- count_query = append_to_query(klass, finder_options.reject{|k, v| [:select, :order].include?(k)})
273
- count = count_query.count unless options[:pagination] == :infinite
274
-
275
- # Converts count to an integer if ActiveRecord returned an OrderedHash
276
- # that happens when finder_options contains a :group key
277
- count = count.length if count.is_a? ActiveSupport::OrderedHash
278
-
279
- full_includes = add_association_to_includes_for_sorting(options[:sorting], full_includes)
280
- finder_options.merge! :includes => full_includes
281
-
277
+
282
278
  # we build the paginator differently for method- and sql-based sorting
283
- if options[:sorting] and options[:sorting].sorts_by_method?
284
- pager = ::Paginator.new(count, options[:per_page]) do |offset, per_page|
285
- sorted_collection = sort_collection_by_column(append_to_query(klass, finder_options).all, *options[:sorting].first)
286
- sorted_collection = sorted_collection.slice(offset, per_page) if options[:pagination]
287
- sorted_collection
288
- end
279
+ records = if options[:sorting] && options[:sorting].sorts_by_method?
280
+ Kaminari.paginate_array(sort_collection_by_column(append_to_query(klass, finder_options).all, *options[:sorting].first))
289
281
  else
290
- pager = ::Paginator.new(count, options[:per_page]) do |offset, per_page|
291
- finder_options.merge!(:offset => offset, :limit => per_page) if options[:pagination]
292
- append_to_query(klass, finder_options).all
293
- end
282
+ append_to_query(klass, finder_options)
294
283
  end
295
- pager.page(options[:page])
284
+ records = records.page(options[:page]).per(options[:per_page]) if options[:pagination]
285
+ records
296
286
  end
297
287
 
298
288
  # if someone excludes association from includes in configuration
@@ -17,12 +17,14 @@ module ActiveScaffold
17
17
  "#{column.active_record_class.human_attribute_name(column.name)} #{as_(value[:opt].downcase).downcase} #{format_number_value(controller.class.condition_value_for_numeric(column, value[:from]), column.options)} #{value[:opt] == 'BETWEEN' ? '- ' + format_number_value(controller.class.condition_value_for_numeric(column, value[:to]), column.options).to_s : ''}"
18
18
  when :string
19
19
  opt = ActiveScaffold::Finder::StringComparators.index(value[:opt]) || value[:opt]
20
- "#{column.active_record_class.human_attribute_name(column.name)} #{as_(opt).downcase} '#{value[:from]}' #{opt == 'BETWEEN' ? '- ' + value[:to].to_s : ''}"
20
+ "#{column.active_record_class.human_attribute_name(column.name)} #{as_(opt).downcase} '#{column.stripped_value(value[:from])}' #{opt == 'BETWEEN' ? '- ' + column.stripped_value(value[:to]).to_s : ''}"
21
21
  when :date, :time, :datetime, :timestamp
22
22
  conversion = column.column.type == :date ? :to_date : :to_time
23
23
  from = controller.condition_value_for_datetime(value[:from], conversion)
24
24
  to = controller.condition_value_for_datetime(value[:to], conversion)
25
- "#{column.active_record_class.human_attribute_name(column.name)} #{as_(value[:opt])} #{I18n.l(from)} #{value[:opt] == 'BETWEEN' ? '- ' + I18n.l(to) : ''}"
25
+ unless from.nil? || (value[:opt] == 'BETWEEN' && to.nil?)
26
+ "#{column.active_record_class.human_attribute_name(column.name)} #{as_(value[:opt])} #{I18n.l(from)} #{value[:opt] == 'BETWEEN' ? '- ' + I18n.l(to) : ''}"
27
+ end
26
28
  when :select, :multi_select, :record_select
27
29
  associated = value
28
30
  associated = [associated].compact unless associated.is_a? Array
@@ -124,6 +124,7 @@ module ActiveScaffold
124
124
  format_column_value(record, column)
125
125
  else
126
126
  value = record.send(column.name)
127
+ value = value.to_s unless value.nil?
127
128
  text, val = column.options[:options].find {|text, val| (val || text).to_s == value}
128
129
  value = active_scaffold_translated_option(column, text, val).first if text
129
130
  format_column_value(record, column, value)
@@ -136,6 +137,16 @@ module ActiveScaffold
136
137
  check_box(:record, column.name, options)
137
138
  end
138
139
 
140
+ # list_column override specific to this controller column combination
141
+ def column_controller_override(column)
142
+ "#{clean_class_name(column.active_record_class.name)}_#{clean_column_name(column.name)}_column"
143
+ end
144
+
145
+ def column_controller_override?(column)
146
+ respond_to?(column_controller_override(column))
147
+ end
148
+
149
+ # list_column overide for a specific column in all controllers
139
150
  def column_override(column)
140
151
  "#{column.name.to_s.gsub('?', '')}_column" # parse out any question marks (see issue 227)
141
152
  end
@@ -316,11 +327,17 @@ module ActiveScaffold
316
327
  def mark_column_heading
317
328
  if active_scaffold_config.mark.mark_all_mode == :page then
318
329
  all_marked = true
319
- @page.items.each do |record|
330
+ @records.each do |record|
320
331
  all_marked = false if !marked_records.entries.include?(record.id)
321
332
  end
322
333
  else
323
- all_marked = (marked_records.length >= @page.pager.count)
334
+ # if relation does not respond to kaminari total_count...
335
+ # kaminari paging is nt active
336
+ if @records.respond_to?(:total_count)
337
+ all_marked = (marked_records.length >= @records.total_count)
338
+ else
339
+ all_marked = (marked_records.length >= @records.count)
340
+ end
324
341
  end
325
342
  tag_options = {:id => "#{controller_id}_mark_heading", :class => "mark_heading in_place_editor_field"}
326
343
  tag_options['data-ie_url'] = url_for({:controller => params_for[:controller], :action => 'mark_all', :eid => params[:eid]})
@@ -363,6 +380,52 @@ module ActiveScaffold
363
380
  end
364
381
  content_tag(:tr, content_tag(:td, rendered.join(' ').html_safe), :class => "inline-adapter-autoopen", 'data-actionlink-controllers' => link_nested_controllers.join('::').html_safe, 'data-as_load'=>"tr");
365
382
  end
383
+
384
+ def generate_list_column_helper_code(column)
385
+ method_name = column_controller_override(column)
386
+ if column_override? column
387
+ "def #{method_name}(column, record)\n #{column_override(column)}(column, record)\nend"
388
+ elsif column.list_ui and override_column_ui?(column.list_ui)
389
+ "def #{method_name}(column, record)\n #{override_column_ui(column.list_ui)}(column, record)\nend"
390
+ elsif column.column and override_column_ui?(column.column.type)
391
+ "def #{method_name}(column, record)\n #{override_column_ui(column.column.type)}(column, record)\nend"
392
+ #associations and virtual columns will use default list_column helper methods..
393
+ elsif column.association || column.column.nil?
394
+ "def #{method_name}(record, column)\n get_column_value(column, record)\nend"
395
+ else
396
+ "def #{method_name}(column, record)\n value ||= record.send(column.name)\n value.nil? ? h(active_scaffold_config.list.empty_field_text) : h(#{list_column_helper_code_by_column_type(column)})\nend"
397
+ end
398
+ end
399
+
400
+ def list_column_helper_code_by_column_type(column)
401
+ case column.column.type
402
+ when :integer
403
+ "#{numeric_to_string_method_code(column.options[:format], true)}"
404
+ when :float, :decimal
405
+ "#{numeric_to_string_method_code(column.options[:format], false)}"
406
+ when :boolean
407
+ "as_(value.to_s.to_sym)"
408
+ when :datetime, :timestamp, :time, :date
409
+ "l(value, :format => :#{column.options[:format] || :default})"
410
+ else
411
+ "value.to_s"
412
+ end
413
+ end
414
+
415
+ def numeric_to_string_method_code(format, is_integer)
416
+ case format
417
+ when :size
418
+ "number_to_human_size(value, column.options[:i18n_options] || {})"
419
+ when :percentage
420
+ "number_to_percentage(value, column.options[:i18n_options] || {})"
421
+ when :currency
422
+ "number_to_currency(value, options[:i18n_options] || {})"
423
+ when :i18n_number
424
+ "number_with_#{is_integer ? 'delimiter' : 'precision'}(value, column.options[:i18n_options] || {})"
425
+ else
426
+ "value"
427
+ end
428
+ end
366
429
  end
367
430
  end
368
431
  end
@@ -0,0 +1,118 @@
1
+ de:
2
+ active_scaffold:
3
+ add: 'Hinzufügen'
4
+ add_existing: 'Existierenden Eintrag hinzufügen'
5
+ add_existing_model: 'Existierende %{model} hinzufügen'
6
+ are_you_sure_to_delete: 'Sind Sie sicher?'
7
+ cancel: 'Abbrechen'
8
+ click_to_edit: 'Zum Editieren anklicken'
9
+ click_to_reset: 'Reset'
10
+ close: 'Schliessen'
11
+ config_list: 'Konfigurieren'
12
+ config_list_model: 'Konfiguriere Spalten für %{model}'
13
+ create: 'Anlegen'
14
+ create_model: 'Lege %{model} an'
15
+ create_another: 'Weitere anlegen'
16
+ created_model: '%{model} angelegt'
17
+ create_new: 'Neu anlegen'
18
+ customize: 'Anpassen'
19
+ delete: 'Löschen'
20
+ deleted_model: '%{model} gelöscht'
21
+ delimiter: 'Trennzeichen'
22
+ download: 'Download'
23
+ edit: 'Bearbeiten'
24
+ export: 'Exportieren'
25
+ nested_for_model: '%{nested_model} für %{parent_model}'
26
+ nested_of_model: '%{nested_model} von %{parent_model}'
27
+ filtered: '(Gefiltert)'
28
+ found: 'Gefunden'
29
+ hide: 'Verstecken'
30
+ live_search: 'Live-Suche'
31
+ loading: 'Lade…'
32
+ next: 'Vor'
33
+ no_entries: 'Keine Einträge'
34
+ no_options: 'Keine Optionen'
35
+ omit_header: 'Lasse Header weg'
36
+ options: 'Optionen'
37
+ pdf: 'PDF'
38
+ previous: 'Zurück'
39
+ print: 'Drucken'
40
+ refresh: 'Neu laden'
41
+ remove: 'Entfernen'
42
+ remove_file: 'Entferne oder Ersetze Datei'
43
+ replace_with_new: 'Mit Neuer ersetzen'
44
+ revisions_for_model: 'Revisionen für %{model}'
45
+ reset: 'Zurücksetzen'
46
+ saving: 'Speichern…'
47
+ search: 'Suche'
48
+ search_terms: 'Suchbegriffe'
49
+ _select_: '- Auswählen -'
50
+ show: 'Anzeigen'
51
+ show_model: 'Zeige %{model} an'
52
+ _to_ : ' zu '
53
+ update: 'Speichern'
54
+ update_model: 'Editiere %{model}'
55
+ updated_model: '%{model} aktualisiert'
56
+ '=': '='
57
+ '>=': '>='
58
+ '<=': '<='
59
+ '>': '>'
60
+ '<': '<'
61
+ '!=': '!='
62
+ between: 'Zwischen'
63
+ contains: 'Enthält'
64
+ begins_with: 'Beginnt'
65
+ ends_with: 'Ended'
66
+ today: 'Heute'
67
+ yesterday: 'Gestern'
68
+ tomorrow: 'Morgen'
69
+ this_week: 'Diese Woche'
70
+ prev_week: 'Letzte Woche'
71
+ next_week: 'Nächste Woche'
72
+ this_month: 'Diesen Monat'
73
+ prev_month: 'Letzten Monat'
74
+ next_month: 'Nächsten Monat'
75
+ this_year: 'Dieses Jahr'
76
+ prev_year: 'Letztes Jahr'
77
+ next_year: 'Nächstes Jahr'
78
+ past: 'Letzten'
79
+ future: 'Nächsten'
80
+ range: 'Zeitraum'
81
+ seconds: 'Sekunden'
82
+ minutes: 'Minuten'
83
+ hours: 'Stunden'
84
+ days: 'Tage'
85
+ weeks: 'Wochen'
86
+ months: 'Monate'
87
+ years: 'Jahre'
88
+ optional_attributes: 'Weitere'
89
+ null: 'Null'
90
+ not_null: 'Nicht Null'
91
+ date_picker_options:
92
+ weekHeader: 'Wo'
93
+ firstDay: 1
94
+ isRTL: false
95
+ showMonthAfterYear: false
96
+ datetime_picker_options:
97
+ timeText: 'Uhrzeit'
98
+ currentText: 'Jetzt'
99
+ closeText: 'Schließen'
100
+ errors:
101
+ template:
102
+ header:
103
+ one: "Konnte %{model} nicht speichern: ein Fehler."
104
+ other: "Konnte %{model} nicht speichern: %{count} Fehler."
105
+ body: "Bitte überprüfen Sie die folgenden Felder:"
106
+ # error_messages
107
+ cant_destroy_record: "%{record} kann nicht gelöscht werden"
108
+ internal_error: 'Fehler bei der Verarbeitung (code 500, Interner Fehler)'
109
+ version_inconsistency: 'Inkonsistente Versionen - dieser Eintrag wurde verändert nachdem Sie mit der Bearbeitung begonnen haben.'
110
+ record_not_saved: 'Eintrag kann nicht gespeichert werden. Ursache unbekannt.'
111
+ no_authorization_for_action: "Keine Berechtigung für Aktion %{action}"
112
+ views:
113
+ pagination:
114
+ first: "&laquo; Erste"
115
+ last: "Letzte &raquo;"
116
+ previous: "&lsaquo; Zurück"
117
+ next: "Vor &rsaquo;"
118
+ truncate: "..."
@@ -0,0 +1,115 @@
1
+ en:
2
+ active_scaffold:
3
+ add: 'Add'
4
+ add_existing: 'Add Existing'
5
+ add_existing_model: 'Add Existing %{model}'
6
+ are_you_sure_to_delete: 'Are you sure you want to delete %{label}?'
7
+ cancel: 'Cancel'
8
+ click_to_edit: 'Click to edit'
9
+ click_to_reset: 'Click to reset'
10
+ close: 'Close'
11
+ config_list: 'Configure'
12
+ config_list_model: 'Configure Columns for %{model}'
13
+ create: 'Create'
14
+ create_model: 'Create %{model}'
15
+ create_another: 'Create Another %{model}'
16
+ created_model: 'Created %{model}'
17
+ create_new: 'Create New'
18
+ customize: 'Customize'
19
+ delete: 'Delete'
20
+ deleted_model: 'Deleted %{model}'
21
+ delimiter: 'Delimiter'
22
+ download: 'Download'
23
+ edit: 'Edit'
24
+ export: 'Export'
25
+ nested_for_model: '%{nested_model} for %{parent_model}'
26
+ nested_of_model: '%{nested_model} of %{parent_model}'
27
+ 'false': 'False'
28
+ filtered: '(Filtered)'
29
+ found: 'Found'
30
+ hide: 'Hide'
31
+ live_search: 'Live Search'
32
+ loading: 'Loading…'
33
+ next: 'Next'
34
+ no_entries: 'No Entries'
35
+ no_options: 'no options'
36
+ omit_header: 'Omit Header'
37
+ options: 'Options'
38
+ pdf: 'PDF'
39
+ previous: 'Previous'
40
+ print: 'Print'
41
+ refresh: 'Refresh'
42
+ remove: 'Remove'
43
+ remove_file: 'Remove or Replace file'
44
+ replace_with_new: 'Replace With New'
45
+ revisions_for_model: 'Revisions for %{model}'
46
+ reset: 'Reset'
47
+ saving: 'Saving…'
48
+ search: 'Search'
49
+ search_terms: 'Search Terms'
50
+ _select_: '- select -'
51
+ show: 'Show'
52
+ show_model: 'Show %{model}'
53
+ _to_ : ' to '
54
+ 'true': 'True'
55
+ update: 'Update'
56
+ update_model: 'Update %{model}'
57
+ updated_model: 'Updated %{model}'
58
+ '=': '='
59
+ '>=': '>='
60
+ '<=': '<='
61
+ '>': '>'
62
+ '<': '<'
63
+ '!=': '!='
64
+ between: 'Between'
65
+ contains: 'Contains'
66
+ begins_with: 'Begins with'
67
+ ends_with: 'Ends with'
68
+ today: 'Today'
69
+ yesterday: 'Yesterday'
70
+ tomorrow: 'Tommorrow'
71
+ this_week: 'This Week'
72
+ prev_week: 'Last Week'
73
+ next_week: 'Next Week'
74
+ this_month: 'This Month'
75
+ prev_month: 'Last Month'
76
+ next_month: 'Next Month'
77
+ this_year: 'This Year'
78
+ prev_year: 'Last Year'
79
+ next_year: 'Next Year'
80
+ past: 'Past'
81
+ future: 'Future'
82
+ range: 'Range'
83
+ seconds: 'Seconds'
84
+ minutes: 'Minutes'
85
+ hours: 'Hours'
86
+ days: 'Days'
87
+ weeks: 'Weeks'
88
+ months: 'Months'
89
+ years: 'Years'
90
+ optional_attributes: 'Further Options'
91
+ null: 'Null'
92
+ not_null: 'Not Null'
93
+ date_picker_options:
94
+ weekHeader: 'Wk'
95
+ firstDay: 0
96
+ isRTL: false
97
+ showMonthAfterYear: false
98
+
99
+ datetime_picker_options:
100
+
101
+ errors:
102
+ template:
103
+ header:
104
+ one: "1 error prohibited this %{model} from being saved."
105
+ other: "%{count} errors prohibited this %{model} from being saved"
106
+
107
+ body: "There were problems with the following fields:"
108
+
109
+
110
+ # error_messages
111
+ cant_destroy_record: "%{record} can't be destroyed"
112
+ internal_error: 'Request Failed (code 500, Internal Error)'
113
+ version_inconsistency: 'Version inconsistency - this record has been modified since you started editing it.'
114
+ record_not_saved: 'Failed to save record cause of an unknown error'
115
+ no_authorization_for_action: "No Authorization for action %{action}"