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
@@ -12,6 +12,9 @@ module ActiveScaffold::DataStructures
12
12
  def label
13
13
  as_(@label) if @label
14
14
  end
15
+ def name
16
+ @label.to_s.underscore
17
+ end
15
18
  def css_class
16
19
  @label.to_s.underscore
17
20
  end
@@ -124,9 +127,22 @@ module ActiveScaffold::DataStructures
124
127
  end
125
128
  end
126
129
 
127
- attr_writer :constraint_columns
130
+ def action_name
131
+ @action.class.name.demodulize.underscore
132
+ end
133
+
134
+ def constraint_columns_key
135
+ "#{@action.core.model_id.to_s.underscore}-#{action_name}"
136
+ end
137
+
138
+ def constraint_columns=(columns)
139
+ Thread.current[:constraint_columns] ||= {}
140
+ Thread.current[:constraint_columns][constraint_columns_key] = columns
141
+ end
142
+
128
143
  def constraint_columns
129
- @constraint_columns ||= []
144
+ constraints = Thread.current[:constraint_columns]
145
+ (constraints[constraint_columns_key] if constraints) || []
130
146
  end
131
147
 
132
148
  attr_writer :unauthorized_columns
@@ -13,19 +13,27 @@ module ActiveScaffold::DataStructures
13
13
  self.crud_type = :create if [:create, :new].include?(action.try(:to_sym))
14
14
  self.crud_type = :update if [:edit, :update].include?(action.try(:to_sym))
15
15
  self.crud_type ||= :read
16
- self.parameters = {}
17
- self.html_options = {}
18
16
  self.column = nil
19
17
  self.image = nil
20
18
  self.dynamic_parameters = nil
19
+ self.weight = 0
21
20
 
22
21
  # apply quick properties
23
22
  options.each_pair do |k, v|
24
23
  setter = "#{k}="
25
24
  self.send(setter, v) if self.respond_to? setter
26
25
  end
26
+ self.toggle = self.action.try(:to_sym) == :index && (parameters.present? || dynamic_parameters) unless options.include? :toggle
27
27
  end
28
28
 
29
+ def initialize_copy(action_link)
30
+ self.parameters = self.parameters.clone if action_link.instance_variable_get(:@parameters)
31
+ self.html_options = self.html_options.clone if action_link.instance_variable_get(:@html_options)
32
+ end
33
+
34
+ # the weight for this link in the action links collection, it will be used to sort the collection
35
+ attr_accessor :weight
36
+
29
37
  # the action-path for this link. what page to request? this is required!
30
38
  attr_accessor :action
31
39
 
@@ -42,7 +50,15 @@ module ActiveScaffold::DataStructures
42
50
  end
43
51
 
44
52
  # a hash of request parameters
45
- attr_accessor :parameters
53
+ attr_writer :parameters
54
+ def parameters
55
+ @parameters ||= {}
56
+ end
57
+
58
+ # if active class is added to link when current request matches link
59
+ # enabled automatically for links to index with parameters or dynamic parameters
60
+ # disable when is not needed so current request match check is skipped
61
+ attr_accessor :toggle
46
62
 
47
63
  # a block for dynamic_parameters
48
64
  attr_accessor :dynamic_parameters
@@ -167,7 +183,10 @@ module ActiveScaffold::DataStructures
167
183
  attr_accessor :type
168
184
 
169
185
  # html options for the link
170
- attr_accessor :html_options
186
+ attr_writer :html_options
187
+ def html_options
188
+ @html_options ||= {}
189
+ end
171
190
 
172
191
  # nested action_links are referencing a column
173
192
  attr_accessor :column
@@ -183,8 +202,8 @@ module ActiveScaffold::DataStructures
183
202
  @column || (parameters && parameters[:named_scope])
184
203
  end
185
204
 
186
- def name_to_cache_link_url
187
- @name_to_cache_link_url ||= :"#{controller || 'self'}_#{action}#{'_' if parameters.present?}#{parameters.map{|k,v| "#{k}_#{v}"}.join('_')}_link_url"
205
+ def name_to_cache
206
+ @name_to_cache ||= "#{controller || 'self'}_#{type}_#{action}#{'_' if parameters.present?}#{parameters.map{|k,v| "#{k}=#{v.is_a?(Array) ? v.join(',') : v}"}.join('_')}"
188
207
  end
189
208
 
190
209
 
@@ -5,6 +5,7 @@ module ActiveScaffold::DataStructures
5
5
  def initialize
6
6
  @set = []
7
7
  @name = :root
8
+ @weight = 0
8
9
  end
9
10
 
10
11
  # adds an ActionLink, creating one from the arguments if need be
@@ -72,6 +73,7 @@ module ActiveScaffold::DataStructures
72
73
  self.each({:include_set => true}) do |link, set|
73
74
  if link.action.to_s == val.to_s
74
75
  set.delete link
76
+ break
75
77
  end
76
78
  end
77
79
  end
@@ -80,8 +82,10 @@ module ActiveScaffold::DataStructures
80
82
  @set.each do |group|
81
83
  if group.name == name
82
84
  @set.delete group
85
+ break
83
86
  else
84
87
  group.delete_group(name)
88
+ break
85
89
  end if group.is_a?(ActiveScaffold::DataStructures::ActionLinks)
86
90
  end
87
91
  end
@@ -89,7 +93,7 @@ module ActiveScaffold::DataStructures
89
93
  # iterates over the links, possibly by type
90
94
  def each(options = {}, &block)
91
95
  method = options[:reverse] ? :reverse_each : :each
92
- @set.send(method) do |item|
96
+ @set.sort_by(&:weight).send(method) do |item|
93
97
  if item.is_a?(ActiveScaffold::DataStructures::ActionLinks) && !options[:groups]
94
98
  item.each(options, &block)
95
99
  else
@@ -138,16 +142,17 @@ module ActiveScaffold::DataStructures
138
142
 
139
143
  def method_missing(name, *args, &block)
140
144
  class_eval %{
141
- def #{name}
142
- @#{name} ||= subgroup('#{name}'.to_sym)
145
+ def #{name}(label = nil)
146
+ @#{name} ||= subgroup('#{name}'.to_sym, label)
143
147
  yield @#{name} if block_given?
144
148
  @#{name}
145
149
  end
146
150
  }
147
- send(name, &block)
151
+ send(name, args.first, &block)
148
152
  end
149
153
 
150
154
  attr_accessor :name
155
+ attr_accessor :weight
151
156
 
152
157
  protected
153
158
 
@@ -21,7 +21,7 @@ class ActiveScaffold::DataStructures::Actions
21
21
  end
22
22
 
23
23
  def include?(val)
24
- super val.to_sym
24
+ val.is_a?(Symbol) ? super : @set.any?{|item| item.to_s == val.to_s}
25
25
  end
26
26
 
27
27
  # swaps one element in the list with the other.
@@ -260,16 +260,16 @@ module ActiveScaffold::DataStructures
260
260
  # the association from the ActiveRecord class
261
261
  attr_reader :association
262
262
  def singular_association?
263
- self.association and [:has_one, :belongs_to].include? self.association.macro
263
+ self.association and !self.association.collection?
264
264
  end
265
265
  def plural_association?
266
- self.association and [:has_many, :has_and_belongs_to_many].include? self.association.macro
266
+ self.association and self.association.collection?
267
267
  end
268
268
  def through_association?
269
269
  self.association and self.association.options[:through]
270
270
  end
271
271
  def polymorphic_association?
272
- self.association and self.association.options.has_key? :polymorphic and self.association.options[:polymorphic]
272
+ self.association and self.association.options[:polymorphic]
273
273
  end
274
274
  def readonly_association?
275
275
  if self.association
@@ -324,14 +324,14 @@ module ActiveScaffold::DataStructures
324
324
  elsif polymorphic_association?
325
325
  [field, quoted_field(@active_record_class.connection.quote_column_name(@association.foreign_type))]
326
326
  elsif @association
327
- if self.association.macro == :belongs_to
327
+ if self.association.belongs_to?
328
328
  [field]
329
329
  else
330
330
  columns = []
331
331
  if active_record_class.columns_hash[count_column = "#{@association.name}_count"]
332
332
  columns << quoted_field(@active_record_class.connection.quote_column_name(count_column))
333
333
  end
334
- if @association.through_reflection.try(:macro) == :belongs_to
334
+ if @association.through_reflection.try(:belongs_to?)
335
335
  columns << quoted_field(@active_record_class.connection.quote_column_name(@association.through_reflection.foreign_key))
336
336
  end
337
337
  columns
@@ -350,7 +350,7 @@ module ActiveScaffold::DataStructures
350
350
  self.css_class = ''
351
351
  self.required = active_record_class.validators_on(self.name).any? do |val|
352
352
  !val.options[:if] && !val.options[:unless] && (ActiveModel::Validations::PresenceValidator === val ||
353
- (ActiveModel::Validations::InclusionValidator === val && !val.options[:allow_nil] && !val.options[:allow_blank])
353
+ (ActiveModel::Validations::InclusionValidator === val && !val.options[:allow_nil] && !val.options[:allow_blank] && !(@form_ui == :checkbox && [[true, false], [false, true]].include?(val.send(:delimiter))))
354
354
  )
355
355
  end
356
356
  self.sort = true
@@ -42,7 +42,7 @@ module ActiveScaffold::DataStructures
42
42
 
43
43
  def exclude(*args)
44
44
  # only remove columns from _inheritable. we never want to completely forget about a column.
45
- args.each { |a| @_inheritable.delete a }
45
+ args.each { |a| @_inheritable.delete a.to_sym }
46
46
  end
47
47
 
48
48
  # returns an array of columns with the provided names
@@ -72,4 +72,4 @@ module ActiveScaffold::DataStructures
72
72
  end
73
73
  end
74
74
  end
75
- end
75
+ end
@@ -119,7 +119,11 @@ module ActiveScaffold::DataStructures
119
119
  end
120
120
 
121
121
  def default_sorting
122
- association.options[:order]
122
+ if association.options[:order] # TODO remove when rails 3 compatibility is removed
123
+ association.options[:order]
124
+ elsif association.respond_to?(:scope) # rails 4
125
+ association.klass.class_eval(&association.scope).values[:order] if association.scope.is_a? Proc
126
+ end
123
127
  end
124
128
 
125
129
  def to_params
@@ -13,15 +13,17 @@ module ActiveScaffold::DataStructures
13
13
 
14
14
  def set_default_sorting(model)
15
15
  model_scope = model.send(:build_default_scope)
16
- order_clause = model_scope.arel.order_clauses.join(",") if model_scope
16
+ order_clause = model_scope.order_values.join(",") if model_scope
17
17
 
18
- # If an ORDER BY clause is found set default sorting according to it, else
19
18
  # fallback to setting primary key ordering
19
+ if model.column_names.include?(model.primary_key)
20
+ set(model.primary_key, 'ASC')
21
+ @sorting_by_primary_key = clause
22
+ end
23
+ # If an ORDER BY clause is found set default sorting according to it
20
24
  if order_clause
21
25
  set_sorting_from_order_clause(order_clause, model.table_name)
22
26
  @default_sorting = true
23
- else
24
- set(model.primary_key, 'ASC') if model.column_names.include?(model.primary_key)
25
27
  end
26
28
  end
27
29
 
@@ -69,6 +71,13 @@ module ActiveScaffold::DataStructures
69
71
  clause[1]
70
72
  end
71
73
 
74
+ SORTING_STAGES = Hash[%w(reset ASC DESC reset).each_cons(2).map{|a|a}].freeze
75
+ DEFAULT_SORTING_STAGES = Hash[%w(ASC DESC ASC).each_cons(2).map{|a|a}].freeze
76
+ def next_sorting_of(column, sorted_by_default)
77
+ stages = sorted_by_default ? DEFAULT_SORTING_STAGES : SORTING_STAGES
78
+ stages[direction_of(column)] || 'ASC'
79
+ end
80
+
72
81
  # checks whether any column is configured to sort by method (using a proc)
73
82
  def sorts_by_method?
74
83
  @clauses.any? { |sorting| sorting[0].sort.is_a? Hash and sorting[0].sort.has_key? :method }
@@ -102,6 +111,7 @@ module ActiveScaffold::DataStructures
102
111
  order << Array(sql).map {|column| "#{column} #{sort_direction}"}.join(', ')
103
112
  end
104
113
 
114
+ order << @sorting_by_primary_key if @sorting_by_primary_key # mandatory for postgres
105
115
  order unless order.empty?
106
116
  end
107
117
 
@@ -135,7 +145,7 @@ module ActiveScaffold::DataStructures
135
145
  order_clause.to_s.split(',').each do |criterion|
136
146
  unless criterion.blank?
137
147
  order_parts = extract_order_parts(criterion)
138
- add(order_parts[:column_name], order_parts[:direction]) unless different_table?(model_table_name, order_parts[:table_name])
148
+ add(order_parts[:column_name], order_parts[:direction]) unless different_table?(model_table_name, order_parts[:table_name]) || get_column(order_parts[:column_name]).nil?
139
149
  end
140
150
  end
141
151
  end
@@ -0,0 +1,30 @@
1
+ module ActiveScaffold
2
+ module DelayedSetup
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ def process(*)
8
+ self.class.config_active_scaffold_delayed
9
+ super
10
+ end
11
+
12
+ module ClassMethods
13
+ def active_scaffold(model_id = nil, &block)
14
+ @active_scaffold_delayed = proc{ super(model_id, &block) }
15
+ end
16
+
17
+ def config_active_scaffold_delayed
18
+ if @active_scaffold_delayed
19
+ block, @active_scaffold_delayed = @active_scaffold_delayed, nil
20
+ block.call
21
+ end
22
+ end
23
+
24
+ def active_scaffold_config
25
+ config_active_scaffold_delayed
26
+ super
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,4 +1,29 @@
1
1
  module ActiveScaffold
2
2
  class Engine < ::Rails::Engine
3
+ initializer "active_scaffold.action_controller" do |app|
4
+ ActiveSupport.on_load :action_controller do
5
+ include ActiveScaffold::Core
6
+ include ActiveScaffold::DelayedSetup if ActiveScaffold.delayed_setup
7
+ include ActiveScaffold::RespondsToParent
8
+ include ActiveScaffold::Helpers::ControllerHelpers
9
+ include ActiveScaffold::ActiveRecordPermissions::ModelUserAccess::Controller
10
+ end
11
+ end
12
+
13
+ initializer "active_scaffold.action_view" do |app|
14
+ ActiveSupport.on_load :action_view do
15
+ include ActiveScaffold::Helpers::ViewHelpers
16
+ end
17
+ end
18
+
19
+ initializer "active_scaffold.active_record" do |app|
20
+ ActiveSupport.on_load :active_record do
21
+ include ActiveScaffold::ActiveRecordPermissions::ModelUserAccess::Model
22
+ ActiveRecord::Associations::Association.send :include, ActiveScaffold::Tableless::Association
23
+ ActiveRecord::Associations::CollectionAssociation.send :include, ActiveScaffold::Tableless::CollectionAssociation
24
+ ActiveRecord::Associations::SingularAssociation.send :include, ActiveScaffold::Tableless::SingularAssociation
25
+ end
26
+ end
27
+
3
28
  end
4
29
  end
@@ -80,7 +80,7 @@ module ActionView::Helpers #:nodoc:
80
80
  if ActiveScaffold.js_framework == :prototype
81
81
  javascript_tag("new Ajax.Updater('#{id}', '#{url}', {method: 'get', evalScripts: true});")
82
82
  elsif ActiveScaffold.js_framework == :jquery
83
- javascript_tag("jQuery('##{id}').load('#{url}', function() { $(this).trigger('as:element_updated'); });")
83
+ javascript_tag("jQuery('##{id}').load('#{url}', function() { jQuery(this).trigger('as:element_updated'); });")
84
84
  end
85
85
  end
86
86
  end
@@ -1,33 +1,73 @@
1
1
  module ActiveScaffold
2
2
  module OuterJoins
3
- def outer_joins(*assocs)
4
- joins(outer_joins_sql(*assocs))
3
+ extend ActiveSupport::Concern
4
+ attr_accessor :outer_joins_values
5
+
6
+ if Rails::VERSION::MAJOR < 4
7
+ included do
8
+ const_get(:MULTI_VALUE_METHODS) << :outer_joins
9
+ end
10
+
11
+ def outer_joins(*args)
12
+ return self if args.compact.blank?
13
+
14
+ relation = clone
15
+
16
+ args.flatten!
17
+ relation.joins_values += [''] # HACK for using outer_joins in update_all/delete_all
18
+ relation.outer_joins_values += args
19
+
20
+ relation
21
+ end
22
+ else
23
+ def outer_joins_values
24
+ @values[:outer_joins] || []
25
+ end
26
+
27
+ def outer_joins_values=(values)
28
+ raise ImmutableRelation if @loaded
29
+ @values[:outer_joins] = values
30
+ end
31
+
32
+ def outer_joins(*args)
33
+ check_if_method_has_arguments!("outer_joins", args)
34
+ spawn.outer_joins!(*args.compact.flatten)
35
+ end
36
+
37
+ def outer_joins!(*args)
38
+ self.joins_values += [''] # HACK for using outer_joins in update_all/delete_all
39
+ self.outer_joins_values += args
40
+ self
41
+ end
5
42
  end
6
43
 
7
- private
8
- def outer_joins_sql(*assocs)
9
- assocs.collect do |assoc|
10
- if assoc.is_a? Array
11
- outer_joins_sql(*assoc)
12
- elsif assoc.is_a? Hash
13
- assoc.collect do |key, val|
14
- [left_outer_join_sql(key), klass.reflect_on_association(key).klass.outer_joins_sql(*val)]
44
+ if Rails.version < '4.1'
45
+ def build_arel
46
+ unless outer_joins_values.empty?
47
+ relation = self.except(:outer_joins)
48
+ join_dependency = ActiveRecord::Associations::JoinDependency.new(@klass, outer_joins_values, [])
49
+ join_dependency.join_associations.each do |association|
50
+ relation = association.join_relation(relation)
15
51
  end
16
- elsif assoc.is_a? Symbol
17
- left_outer_join_sql(assoc)
18
- elsif assoc
19
- assoc
52
+ relation.build_arel
53
+ else
54
+ super
20
55
  end
21
- end.flatten.compact
22
- end
23
-
24
- def left_outer_join_sql(association_name)
25
- t = ActiveRecord::Associations::JoinDependency.new(klass, association_name, []).join_associations.first.join_relation(klass).arel
26
- t.joins(t)
56
+ end
57
+ else
58
+ def build_arel
59
+ unless outer_joins_values.empty?
60
+ relation = self.except(:outer_joins)
61
+ relation.joins! ActiveRecord::Associations::JoinDependency.new(@klass, outer_joins_values, [])
62
+ relation.build_arel
63
+ else
64
+ super
65
+ end
66
+ end
27
67
  end
28
68
  end
29
69
  end
30
70
  ActiveRecord::Relation.send :include, ActiveScaffold::OuterJoins
31
71
  module ActiveRecord::Querying
32
- delegate :outer_joins, :outer_joins_sql, :to => :scoped
72
+ delegate :outer_joins, :to => Rails::VERSION::MAJOR < 4 ? :scoped : :all
33
73
  end