active_scaffold 3.4.43 → 3.5.0

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