active_scaffold 3.0.12 → 3.0.21

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.
Files changed (142) hide show
  1. data/README +21 -11
  2. data/frontends/default/images/close_touch.png +0 -0
  3. data/frontends/default/javascripts/jquery/active_scaffold.js +187 -99
  4. data/frontends/default/javascripts/prototype/active_scaffold.js +105 -33
  5. data/frontends/default/javascripts/prototype/dhtml_history.js +80 -77
  6. data/frontends/default/stylesheets/stylesheet.css +121 -2
  7. data/frontends/default/views/_action_group.html.erb +6 -2
  8. data/frontends/default/views/_base_form.html.erb +11 -5
  9. data/frontends/default/views/_base_form.html.erb~ +42 -0
  10. data/frontends/default/views/_field_search.html.erb +1 -1
  11. data/frontends/default/views/_form.html.erb +9 -7
  12. data/frontends/default/views/_form_association.html.erb +8 -3
  13. data/frontends/default/views/_form_association_footer.html.erb +10 -3
  14. data/frontends/default/views/_form_attribute.html.erb +8 -3
  15. data/frontends/default/views/_horizontal_subform.html.erb +12 -2
  16. data/frontends/default/views/_horizontal_subform_header.html.erb +1 -1
  17. data/frontends/default/views/_horizontal_subform_record.html.erb +5 -4
  18. data/frontends/default/views/_list_messages.html.erb +1 -1
  19. data/frontends/default/views/_list_with_header.html.erb +1 -1
  20. data/frontends/default/views/_render_field.js.rjs +4 -6
  21. data/frontends/default/views/_vertical_subform.html.erb +1 -1
  22. data/frontends/default/views/_vertical_subform_record.html.erb +2 -2
  23. data/frontends/default/views/on_action_update.js.rjs +3 -1
  24. data/frontends/default/views/on_mark_all.js.rjs +12 -0
  25. data/frontends/default/views/on_update.js.rjs +1 -1
  26. data/frontends/default/views/render_field.js.rjs +1 -0
  27. data/frontends/default/views/update_column.js.rjs +1 -1
  28. data/lib/active_scaffold.rb +60 -21
  29. data/lib/active_scaffold/actions/common_search.rb +2 -2
  30. data/lib/active_scaffold/actions/core.rb +30 -9
  31. data/lib/active_scaffold/actions/create.rb +14 -10
  32. data/lib/active_scaffold/actions/field_search.rb +6 -6
  33. data/lib/active_scaffold/actions/list.rb +22 -12
  34. data/lib/active_scaffold/actions/mark.rb +34 -9
  35. data/lib/active_scaffold/actions/nested.rb +12 -16
  36. data/lib/active_scaffold/actions/show.rb +2 -2
  37. data/lib/active_scaffold/actions/subform.rb +15 -8
  38. data/lib/active_scaffold/actions/update.rb +14 -4
  39. data/lib/active_scaffold/attribute_params.rb +15 -10
  40. data/lib/active_scaffold/bridges/bridge.rb +21 -12
  41. data/lib/active_scaffold/bridges/calendar_date_select/bridge.rb +3 -3
  42. data/lib/active_scaffold/bridges/cancan/bridge.rb +12 -0
  43. data/lib/active_scaffold/bridges/cancan/lib/cancan_bridge.rb +107 -0
  44. data/lib/active_scaffold/bridges/carrierwave/bridge.rb +1 -1
  45. data/lib/active_scaffold/bridges/carrierwave/lib/carrierwave_bridge.rb +3 -8
  46. data/lib/active_scaffold/bridges/carrierwave/lib/carrierwave_bridge_helpers.rb +1 -15
  47. data/lib/active_scaffold/bridges/carrierwave/lib/form_ui.rb +23 -13
  48. data/lib/active_scaffold/bridges/carrierwave/lib/list_ui.rb +1 -1
  49. data/lib/active_scaffold/bridges/country_helper/bridge.rb +9 -0
  50. data/lib/active_scaffold/bridges/country_helper/lib/country_helper_bridge.rb +358 -0
  51. data/lib/active_scaffold/bridges/date_picker/bridge.rb +5 -3
  52. data/lib/active_scaffold/bridges/date_picker/lib/datepicker_bridge.rb +9 -0
  53. data/lib/active_scaffold/bridges/dragonfly/bridge.rb +9 -0
  54. data/lib/active_scaffold/bridges/dragonfly/bridge.rb~ +12 -0
  55. data/lib/active_scaffold/bridges/dragonfly/lib/dragonfly_bridge.rb +36 -0
  56. data/lib/active_scaffold/bridges/dragonfly/lib/dragonfly_bridge.rb~ +36 -0
  57. data/lib/active_scaffold/bridges/dragonfly/lib/dragonfly_bridge_helpers.rb +12 -0
  58. data/lib/active_scaffold/bridges/dragonfly/lib/dragonfly_bridge_helpers.rb~ +12 -0
  59. data/lib/active_scaffold/bridges/dragonfly/lib/form_ui.rb +27 -0
  60. data/lib/active_scaffold/bridges/dragonfly/lib/form_ui.rb~ +27 -0
  61. data/lib/active_scaffold/bridges/dragonfly/lib/list_ui.rb +16 -0
  62. data/lib/active_scaffold/bridges/dragonfly/lib/list_ui.rb~ +16 -0
  63. data/lib/active_scaffold/bridges/paperclip/bridge.rb +1 -1
  64. data/lib/active_scaffold/bridges/record_select/bridge.rb +5 -0
  65. data/lib/active_scaffold/bridges/record_select/lib/record_select_bridge.rb +87 -0
  66. data/lib/active_scaffold/bridges/record_select/lib/record_select_bridge.rb~ +84 -0
  67. data/lib/active_scaffold/bridges/shared/date_bridge.rb +56 -34
  68. data/lib/active_scaffold/bridges/tiny_mce/lib/tiny_mce_bridge.rb +19 -3
  69. data/lib/active_scaffold/config/base.rb +4 -4
  70. data/lib/active_scaffold/config/core.rb +4 -0
  71. data/lib/active_scaffold/config/create.rb +1 -1
  72. data/lib/active_scaffold/config/field_search.rb +7 -7
  73. data/lib/active_scaffold/config/form.rb +8 -2
  74. data/lib/active_scaffold/config/list.rb +22 -8
  75. data/lib/active_scaffold/config/mark.rb +18 -5
  76. data/lib/active_scaffold/config/nested.rb +3 -3
  77. data/lib/active_scaffold/config/search.rb +1 -1
  78. data/lib/active_scaffold/config/show.rb +1 -1
  79. data/lib/active_scaffold/data_structures/action_columns.rb +10 -6
  80. data/lib/active_scaffold/data_structures/action_link.rb +14 -10
  81. data/lib/active_scaffold/data_structures/action_links.rb +2 -2
  82. data/lib/active_scaffold/data_structures/column.rb +25 -11
  83. data/lib/active_scaffold/data_structures/nested_info.rb +21 -21
  84. data/lib/active_scaffold/data_structures/set.rb +2 -3
  85. data/lib/active_scaffold/data_structures/sorting.rb +8 -8
  86. data/lib/{extensions → active_scaffold/extensions}/action_controller_rendering.rb +3 -1
  87. data/lib/{extensions → active_scaffold/extensions}/action_view_rendering.rb +31 -33
  88. data/lib/{extensions → active_scaffold/extensions}/action_view_resolver.rb +0 -0
  89. data/lib/{extensions → active_scaffold/extensions}/active_association_reflection.rb +0 -0
  90. data/lib/active_scaffold/extensions/active_record_offset.rb +12 -0
  91. data/lib/{extensions → active_scaffold/extensions}/array.rb +0 -0
  92. data/lib/{extensions → active_scaffold/extensions}/localize.rb +1 -1
  93. data/lib/{extensions → active_scaffold/extensions}/name_option_for_datetime.rb +1 -1
  94. data/lib/{extensions → active_scaffold/extensions}/nil_id_in_url_params.rb +0 -0
  95. data/lib/{extensions → active_scaffold/extensions}/paginator_extensions.rb +2 -2
  96. data/lib/{extensions → active_scaffold/extensions}/reverse_associations.rb +1 -1
  97. data/lib/{extensions → active_scaffold/extensions}/routing_mapper.rb +2 -2
  98. data/lib/{extensions → active_scaffold/extensions}/to_label.rb +0 -0
  99. data/lib/{extensions → active_scaffold/extensions}/unsaved_associated.rb +0 -0
  100. data/lib/{extensions → active_scaffold/extensions}/unsaved_record.rb +0 -0
  101. data/lib/active_scaffold/extensions/usa_state.rb +46 -0
  102. data/lib/active_scaffold/finder.rb +30 -19
  103. data/lib/active_scaffold/helpers/controller_helpers.rb +3 -5
  104. data/lib/active_scaffold/helpers/form_column_helpers.rb +19 -45
  105. data/lib/active_scaffold/helpers/human_condition_helpers.rb +1 -1
  106. data/lib/active_scaffold/helpers/id_helpers.rb +2 -2
  107. data/lib/active_scaffold/helpers/list_column_helpers.rb +28 -17
  108. data/lib/active_scaffold/helpers/search_column_helpers.rb +51 -40
  109. data/lib/active_scaffold/helpers/search_column_helpers.rb~ +215 -0
  110. data/lib/active_scaffold/helpers/show_column_helpers.rb +8 -4
  111. data/lib/active_scaffold/helpers/view_helpers.rb +50 -27
  112. data/lib/active_scaffold/locale/de.yml +111 -0
  113. data/lib/active_scaffold/locale/en.yml +115 -0
  114. data/lib/active_scaffold/locale/es.yml +32 -32
  115. data/lib/active_scaffold/locale/fr.yml +118 -0
  116. data/lib/active_scaffold/marked_model.rb +6 -6
  117. data/lib/active_scaffold/version.rb +1 -1
  118. data/lib/active_scaffold_assets.rb +1 -3
  119. data/lib/active_scaffold_env.rb +1 -2
  120. data/lib/generators/active_scaffold/active_scaffold_generator.rb +5 -5
  121. data/lib/generators/active_scaffold_controller/active_scaffold_controller_generator.rb +3 -2
  122. data/lib/generators/active_scaffold_controller/templates/helper.rb +2 -0
  123. data/lib/generators/active_scaffold_setup/active_scaffold_setup_generator.rb +17 -19
  124. data/shoulda_macros/macros.rb +4 -4
  125. data/test/misc/finder_test.rb +2 -2
  126. data/test/mock_app/public/stylesheets/active_scaffold/default/stylesheet.css +4 -1
  127. metadata +144 -126
  128. data/.autotest +0 -27
  129. data/.document +0 -5
  130. data/Gemfile +0 -13
  131. data/Gemfile.lock +0 -20
  132. data/Rakefile +0 -53
  133. data/active_scaffold.gemspec +0 -385
  134. data/init.rb +0 -2
  135. data/lib/active_scaffold/helpers/country_helpers.rb +0 -358
  136. data/lib/active_scaffold/locale/de.rb +0 -120
  137. data/lib/active_scaffold/locale/en.rb +0 -119
  138. data/lib/active_scaffold/locale/fr.rb +0 -116
  139. data/lib/extensions/active_record_offset.rb +0 -12
  140. data/lib/extensions/usa_state.rb +0 -50
  141. data/test/mock_app/.gitignore +0 -2
  142. data/uninstall.rb +0 -13
@@ -26,6 +26,15 @@ ActiveScaffold::Config::Core.class_eval do
26
26
  alias_method_chain :initialize, :date_picker
27
27
  end
28
28
 
29
+ ActiveRecord::ConnectionAdapters::Column.class_eval do
30
+ class << self
31
+ def fallback_string_to_date_with_date_picker(string)
32
+ Date.strptime(string, I18n.t('date.formats.default')) rescue fallback_string_to_date_without_date_picker(string)
33
+ end
34
+ alias_method_chain :fallback_string_to_date, :date_picker
35
+ end
36
+ end
37
+
29
38
 
30
39
  module ActiveScaffold
31
40
  module Bridges
@@ -0,0 +1,9 @@
1
+ ActiveScaffold::Bridges.bridge "Dragonfly" do
2
+ install do
3
+ require File.join(File.dirname(__FILE__), "lib/form_ui")
4
+ require File.join(File.dirname(__FILE__), "lib/list_ui")
5
+ require File.join(File.dirname(__FILE__), "lib/dragonfly_bridge_helpers")
6
+ require File.join(File.dirname(__FILE__), "lib/dragonfly_bridge")
7
+ ActiveScaffold::Config::Core.send :include, ActiveScaffold::Bridges::Dragonfly::Lib::DragonflyBridge
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ ActiveScaffold::Bridges.bridge "Paperclip" do
2
+ install do
3
+ if ActiveScaffold::Config::Core.instance_methods.include?("initialize_with_paperclip")
4
+ raise RuntimeError, "We've detected that you have active_scaffold_paperclip_bridge installed. This plugin has been moved to core. Please remove active_scaffold_paperclip_bridge to prevent any conflicts"
5
+ end
6
+ require File.join(File.dirname(__FILE__), "lib/form_ui")
7
+ require File.join(File.dirname(__FILE__), "lib/list_ui")
8
+ require File.join(File.dirname(__FILE__), "lib/paperclip_bridge_helpers")
9
+ require File.join(File.dirname(__FILE__), "lib/paperclip_bridge")
10
+ ActiveScaffold::Config::Core.send :include, ActiveScaffold::Bridges::Paperclip::Lib::PaperclipBridge
11
+ end
12
+ end
@@ -0,0 +1,36 @@
1
+ module ActiveScaffold
2
+ module Bridges
3
+ module Dragonfly
4
+ module Lib
5
+ module DragonflyBridge
6
+ def initialize_with_dragonfly(model_id)
7
+ initialize_without_dragonfly(model_id)
8
+ return unless self.model.respond_to?(:dragonfly_attachment_classes) && self.model.dragonfly_attachment_classes.present?
9
+
10
+ self.update.multipart = true
11
+ self.create.multipart = true
12
+
13
+ self.model.dragonfly_attachment_classes.each do |attachment|
14
+ configure_dragonfly_field(attachment.attribute)
15
+ end
16
+ end
17
+
18
+ def self.included(base)
19
+ base.alias_method_chain :initialize, :dragonfly
20
+ end
21
+
22
+ private
23
+ def configure_dragonfly_field(field)
24
+ self.columns << field
25
+ self.columns[field].form_ui ||= :dragonfly
26
+ self.columns[field].params.add "remove_#{field}"
27
+
28
+ [:name, :uid].each do |f|
29
+ self.columns.exclude("#{field}_#{f}".to_sym)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ module ActiveScaffold
2
+ module Bridges
3
+ module Dragonfly
4
+ module Lib
5
+ module DragonflyBridge
6
+ def initialize_with_dragonfly(model_id)
7
+ initialize_without_dragonfly(model_id)
8
+ return unless self.model.respond_to?(:dragonfly_attachment_classes) && self.model.dragonfly_attachment_classes.present?
9
+
10
+ self.update.multipart = true
11
+ self.create.multipart = true
12
+
13
+ self.model.dragonfly_attachment_classes.each do |attachment|
14
+ configure_dragonfly_field(attachment.attribute)
15
+ end
16
+ end
17
+
18
+ def self.included(base)
19
+ base.alias_method_chain :initialize, :dragonfly
20
+ end
21
+
22
+ private
23
+ def configure_dragonfly_field(field)
24
+ self.columns << field
25
+ self.columns[field].form_ui ||= :dragonfly
26
+ self.columns[field].params.add "delete_#{field}"
27
+
28
+ [:name, :uid].each do |f|
29
+ self.columns.exclude("#{field}_#{f}".to_sym)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,12 @@
1
+ module ActiveScaffold
2
+ module Bridges
3
+ module Dragonfly
4
+ module Lib
5
+ module DragonflyBridgeHelpers
6
+ mattr_accessor :thumbnail_style
7
+ self.thumbnail_style = 'x30>'
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module ActiveScaffold
2
+ module Bridges
3
+ module Dragonfly
4
+ module Lib
5
+ module DragonflyBridgeHelpers
6
+ mattr_accessor :thumbnail_style
7
+ self.thumbnail_style = :thumbnail
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,27 @@
1
+ module ActiveScaffold
2
+ module Helpers
3
+ module FormColumnHelpers
4
+ def active_scaffold_input_dragonfly(column, options)
5
+ options = active_scaffold_input_text_options(options)
6
+ input = file_field(:record, column.name, options)
7
+ dragonfly = @record.send("#{column.name}")
8
+ if dragonfly.present?
9
+ if ActiveScaffold.js_framework == :jquery
10
+ js_remove_file_code = "$(this).prev().val('true'); $(this).parent().hide().next().show(); return false;";
11
+ else
12
+ js_remove_file_code = "$(this).previous().value='true'; $(this).up().hide().next().show(); return false;";
13
+ end
14
+
15
+ content = active_scaffold_column_dragonfly(column, @record)
16
+ content_tag(:div,
17
+ content + " | " +
18
+ hidden_field(:record, "remove_#{column.name}", :value => "false") +
19
+ content_tag(:a, as_(:remove_file), {:href => '#', :onclick => js_remove_file_code})
20
+ ) + content_tag(:div, input, :style => "display: none")
21
+ else
22
+ input
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ module ActiveScaffold
2
+ module Helpers
3
+ module FormColumnHelpers
4
+ def active_scaffold_input_dragonfly(column, options)
5
+ options = active_scaffold_input_text_options(options)
6
+ input = file_field(:record, column.name, options)
7
+ dragonfly = @record.send("#{column.name}")
8
+ if dragonfly && dragonfly.file?
9
+ if ActiveScaffold.js_framework == :jquery
10
+ js_remove_file_code = "$(this).prev().val('true'); $(this).parent().hide().next().show(); return false;";
11
+ else
12
+ js_remove_file_code = "$(this).previous().value='true'; $(this).up().hide().next().show(); return false;";
13
+ end
14
+
15
+ content = active_scaffold_column_dragonfly(column, @record)
16
+ content_tag(:div,
17
+ content + " | " +
18
+ hidden_field(:record, "remove_#{column.name}", :value => "false") +
19
+ content_tag(:a, as_(:remove_file), {:href => '#', :onclick => js_remove_file_code})
20
+ ) + content_tag(:div, input, :style => "display: none")
21
+ else
22
+ input
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ module ActiveScaffold
2
+ module Helpers
3
+ module ListColumnHelpers
4
+ def active_scaffold_column_dragonfly(column, record)
5
+ attachment = record.send("#{column.name}")
6
+ return nil unless attachment.present?
7
+ content = if attachment.image?
8
+ image_tag(attachment.thumb(column.options[:thumb] || ActiveScaffold::Bridges::Dragonfly::Lib::DragonflyBridgeHelpers.thumbnail_style).url, :border => 0)
9
+ else
10
+ attachment.name
11
+ end
12
+ link_to(content, attachment.remote_url, {'data-popup' => true, :target => '_blank'})
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module ActiveScaffold
2
+ module Helpers
3
+ module ListColumnHelpers
4
+ def active_scaffold_column_dragonfly(column, record)
5
+ attachment = record.send("#{column.name}")
6
+ return nil unless attachment.present?
7
+ content = if attachment.image?
8
+ image_tag(attachment.thumb(ActiveScaffold::Bridges::Dragonfly::Lib::DragonflyBridgeHelpers.thumbnail_style).url, :border => 0)
9
+ else
10
+ attachment.name
11
+ end
12
+ link_to(content, attachment.remote_url, {'data-popup' => true, :target => '_blank'})
13
+ end
14
+ end
15
+ end
16
+ end
@@ -9,4 +9,4 @@ ActiveScaffold::Bridges.bridge "Paperclip" do
9
9
  require File.join(File.dirname(__FILE__), "lib/paperclip_bridge")
10
10
  ActiveScaffold::Config::Core.send :include, ActiveScaffold::Bridges::Paperclip::Lib::PaperclipBridge
11
11
  end
12
- end
12
+ end
@@ -0,0 +1,5 @@
1
+ ActiveScaffold::Bridges.bridge "RecordSelect" do
2
+ install do
3
+ require File.join(File.dirname(__FILE__), "lib/record_select_bridge.rb")
4
+ end
5
+ end
@@ -0,0 +1,87 @@
1
+ module ActiveScaffold
2
+ module RecordSelectBridge
3
+ def self.included(base)
4
+ base.class_eval do
5
+ include FormColumnHelpers
6
+ include SearchColumnHelpers
7
+ include ViewHelpers
8
+ end
9
+ end
10
+
11
+ module ViewHelpers
12
+ def self.included(base)
13
+ base.alias_method_chain :active_scaffold_includes, :record_select
14
+ end
15
+
16
+ def active_scaffold_includes_with_record_select(*args)
17
+ active_scaffold_includes_without_record_select(*args) + record_select_includes
18
+ end
19
+ end
20
+
21
+ module FormColumnHelpers
22
+ # requires RecordSelect plugin to be installed and configured.
23
+ def active_scaffold_input_record_select(column, options)
24
+ if column.singular_association?
25
+ multiple = false
26
+ multiple = column.options[:html_options][:multiple] if column.options[:html_options] && column.options[:html_options][:multiple]
27
+ active_scaffold_record_select(column, options, @record.send(column.name), multiple)
28
+ elsif column.plural_association?
29
+ active_scaffold_record_select(column, options, @record.send(column.name), true)
30
+ end
31
+ end
32
+
33
+ def active_scaffold_record_select(column, options, value, multiple)
34
+ unless column.association
35
+ raise ArgumentError, "record_select can only work against associations (and #{column.name} is not). A common mistake is to specify the foreign key field (like :user_id), instead of the association (:user)."
36
+ end
37
+ remote_controller = active_scaffold_controller_for(column.association.klass).controller_path
38
+
39
+ # if the opposite association is a :belongs_to (in that case association in this class must be has_one or has_many)
40
+ # then only show records that have not been associated yet
41
+ if [:has_one, :has_many].include?(column.association.macro)
42
+ params.merge!({column.association.primary_key_name => ''})
43
+ end
44
+
45
+ record_select_options = {:controller => remote_controller, :id => options[:id]}
46
+ record_select_options.merge!(active_scaffold_input_text_options)
47
+ record_select_options.merge!(column.options)
48
+ if options['data-update_url']
49
+ record_select_options[:onchange] = %|function(id, label) {
50
+ ActiveScaffold.update_column($("##{options[:id]}"), "#{options['data-update_url']}", #{options['data-update_send_form'].to_json}, "#{options[:id]}", id);
51
+ }|
52
+ end
53
+
54
+ if multiple
55
+ record_multi_select_field(options[:name], value || [], record_select_options)
56
+ else
57
+ record_select_field(options[:name], value || column.association.klass.new, record_select_options)
58
+ end
59
+ end
60
+ end
61
+
62
+ module SearchColumnHelpers
63
+ def active_scaffold_search_record_select(column, options)
64
+ value = field_search_record_select_value(column)
65
+ active_scaffold_record_select(column, options, value, column.options[:multiple])
66
+ end
67
+
68
+ def field_search_record_select_value(column)
69
+ begin
70
+ value = field_search_params[column.name]
71
+ unless value.blank?
72
+ if column.options[:multiple]
73
+ column.association.klass.find value.collect!(&:to_i)
74
+ else
75
+ column.association.klass.find(value.to_i)
76
+ end
77
+ end
78
+ rescue Exception => e
79
+ logger.error Time.now.to_s + "Sorry, we are not that smart yet. Attempted to restore search values to search fields but instead got -- #{e.inspect} -- on the ActiveScaffold column = :#{column.name} in #{@controller.class}"
80
+ raise e
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ ActionView::Base.class_eval { include ActiveScaffold::RecordSelectBridge }
@@ -0,0 +1,84 @@
1
+ module ActiveScaffold
2
+ module RecordSelectBridge
3
+ def self.included(base)
4
+ base.class_eval do
5
+ include FormColumnHelpers
6
+ include SearchColumnHelpers
7
+ include ViewHelpers
8
+ end
9
+ end
10
+
11
+ module ViewHelpers
12
+ def self.included(base)
13
+ base.alias_method_chain :active_scaffold_includes, :record_select
14
+ end
15
+
16
+ def active_scaffold_includes_with_record_select(*args)
17
+ active_scaffold_includes_without_record_select(*args) + record_select_includes
18
+ end
19
+ end
20
+
21
+ module FormColumnHelpers
22
+ # requires RecordSelect plugin to be installed and configured.
23
+ def active_scaffold_input_record_select(column, options)
24
+ if column.singular_association?
25
+ multiple = false
26
+ multiple = column.options[:html_options][:multiple] if column.options[:html_options] && column.options[:html_options][:multiple]
27
+ active_scaffold_record_select(column, options, @record.send(column.name), multiple)
28
+ elsif column.plural_association?
29
+ active_scaffold_record_select(column, options, @record.send(column.name), true)
30
+ end
31
+ end
32
+
33
+ def active_scaffold_record_select(column, options, value, multiple)
34
+ unless column.association
35
+ raise ArgumentError, "record_select can only work against associations (and #{column.name} is not). A common mistake is to specify the foreign key field (like :user_id), instead of the association (:user)."
36
+ end
37
+ remote_controller = active_scaffold_controller_for(column.association.klass).controller_path
38
+
39
+ # if the opposite association is a :belongs_to (in that case association in this class must be has_one or has_many)
40
+ # then only show records that have not been associated yet
41
+ if [:has_one, :has_many].include?(column.association.macro)
42
+ params.merge!({column.association.primary_key_name => ''})
43
+ end
44
+
45
+ record_select_options = {:controller => remote_controller, :id => options[:id]}
46
+ record_select_options.merge!(active_scaffold_input_text_options)
47
+ record_select_options.merge!(column.options)
48
+
49
+ if multiple
50
+ record_multi_select_field(options[:name], value || [], record_select_options)
51
+ else
52
+ record_select_field(options[:name], value || column.association.klass.new, record_select_options)
53
+ end
54
+ end
55
+ end
56
+
57
+ module SearchColumnHelpers
58
+ def active_scaffold_search_record_select(column, options)
59
+ value = field_search_record_select_value(column)
60
+ active_scaffold_record_select(column, options, value, column.options[:multiple])
61
+ end
62
+
63
+ def field_search_record_select_value(column)
64
+ begin
65
+ value = field_search_params[column.name]
66
+ value = unless value.blank?
67
+ if column.options[:multiple]
68
+ column.association.klass.find value.collect!(&:to_i)
69
+ else
70
+ column.association.klass.find(value.to_i)
71
+ end
72
+ end
73
+ rescue Exception => e
74
+ logger.error Time.now.to_s + "Sorry, we are not that smart yet. Attempted to restore search values to search fields but instead got -- #{e.inspect} -- on the ActiveScaffold column = :#{column.name} in #{@controller.class}"
75
+ raise e
76
+ end
77
+
78
+ active_scaffold_record_select(column, options, value, column.options[:multiple])
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ ActionView::Base.class_eval { include ActiveScaffold::RecordSelectBridge }
@@ -14,26 +14,26 @@ module ActiveScaffold
14
14
  tags << active_scaffold_search_date_bridge_range_tag(column, options, current_search)
15
15
  tags.join("&nbsp;").html_safe
16
16
  end
17
-
17
+
18
18
  def active_scaffold_search_date_bridge_comparator_options(column)
19
19
  select_options = ActiveScaffold::Finder::DateComparators.collect {|comp| [as_(comp.downcase.to_sym), comp]}
20
20
  select_options + ActiveScaffold::Finder::NumericComparators.collect {|comp| [as_(comp.downcase.to_sym), comp]}
21
21
  end
22
-
22
+
23
23
  def active_scaffold_search_date_bridge_comparator_tag(column, options, current_search)
24
24
  select_tag("#{options[:name]}[opt]", options_for_select(active_scaffold_search_date_bridge_comparator_options(column),current_search['opt']), :id => "#{options[:id]}_opt", :class => "as_search_range_option as_search_date_time_option")
25
25
  end
26
-
26
+
27
27
  def active_scaffold_search_date_bridge_numeric_tag(column, options, current_search)
28
- numeric_controls = "" <<
28
+ numeric_controls = "" <<
29
29
  active_scaffold_search_date_bridge_calendar_control(column, options, current_search, 'from') <<
30
30
  content_tag(:span, (" - " + active_scaffold_search_date_bridge_calendar_control(column, options, current_search, 'to')).html_safe,
31
- :id => "#{options[:id]}_between", :class => "as_search_range_between", :style => "display:#{current_search['opt'] == 'BETWEEN' ? '' : 'none'}")
31
+ :id => "#{options[:id]}_between", :class => "as_search_range_between", :style => "display:#{current_search['opt'] == 'BETWEEN' ? '' : 'none'}")
32
32
  content_tag("span", numeric_controls.html_safe, :id => "#{options[:id]}_numeric", :style => "display:#{ActiveScaffold::Finder::NumericComparators.include?(current_search['opt']) ? '' : 'none'}")
33
33
  end
34
-
34
+
35
35
  def active_scaffold_search_date_bridge_trend_tag(column, options, current_search)
36
- active_scaffold_date_bridge_trend_tag(column, options,
36
+ active_scaffold_date_bridge_trend_tag(column, options,
37
37
  {:name_prefix => 'search',
38
38
  :number_value => current_search['number'],
39
39
  :unit_value => current_search["unit"],
@@ -43,7 +43,7 @@ module ActiveScaffold
43
43
  def active_scaffold_date_bridge_trend_tag(column, options, trend_options)
44
44
  trend_controls = text_field_tag("#{trend_options[:name_prefix]}[#{column.name}][number]", trend_options[:number_value], :class => 'text-input', :size => 10, :autocomplete => 'off') << " " <<
45
45
  select_tag("#{trend_options[:name_prefix]}[#{column.name}][unit]",
46
- options_for_select(active_scaffold_search_date_bridge_trend_units(column), trend_options[:name_prefix]),
46
+ options_for_select(active_scaffold_search_date_bridge_trend_units(column), trend_options[:unit_value]),
47
47
  :class => 'text-input')
48
48
  content_tag("span", trend_controls.html_safe, :id => "#{options[:id]}_trend", :style => "display:#{trend_options[:show] ? '' : 'none'}")
49
49
  end
@@ -53,14 +53,14 @@ module ActiveScaffold
53
53
  options = ActiveScaffold::Finder::TimeUnits.collect{|unit| [as_(unit.downcase.to_sym), unit]} + options if column_datetime?(column)
54
54
  options
55
55
  end
56
-
56
+
57
57
  def active_scaffold_search_date_bridge_range_tag(column, options, current_search)
58
- range_controls = select_tag("search[#{column.name}][range]",
59
- options_for_select( ActiveScaffold::Finder::DateRanges.collect{|range| [as_(range.downcase.to_sym), range]}, current_search["range"]),
58
+ range_controls = select_tag("search[#{column.name}][range]",
59
+ options_for_select( ActiveScaffold::Finder::DateRanges.collect{|range| [as_(range.downcase.to_sym), range]}, current_search["range"]),
60
60
  :class => 'text-input')
61
61
  content_tag("span", range_controls.html_safe, :id => "#{options[:id]}_range", :style => "display:#{(current_search['opt'] == 'RANGE') ? '' : 'none'}")
62
62
  end
63
-
63
+
64
64
  def column_datetime?(column)
65
65
  (!column.column.nil? && [:datetime, :time].include?(column.column.type))
66
66
  end
@@ -70,33 +70,55 @@ module ActiveScaffold
70
70
  def active_scaffold_human_condition_date_bridge(column, value)
71
71
  case value[:opt]
72
72
  when 'RANGE'
73
- "#{column.active_record_class.human_attribute_name(column.name)} = #{as_(value[:range].downcase).downcase}"
73
+ range_type, range = value[:range].downcase.split('_')
74
+ format = active_scaffold_human_condition_date_bridge_range_format(range_type, range)
75
+ from, to = controller.class.date_bridge_from_to(column, value)
76
+ "#{column.active_record_class.human_attribute_name(column.name)} = #{as_(value[:range].downcase).downcase} (#{I18n.l(from, :format => format)})"
74
77
  when 'PAST', 'FUTURE'
75
- "#{column.active_record_class.human_attribute_name(column.name)} #{as_(value[:opt].downcase).downcase} #{as_(value[:number])} #{as_(value[:unit].downcase)}"
78
+ from, to = controller.class.date_bridge_from_to(column, value)
79
+ "#{column.active_record_class.human_attribute_name(column.name)} #{as_('BETWEEN'.downcase).downcase} #{I18n.l(from)} - #{I18n.l(to)}"
76
80
  else
77
81
  from, to = controller.class.date_bridge_from_to(column, value)
78
82
  "#{column.active_record_class.human_attribute_name(column.name)} #{as_(value[:opt].downcase).downcase} #{I18n.l(from)} #{value[:opt] == 'BETWEEN' ? '- ' + I18n.l(to) : ''}"
79
83
  end
80
84
  end
81
- end
82
85
 
86
+ def active_scaffold_human_condition_date_bridge_range_format(range_type, range)
87
+ case range
88
+ when 'week'
89
+ first_day_of_week = I18n.translate 'active_scaffold.date_picker_options.firstDay'
90
+ if first_day_of_week == 1
91
+ '%W %Y'
92
+ else
93
+ '%U %Y'
94
+ end
95
+ when 'month'
96
+ '%b %Y'
97
+ when 'year'
98
+ '%Y'
99
+ else
100
+ I18n.translate 'date.formats.default'
101
+ end
102
+ end
103
+ end
104
+
83
105
  module Finder
84
106
  module ClassMethods
85
107
  def condition_for_date_bridge_type(column, value, like_pattern)
86
108
  operator = ActiveScaffold::Finder::NumericComparators.include?(value[:opt]) && value[:opt] != 'BETWEEN' ? value[:opt] : nil
87
109
  from_value, to_value = date_bridge_from_to(column, value)
88
-
110
+
89
111
  if column.search_sql.is_a? Proc
90
112
  column.search_sql.call(from_value, to_value, operator)
91
113
  else
92
114
  unless operator.nil?
93
115
  ["#{column.search_sql} #{value[:opt]} ?", from_value.to_s(:db)] unless from_value.nil?
94
116
  else
95
- ["#{column.search_sql} BETWEEN ? AND ?", from_value.to_s(:db), to_value.to_s(:db)] unless from_value.nil? && to_value.nil?
117
+ ["#{column.search_sql} BETWEEN ? AND ?", from_value.to_s(:db), to_value.to_s(:db)] unless from_value.nil? && to_value.nil?
96
118
  end
97
119
  end
98
120
  end
99
-
121
+
100
122
  def date_bridge_from_to(column, value)
101
123
  conversion = column.column.type == :date ? :to_date : :to_time
102
124
  case value[:opt]
@@ -109,11 +131,15 @@ module ActiveScaffold
109
131
  end
110
132
  end
111
133
 
134
+ def date_bridge_now
135
+ Time.zone.now
136
+ end
137
+
112
138
  def date_bridge_from_to_for_trend(column, value)
113
139
  case value['opt']
114
140
  when "PAST"
115
141
  trend_number = [value['number'].to_i, 1].max
116
- now = Time.zone.now
142
+ now = date_bridge_now
117
143
  if date_bridge_column_date?(column)
118
144
  from = now.beginning_of_day.ago((trend_number).send(value['unit'].downcase.singularize.to_sym))
119
145
  to = now.end_of_day
@@ -124,7 +150,7 @@ module ActiveScaffold
124
150
  return from, to
125
151
  when "FUTURE"
126
152
  trend_number = [value['number'].to_i, 1].max
127
- now = Time.zone.now
153
+ now = date_bridge_now
128
154
  if date_bridge_column_date?(column)
129
155
  from = now.beginning_of_day
130
156
  to = now.end_of_day.in((trend_number).send(value['unit'].downcase.singularize.to_sym))
@@ -135,27 +161,27 @@ module ActiveScaffold
135
161
  return from, to
136
162
  end
137
163
  end
138
-
164
+
139
165
  def date_bridge_from_to_for_range(column, value)
140
166
  case value[:range]
141
167
  when 'TODAY'
142
- return Time.zone.now.beginning_of_day, Time.zone.now.end_of_day
168
+ return date_bridge_now.beginning_of_day, date_bridge_now.end_of_day
143
169
  when 'YESTERDAY'
144
- return Time.zone.now.ago(1.day).beginning_of_day, Time.zone.now.ago(1.day).end_of_day
145
- when 'TOMMORROW'
146
- return Time.zone.now.in(1.day).beginning_of_day, Time.zone.now.in(1.day).end_of_day
170
+ return date_bridge_now.ago(1.day).beginning_of_day, date_bridge_now.ago(1.day).end_of_day
171
+ when 'TOMORROW'
172
+ return date_bridge_now.in(1.day).beginning_of_day, date_bridge_now.in(1.day).end_of_day
147
173
  else
148
174
  range_type, range = value[:range].downcase.split('_')
149
175
  raise ArgumentError unless ['week', 'month', 'year'].include?(range)
150
176
  case range_type
151
177
  when 'this'
152
- return Time.zone.now.send("beginning_of_#{range}".to_sym), Time.zone.now.send("end_of_#{range}")
178
+ return date_bridge_now.send("beginning_of_#{range}".to_sym), date_bridge_now.send("end_of_#{range}")
153
179
  when 'prev'
154
- return Time.zone.now.ago(1.send(range.to_sym)).send("beginning_of_#{range}".to_sym), Time.zone.now.ago(1.send(range.to_sym)).send("end_of_#{range}".to_sym)
180
+ return date_bridge_now.ago(1.send(range.to_sym)).send("beginning_of_#{range}".to_sym), date_bridge_now.ago(1.send(range.to_sym)).send("end_of_#{range}".to_sym)
155
181
  when 'next'
156
- return Time.zone.now.in(1.send(range.to_sym)).send("beginning_of_#{range}".to_sym), Time.zone.now.in(1.send(range.to_sym)).send("end_of_#{range}".to_sym)
182
+ return date_bridge_now.in(1.send(range.to_sym)).send("beginning_of_#{range}".to_sym), date_bridge_now.in(1.send(range.to_sym)).send("end_of_#{range}".to_sym)
157
183
  else
158
- return nil, nil
184
+ return nil, nil
159
185
  end
160
186
  end
161
187
  end
@@ -180,8 +206,4 @@ ActiveScaffold::Finder.const_set('TimeUnits', ["SECONDS", "MINUTES", "HOURS"])
180
206
  ActiveScaffold::Finder.const_set('DateRanges', ["TODAY", "YESTERDAY", "TOMORROW",
181
207
  "THIS_WEEK", "PREV_WEEK", "NEXT_WEEK",
182
208
  "THIS_MONTH", "PREV_MONTH", "NEXT_MONTH",
183
- "THIS_YEAR", "PREV_YEAR", "NEXT_YEAR"])
184
-
185
-
186
-
187
-
209
+ "THIS_YEAR", "PREV_YEAR", "NEXT_YEAR"])