active_scaffold_vho 3.1.4 → 3.1.5

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