active_scaffold 3.3.3 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (198) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +39 -0
  3. data/README.md +5 -3
  4. data/app/assets/images/active_scaffold/refresh.png +0 -0
  5. data/app/assets/javascripts/jquery/active_scaffold.js +182 -91
  6. data/app/assets/javascripts/jquery/date_picker_bridge.js.erb +14 -16
  7. data/app/assets/javascripts/jquery/draggable_lists.js +33 -26
  8. data/app/assets/javascripts/jquery/jquery.editinplace.js +3 -3
  9. data/app/assets/javascripts/prototype/active_scaffold.js +61 -19
  10. data/app/assets/stylesheets/active_scaffold_colors.css.scss +4 -0
  11. data/app/assets/stylesheets/active_scaffold_images.css.scss +3 -0
  12. data/app/assets/stylesheets/active_scaffold_layout.css +23 -2
  13. data/app/views/active_scaffold_overrides/_add_existing_form.html.erb +1 -3
  14. data/app/views/active_scaffold_overrides/_base_form.html.erb +7 -5
  15. data/app/views/active_scaffold_overrides/_field_search.html.erb +1 -2
  16. data/app/views/active_scaffold_overrides/_form.html.erb +6 -4
  17. data/app/views/active_scaffold_overrides/_form_association.html.erb +4 -3
  18. data/app/views/active_scaffold_overrides/_form_association_footer.html.erb +5 -5
  19. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +8 -6
  20. data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +3 -2
  21. data/app/views/active_scaffold_overrides/_list.html.erb +8 -6
  22. data/app/views/active_scaffold_overrides/_list_column_headings.html.erb +1 -4
  23. data/app/views/active_scaffold_overrides/_list_pagination.html.erb +4 -4
  24. data/app/views/active_scaffold_overrides/_list_pagination_links.html.erb +1 -1
  25. data/app/views/active_scaffold_overrides/_list_record.html.erb +3 -3
  26. data/app/views/active_scaffold_overrides/_refresh_list.js.erb +8 -1
  27. data/app/views/active_scaffold_overrides/_search.html.erb +7 -13
  28. data/app/views/active_scaffold_overrides/_show_columns.html.erb +1 -1
  29. data/app/views/active_scaffold_overrides/on_create.js.erb +4 -4
  30. data/app/views/active_scaffold_overrides/render_field_inplace.html.erb +1 -1
  31. data/app/views/active_scaffold_overrides/row.js.erb +1 -1
  32. data/config/locales/de.yml +106 -95
  33. data/config/locales/en.yml +108 -97
  34. data/config/locales/es.yml +109 -98
  35. data/config/locales/fr.yml +108 -97
  36. data/config/locales/hu.yml +109 -98
  37. data/config/locales/ja.yml +100 -89
  38. data/config/locales/ru.yml +115 -104
  39. data/lib/active_scaffold.rb +18 -294
  40. data/lib/active_scaffold/actions/common_search.rb +50 -17
  41. data/lib/active_scaffold/actions/core.rb +93 -22
  42. data/lib/active_scaffold/actions/create.rb +15 -6
  43. data/lib/active_scaffold/actions/field_search.rb +68 -60
  44. data/lib/active_scaffold/actions/list.rb +49 -28
  45. data/lib/active_scaffold/actions/nested.rb +14 -6
  46. data/lib/active_scaffold/actions/search.rb +36 -35
  47. data/lib/active_scaffold/actions/show.rb +9 -4
  48. data/lib/active_scaffold/actions/subform.rb +1 -1
  49. data/lib/active_scaffold/actions/update.rb +22 -7
  50. data/lib/active_scaffold/active_record_permissions.rb +125 -118
  51. data/lib/active_scaffold/attribute_params.rb +84 -66
  52. data/lib/active_scaffold/bridges.rb +3 -3
  53. data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +10 -5
  54. data/lib/active_scaffold/bridges/cancan.rb +2 -1
  55. data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +13 -2
  56. data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +11 -6
  57. data/lib/active_scaffold/bridges/chosen/helpers.rb +2 -2
  58. data/lib/active_scaffold/bridges/country_helper/country_helper_bridge.rb +45 -29
  59. data/lib/active_scaffold/bridges/date_picker/ext.rb +11 -6
  60. data/lib/active_scaffold/bridges/date_picker/helper.rb +5 -1
  61. data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +10 -5
  62. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +6 -1
  63. data/lib/active_scaffold/bridges/file_column/form_ui.rb +12 -11
  64. data/lib/active_scaffold/bridges/paperclip/form_ui.rb +14 -6
  65. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
  66. data/lib/active_scaffold/bridges/record_select/helpers.rb +15 -12
  67. data/lib/active_scaffold/bridges/shared/date_bridge.rb +7 -8
  68. data/lib/active_scaffold/bridges/tiny_mce.rb +5 -3
  69. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +4 -5
  70. data/lib/active_scaffold/config/base.rb +4 -0
  71. data/lib/active_scaffold/config/core.rb +12 -5
  72. data/lib/active_scaffold/config/delete.rb +0 -2
  73. data/lib/active_scaffold/config/field_search.rb +1 -4
  74. data/lib/active_scaffold/config/form.rb +0 -2
  75. data/lib/active_scaffold/config/list.rb +31 -1
  76. data/lib/active_scaffold/config/search.rb +0 -3
  77. data/lib/active_scaffold/config/show.rb +0 -6
  78. data/lib/active_scaffold/config/subform.rb +1 -0
  79. data/lib/active_scaffold/configurable.rb +2 -2
  80. data/lib/active_scaffold/constraints.rb +11 -14
  81. data/lib/active_scaffold/core.rb +277 -0
  82. data/lib/active_scaffold/data_structures/action_columns.rb +18 -2
  83. data/lib/active_scaffold/data_structures/action_link.rb +25 -6
  84. data/lib/active_scaffold/data_structures/action_links.rb +9 -4
  85. data/lib/active_scaffold/data_structures/actions.rb +1 -1
  86. data/lib/active_scaffold/data_structures/column.rb +6 -6
  87. data/lib/active_scaffold/data_structures/columns.rb +2 -2
  88. data/lib/active_scaffold/data_structures/nested_info.rb +5 -1
  89. data/lib/active_scaffold/data_structures/sorting.rb +15 -5
  90. data/lib/active_scaffold/delayed_setup.rb +30 -0
  91. data/lib/active_scaffold/engine.rb +25 -0
  92. data/lib/active_scaffold/extensions/action_view_rendering.rb +1 -1
  93. data/lib/active_scaffold/extensions/left_outer_joins.rb +61 -21
  94. data/lib/active_scaffold/extensions/localize.rb +1 -1
  95. data/lib/active_scaffold/extensions/name_option_for_datetime.rb +13 -8
  96. data/lib/active_scaffold/extensions/paginator_extensions.rb +5 -1
  97. data/lib/active_scaffold/extensions/reverse_associations.rb +1 -0
  98. data/lib/active_scaffold/extensions/routing_mapper.rb +1 -1
  99. data/lib/active_scaffold/extensions/unsaved_record.rb +4 -6
  100. data/lib/active_scaffold/finder.rb +79 -27
  101. data/lib/active_scaffold/helpers/association_helpers.rb +48 -18
  102. data/lib/active_scaffold/helpers/controller_helpers.rb +19 -10
  103. data/lib/active_scaffold/helpers/form_column_helpers.rb +185 -87
  104. data/lib/active_scaffold/helpers/human_condition_helpers.rb +2 -1
  105. data/lib/active_scaffold/helpers/id_helpers.rb +14 -8
  106. data/lib/active_scaffold/helpers/list_column_helpers.rb +65 -56
  107. data/lib/active_scaffold/helpers/pagination_helpers.rb +5 -1
  108. data/lib/active_scaffold/helpers/search_column_helpers.rb +21 -18
  109. data/lib/active_scaffold/helpers/view_helpers.rb +102 -64
  110. data/lib/active_scaffold/responds_to_parent.rb +39 -64
  111. data/lib/active_scaffold/tableless.rb +129 -10
  112. data/lib/active_scaffold/version.rb +2 -2
  113. data/test/bridges/bridge_test.rb +1 -1
  114. data/test/bridges/date_picker_test.rb +2 -2
  115. data/test/bridges/paperclip_test.rb +10 -8
  116. data/test/bridges/tiny_mce_test.rb +2 -2
  117. data/test/company.rb +22 -10
  118. data/test/config/base_test.rb +1 -1
  119. data/test/config/core_test.rb +8 -6
  120. data/test/config/create_test.rb +6 -6
  121. data/test/config/delete_test.rb +4 -4
  122. data/test/config/field_search_test.rb +6 -6
  123. data/test/config/list_test.rb +7 -7
  124. data/test/config/nested_test.rb +8 -7
  125. data/test/config/search_test.rb +7 -7
  126. data/test/config/show_test.rb +5 -5
  127. data/test/config/subform_test.rb +1 -1
  128. data/test/config/update_test.rb +5 -4
  129. data/test/data_structures/action_columns_test.rb +15 -16
  130. data/test/data_structures/action_link_test.rb +10 -10
  131. data/test/data_structures/action_links_test.rb +6 -6
  132. data/test/data_structures/actions_test.rb +4 -4
  133. data/test/data_structures/association_column_test.rb +4 -4
  134. data/test/data_structures/column_test.rb +9 -9
  135. data/test/data_structures/columns_test.rb +7 -7
  136. data/test/data_structures/error_message_test.rb +2 -4
  137. data/test/data_structures/set_test.rb +13 -13
  138. data/test/data_structures/sorting_test.rb +8 -8
  139. data/test/data_structures/standard_column_test.rb +2 -2
  140. data/test/data_structures/validation_reflection_test.rb +8 -8
  141. data/test/data_structures/virtual_column_test.rb +5 -5
  142. data/test/extensions/active_record_test.rb +1 -1
  143. data/test/helpers/form_column_helpers_test.rb +5 -5
  144. data/test/helpers/list_column_helpers_test.rb +2 -1
  145. data/test/helpers/pagination_helpers_test.rb +1 -1
  146. data/test/misc/active_record_permissions_test.rb +23 -4
  147. data/test/misc/attribute_params_test.rb +304 -136
  148. data/test/misc/calculation_test.rb +55 -0
  149. data/test/misc/configurable_test.rb +22 -21
  150. data/test/misc/constraints_test.rb +10 -7
  151. data/test/misc/convert_numbers_format_test.rb +149 -0
  152. data/test/misc/finder_test.rb +17 -13
  153. data/test/misc/lang_test.rb +1 -1
  154. data/test/misc/tableless_test.rb +18 -0
  155. data/test/mock_app/app/controllers/addresses_controller.rb +4 -0
  156. data/test/mock_app/app/controllers/buildings_controller.rb +4 -0
  157. data/test/mock_app/app/controllers/cars_controller.rb +4 -0
  158. data/test/mock_app/app/controllers/contacts_controller.rb +4 -0
  159. data/test/mock_app/app/controllers/floors_controller.rb +6 -0
  160. data/test/mock_app/app/controllers/people_controller.rb +4 -0
  161. data/test/mock_app/app/models/address.rb +3 -0
  162. data/test/mock_app/app/models/building.rb +8 -0
  163. data/test/mock_app/app/models/car.rb +3 -0
  164. data/test/mock_app/app/models/contact.rb +3 -0
  165. data/test/mock_app/app/models/file_model.rb +19 -0
  166. data/test/mock_app/app/models/floor.rb +8 -0
  167. data/test/mock_app/app/models/person.rb +11 -0
  168. data/test/mock_app/config/application.rb +2 -0
  169. data/test/mock_app/config/environments/test.rb +1 -1
  170. data/test/mock_app/config/initializers/secret_token.rb +5 -1
  171. data/test/mock_app/config/routes.rb +1 -1
  172. data/test/mock_app/db/schema.rb +51 -0
  173. data/test/model_stub.rb +3 -3
  174. data/test/test_helper.rb +15 -12
  175. metadata +51 -50
  176. data/lib/active_scaffold/extensions/array.rb +0 -7
  177. data/lib/active_scaffold/extensions/cache_association.rb +0 -16
  178. data/lib/active_scaffold/extensions/usa_state.rb +0 -46
  179. data/lib/active_scaffold_env.rb +0 -13
  180. data/test/extensions/array_test.rb +0 -12
  181. data/test/mock_app/public/blank.html +0 -33
  182. data/test/mock_app/public/images/active_scaffold/DO_NOT_EDIT +0 -2
  183. data/test/mock_app/public/images/active_scaffold/default/add.gif +0 -0
  184. data/test/mock_app/public/images/active_scaffold/default/arrow_down.gif +0 -0
  185. data/test/mock_app/public/images/active_scaffold/default/arrow_up.gif +0 -0
  186. data/test/mock_app/public/images/active_scaffold/default/close.gif +0 -0
  187. data/test/mock_app/public/images/active_scaffold/default/cross.png +0 -0
  188. data/test/mock_app/public/images/active_scaffold/default/indicator-small.gif +0 -0
  189. data/test/mock_app/public/images/active_scaffold/default/indicator.gif +0 -0
  190. data/test/mock_app/public/images/active_scaffold/default/magnifier.png +0 -0
  191. data/test/mock_app/public/javascripts/active_scaffold/DO_NOT_EDIT +0 -2
  192. data/test/mock_app/public/javascripts/active_scaffold/default/active_scaffold.js +0 -532
  193. data/test/mock_app/public/javascripts/active_scaffold/default/dhtml_history.js +0 -867
  194. data/test/mock_app/public/javascripts/active_scaffold/default/form_enhancements.js +0 -117
  195. data/test/mock_app/public/javascripts/active_scaffold/default/rico_corner.js +0 -370
  196. data/test/mock_app/public/stylesheets/active_scaffold/DO_NOT_EDIT +0 -2
  197. data/test/mock_app/public/stylesheets/active_scaffold/default/stylesheet-ie.css +0 -35
  198. data/test/mock_app/public/stylesheets/active_scaffold/default/stylesheet.css +0 -848
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class ActiveRecordTest < Test::Unit::TestCase
3
+ class ActiveRecordTest < MiniTest::Test
4
4
  def setup
5
5
  @record = ModelStub.new
6
6
  end
@@ -10,22 +10,22 @@ class FormColumnHelpersTest < ActionView::TestCase
10
10
 
11
11
  def test_choices_for_select_form_ui_for_simple_column
12
12
  @column.options[:options] = [:value_1, :value_2, :value_3]
13
- assert_dom_equal "<select name=\"record[a]\" id=\"record_a\"><option value=\"value_1\">Value 1</option>\n<option value=\"value_2\">Value 2</option>\n<option value=\"value_3\">Value 3</option></select>", active_scaffold_input_select(@column, {})
13
+ assert_dom_equal "<select name=\"record[a]\" id=\"record_a\"><option value=\"value_1\">Value 1</option>\n<option value=\"value_2\">Value 2</option>\n<option value=\"value_3\">Value 3</option></select>", active_scaffold_input_select(@column, :object => @record)
14
14
 
15
15
  @column.options[:options] = %w(value_1 value_2 value_3)
16
- assert_dom_equal "<select name=\"record[a]\" id=\"record_a\"><option value=\"value_1\">value_1</option>\n<option value=\"value_2\">value_2</option>\n<option value=\"value_3\">value_3</option></select>", active_scaffold_input_select(@column, {})
16
+ assert_dom_equal "<select name=\"record[a]\" id=\"record_a\"><option value=\"value_1\">value_1</option>\n<option value=\"value_2\">value_2</option>\n<option value=\"value_3\">value_3</option></select>", active_scaffold_input_select(@column, :object => @record)
17
17
 
18
18
  @column.options[:options] = [%w(text_1 value_1), %w(text_2 value_2), %w(text_3 value_3)]
19
- assert_dom_equal "<select name=\"record[a]\" id=\"record_a\"><option value=\"value_1\">text_1</option>\n<option value=\"value_2\">text_2</option>\n<option value=\"value_3\">text_3</option></select>", active_scaffold_input_select(@column, {})
19
+ assert_dom_equal "<select name=\"record[a]\" id=\"record_a\"><option value=\"value_1\">text_1</option>\n<option value=\"value_2\">text_2</option>\n<option value=\"value_3\">text_3</option></select>", active_scaffold_input_select(@column, :object => @record)
20
20
 
21
21
  @column.options[:options] = [[:text_1, :value_1], [:text_2, :value_2], [:text_3, :value_3]]
22
- assert_dom_equal "<select name=\"record[a]\" id=\"record_a\"><option value=\"value_1\">Text 1</option>\n<option value=\"value_2\">Text 2</option>\n<option value=\"value_3\">Text 3</option></select>", active_scaffold_input_select(@column, {})
22
+ assert_dom_equal "<select name=\"record[a]\" id=\"record_a\"><option value=\"value_1\">Text 1</option>\n<option value=\"value_2\">Text 2</option>\n<option value=\"value_3\">Text 3</option></select>", active_scaffold_input_select(@column, :object => @record)
23
23
  end
24
24
 
25
25
  def test_options_for_select_form_ui_for_simple_column
26
26
  @column.options = {:include_blank => 'None', :selected => 'value_2', :disabled => %w(value_1 value_3)}
27
27
  @column.options[:options] = %w(value_1 value_2 value_3)
28
28
  @column.options[:html_options] = {:class => 'big'}
29
- assert_dom_equal "<select name=\"record[a]\" class=\"big\" id=\"record_a\"><option value=\"\">None</option>\n<option disabled=\"disabled\" value=\"value_1\">value_1</option>\n<option selected=\"selected\" value=\"value_2\">value_2</option>\n<option disabled=\"disabled\" value=\"value_3\">value_3</option></select>", active_scaffold_input_select(@column, {})
29
+ assert_dom_equal "<select name=\"record[a]\" class=\"big\" id=\"record_a\"><option value=\"\">None</option>\n<option disabled=\"disabled\" value=\"value_1\">value_1</option>\n<option selected=\"selected\" value=\"value_2\">value_2</option>\n<option disabled=\"disabled\" value=\"value_3\">value_3</option></select>", active_scaffold_input_select(@column, :object => @record)
30
30
  end
31
31
  end
@@ -1,3 +1,4 @@
1
+ #encoding: utf-8
1
2
  require 'test_helper'
2
3
 
3
4
  class ListColumnHelpersTest < ActionView::TestCase
@@ -11,7 +12,7 @@ class ListColumnHelpersTest < ActionView::TestCase
11
12
  @record = stub(:a => 'value_2')
12
13
  @config = stub(:list => stub(:empty_field_text => '-', :association_join_text => ', '))
13
14
  @association_column = ActiveScaffold::DataStructures::Column.new(:b, ModelStub)
14
- @association_column.stubs(:association).returns(stub(:macro => :has_many))
15
+ @association_column.stubs(:association).returns(stub(:collection? => true))
15
16
  end
16
17
 
17
18
  def test_options_for_select_list_ui_for_simple_column
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class PaginationHelpersTest < Test::Unit::TestCase
3
+ class PaginationHelpersTest < MiniTest::Test
4
4
  include ActiveScaffold::Helpers::PaginationHelpers
5
5
 
6
6
  def active_scaffold_config
@@ -1,7 +1,10 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class PermissionModel < ActiveRecord::Base
4
+ include ActiveScaffold::ActiveRecordPermissions::ModelUserAccess::Model
4
5
  def self.columns; [] end
6
+ def self.column_types; [] end
7
+ def self.columns_hash; {} end
5
8
 
6
9
  def authorized_for_read?; true; end
7
10
  def authorized_for_update?; false; end
@@ -50,7 +53,7 @@ class PermissionModel < ActiveRecord::Base
50
53
  #def c1_authorized_for_update?; end
51
54
  end
52
55
 
53
- class ActiveRecordPermissionsTest < Test::Unit::TestCase
56
+ class ActiveRecordPermissionsTest < MiniTest::Test
54
57
  def setup
55
58
  @model = PermissionModel.new
56
59
  end
@@ -59,7 +62,11 @@ class ActiveRecordPermissionsTest < Test::Unit::TestCase
59
62
  # columns are: crud_type method, column method, crud_type/column method
60
63
  # symbols are: is (a)bsent, returns (f)alse, returns (t)rue, or n/a (_)
61
64
  def test_method_combinations_with_default_true
62
- ActiveRecordPermissions.default_permission = true
65
+ old_permission = nil
66
+ ActiveScaffold.set_defaults do |config|
67
+ old_permission = config.security.default_permission
68
+ config.security.default_permission = true
69
+ end
63
70
 
64
71
  pass(@model.authorized_for?(:column => :a3), '_a_')
65
72
  fail(@model.authorized_for?(:column => :a2), '_f_')
@@ -98,10 +105,18 @@ class ActiveRecordPermissionsTest < Test::Unit::TestCase
98
105
  pass(@model.authorized_for?(:crud_type => :read, :column => :c1), 'tta')
99
106
  fail(@model.authorized_for?(:crud_type => :read, :column => :b1), 'ttf')
100
107
  pass(@model.authorized_for?(:crud_type => :read, :column => :a1), 'ttt')
108
+
109
+ ActiveScaffold.set_defaults do |config|
110
+ config.security.default_permission = old_permission
111
+ end
101
112
  end
102
113
 
103
114
  def test_method_combinations_with_default_false
104
- ActiveRecordPermissions.default_permission = false
115
+ old_permission = nil
116
+ ActiveScaffold.set_defaults do |config|
117
+ old_permission = config.security.default_permission
118
+ config.security.default_permission = false
119
+ end
105
120
 
106
121
  fail(@model.authorized_for?(:column => :a3), '_a_')
107
122
  fail(@model.authorized_for?(:column => :a2), '_f_')
@@ -140,6 +155,10 @@ class ActiveRecordPermissionsTest < Test::Unit::TestCase
140
155
  pass(@model.authorized_for?(:crud_type => :read, :column => :c1), 'tta')
141
156
  fail(@model.authorized_for?(:crud_type => :read, :column => :b1), 'ttf')
142
157
  pass(@model.authorized_for?(:crud_type => :read, :column => :a1), 'ttt')
158
+
159
+ ActiveScaffold.set_defaults do |config|
160
+ config.security.default_permission = old_permission
161
+ end
143
162
  end
144
163
 
145
164
  private
@@ -149,6 +168,6 @@ class ActiveRecordPermissionsTest < Test::Unit::TestCase
149
168
  end
150
169
 
151
170
  def fail(value, message = nil)
152
- assert !value, "#{message} should fail"
171
+ refute value, "#{message} should fail"
153
172
  end
154
173
  end
@@ -1,145 +1,313 @@
1
1
  require 'test_helper'
2
2
 
3
- class NumberModel < ActiveRecord::Base
4
- abstract_class = true
5
- def self.columns
6
- @columns ||= [ActiveRecord::ConnectionAdapters::Column.new('number', '', 'double(10,2)')]
3
+ class AttributeParamsTest < MiniTest::Test
4
+ def setup
5
+ @controller = Controller.new
6
+ end
7
+
8
+ def test_saving_simple_record
9
+ model = update_record_from_params(Person.new, :create, :first_name, :last_name, :first_name => 'First', :last_name => '')
10
+ assert_equal 'First', model.first_name
11
+ assert_nil model.last_name
12
+ assert model.buildings.blank?
13
+ assert model.save
14
+
15
+ model.buildings.create(:name => '1st building')
16
+ model = update_record_from_params(model, :update, :first_name, :last_name, :first_name => 'Name', :last_name => 'Last')
17
+ assert_equal 'Name', model.first_name
18
+ assert_equal 'Last', model.last_name
19
+ assert model.buildings.present?, 'buildings should not be cleared'
20
+ assert model.save
21
+ end
22
+
23
+ def test_saving_unexpected_column_is_ignored
24
+ model = Person.new(:first_name => 'First', :last_name => 'Last')
25
+ model.buildings.build(:name => '1st building')
26
+ assert model.save
27
+
28
+ model = update_record_from_params(model, :update, :first_name, :first_name => 'Name', :last_name => 'Surname')
29
+ assert_equal 'Name', model.first_name
30
+ assert_equal 'Last', model.last_name
31
+ assert model.buildings.present?, 'buildings should not be cleared'
32
+ assert model.save
33
+ end
34
+
35
+ def test_saving_multiparameter_attribute
36
+ model = update_record_from_params(Contact.new, :update, :first_name, :birthday, :first_name => 'Christopher', :last_name => 'Columbus', 'birthday(1i)' => '1451', 'birthday(2i)' => '10', 'birthday(3i)' => '31')
37
+ assert_equal 'Christopher', model.first_name
38
+ assert_equal Date.new(1451, 10, 31), model.birthday
39
+ end
40
+
41
+ def test_saving_has_many_select
42
+ buildings = 2.times.map { Building.create }
43
+ model = update_record_from_params(Person.new, :create, :first_name, :last_name, :buildings, :first_name => 'First', :last_name => '', :buildings => ['', *buildings.map{|b| b.id.to_s}]) # checkbox_list always add a hidden tag with empty value
44
+ assert_equal 'First', model.first_name
45
+ assert_nil model.last_name
46
+ assert_equal buildings.map(&:id), model.building_ids
47
+ assert_equal buildings, model.buildings
48
+ assert model.save
49
+
50
+ model = update_record_from_params(model, :update, :first_name, :last_name, :buildings, :first_name => 'Name', :last_name => 'Last', :buildings => ['']) { raise ActiveRecord::Rollback }
51
+ assert_equal 'Name', model.first_name
52
+ assert_equal 'Last', model.last_name
53
+ assert_equal [model.id]*2, buildings.map{|b| b.reload.owner_id}, 'owners should not be saved'
54
+ assert model.building_ids.blank?, 'buildings should be cleared'
55
+ assert model.buildings.blank?, 'buildings should be cleared'
56
+
57
+ model.reload
58
+ model = update_record_from_params(model, :update, :first_name, :last_name, :buildings, :first_name => 'Name', :last_name => 'Last', :buildings => [''])
59
+ assert_equal 'Name', model.first_name
60
+ assert_equal 'Last', model.last_name
61
+ assert model.building_ids.blank?, 'buildings should be cleared'
62
+ assert model.buildings.blank?, 'buildings should be cleared'
63
+ assert_equal [nil]*2, buildings.map{|b| b.reload.owner_id}, 'buildings should be saved'
64
+ assert model.save
65
+ end
66
+
67
+ def test_saving_belongs_to_select
68
+ person = Person.create
69
+ assert person.persisted?
70
+
71
+ model = update_record_from_params(Floor.new, :create, :number, :tenant, :number => '1', :tenant => person.id.to_s)
72
+ assert_equal 1, model.number
73
+ assert_equal person.id, model.tenant_id
74
+ assert_equal person, model.tenant
75
+ assert model.save
76
+
77
+ model = update_record_from_params(model, :update, :number, :tenant, :number => '1', :tenant => '')
78
+ assert_equal 1, model.number
79
+ assert_nil model.tenant_id, 'tenant should be cleared'
80
+ assert_nil model.tenant, 'tenant should be cleared'
81
+ assert_equal person.id, Floor.find(model).tenant_id, 'floor should not be saved yet'
82
+ assert model.save
83
+ assert_nil Floor.find(model).tenant_id, 'floor should not be saved'
84
+ end
85
+
86
+ def test_saving_has_one_select
87
+ floor = Floor.create
88
+ assert floor.persisted?
89
+
90
+ model = update_record_from_params(Person.new, :create, :first_name, :floor, :first_name => 'Name', :floor => floor.id.to_s)
91
+ assert_equal 'Name', model.first_name
92
+ assert model.floor.present?
93
+ assert_equal floor.id, model.floor.id
94
+ assert_nil floor.reload.tenant_id, 'tenant_id should not be saved yet'
95
+ assert model.save
96
+ assert_equal model.id, floor.reload.tenant_id, 'tenant_id should be saved'
97
+
98
+ model = update_record_from_params(model, :update, :first_name, :floor, :first_name => 'First', :floor => '') { raise ActiveRecord::Rollback }
99
+ assert_equal 'First', model.first_name
100
+ assert_equal model.id, floor.reload.tenant_id, 'previous car should not be saved and nullified'
101
+ assert_nil model.floor, 'floor should be cleared'
102
+
103
+ model.reload
104
+ model = update_record_from_params(model, :update, :first_name, :floor, :first_name => 'First', :floor => '')
105
+ assert_equal 'First', model.first_name
106
+ assert_nil floor.reload.tenant_id, 'previous car should be saved and nullified'
107
+ assert_nil model.floor, 'floor should be cleared'
108
+ assert model.save
109
+ end
110
+
111
+ def test_saving_has_one_through_select
112
+ building = Building.create
113
+ assert building.persisted?
114
+ assert building.floors.create(:number => 2)
115
+
116
+ model = update_record_from_params(Person.new, :create, :first_name, :home, :first_name => 'Name', :home => building.id.to_s)
117
+ assert_equal 'Name', model.first_name
118
+ assert model.home.present?
119
+ assert model.floor.present?
120
+ assert_equal [nil], building.floors(true).map(&:tenant_id), 'floor should not be saved yet'
121
+ assert model.save
122
+ assert_equal model.id, model.floor.tenant_id, 'tenant_id should be saved'
123
+ assert_equal [nil, model.id], building.floors(true).map(&:tenant_id)
124
+
125
+ model = update_record_from_params(model, :update, :first_name, :home, :first_name => 'First', :home => '') { raise ActiveRecord::Rollback }
126
+ assert_equal 'First', model.first_name
127
+ assert_equal [nil, model.id], building.floors(true).map(&:tenant_id), 'previous floor should not be deleted'
128
+ assert_nil model.home, 'home should be cleared'
129
+
130
+ model.reload
131
+ model = update_record_from_params(model, :update, :first_name, :home, :first_name => 'First', :home => '')
132
+ assert_equal 'First', model.first_name
133
+ assert_equal [nil], building.floors(true).map(&:tenant_id), 'previous floor should be deleted'
134
+ assert_nil model.home, 'home should be cleared'
135
+ assert model.save
136
+ end
137
+
138
+ def test_saving_has_many_through_select
139
+ people = 2.times.map { Person.create }
140
+ assert people.all?(&:persisted?)
141
+
142
+ model = update_record_from_params(Building.new, :create, :name, :tenants, :name => 'Tower', :tenants => ['', *people.map{|b| b.id.to_s}]) # checkbox_list always add a hidden tag with empty value
143
+ assert_equal 'Tower', model.name
144
+ assert model.tenants.present?
145
+ assert_equal [nil]*2, people.map {|p| p.floor(true)}, 'floor should not be saved yet'
146
+ assert model.save
147
+ assert_equal [model.id]*2, model.floors.map(&:building_id)
148
+ assert_equal [model.id]*2, people.map {|p| p.floor(true).building_id}, 'floor should be saved'
149
+
150
+ model = update_record_from_params(model, :update, :name, :tenants, :name => 'Skyscrapper', :tenants => ['']) { raise ActiveRecord::Rollback }
151
+ assert_equal 'Skyscrapper', model.name
152
+ assert_equal [model.id]*2, people.map {|p| p.floor(true).building_id}, 'previous floor should not be deleted'
153
+ assert model.tenants.empty?, 'tenants should be cleared'
154
+
155
+ model.reload
156
+ model = update_record_from_params(model, :update, :name, :tenants, :name => 'Skyscrapper', :tenants => [''])
157
+ assert_equal 'Skyscrapper', model.name
158
+ assert_equal [nil]*2, people.map {|p| p.floor(true)}, 'previous floor should be deleted'
159
+ assert model.tenants.empty?, 'tenants should be cleared'
160
+ assert model.save
161
+ end
162
+
163
+ def test_saving_has_many_crud_with_error
164
+ building = Building.create(:name => 'First')
165
+ key = Time.now.to_i.to_s
166
+ floors = {'0' => '', key => {:number => '', 'tenant' => '', :number_required => true}}
167
+ model = update_record_from_params(building, :create, :name, :floors, :name => 'First', :floors => floors)
168
+ assert_equal 'First', model.name
169
+ assert_equal 1, model.floors.size
170
+ assert model.floors.first.errors.present?
171
+ refute model.floors.first.persisted?
172
+ end
173
+
174
+ def test_saving_has_many_crud_and_belongs_to_select
175
+ floor = Floor.create
176
+ people = 2.times.map { Person.create }
177
+ key = Time.now.to_i.to_s
178
+ floors = {'0' => '', '1' => {:number => '1', :tenant => '', :id => floor.id.to_s}, key => {:number => '2', 'tenant' => people.first.id.to_s}, key.succ => {:number => '4', 'tenant' => people.last.id.to_s}}
179
+ model = update_record_from_params(Building.new, :create, :name, :floors, :name => 'First', :floors => floors)
180
+ assert_equal 'First', model.name
181
+ assert_equal 3, model.floors.size
182
+ assert_equal floor.id, model.floors.first.id
183
+ assert_equal [nil, *people.map(&:id)], model.floors.map(&:tenant_id)
184
+ assert model.save
185
+
186
+ model = update_record_from_params(model, :update, :name, :floors, :name => 'Tower', :floors => {'0' => ''})
187
+ assert_equal 'Tower', model.name
188
+ assert model.floors.blank?, 'floors should be cleared'
189
+ assert model.save
190
+ end
191
+
192
+ def test_saving_belongs_to_crud
193
+ person = Person.create
194
+ assert person.persisted?
195
+
196
+ model = update_record_from_params(Car.new, :create, :brand, :person, :brand => 'Ford', :person => {:first_name => 'First'})
197
+ assert_equal 'Ford', model.brand
198
+ assert model.person.present?
199
+ assert model.person.new_record?
200
+ assert model.save
201
+ assert model.person.persisted?
202
+
203
+ model = update_record_from_params(model, :update, :brand, :person, :brand => 'Ford', :person => {:first_name => 'First', :id => person.id.to_s})
204
+ assert_equal 'Ford', model.brand
205
+ assert model.person.present?
206
+ assert_equal person.id, model.person.id
207
+ assert model.save
208
+
209
+ model = update_record_from_params(model, :update, :brand, :person, :brand => 'Mercedes', :person => {:first_name => ''})
210
+ assert_equal 'Mercedes', model.brand
211
+ assert model.person.blank?, 'person should be cleared'
212
+ assert model.save
213
+ end
214
+
215
+ def test_saving_has_one_crud
216
+ car = Car.create :brand => 'Renault'
217
+ assert car.persisted?
218
+
219
+ model = update_record_from_params(Person.new, :create, :first_name, :car, :first_name => 'First', :car => {:brand => 'Ford'})
220
+ assert_equal 'First', model.first_name
221
+ assert model.car.present?
222
+ assert model.car.new_record?
223
+ assert model.save
224
+ assert model.car.persisted?
225
+
226
+ model = update_record_from_params(Person.new, :create, :first_name, :car, :first_name => 'First', :car => {:brand => 'Peugeot', :id => car.id.to_s})
227
+ assert_equal 'First', model.first_name
228
+ assert model.car.present?
229
+ assert_equal car.id, model.car.id
230
+ assert_nil car.reload.person_id, 'person_id should not be saved yet'
231
+ assert_equal 'Peugeot', model.car.brand
232
+ assert_equal 'Renault', car.reload.brand, 'brand should not be saved yet'
233
+ assert model.save
234
+ assert_equal model.id, car.reload.person_id, 'person_id should be saved'
235
+
236
+ model = update_record_from_params(model, :update, :first_name, :car, :first_name => 'First', :car => {:brand => 'Mercedes', :id => car.id.to_s})
237
+ assert_equal 'First', model.first_name
238
+ assert model.car.present?
239
+ assert_equal 'Mercedes', model.car.brand
240
+ assert model.save
241
+ assert model.save_associated
242
+ assert_equal 'Mercedes', car.reload.brand, 'brand should be saved'
243
+
244
+ model = update_record_from_params(model, :update, :first_name, :car, :first_name => 'First', :car => {:brand => 'Mercedes'})
245
+ assert_equal 'First', model.first_name
246
+ assert_nil Car.where(:id => car.id).first, 'previous car should be deleted'
247
+ assert model.car.present?
248
+ refute_equal car.id, model.car.id
249
+ assert model.save
250
+
251
+ car = model.car.reload
252
+ model = update_record_from_params(model, :update, :first_name, :car, :first_name => 'Name', :car => {:brand => ''})
253
+ assert_equal 'Name', model.first_name
254
+ assert_nil Car.where(:id => car.id).first, 'previous car should be deleted'
255
+ assert model.car.blank?, 'car should be cleared'
256
+ assert model.save
257
+ end
258
+
259
+ def test_saving_belongs_to_polymorphic_select
260
+ person = Person.create
261
+ assert person.persisted?
262
+
263
+ model = update_record_from_params(Contact.new, :create, :first_name, :contactable_type, :contactable, :first_name => 'First', :contactable_type => person.class.name, :contactable => person.id.to_s)
264
+ assert_equal 'First', model.first_name
265
+ assert_equal person.class.name, model.contactable_type
266
+ assert_equal person.id, model.contactable_id
267
+ assert_equal person, model.contactable
268
+ assert model.save
269
+
270
+ model = update_record_from_params(model, :update, :first_name, :contactable_type, :contactable, :first_name => 'Name', :contactable_type => person.class.name, :contactable => '')
271
+ assert_equal 'Name', model.first_name
272
+ assert_nil model.contactable_type
273
+ assert_nil model.contactable_id, 'contactable should be cleared'
274
+ assert_nil model.contactable, 'contactable should be cleared'
275
+ assert_equal person.id, Contact.find(model).contactable_id, 'contact should not be saved yet'
276
+ assert model.save
277
+ assert_nil Contact.find(model).contactable_id, 'contact should be saved'
278
+ end
279
+
280
+ protected
281
+ MODELS = [Address, Building, Car, Contact, Floor, Person]
282
+ def update_record_from_params(record, action, *columns, &block)
283
+ params = columns.extract_options!.with_indifferent_access
284
+ new_record = nil
285
+ record.class.transaction do
286
+ new_record = @controller.update_record_from_params(record, build_action_columns(record, action, columns), params)
287
+ MODELS.each { |model| model.any_instance.unstub(:save) }
288
+ yield if block_given?
289
+ Thread.current[:constraint_columns] = nil
290
+ end
291
+ new_record
292
+ end
293
+
294
+ def build_action_columns(record, action, *columns)
295
+ controller = ActiveScaffold::Core.active_scaffold_controller_for record.class
296
+ controller.active_scaffold_config.send(action).columns = columns
297
+ controller.active_scaffold_config.send(action).columns
7
298
  end
8
299
  end
9
300
 
10
- class AttributeParamsTest < Test::Unit::TestCase
301
+ class Controller
302
+ def self.helper_method(*args); end
303
+ def self.before_filter(*args); end
304
+
305
+ include ActiveScaffold::Core
306
+ include ActiveScaffold::Helpers::ControllerHelpers
11
307
  include ActiveScaffold::AttributeParams
12
- include ActiveScaffold::Finder
308
+ public :update_record_from_params
13
309
 
14
- def setup
15
- I18n.backend.store_translations :en, :number => {:format => {
16
- :delimiter => ',',
17
- :separator => '.'
18
- }}
19
- I18n.backend.store_translations :es, :number => {:format => {
20
- :delimiter => '.',
21
- :separator => ','
22
- }}
23
- I18n.backend.store_translations :ru, :number => {:currency => {
24
- :format => {
25
- :separator => ',',
26
- :delimiter => ''
27
- }
28
- }}
29
-
30
- @config = config_for('number_model')
31
- @config.columns[:number].form_ui = nil
32
- @config.list.columns.set_columns @config.columns
33
- end
34
-
35
- def teardown
36
- I18n.locale = :en
37
- end
38
-
39
- def test_english_format_with_decimal_separator_using_english_language
40
- I18n.locale = :en
41
- assert_equal 0.1, convert_number('.1')
42
- assert_equal 0.1, convert_number('.100')
43
- assert_equal 0.1, convert_number('0.1')
44
- assert_equal 0.345, convert_number('0.345')
45
- assert_equal 0.345, convert_number('+0.345')
46
- assert_equal -0.345, convert_number('-0.345')
47
- assert_equal 9.345, convert_number('9.345')
48
- assert_equal 9.1, convert_number('9.1')
49
- assert_equal 90.1, convert_number('90.1')
50
- end
51
-
52
- def test_english_format_with_thousand_delimiter_using_english_language
53
- I18n.locale = :en
54
- assert_equal 1000, convert_number('1,000')
55
- assert_equal 1000, convert_number('+1,000')
56
- assert_equal -1000, convert_number('-1,000')
57
- assert_equal 1000000, convert_number('1,000,000')
58
- end
59
-
60
- def test_english_format_with_separator_and_delimiter_using_english_language
61
- I18n.locale = :en
62
- assert_equal 1234.1, convert_number('1,234.1')
63
- assert_equal 1234.1, convert_number('1,234.100')
64
- assert_equal 1234.345, convert_number('+1,234.345')
65
- assert_equal -1234.345, convert_number('-1,234.345')
66
- assert_equal 1234000.1, convert_number('1,234,000.100')
67
- end
68
-
69
- def test_english_format_with_decimal_separator_using_spanish_language
70
- I18n.locale = :es
71
- assert_equal 0.1, convert_number('.1')
72
- assert_equal 0.1, convert_number('0.1')
73
- assert_equal 0.12, convert_number('+0.12')
74
- assert_equal -0.12, convert_number('-0.12')
75
- assert_equal 9.1, convert_number('9.1')
76
- assert_equal 90.1, convert_number('90.1')
77
- end
78
-
79
- def test_spanish_format_with_decimal_separator_using_spanish_language
80
- I18n.locale = :es
81
- assert_equal 0.1, convert_number(',1')
82
- assert_equal 0.1, convert_number(',100')
83
- assert_equal 0.1, convert_number('0,1')
84
- assert_equal 0.345, convert_number('0,345')
85
- assert_equal 0.345, convert_number('+0,345')
86
- assert_equal -0.345, convert_number('-0,345')
87
- assert_equal 9.1, convert_number('9,1')
88
- assert_equal 90.1, convert_number('90,1')
89
- assert_equal 9.1, convert_number('9,100')
90
- end
91
-
92
- def test_spanish_format_with_thousand_delimiter_using_spanish_language
93
- I18n.locale = :es
94
- assert_equal 1000, convert_number('1.000')
95
- assert_equal 1000, convert_number('+1.000')
96
- assert_equal -1000, convert_number('-1.000')
97
- assert_equal 1000000, convert_number('1.000.000')
98
- end
99
-
100
- def test_spanish_format_with_separator_and_decimal_using_spanish_language
101
- I18n.locale = :es
102
- assert_equal 1230.1, convert_number('1.230,1')
103
- assert_equal 1230.1, convert_number('1.230,100')
104
- assert_equal 1234.345, convert_number('+1.234,345')
105
- assert_equal -1234.345, convert_number('-1.234,345')
106
- assert_equal 1234000.1, convert_number('1.234.000,100')
107
- end
108
-
109
- def test_english_currency_format_with_decimal_separator_using_russian_language
110
- I18n.locale = :ru
111
- assert_equal 0.1, convert_number('.1', :currency)
112
- assert_equal 0.1, convert_number('0.1', :currency)
113
- assert_equal 0.12, convert_number('+0.12', :currency)
114
- assert_equal -0.12, convert_number('-0.12', :currency)
115
- assert_equal 9.1, convert_number('9.1', :currency)
116
- assert_equal 90.1, convert_number('90.1', :currency)
117
- end
118
-
119
- def test_russian_currency_format_with_decimal_separator_using_russian_language
120
- I18n.locale = :ru
121
- assert_equal 0.1, convert_number(',1', :currency)
122
- assert_equal 0.1, convert_number(',100', :currency)
123
- assert_equal 0.1, convert_number('0,1', :currency)
124
- assert_equal 0.345, convert_number('0,345', :currency)
125
- assert_equal 0.345, convert_number('+0,345', :currency)
126
- assert_equal -0.345, convert_number('-0,345', :currency)
127
- assert_equal 9.1, convert_number('9,1', :currency)
128
- assert_equal 90.1, convert_number('90,1', :currency)
129
- assert_equal 9.1, convert_number('9,100', :currency)
130
- end
131
-
132
- def test_english_format_with_decimal_separator_with_no_localized_format
133
- I18n.locale = :ru
134
- assert_equal 0.1, convert_number('.1')
135
- assert_equal 0.1, convert_number('0.1')
136
- end
137
-
138
- private
139
- def convert_number(value, format = nil)
140
- record = NumberModel.new
141
- @config.columns[:number].options[:format] = format unless format.nil?
142
- update_record_from_params(record, @config.list.columns, HashWithIndifferentAccess.new({:number => value}))
143
- record.number
310
+ def logger
311
+ @logger ||= Logger.new(STDOUT)
144
312
  end
145
313
  end