active_scaffold 3.4.43 → 3.5.0

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 (216) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +39 -0
  3. data/{LICENSE → LICENSE.md} +1 -1
  4. data/README.md +27 -19
  5. data/app/assets/javascripts/active_scaffold.js.erb +1 -1
  6. data/app/assets/javascripts/jquery/active_scaffold.js +95 -43
  7. data/app/assets/javascripts/jquery/tiny_mce_bridge.js +30 -6
  8. data/app/assets/javascripts/prototype/tiny_mce_bridge.js +11 -1
  9. data/app/assets/stylesheets/active_scaffold_colors.scss +2 -2
  10. data/app/assets/stylesheets/active_scaffold_layout.css +36 -28
  11. data/app/views/active_scaffold_overrides/_base_form.html.erb +2 -3
  12. data/app/views/active_scaffold_overrides/_field_search.html.erb +8 -7
  13. data/app/views/active_scaffold_overrides/_form_association.html.erb +9 -9
  14. data/app/views/active_scaffold_overrides/_form_association_footer.html.erb +6 -6
  15. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +52 -50
  16. data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +1 -1
  17. data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +1 -1
  18. data/app/views/active_scaffold_overrides/_human_conditions.html.erb +3 -1
  19. data/app/views/active_scaffold_overrides/_list_calculations.html.erb +1 -1
  20. data/app/views/active_scaffold_overrides/_list_column_headings.html.erb +2 -0
  21. data/app/views/active_scaffold_overrides/_list_messages.html.erb +5 -3
  22. data/app/views/active_scaffold_overrides/_list_record.html.erb +3 -1
  23. data/app/views/active_scaffold_overrides/_list_with_header.html.erb +9 -9
  24. data/app/views/active_scaffold_overrides/_messages.html.erb +1 -1
  25. data/app/views/active_scaffold_overrides/_refresh_list.js.erb +18 -10
  26. data/app/views/active_scaffold_overrides/_render_field.js.erb +3 -3
  27. data/app/views/active_scaffold_overrides/_search.html.erb +7 -6
  28. data/app/views/active_scaffold_overrides/_show_actions.html.erb +14 -0
  29. data/app/views/active_scaffold_overrides/_show_association.html.erb +1 -1
  30. data/app/views/active_scaffold_overrides/_update_actions.html.erb +6 -2
  31. data/app/views/active_scaffold_overrides/_update_column.js.erb +1 -1
  32. data/app/views/active_scaffold_overrides/_update_form.html.erb +1 -1
  33. data/app/views/active_scaffold_overrides/destroy.js.erb +2 -3
  34. data/app/views/active_scaffold_overrides/edit_associated.js.erb +4 -3
  35. data/app/views/active_scaffold_overrides/on_action_update.js.erb +5 -3
  36. data/app/views/active_scaffold_overrides/on_create.js.erb +4 -4
  37. data/app/views/active_scaffold_overrides/on_update.js.erb +6 -6
  38. data/app/views/active_scaffold_overrides/show.html.erb +6 -0
  39. data/app/views/active_scaffold_overrides/update.html.erb +1 -1
  40. data/app/views/active_scaffold_overrides/update_column.js.erb +1 -1
  41. data/config/brakeman.ignore +26 -0
  42. data/config/brakeman.yml +3 -0
  43. data/config/i18n-tasks.yml +121 -0
  44. data/config/locales/de.yml +81 -70
  45. data/config/locales/en.yml +83 -74
  46. data/config/locales/es.yml +82 -73
  47. data/config/locales/fr.yml +86 -75
  48. data/config/locales/hu.yml +81 -70
  49. data/config/locales/ja.yml +71 -60
  50. data/config/locales/ru.yml +85 -74
  51. data/lib/active_scaffold.rb +3 -0
  52. data/lib/active_scaffold/actions/common_search.rb +11 -7
  53. data/lib/active_scaffold/actions/core.rb +119 -47
  54. data/lib/active_scaffold/actions/create.rb +1 -1
  55. data/lib/active_scaffold/actions/delete.rb +11 -8
  56. data/lib/active_scaffold/actions/field_search.rb +104 -6
  57. data/lib/active_scaffold/actions/list.rb +25 -21
  58. data/lib/active_scaffold/actions/mark.rb +12 -4
  59. data/lib/active_scaffold/actions/nested.rb +26 -26
  60. data/lib/active_scaffold/actions/search.rb +2 -2
  61. data/lib/active_scaffold/actions/show.rb +4 -5
  62. data/lib/active_scaffold/actions/subform.rb +9 -7
  63. data/lib/active_scaffold/actions/update.rb +20 -13
  64. data/lib/active_scaffold/active_record_permissions.rb +24 -5
  65. data/lib/active_scaffold/attribute_params.rb +68 -49
  66. data/lib/active_scaffold/bridges.rb +1 -1
  67. data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +15 -19
  68. data/lib/active_scaffold/bridges/bitfields.rb +1 -1
  69. data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +10 -14
  70. data/lib/active_scaffold/bridges/calendar_date_select.rb +0 -7
  71. data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +19 -22
  72. data/lib/active_scaffold/bridges/cancan.rb +4 -3
  73. data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +11 -21
  74. data/lib/active_scaffold/bridges/carrierwave.rb +2 -1
  75. data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +2 -6
  76. data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +6 -39
  77. data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +1 -1
  78. data/lib/active_scaffold/bridges/chosen.rb +4 -1
  79. data/lib/active_scaffold/bridges/chosen/helpers.rb +3 -2
  80. data/lib/active_scaffold/bridges/country_select/country_select_bridge_helper.rb +2 -2
  81. data/lib/active_scaffold/bridges/date_picker.rb +3 -0
  82. data/lib/active_scaffold/bridges/date_picker/ext.rb +43 -38
  83. data/lib/active_scaffold/bridges/date_picker/helper.rb +24 -23
  84. data/lib/active_scaffold/bridges/dragonfly.rb +1 -1
  85. data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge.rb +3 -7
  86. data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +3 -25
  87. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +2 -2
  88. data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +6 -8
  89. data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +1 -1
  90. data/lib/active_scaffold/bridges/file_column/form_ui.rb +0 -2
  91. data/lib/active_scaffold/bridges/file_column/list_ui.rb +2 -1
  92. data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +1 -1
  93. data/lib/active_scaffold/bridges/paper_trail/actions.rb +1 -1
  94. data/lib/active_scaffold/bridges/paper_trail/helper.rb +1 -2
  95. data/lib/active_scaffold/bridges/paper_trail/paper_trail_bridge.rb +3 -7
  96. data/lib/active_scaffold/bridges/paperclip.rb +1 -1
  97. data/lib/active_scaffold/bridges/paperclip/form_ui.rb +3 -28
  98. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
  99. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +3 -7
  100. data/lib/active_scaffold/bridges/record_select.rb +2 -0
  101. data/lib/active_scaffold/bridges/record_select/helpers.rb +14 -18
  102. data/lib/active_scaffold/bridges/semantic_attributes/column.rb +4 -8
  103. data/lib/active_scaffold/bridges/shared/date_bridge.rb +20 -20
  104. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +7 -22
  105. data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +14 -14
  106. data/lib/active_scaffold/config/base.rb +9 -6
  107. data/lib/active_scaffold/config/core.rb +30 -21
  108. data/lib/active_scaffold/config/create.rb +2 -1
  109. data/lib/active_scaffold/config/delete.rb +2 -2
  110. data/lib/active_scaffold/config/field_search.rb +9 -3
  111. data/lib/active_scaffold/config/form.rb +4 -4
  112. data/lib/active_scaffold/config/list.rb +27 -23
  113. data/lib/active_scaffold/config/nested.rb +4 -4
  114. data/lib/active_scaffold/config/search.rb +6 -6
  115. data/lib/active_scaffold/config/show.rb +11 -1
  116. data/lib/active_scaffold/config/subform.rb +1 -1
  117. data/lib/active_scaffold/config/update.rb +4 -2
  118. data/lib/active_scaffold/constraints.rb +39 -36
  119. data/lib/active_scaffold/core.rb +36 -15
  120. data/lib/active_scaffold/data_structures/action_columns.rb +14 -9
  121. data/lib/active_scaffold/data_structures/action_link.rb +4 -5
  122. data/lib/active_scaffold/data_structures/action_links.rb +5 -4
  123. data/lib/active_scaffold/data_structures/actions.rb +2 -2
  124. data/lib/active_scaffold/data_structures/association.rb +8 -0
  125. data/lib/active_scaffold/data_structures/association/abstract.rb +147 -0
  126. data/lib/active_scaffold/data_structures/association/active_mongoid.rb +42 -0
  127. data/lib/active_scaffold/data_structures/association/active_record.rb +94 -0
  128. data/lib/active_scaffold/data_structures/association/mongoid.rb +45 -0
  129. data/lib/active_scaffold/data_structures/bridge.rb +3 -6
  130. data/lib/active_scaffold/data_structures/column.rb +100 -82
  131. data/lib/active_scaffold/data_structures/columns.rb +21 -3
  132. data/lib/active_scaffold/data_structures/nested_info.rb +22 -37
  133. data/lib/active_scaffold/data_structures/set.rb +4 -4
  134. data/lib/active_scaffold/data_structures/sorting.rb +29 -15
  135. data/lib/active_scaffold/engine.rb +3 -1
  136. data/lib/active_scaffold/extensions/action_controller_rendering.rb +10 -5
  137. data/lib/active_scaffold/extensions/action_view_rendering.rb +65 -59
  138. data/lib/active_scaffold/extensions/left_outer_joins.rb +48 -53
  139. data/lib/active_scaffold/extensions/localize.rb +3 -4
  140. data/lib/active_scaffold/extensions/name_option_for_datetime.rb +7 -11
  141. data/lib/active_scaffold/extensions/paginator_extensions.rb +20 -18
  142. data/lib/active_scaffold/extensions/routing_mapper.rb +104 -40
  143. data/lib/active_scaffold/extensions/to_label.rb +1 -1
  144. data/lib/active_scaffold/extensions/unsaved_associated.rb +4 -13
  145. data/lib/active_scaffold/extensions/unsaved_record.rb +12 -1
  146. data/lib/active_scaffold/finder.rb +200 -134
  147. data/lib/active_scaffold/helpers/action_link_helpers.rb +398 -0
  148. data/lib/active_scaffold/helpers/association_helpers.rb +12 -30
  149. data/lib/active_scaffold/helpers/controller_helpers.rb +74 -24
  150. data/lib/active_scaffold/helpers/form_column_helpers.rb +205 -112
  151. data/lib/active_scaffold/helpers/human_condition_helpers.rb +21 -11
  152. data/lib/active_scaffold/helpers/id_helpers.rb +1 -1
  153. data/lib/active_scaffold/helpers/list_column_helpers.rb +117 -39
  154. data/lib/active_scaffold/helpers/pagination_helpers.rb +11 -14
  155. data/lib/active_scaffold/helpers/search_column_helpers.rb +69 -32
  156. data/lib/active_scaffold/helpers/show_column_helpers.rb +9 -3
  157. data/lib/active_scaffold/helpers/view_helpers.rb +41 -426
  158. data/lib/active_scaffold/orm_checks.rb +109 -0
  159. data/lib/active_scaffold/paginator.rb +1 -1
  160. data/lib/active_scaffold/responds_to_parent.rb +12 -10
  161. data/lib/active_scaffold/tableless.rb +81 -43
  162. data/lib/active_scaffold/version.rb +2 -2
  163. data/lib/generators/active_scaffold/controller_generator.rb +49 -0
  164. data/lib/generators/active_scaffold/install_generator.rb +45 -0
  165. data/lib/generators/active_scaffold/resource_generator.rb +56 -0
  166. data/lib/generators/{active_scaffold_controller/templates → templates}/controller.rb +0 -0
  167. data/lib/generators/{active_scaffold_controller/templates → templates}/helper.rb +0 -0
  168. data/shoulda_macros/macros.rb +3 -3
  169. data/test/active_scaffold_config_mock.rb +33 -0
  170. data/test/bridges/bridge_test.rb +9 -9
  171. data/test/bridges/date_picker_test.rb +3 -1
  172. data/test/bridges/paper_trail_test.rb +2 -3
  173. data/test/bridges/paperclip_test.rb +21 -10
  174. data/test/bridges/tiny_mce_test.rb +20 -21
  175. data/test/class_with_finder.rb +42 -0
  176. data/test/company.rb +6 -4
  177. data/test/config/core_test.rb +1 -1
  178. data/test/config/create_test.rb +1 -1
  179. data/test/config/list_test.rb +3 -3
  180. data/test/config/update_test.rb +3 -3
  181. data/test/data_structures/action_columns_test.rb +3 -3
  182. data/test/data_structures/association_column_test.rb +5 -5
  183. data/test/data_structures/column_test.rb +14 -14
  184. data/test/data_structures/columns_test.rb +2 -2
  185. data/test/data_structures/set_test.rb +2 -2
  186. data/test/data_structures/sorting_test.rb +6 -4
  187. data/test/extensions/active_record_test.rb +1 -1
  188. data/test/extensions/routing_mapper_test.rb +64 -13
  189. data/test/helpers/form_column_helpers_test.rb +6 -6
  190. data/test/helpers/list_column_helpers_test.rb +9 -5
  191. data/test/helpers/pagination_helpers_test.rb +1 -0
  192. data/test/misc/active_record_permissions_test.rb +18 -1
  193. data/test/misc/attribute_params_test.rb +26 -17
  194. data/test/misc/calculation_test.rb +8 -31
  195. data/test/misc/configurable_test.rb +3 -2
  196. data/test/misc/constraints_test.rb +33 -22
  197. data/test/misc/convert_numbers_format_test.rb +28 -10
  198. data/test/misc/finder_test.rb +6 -29
  199. data/test/misc/parse_datetime_test.rb +160 -0
  200. data/test/misc/render_test.rb +1 -1
  201. data/test/misc/tableless_test.rb +24 -0
  202. data/test/mock_app/app/models/building.rb +2 -1
  203. data/test/mock_app/config.ru +1 -1
  204. data/test/mock_app/config/environments/test.rb +1 -1
  205. data/test/mock_app/config/routes.rb +11 -3
  206. data/test/model_stub.rb +11 -6
  207. data/test/run_all.rb +1 -1
  208. data/test/test_helper.rb +19 -4
  209. metadata +42 -23
  210. data/lib/active_scaffold/data_structures/error_message.rb +0 -22
  211. data/lib/active_scaffold/extensions/reverse_associations.rb +0 -119
  212. data/lib/generators/active_scaffold/USAGE +0 -29
  213. data/lib/generators/active_scaffold/active_scaffold_generator.rb +0 -21
  214. data/lib/generators/active_scaffold_controller/USAGE +0 -19
  215. data/lib/generators/active_scaffold_controller/active_scaffold_controller_generator.rb +0 -29
  216. data/test/data_structures/error_message_test.rb +0 -25
@@ -0,0 +1,94 @@
1
+ module ActiveScaffold::DataStructures::Association
2
+ class ActiveRecord < Abstract
3
+ def self.reflect_on_all_associations(klass)
4
+ klass.reflect_on_all_associations
5
+ end
6
+
7
+ delegate :collection?, :polymorphic?, :association_primary_key, :foreign_type, :table_name, to: :@association
8
+
9
+ def through?
10
+ @association.options[:through].present?
11
+ end
12
+
13
+ def readonly?
14
+ scope_values[:readonly]
15
+ end
16
+
17
+ def through_reflection
18
+ @association.through_reflection if through?
19
+ end
20
+
21
+ def source_reflection
22
+ @association.source_reflection if through?
23
+ end
24
+
25
+ def scope
26
+ @association.scope
27
+ end
28
+
29
+ def inverse_klass
30
+ @association.active_record
31
+ end
32
+
33
+ def primary_key
34
+ @association.options[:primary_key]
35
+ end
36
+
37
+ def counter_cache
38
+ @association.options[:counter_cache]
39
+ end
40
+
41
+ def as
42
+ @association.options[:as]
43
+ end
44
+
45
+ def dependent
46
+ @association.options[:dependent]
47
+ end
48
+
49
+ # name of inverse
50
+ def inverse
51
+ @association.inverse_of.try(:name)
52
+ end
53
+
54
+ def quoted_table_name
55
+ @association.klass.quoted_table_name
56
+ end
57
+
58
+ def quoted_primary_key
59
+ @association.klass.quoted_primary_key
60
+ end
61
+
62
+ def respond_to_target?
63
+ true
64
+ end
65
+
66
+ def counter_cache_hack?
67
+ if has_many?
68
+ Rails.version < '5.0' && as
69
+ elsif belongs_to?
70
+ counter_cache && (Rails.version >= '5.0' || !polymorphic?)
71
+ end
72
+ end
73
+
74
+ protected
75
+
76
+ def scope_values
77
+ return {} unless @association.scope
78
+ @scope_values ||= @association.klass.instance_exec(&@association.scope).values rescue {}
79
+ end
80
+
81
+ def reverse_through_match?(assoc)
82
+ assoc.options[:through] && assoc.through_reflection.class_name == through_reflection.class_name
83
+ end
84
+
85
+ def reverse_habtm_match?(assoc)
86
+ super && assoc.options[:join_table] == @association.options[:join_table]
87
+ end
88
+
89
+ def reverse_direct_match?(assoc)
90
+ # skip over has_many :through associations
91
+ !assoc.options[:through] && super
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,45 @@
1
+ module ActiveScaffold::DataStructures::Association
2
+ class Mongoid < Abstract
3
+ delegate :inverse_klass, :as, :dependent, :inverse, to: :@association
4
+ def collection?
5
+ %i[has_many has_and_belongs_to_many].include?(@association.macro)
6
+ end
7
+
8
+ # polymorphic belongs_to
9
+ def polymorphic?
10
+ belongs_to? && @association.polymorphic?
11
+ end
12
+
13
+ def primary_key
14
+ @association[:primary_key]
15
+ end
16
+
17
+ def association_primary_key
18
+ @association.primary_key
19
+ end
20
+
21
+ def foreign_type
22
+ @association.type
23
+ end
24
+
25
+ def counter_cache
26
+ @association[:counter_cache]
27
+ end
28
+
29
+ def table_name
30
+ @association.klass.collection.name
31
+ end
32
+
33
+ def quoted_table_name
34
+ table_name
35
+ end
36
+
37
+ def quoted_primary_key
38
+ '_id'
39
+ end
40
+
41
+ def self.reflect_on_all_associations(klass)
42
+ klass.relations.values
43
+ end
44
+ end
45
+ end
@@ -4,8 +4,7 @@ module ActiveScaffold::DataStructures
4
4
  raise RunTimeError, "install not defined for bridge #{name}"
5
5
  end
6
6
 
7
- def self.prepare
8
- end
7
+ def self.prepare; end
9
8
 
10
9
  # by convention and default, use the bridge name as the required constant for installation
11
10
  def self.install?
@@ -16,10 +15,8 @@ module ActiveScaffold::DataStructures
16
15
  install if install?
17
16
  end
18
17
 
19
- def self.stylesheets
20
- end
18
+ def self.stylesheets; end
21
19
 
22
- def self.javascripts
23
- end
20
+ def self.javascripts; end
24
21
  end
25
22
  end
@@ -1,8 +1,10 @@
1
1
  module ActiveScaffold::DataStructures
2
2
  class Column
3
3
  include ActiveScaffold::Configurable
4
+ include ActiveScaffold::OrmChecks
4
5
 
5
6
  attr_reader :active_record_class
7
+ alias model active_record_class
6
8
 
7
9
  # this is the name of the getter on the ActiveRecord model. it is the only absolutely required attribute ... all others will be inferred from this name.
8
10
  attr_accessor :name
@@ -76,7 +78,7 @@ module ActiveScaffold::DataStructures
76
78
  end
77
79
 
78
80
  # send all the form instead of only new value when this column change
79
- cattr_accessor :send_form_on_update_column
81
+ cattr_accessor :send_form_on_update_column, instance_accessor: false
80
82
  attr_accessor :send_form_on_update_column
81
83
 
82
84
  # sorting on a column can be configured four ways:
@@ -132,11 +134,11 @@ module ActiveScaffold::DataStructures
132
134
 
133
135
  attr_writer :search_ui
134
136
  def search_ui
135
- @search_ui || @form_ui || (@association && !polymorphic_association? ? :select : nil)
137
+ @search_ui || @form_ui || (:select if association && !association.polymorphic?)
136
138
  end
137
139
 
138
140
  # a place to store dev's column specific options
139
- attr_accessor :options
141
+ attr_writer :options
140
142
  def options
141
143
  @options ||= {}
142
144
  end
@@ -181,8 +183,8 @@ module ActiveScaffold::DataStructures
181
183
  attr_reader :includes
182
184
  def includes=(value)
183
185
  @includes = case value
184
- when Array then value
185
- else value ? [value] : value # not convert nil to [nil]
186
+ when Array then value
187
+ else value ? [value] : value # not convert nil to [nil]
186
188
  end
187
189
  end
188
190
 
@@ -193,8 +195,8 @@ module ActiveScaffold::DataStructures
193
195
 
194
196
  def search_joins=(value)
195
197
  @search_joins = case value
196
- when Array then value
197
- else [value] # automatically convert to an array
198
+ when Array then value
199
+ else [value] # automatically convert to an array
198
200
  end
199
201
  end
200
202
 
@@ -227,12 +229,12 @@ module ActiveScaffold::DataStructures
227
229
  attr_accessor :weight
228
230
 
229
231
  # to set how many associated records a column with plural association must show in list
230
- cattr_accessor :associated_limit
232
+ cattr_accessor :associated_limit, instance_accessor: false
231
233
  @@associated_limit = 3
232
234
  attr_accessor :associated_limit
233
235
 
234
236
  # whether the number of associated records must be shown or not
235
- cattr_accessor :associated_number
237
+ cattr_accessor :associated_number, instance_accessor: false
236
238
  @@associated_number = true
237
239
  attr_writer :associated_number
238
240
  def associated_number?
@@ -240,18 +242,18 @@ module ActiveScaffold::DataStructures
240
242
  end
241
243
 
242
244
  # whether a blank row must be shown in the subform
243
- cattr_accessor :show_blank_record
245
+ cattr_accessor :show_blank_record, instance_accessor: false
244
246
  @@show_blank_record = true
245
247
  attr_writer :show_blank_record
246
248
  def show_blank_record?(associated)
247
249
  return false unless @show_blank_record
248
- return false unless association.klass.authorized_for?(:crud_type => :create) && !association.options[:readonly]
249
- self.plural_association? || (self.singular_association? && associated.blank?)
250
+ return false unless association.klass.authorized_for?(:crud_type => :create) && !association.readonly?
251
+ association.collection? || (association.singular? && associated.blank?)
250
252
  end
251
253
 
252
254
  # methods for automatic links in singular association columns
253
- cattr_accessor :actions_for_association_links
254
- @@actions_for_association_links = [:new, :edit, :show]
255
+ cattr_accessor :actions_for_association_links, instance_accessor: false
256
+ @@actions_for_association_links = %i[new edit show]
255
257
  attr_accessor :actions_for_association_links
256
258
 
257
259
  cattr_accessor :association_form_ui
@@ -266,30 +268,9 @@ module ActiveScaffold::DataStructures
266
268
 
267
269
  # the association from the ActiveRecord class
268
270
  attr_reader :association
269
- def singular_association?
270
- association && !association.collection?
271
- end
272
-
273
- def plural_association?
274
- association && association.collection?
275
- end
276
271
 
277
- def through_association?
278
- association && association.options[:through]
279
- end
280
-
281
- def polymorphic_association?
282
- association && association.options[:polymorphic]
283
- end
284
-
285
- def readonly_association?
286
- return false unless association
287
- if association.options.key? :readonly
288
- association.options[:readonly]
289
- else
290
- self.through_association?
291
- end
292
- end
272
+ # the singular association which this column belongs to
273
+ attr_reader :delegated_association
293
274
 
294
275
  # an interpreted property. the column is virtual if it isn't from the active record model or any associated models
295
276
  def virtual?
@@ -310,54 +291,57 @@ module ActiveScaffold::DataStructures
310
291
  # another column
311
292
  if other.respond_to?(:name) && other.class == self.class
312
293
  name == other.name.to_sym
313
- # a string or symbol
314
- elsif other.respond_to? :to_sym
315
- name == other.to_sym rescue false # catch "interning empty string"
316
- # unknown
317
- else
318
- self.eql? other
294
+ elsif other.is_a? Symbol
295
+ name == other
296
+ elsif other.is_a? String
297
+ name.to_s == other # avoid creating new symbols
298
+ else # unknown
299
+ eql? other
319
300
  end
320
301
  end
321
302
 
322
303
  # instantiation is handled internally through the DataStructures::Columns object
323
- def initialize(name, active_record_class) #:nodoc:
304
+ def initialize(name, active_record_class, delegated_association = nil) #:nodoc:
324
305
  self.name = name.to_sym
325
- @tableless = active_record_class < ActiveScaffold::Tableless
326
- @column = active_record_class.columns_hash[self.name.to_s]
327
- @association = active_record_class.reflect_on_association(self.name)
328
- @autolink = !@association.nil?
329
306
  @active_record_class = active_record_class
330
- @table = active_record_class.table_name
307
+ @column = _columns_hash[self.name.to_s]
308
+ @delegated_association = delegated_association
309
+ setup_association_info
310
+
311
+ @autolink = self.association.present?
312
+ @table = _table_name
331
313
  @associated_limit = self.class.associated_limit
332
314
  @associated_number = self.class.associated_number
333
315
  @show_blank_record = self.class.show_blank_record
334
316
  @send_form_on_update_column = self.class.send_form_on_update_column
335
- @actions_for_association_links = self.class.actions_for_association_links.clone if @association
317
+ @actions_for_association_links = self.class.actions_for_association_links.clone if self.association
336
318
  @select_columns = default_select_columns
337
319
 
338
- @text = @column.nil? || [:string, :text].include?(@column.type)
320
+ @text = @column.nil? || [:string, :text, String].include?(column_type)
321
+ @number = false
339
322
  if @column
340
323
  if active_record_class.respond_to?(:defined_enums) && active_record_class.defined_enums[name.to_s]
341
324
  @form_ui = :select
342
- @options = {:options => active_record_class.send(name.to_s.pluralize).keys}
343
- elsif @column.number?
325
+ @options = {:options => active_record_class.send(name.to_s.pluralize).keys.map(&:to_sym)}
326
+ elsif column_number?
344
327
  @number = true
345
328
  @form_ui = :number
346
329
  @options = {:format => :i18n_number}
347
330
  else
348
331
  @form_ui = case @column.type
349
- when :boolean then :checkbox
350
- when :text then :textarea
332
+ when :boolean then :checkbox
333
+ when :text then :textarea
351
334
  end
352
335
  end
353
336
  end
354
337
  @allow_add_existing = true
355
338
  @form_ui = self.class.association_form_ui if @association && self.class.association_form_ui
356
339
 
357
- if association && !polymorphic_association?
358
- self.includes = [association.name]
359
- self.search_joins = includes.clone
340
+ self.includes = [association.name] if association && association.allow_join?
341
+ if delegated_association
342
+ self.includes = includes ? [delegated_association.name => includes] : [delegated_association.name]
360
343
  end
344
+ self.search_joins = includes.clone if includes
361
345
 
362
346
  # default all the configurable variables
363
347
  self.css_class = ''
@@ -373,12 +357,12 @@ module ActiveScaffold::DataStructures
373
357
  # just the field (not table.field)
374
358
  def field_name
375
359
  return nil if virtual?
376
- @field_name ||= column ? @active_record_class.connection.quote_column_name(column.name) : association.foreign_key
360
+ @field_name ||= column ? quoted_field_name(column.name) : association.foreign_key
377
361
  end
378
362
 
379
363
  def <=>(other)
380
364
  order_weight = weight <=> other.weight
381
- order_weight != 0 ? order_weight : name.to_s <=> other.name.to_s
365
+ order_weight.nonzero? ? order_weight : name.to_s <=> other.name.to_s
382
366
  end
383
367
 
384
368
  def number_to_native(value)
@@ -386,12 +370,12 @@ module ActiveScaffold::DataStructures
386
370
  native = '.' # native ruby separator
387
371
  format = {:separator => '', :delimiter => ''}.merge! I18n.t('number.format', :default => {})
388
372
  specific = case options[:format]
389
- when :currency
390
- I18n.t('number.currency.format', :default => nil)
391
- when :size
392
- I18n.t('number.human.format', :default => nil)
393
- when :percentage
394
- I18n.t('number.percentage.format', :default => nil)
373
+ when :currency
374
+ I18n.t('number.currency.format', :default => nil)
375
+ when :size
376
+ I18n.t('number.human.format', :default => nil)
377
+ when :percentage
378
+ I18n.t('number.percentage.format', :default => nil)
395
379
  end
396
380
  format.merge! specific unless specific.nil?
397
381
  if format[:separator].blank? || !value.include?(format[:separator]) && value.include?(native) && (format[:delimiter] != native || value !~ /\.\d{3}$/)
@@ -412,8 +396,29 @@ module ActiveScaffold::DataStructures
412
396
  @field ||= quoted_field(field_name)
413
397
  end
414
398
 
399
+ def type_for_attribute
400
+ ActiveScaffold::OrmChecks.type_for_attribute active_record_class, name
401
+ end
402
+
403
+ def column_type
404
+ ActiveScaffold::OrmChecks.column_type active_record_class, name
405
+ end
406
+
415
407
  protected
416
408
 
409
+ def setup_association_info
410
+ assoc = active_record_class.reflect_on_association(self.name)
411
+ @association = if assoc
412
+ case
413
+ when active_record? then Association::ActiveRecord.new(assoc)
414
+ when mongoid? then Association::Mongoid.new(assoc)
415
+ end
416
+ elsif defined?(ActiveMongoid) && model < ActiveMongoid::Associations
417
+ assoc = active_record_class.reflect_on_am_association(name)
418
+ Association::ActiveMongoid.new(assoc) if assoc
419
+ end
420
+ end
421
+
417
422
  def validator_force_required?(val)
418
423
  return false if val.options[:if] || val.options[:unless]
419
424
  case val
@@ -433,34 +438,47 @@ module ActiveScaffold::DataStructures
433
438
  def default_select_columns
434
439
  if association.nil? && column
435
440
  [field]
436
- elsif polymorphic_association?
437
- [field, quoted_field(@active_record_class.connection.quote_column_name(association.foreign_type))]
441
+ elsif association.try(:polymorphic?)
442
+ [field, quoted_field(quoted_field_name(association.foreign_type))]
438
443
  elsif association
439
444
  if association.belongs_to?
440
445
  [field]
441
446
  else
442
447
  columns = []
443
- if active_record_class.columns_hash[count_column = "#{association.name}_count"]
444
- columns << quoted_field(@active_record_class.connection.quote_column_name(count_column))
448
+ if _columns_hash[count_column = "#{association.name}_count"]
449
+ columns << quoted_field(quoted_field_name(count_column))
445
450
  end
446
451
  if association.through_reflection.try(:belongs_to?)
447
- columns << quoted_field(@active_record_class.connection.quote_column_name(association.through_reflection.foreign_key))
452
+ columns << quoted_field(quoted_field_name(association.through_reflection.foreign_key))
448
453
  end
449
454
  columns
450
455
  end
451
456
  end
452
457
  end
453
458
 
459
+ def column_number?
460
+ return %i[float decimal integer].include? @column.type if active_record?
461
+ return @column.type < Numeric if mongoid?
462
+ end
463
+
464
+ def quoted_field_name(column_name)
465
+ if active_record?
466
+ @active_record_class.connection.quote_column_name(column_name)
467
+ else
468
+ column_name.to_s
469
+ end
470
+ end
471
+
454
472
  def quoted_field(name)
455
- [@active_record_class.quoted_table_name, name].join('.')
473
+ active_record? ? [_quoted_table_name, name].compact.join('.') : name
456
474
  end
457
475
 
458
476
  def initialize_sort
459
- if self.virtual?
477
+ if virtual?
460
478
  # we don't automatically enable method sorting for virtual columns because it's slow, and we expect fewer complaints this way.
461
479
  self.sort = false
462
480
  else
463
- if column && !@tableless
481
+ if column && !tableless?
464
482
  self.sort = {:sql => field}
465
483
  else
466
484
  self.sort = false
@@ -470,11 +488,11 @@ module ActiveScaffold::DataStructures
470
488
 
471
489
  def initialize_search_sql
472
490
  self.search_sql =
473
- unless self.virtual?
491
+ unless virtual?
474
492
  if association.nil?
475
- field.to_s unless @tableless
476
- elsif !self.polymorphic_association?
477
- [association.klass.quoted_table_name, association.klass.quoted_primary_key].join('.') unless association.klass < ActiveScaffold::Tableless
493
+ field.to_s unless tableless?
494
+ elsif association.allow_join?
495
+ [association.quoted_table_name, association.quoted_primary_key].join('.') unless association.klass < ActiveScaffold::Tableless
478
496
  end
479
497
  end
480
498
  end
@@ -483,13 +501,13 @@ module ActiveScaffold::DataStructures
483
501
  attr_reader :table
484
502
 
485
503
  def estimate_weight
486
- if singular_association?
504
+ if association.try(:singular?)
487
505
  400
488
- elsif plural_association?
506
+ elsif association.try(:collection?)
489
507
  500
490
- elsif [:created_at, :updated_at].include?(name)
508
+ elsif %i[created_at updated_at].include?(name)
491
509
  600
492
- elsif [:name, :label, :title].include?(name)
510
+ elsif %i[name label title].include?(name)
493
511
  100
494
512
  elsif required?
495
513
  200