active_scaffold 3.4.17 → 3.4.18

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 (183) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +12 -1
  3. data/README.md +8 -4
  4. data/app/assets/javascripts/jquery/active_scaffold.js +82 -67
  5. data/app/assets/stylesheets/active_scaffold.scss +1 -1
  6. data/app/assets/stylesheets/active_scaffold_colors.scss +1 -1
  7. data/app/assets/stylesheets/blue-theme.css +1 -1
  8. data/app/views/active_scaffold_overrides/_form_association.html.erb +3 -3
  9. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +3 -3
  10. data/app/views/active_scaffold_overrides/_show_columns.html.erb +1 -1
  11. data/lib/active_scaffold.rb +16 -16
  12. data/lib/active_scaffold/actions/common_search.rb +13 -11
  13. data/lib/active_scaffold/actions/core.rb +85 -78
  14. data/lib/active_scaffold/actions/create.rb +29 -28
  15. data/lib/active_scaffold/actions/delete.rb +17 -17
  16. data/lib/active_scaffold/actions/field_search.rb +18 -19
  17. data/lib/active_scaffold/actions/list.rb +30 -22
  18. data/lib/active_scaffold/actions/mark.rb +1 -1
  19. data/lib/active_scaffold/actions/nested.rb +78 -65
  20. data/lib/active_scaffold/actions/search.rb +13 -10
  21. data/lib/active_scaffold/actions/show.rb +10 -6
  22. data/lib/active_scaffold/actions/subform.rb +1 -2
  23. data/lib/active_scaffold/actions/update.rb +39 -31
  24. data/lib/active_scaffold/active_record_permissions.rb +14 -15
  25. data/lib/active_scaffold/attribute_params.rb +42 -43
  26. data/lib/active_scaffold/bridges.rb +22 -12
  27. data/lib/active_scaffold/bridges/ancestry.rb +1 -1
  28. data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +6 -6
  29. data/lib/active_scaffold/bridges/bitfields.rb +1 -1
  30. data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +12 -13
  31. data/lib/active_scaffold/bridges/calendar_date_select.rb +5 -5
  32. data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +17 -20
  33. data/lib/active_scaffold/bridges/cancan.rb +1 -1
  34. data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +8 -9
  35. data/lib/active_scaffold/bridges/carrierwave.rb +4 -4
  36. data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +9 -8
  37. data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +11 -10
  38. data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +7 -6
  39. data/lib/active_scaffold/bridges/chosen.rb +1 -1
  40. data/lib/active_scaffold/bridges/chosen/helpers.rb +4 -4
  41. data/lib/active_scaffold/bridges/country_helper.rb +1 -1
  42. data/lib/active_scaffold/bridges/country_helper/country_helper_bridge.rb +259 -260
  43. data/lib/active_scaffold/bridges/date_picker.rb +2 -2
  44. data/lib/active_scaffold/bridges/date_picker/ext.rb +9 -11
  45. data/lib/active_scaffold/bridges/date_picker/helper.rb +61 -67
  46. data/lib/active_scaffold/bridges/dragonfly.rb +4 -4
  47. data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge.rb +9 -8
  48. data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +11 -10
  49. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +6 -5
  50. data/lib/active_scaffold/bridges/file_column.rb +5 -5
  51. data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +20 -23
  52. data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +20 -23
  53. data/lib/active_scaffold/bridges/file_column/form_ui.rb +13 -14
  54. data/lib/active_scaffold/bridges/file_column/list_ui.rb +7 -8
  55. data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +18 -22
  56. data/lib/active_scaffold/bridges/file_column/test/mock_model.rb +5 -4
  57. data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +2 -10
  58. data/lib/active_scaffold/bridges/paper_trail.rb +7 -5
  59. data/lib/active_scaffold/bridges/paper_trail/paper_trail_bridge.rb +4 -3
  60. data/lib/active_scaffold/bridges/paperclip.rb +5 -5
  61. data/lib/active_scaffold/bridges/paperclip/form_ui.rb +11 -10
  62. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +6 -5
  63. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +10 -9
  64. data/lib/active_scaffold/bridges/record_select.rb +1 -1
  65. data/lib/active_scaffold/bridges/record_select/helpers.rb +28 -28
  66. data/lib/active_scaffold/bridges/semantic_attributes.rb +1 -1
  67. data/lib/active_scaffold/bridges/semantic_attributes/column.rb +1 -1
  68. data/lib/active_scaffold/bridges/shared/date_bridge.rb +58 -52
  69. data/lib/active_scaffold/bridges/tiny_mce.rb +2 -2
  70. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +3 -3
  71. data/lib/active_scaffold/config/base.rb +9 -10
  72. data/lib/active_scaffold/config/core.rb +24 -29
  73. data/lib/active_scaffold/config/create.rb +0 -1
  74. data/lib/active_scaffold/config/field_search.rb +8 -10
  75. data/lib/active_scaffold/config/form.rb +5 -5
  76. data/lib/active_scaffold/config/list.rb +21 -20
  77. data/lib/active_scaffold/config/mark.rb +3 -3
  78. data/lib/active_scaffold/config/nested.rb +11 -10
  79. data/lib/active_scaffold/config/search.rb +2 -3
  80. data/lib/active_scaffold/config/show.rb +1 -1
  81. data/lib/active_scaffold/config/update.rb +1 -2
  82. data/lib/active_scaffold/configurable.rb +9 -11
  83. data/lib/active_scaffold/constraints.rb +9 -8
  84. data/lib/active_scaffold/core.rb +72 -84
  85. data/lib/active_scaffold/data_structures/action_columns.rb +26 -25
  86. data/lib/active_scaffold/data_structures/action_link.rb +43 -43
  87. data/lib/active_scaffold/data_structures/action_links.rb +17 -15
  88. data/lib/active_scaffold/data_structures/actions.rb +5 -5
  89. data/lib/active_scaffold/data_structures/bridge.rb +6 -3
  90. data/lib/active_scaffold/data_structures/column.rb +110 -89
  91. data/lib/active_scaffold/data_structures/columns.rb +3 -3
  92. data/lib/active_scaffold/data_structures/error_message.rb +4 -6
  93. data/lib/active_scaffold/data_structures/nested_info.rb +43 -48
  94. data/lib/active_scaffold/data_structures/set.rb +7 -8
  95. data/lib/active_scaffold/data_structures/sorting.rb +38 -33
  96. data/lib/active_scaffold/delayed_setup.rb +5 -6
  97. data/lib/active_scaffold/engine.rb +4 -4
  98. data/lib/active_scaffold/extensions/action_controller_rendering.rb +3 -4
  99. data/lib/active_scaffold/extensions/action_controller_rescueing.rb +1 -1
  100. data/lib/active_scaffold/extensions/action_view_rendering.rb +5 -6
  101. data/lib/active_scaffold/extensions/left_outer_joins.rb +11 -11
  102. data/lib/active_scaffold/extensions/localize.rb +1 -1
  103. data/lib/active_scaffold/extensions/name_option_for_datetime.rb +1 -1
  104. data/lib/active_scaffold/extensions/paginator_extensions.rb +2 -5
  105. data/lib/active_scaffold/extensions/reverse_associations.rb +13 -13
  106. data/lib/active_scaffold/extensions/routing_mapper.rb +9 -9
  107. data/lib/active_scaffold/extensions/unsaved_associated.rb +9 -9
  108. data/lib/active_scaffold/finder.rb +90 -93
  109. data/lib/active_scaffold/helpers/association_helpers.rb +5 -5
  110. data/lib/active_scaffold/helpers/controller_helpers.rb +22 -19
  111. data/lib/active_scaffold/helpers/form_column_helpers.rb +115 -105
  112. data/lib/active_scaffold/helpers/human_condition_helpers.rb +62 -35
  113. data/lib/active_scaffold/helpers/id_helpers.rb +6 -6
  114. data/lib/active_scaffold/helpers/list_column_helpers.rb +89 -94
  115. data/lib/active_scaffold/helpers/pagination_helpers.rb +9 -9
  116. data/lib/active_scaffold/helpers/search_column_helpers.rb +47 -44
  117. data/lib/active_scaffold/helpers/show_column_helpers.rb +2 -2
  118. data/lib/active_scaffold/helpers/view_helpers.rb +86 -91
  119. data/lib/active_scaffold/marked_model.rb +10 -10
  120. data/lib/active_scaffold/paginator.rb +30 -34
  121. data/lib/active_scaffold/responds_to_parent.rb +27 -28
  122. data/lib/active_scaffold/tableless.rb +20 -15
  123. data/lib/active_scaffold/version.rb +1 -1
  124. data/lib/generators/active_scaffold/active_scaffold_generator.rb +8 -8
  125. data/lib/generators/active_scaffold_controller/active_scaffold_controller_generator.rb +9 -9
  126. data/shoulda_macros/macros.rb +27 -22
  127. data/test/bridges/bridge_test.rb +38 -29
  128. data/test/bridges/date_picker_test.rb +1 -1
  129. data/test/bridges/paper_trail_test.rb +17 -0
  130. data/test/bridges/paperclip_test.rb +3 -2
  131. data/test/bridges/tiny_mce_test.rb +5 -2
  132. data/test/company.rb +25 -30
  133. data/test/config/base_test.rb +1 -1
  134. data/test/config/core_test.rb +9 -9
  135. data/test/config/create_test.rb +14 -8
  136. data/test/config/delete_test.rb +4 -4
  137. data/test/config/field_search_test.rb +6 -6
  138. data/test/config/list_test.rb +16 -16
  139. data/test/config/nested_test.rb +4 -4
  140. data/test/config/search_test.rb +8 -8
  141. data/test/config/show_test.rb +6 -6
  142. data/test/config/subform_test.rb +1 -1
  143. data/test/config/update_test.rb +5 -5
  144. data/test/const_mocker.rb +4 -4
  145. data/test/data_structures/action_columns_test.rb +4 -5
  146. data/test/data_structures/action_link_test.rb +1 -0
  147. data/test/data_structures/action_links_test.rb +5 -5
  148. data/test/data_structures/column_test.rb +9 -9
  149. data/test/data_structures/columns_test.rb +2 -2
  150. data/test/data_structures/error_message_test.rb +4 -5
  151. data/test/data_structures/set_test.rb +1 -2
  152. data/test/data_structures/sorting_test.rb +10 -10
  153. data/test/data_structures/validation_reflection_test.rb +8 -0
  154. data/test/extensions/routing_mapper_test.rb +2 -2
  155. data/test/helpers/list_column_helpers_test.rb +3 -2
  156. data/test/helpers/pagination_helpers_test.rb +5 -4
  157. data/test/helpers/search_column_helpers_test.rb +1 -1
  158. data/test/misc/active_record_permissions_test.rb +63 -50
  159. data/test/misc/attribute_params_test.rb +28 -26
  160. data/test/misc/calculation_test.rb +10 -3
  161. data/test/misc/configurable_test.rb +12 -13
  162. data/test/misc/constraints_test.rb +6 -6
  163. data/test/misc/convert_numbers_format_test.rb +7 -6
  164. data/test/misc/finder_test.rb +17 -12
  165. data/test/misc/lang_test.rb +3 -4
  166. data/test/misc/tableless_test.rb +2 -3
  167. data/test/mock_app/app/controllers/addresses_controller.rb +1 -1
  168. data/test/mock_app/app/controllers/buildings_controller.rb +1 -1
  169. data/test/mock_app/app/controllers/cars_controller.rb +1 -1
  170. data/test/mock_app/app/controllers/contacts_controller.rb +1 -1
  171. data/test/mock_app/app/controllers/people_controller.rb +1 -1
  172. data/test/mock_app/app/models/file_model.rb +2 -2
  173. data/test/mock_app/app/models/person.rb +1 -1
  174. data/test/mock_app/config/application.rb +3 -3
  175. data/test/mock_app/config/boot.rb +1 -1
  176. data/test/mock_app/config/environment.rb +1 -0
  177. data/test/mock_app/config/environments/development.rb +0 -1
  178. data/test/mock_app/config/environments/production.rb +1 -1
  179. data/test/mock_app/db/schema.rb +14 -15
  180. data/test/model_stub.rb +13 -16
  181. data/test/run_all.rb +5 -7
  182. data/test/test_helper.rb +12 -9
  183. metadata +19 -3
@@ -16,7 +16,7 @@ module ActiveScaffold
16
16
  end
17
17
 
18
18
  def reverse(klass = nil)
19
- unless defined? @reverse
19
+ unless defined? @reverse # rubocop:disable Style/IfUnlessModifier
20
20
  @reverse ||= inverse_of.try(:name)
21
21
  end
22
22
  @reverse || (autodetect_inverse(klass).try(:name) unless klass.nil?)
@@ -27,10 +27,10 @@ module ActiveScaffold
27
27
  klass ||= self.klass
28
28
 
29
29
  # name-based matching (association name vs self.active_record.to_s)
30
- matches = self.reverse_matches(klass)
30
+ matches = reverse_matches(klass)
31
31
  if matches.length > 1
32
32
  matches.find_all do |assoc|
33
- self.active_record.to_s.underscore.include? assoc.name.to_s.pluralize.singularize
33
+ active_record.to_s.underscore.include? assoc.name.to_s.pluralize.singularize
34
34
  end
35
35
  end
36
36
 
@@ -42,8 +42,9 @@ module ActiveScaffold
42
42
  def self.included(base)
43
43
  base.send :include, ActiveScaffold::ReverseAssociation::CommonMethods
44
44
  end
45
-
45
+
46
46
  protected
47
+
47
48
  def reverse_matches(klass)
48
49
  reverse_matches = []
49
50
 
@@ -52,20 +53,20 @@ module ActiveScaffold
52
53
  next if assoc == self
53
54
  # skip over has_many :through associations
54
55
  next if assoc.options[:through]
55
- next unless assoc.options[:polymorphic] or assoc.class_name == self.active_record.name
56
+ next unless assoc.options[:polymorphic] || assoc.class_name == active_record.name
56
57
 
57
- case [assoc.macro, self.macro].find_all{|m| m == :has_and_belongs_to_many}.length
58
+ case [assoc.macro, macro].find_all { |m| m == :has_and_belongs_to_many }.length
58
59
  # if both are a habtm, then match them based on the join table
59
60
  when 2
60
- next unless assoc.options[:join_table] == self.options[:join_table]
61
+ next unless assoc.options[:join_table] == options[:join_table]
61
62
 
62
63
  # if only one is a habtm, they do not match
63
64
  when 1
64
- next
65
+ next
65
66
 
66
67
  # otherwise, match them based on the foreign_key
67
68
  when 0
68
- next unless assoc.foreign_key.to_sym == self.foreign_key.to_sym
69
+ next unless assoc.foreign_key.to_sym == foreign_key.to_sym
69
70
  end
70
71
 
71
72
  reverse_matches << assoc
@@ -89,15 +90,14 @@ module ActiveScaffold
89
90
  next if assoc == self
90
91
  # only iterate has_many :through associations
91
92
  next unless assoc.options[:through]
92
- next unless assoc.class_name == self.active_record.name
93
- next unless assoc.through_reflection.class_name == self.through_reflection.class_name
94
-
93
+ next unless assoc.class_name == active_record.name
94
+ next unless assoc.through_reflection.class_name == through_reflection.class_name
95
+
95
96
  reverse_matches << assoc
96
97
  end
97
98
  reverse_matches
98
99
  end
99
100
  end
100
-
101
101
  end
102
102
  end
103
103
 
@@ -1,14 +1,14 @@
1
1
  module ActionDispatch
2
2
  module Routing
3
3
  ACTIVE_SCAFFOLD_CORE_ROUTING = {
4
- :collection => {:show_search => :get, :render_field => :post, :mark => :post},
5
- :member => {:update_column => :post, :render_field => [:get, :post], :mark => :post}
4
+ :collection => {:show_search => :get, :render_field => :post, :mark => :post},
5
+ :member => {:update_column => :post, :render_field => [:get, :post], :mark => :post}
6
6
  }
7
7
  ACTIVE_SCAFFOLD_ASSOCIATION_ROUTING = {
8
- :collection => {:edit_associated => :get, :new_existing => :get, :add_existing => :post},
9
- :member => {:edit_associated => :get, :destroy_existing => :delete}
8
+ :collection => {:edit_associated => :get, :new_existing => :get, :add_existing => :post},
9
+ :member => {:edit_associated => :get, :destroy_existing => :delete}
10
10
  }
11
-
11
+
12
12
  class Mapper
13
13
  module Resources
14
14
  class ActiveScaffold < Resource
@@ -39,10 +39,10 @@ module ActionDispatch
39
39
  end
40
40
  as_association_routes if opts[:association]
41
41
  end
42
-
42
+
43
43
  def as_association_routes
44
44
  resource_scope(:resource, ActiveScaffoldAssociation.new(parent_resource.name, parent_resource.options)) do
45
- collection do
45
+ collection do
46
46
  ActionDispatch::Routing::ACTIVE_SCAFFOLD_ASSOCIATION_ROUTING[:collection].each do |name, type|
47
47
  match(name, :via => type) if parent_resource.actions.include? name
48
48
  end
@@ -54,14 +54,14 @@ module ActionDispatch
54
54
  end
55
55
  end
56
56
  end
57
-
57
+
58
58
  def as_nested_resources(*resources)
59
59
  options = resources.extract_options!
60
60
  resources.each do |resource|
61
61
  resources(resource, options.merge(:parent_scaffold => merge_module_scope(@scope[:module], parent_resource.plural), :association => resource)) { yield if block_given? }
62
62
  end
63
63
  end
64
-
64
+
65
65
  def as_scoped_routes(*scopes)
66
66
  options = scopes.extract_options!
67
67
  scopes.each do |scope|
@@ -9,15 +9,15 @@ class ActiveRecord::Base
9
9
  end
10
10
 
11
11
  def save_associated
12
- with_unsaved_associated { |a| a.save and a.save_associated }
12
+ with_unsaved_associated { |a| a.save && a.save_associated }
13
13
  end
14
14
 
15
15
  def save_associated!
16
- save_associated or raise(ActiveRecord::RecordNotSaved)
16
+ save_associated || raise(ActiveRecord::RecordNotSaved)
17
17
  end
18
18
 
19
19
  def no_errors_in_associated?
20
- with_unsaved_associated {|a| a.errors.count == 0 and a.no_errors_in_associated?}
20
+ with_unsaved_associated { |a| a.errors.count == 0 && a.no_errors_in_associated? }
21
21
  end
22
22
 
23
23
  protected
@@ -33,10 +33,10 @@ class ActiveRecord::Base
33
33
  #
34
34
  # Otherwise the default behaviour of traversing all associations will be preserved.
35
35
  def associations_for_update
36
- if self.respond_to?( :scaffold_update_nofollow )
37
- self.class.reflect_on_all_associations.reject { |association| self.scaffold_update_nofollow.include?( association.name ) }
38
- elsif self.respond_to?( :scaffold_update_follow )
39
- self.class.reflect_on_all_associations.select { |association| self.scaffold_update_follow.include?( association.name ) }
36
+ if self.respond_to?(:scaffold_update_nofollow)
37
+ self.class.reflect_on_all_associations.reject { |association| scaffold_update_nofollow.include?(association.name) }
38
+ elsif self.respond_to?(:scaffold_update_follow)
39
+ self.class.reflect_on_all_associations.select { |association| scaffold_update_follow.include?(association.name) }
40
40
  else
41
41
  self.class.reflect_on_all_associations
42
42
  end
@@ -49,11 +49,11 @@ class ActiveRecord::Base
49
49
  # returns true otherwise, even when none of the associations have been instantiated. build wrapper methods accordingly.
50
50
  def with_unsaved_associated
51
51
  associations_for_update.all? do |assoc|
52
- association_proxy = self.association(assoc.name)
52
+ association_proxy = association(assoc.name)
53
53
  if association_proxy.target.present?
54
54
  records = association_proxy.target
55
55
  records = [records] unless records.is_a? Array # convert singular associations into collections for ease of use
56
- records.select {|r| r.unsaved? and not r.readonly?}.all? {|r| yield r} # must use select instead of find_all, which Rails overrides on association proxies for db access
56
+ records.select { |r| r.unsaved? && !r.readonly? }.all? { |r| yield r } # must use select instead of find_all, which Rails overrides on association proxies for db access
57
57
  else
58
58
  true
59
59
  end
@@ -1,7 +1,7 @@
1
1
  module ActiveScaffold
2
2
  module Finder
3
3
  def self.like_operator
4
- @@like_operator ||= ::ActiveRecord::Base.connection.adapter_name == "PostgreSQL" ? "ILIKE" : "LIKE"
4
+ @@like_operator ||= ::ActiveRecord::Base.connection.adapter_name == 'PostgreSQL' ? 'ILIKE' : 'LIKE'
5
5
  end
6
6
 
7
7
  module ClassMethods
@@ -24,11 +24,10 @@ module ActiveScaffold
24
24
  phrase = where_clauses.join(' OR ')
25
25
 
26
26
  tokens.collect do |value|
27
- columns.inject([phrase]) do |condition, column|
27
+ columns.each_with_object([phrase]) do |column, condition|
28
28
  Array(column.search_sql).size.times do
29
29
  condition.push(column.text? ? like_pattern.sub('?', value) : ActiveScaffold::Core.column_type_cast(value, column.column))
30
30
  end
31
- condition
32
31
  end
33
32
  end
34
33
  end
@@ -39,57 +38,62 @@ module ActiveScaffold
39
38
  def condition_for_column(column, value, text_search = :full)
40
39
  like_pattern = like_pattern(text_search)
41
40
  if self.respond_to?("condition_for_#{column.name}_column")
42
- return self.send("condition_for_#{column.name}_column", column, value, like_pattern)
41
+ return send("condition_for_#{column.name}_column", column, value, like_pattern)
43
42
  end
44
- return unless column and column.search_sql and not value.blank?
43
+ return unless column && column.search_sql && !value.blank?
45
44
  search_ui = column.search_ui || column.column.try(:type)
46
45
  begin
47
- sql, *values = if search_ui && self.respond_to?("condition_for_#{search_ui}_type")
48
- self.send("condition_for_#{search_ui}_type", column, value, like_pattern)
49
- else
50
- if column.search_sql.instance_of? Proc
51
- column.search_sql.call(value)
46
+ sql, *values =
47
+ if search_ui && self.respond_to?("condition_for_#{search_ui}_type")
48
+ send("condition_for_#{search_ui}_type", column, value, like_pattern)
52
49
  else
53
- case search_ui
54
- when :boolean, :checkbox
55
- ["%{search_sql} = ?", column.column ? ActiveScaffold::Core.column_type_cast(value, column.column) : value]
56
- when :integer, :decimal, :float
57
- condition_for_numeric(column, value)
58
- when :string, :range
59
- condition_for_range(column, value, like_pattern)
60
- when :date, :time, :datetime, :timestamp
61
- condition_for_datetime(column, value)
62
- when :select, :multi_select, :country, :usa_state, :chosen, :multi_chosen
63
- ["%{search_sql} in (?)", Array(value)]
50
+ if column.search_sql.instance_of? Proc
51
+ column.search_sql.call(value)
64
52
  else
65
- if column.text?
66
- ["%{search_sql} #{ActiveScaffold::Finder.like_operator} ?", like_pattern.sub('?', value)]
67
- else
68
- ["%{search_sql} = ?", ActiveScaffold::Core.column_type_cast(value, column.column)]
69
- end
53
+ condition_for_search_ui(column, value, like_pattern, search_ui)
70
54
  end
71
55
  end
72
- end
73
56
  return nil unless sql
74
57
 
75
58
  conditions = [column.search_sql.collect { |search_sql| sql % {:search_sql => search_sql} }.join(' OR ')]
76
- conditions += values*column.search_sql.size if values.present?
59
+ conditions += values * column.search_sql.size if values.present?
77
60
  conditions
78
- rescue Exception => e
79
- logger.error "#{e.class.name}: #{e.message} -- on the ActiveScaffold column :#{column.name}, search_ui = #{search_ui} in #{self.name}"
61
+ rescue StandardError => e
62
+ logger.error "#{e.class.name}: #{e.message} -- on the ActiveScaffold column :#{column.name}, search_ui = #{search_ui} in #{name}"
80
63
  raise e
81
64
  end
82
65
  end
83
66
 
67
+ def condition_for_search_ui(column, value, like_pattern, search_ui)
68
+ case search_ui
69
+ when :boolean, :checkbox
70
+ ['%{search_sql} = ?', column.column ? ActiveScaffold::Core.column_type_cast(value, column.column) : value]
71
+ when :integer, :decimal, :float
72
+ condition_for_numeric(column, value)
73
+ when :string, :range
74
+ condition_for_range(column, value, like_pattern)
75
+ when :date, :time, :datetime, :timestamp
76
+ condition_for_datetime(column, value)
77
+ when :select, :multi_select, :country, :usa_state, :chosen, :multi_chosen
78
+ ['%{search_sql} in (?)', Array(value)]
79
+ else
80
+ if column.text?
81
+ ["%{search_sql} #{ActiveScaffold::Finder.like_operator} ?", like_pattern.sub('?', value)]
82
+ else
83
+ ['%{search_sql} = ?', ActiveScaffold::Core.column_type_cast(value, column.column)]
84
+ end
85
+ end
86
+ end
87
+
84
88
  def condition_for_numeric(column, value)
85
89
  if !value.is_a?(Hash)
86
- ["%{search_sql} = ?", condition_value_for_numeric(column, value)]
87
- elsif ActiveScaffold::Finder::NullComparators.include?(value[:opt])
90
+ ['%{search_sql} = ?', condition_value_for_numeric(column, value)]
91
+ elsif ActiveScaffold::Finder::NULL_COMPARATORS.include?(value[:opt])
88
92
  condition_for_null_type(column, value[:opt])
89
- elsif value[:from].blank? or not ActiveScaffold::Finder::NumericComparators.include?(value[:opt])
93
+ elsif value[:from].blank? || !ActiveScaffold::Finder::NUMERIC_COMPARATORS.include?(value[:opt])
90
94
  nil
91
95
  elsif value[:opt] == 'BETWEEN'
92
- ["(%{search_sql} BETWEEN ? AND ?)", condition_value_for_numeric(column, value[:from]), condition_value_for_numeric(column, value[:to])]
96
+ ['(%{search_sql} BETWEEN ? AND ?)', condition_value_for_numeric(column, value[:from]), condition_value_for_numeric(column, value[:to])]
93
97
  else
94
98
  ["%{search_sql} #{value[:opt]} ?", condition_value_for_numeric(column, value[:from])]
95
99
  end
@@ -100,20 +104,18 @@ module ActiveScaffold
100
104
  if column.text?
101
105
  ["%{search_sql} #{ActiveScaffold::Finder.like_operator} ?", like_pattern.sub('?', value)]
102
106
  else
103
- ["%{search_sql} = ?", ActiveScaffold::Core.column_type_cast(value, column.column)]
107
+ ['%{search_sql} = ?', ActiveScaffold::Core.column_type_cast(value, column.column)]
104
108
  end
105
- elsif ActiveScaffold::Finder::NullComparators.include?(value[:opt])
109
+ elsif ActiveScaffold::Finder::NULL_COMPARATORS.include?(value[:opt])
106
110
  condition_for_null_type(column, value[:opt], like_pattern)
107
111
  elsif value[:from].blank?
108
112
  nil
109
- elsif ActiveScaffold::Finder::StringComparators.values.include?(value[:opt])
113
+ elsif ActiveScaffold::Finder::STRING_COMPARATORS.values.include?(value[:opt])
110
114
  ["%{search_sql} #{ActiveScaffold::Finder.like_operator} ?", value[:opt].sub('?', value[:from])]
111
115
  elsif value[:opt] == 'BETWEEN'
112
- ["(%{search_sql} BETWEEN ? AND ?)", value[:from], value[:to]]
113
- elsif ActiveScaffold::Finder::NumericComparators.include?(value[:opt])
116
+ ['(%{search_sql} BETWEEN ? AND ?)', value[:from], value[:to]]
117
+ elsif ActiveScaffold::Finder::NUMERIC_COMPARATORS.include?(value[:opt])
114
118
  ["%{search_sql} #{value[:opt]} ?", value[:from]]
115
- else
116
- nil
117
119
  end
118
120
  end
119
121
 
@@ -135,7 +137,7 @@ module ActiveScaffold
135
137
 
136
138
  def condition_value_for_datetime(column, value, conversion = :to_time)
137
139
  if value.is_a? Hash
138
- Time.zone.local(*[:year, :month, :day, :hour, :minute, :second].collect {|part| value[part].to_i}) rescue nil
140
+ Time.zone.local(*[:year, :month, :day, :hour, :minute, :second].collect { |part| value[part].to_i }) rescue nil
139
141
  elsif value.respond_to?(:strftime)
140
142
  if conversion == :to_time
141
143
  # Explicitly get the current zone, because TimeWithZone#to_time in rails 3.2.3 returns UTC.
@@ -150,11 +152,11 @@ module ActiveScaffold
150
152
  parts = Date._parse(value)
151
153
  format = I18n.translate "time.formats.#{column.options[:format] || :picker}", :default => '' if ActiveScaffold.js_framework == :jquery
152
154
  if format.blank?
153
- time_parts = [[:hour, '%H'], [:min, '%M'], [:sec, '%S']].collect {|part, format_part| format_part if parts[part].present?}.compact
155
+ time_parts = [[:hour, '%H'], [:min, '%M'], [:sec, '%S']].collect { |part, format_part| format_part if parts[part].present? }.compact
154
156
  format = "#{I18n.t('date.formats.default')} #{time_parts.join(':')} #{'%z' if parts[:offset].present?}"
155
157
  else
156
158
  if parts[:hour]
157
- [[:min, '%M'], [:sec, '%S']].each {|part, f| format.gsub!(":#{f}", '') unless parts[part].present?}
159
+ [[:min, '%M'], [:sec, '%S']].each { |part, f| format.gsub!(":#{f}", '') unless parts[part].present? }
158
160
  else
159
161
  value += ' 00:00:00'
160
162
  end
@@ -198,33 +200,31 @@ module ActiveScaffold
198
200
  from_value = condition_value_for_datetime(column, value[:from], conversion)
199
201
  to_value = condition_value_for_datetime(column, value[:to], conversion)
200
202
 
201
- if from_value.nil? and to_value.nil?
203
+ if from_value.nil? && to_value.nil?
202
204
  nil
203
205
  elsif !from_value
204
- ["%{search_sql} <= ?", to_value.to_s(:db)]
206
+ ['%{search_sql} <= ?', to_value.to_s(:db)]
205
207
  elsif !to_value
206
- ["%{search_sql} >= ?", from_value.to_s(:db)]
208
+ ['%{search_sql} >= ?', from_value.to_s(:db)]
207
209
  else
208
- ["%{search_sql} BETWEEN ? AND ?", from_value.to_s(:db), to_value.to_s(:db)]
210
+ ['%{search_sql} BETWEEN ? AND ?', from_value.to_s(:db), to_value.to_s(:db)]
209
211
  end
210
212
  end
211
213
 
212
214
  def condition_for_record_select_type(column, value, like_pattern = nil)
213
215
  if value.is_a?(Array)
214
- ["%{search_sql} IN (?)", value]
216
+ ['%{search_sql} IN (?)', value]
215
217
  else
216
- ["%{search_sql} = ?", value]
218
+ ['%{search_sql} = ?', value]
217
219
  end
218
220
  end
219
221
 
220
222
  def condition_for_null_type(column, value, like_pattern = nil)
221
- case value.to_sym
222
- when :null
223
- ["%{search_sql} is null", []]
224
- when :not_null
225
- ["%{search_sql} is not null", []]
226
- else
227
- nil
223
+ case value.to_s
224
+ when 'null'
225
+ ['%{search_sql} is null', []]
226
+ when 'not_null'
227
+ ['%{search_sql} is not null', []]
228
228
  end
229
229
  end
230
230
 
@@ -238,7 +238,7 @@ module ActiveScaffold
238
238
  end
239
239
  end
240
240
 
241
- NumericComparators = [
241
+ NUMERIC_COMPARATORS = [
242
242
  '=',
243
243
  '>=',
244
244
  '<=',
@@ -247,17 +247,12 @@ module ActiveScaffold
247
247
  '!=',
248
248
  'BETWEEN'
249
249
  ]
250
- StringComparators = {
250
+ STRING_COMPARATORS = {
251
251
  :contains => '%?%',
252
252
  :begins_with => '?%',
253
253
  :ends_with => '%?'
254
254
  }
255
- NullComparators = [
256
- 'null',
257
- 'not_null'
258
- ]
259
-
260
-
255
+ NULL_COMPARATORS = %w(null not_null)
261
256
 
262
257
  def self.included(klass)
263
258
  klass.extend ClassMethods
@@ -282,7 +277,7 @@ module ActiveScaffold
282
277
 
283
278
  def active_scaffold_includes
284
279
  ActiveSupport::Deprecation.warn "active_scaffold_includes doesn't exist anymore, use active_scaffold_preload, active_scaffold_outer_joins or active_scaffold_references"
285
- self.active_scaffold_preload
280
+ active_scaffold_preload
286
281
  end
287
282
 
288
283
  attr_writer :active_scaffold_habtm_joins
@@ -335,7 +330,7 @@ module ActiveScaffold
335
330
  record = klass.find(id)
336
331
  security_options = {:crud_type => security_options.to_sym} unless security_options.is_a? Hash
337
332
  raise ActiveScaffold::RecordNotAllowed, "#{klass} with id = #{id}" unless record.authorized_for? security_options
338
- return record
333
+ record
339
334
  end
340
335
  # valid options may include:
341
336
  # * :sorting - a Sorting DataStructure (basically an array of hashes of field => direction, e.g. [{:field1 => 'asc'}, {:field2 => 'desc'}]). please note that multi-column sorting has some limitations: if any column in a multi-field sort uses method-based sorting, it will be ignored. method sorting only works for single-column sorting.
@@ -346,13 +341,15 @@ module ActiveScaffold
346
341
  full_includes = (active_scaffold_references.blank? ? nil : active_scaffold_references)
347
342
 
348
343
  # create a general-use options array that's compatible with Rails finders
349
- finder_options = { :reorder => options[:sorting].try(:clause),
350
- :conditions => search_conditions,
351
- :joins => joins_for_finder,
352
- :outer_joins => active_scaffold_outer_joins,
353
- :preload => active_scaffold_preload,
354
- :includes => full_includes,
355
- :select => options[:select]}
344
+ finder_options = {
345
+ :reorder => options[:sorting].try(:clause),
346
+ :conditions => search_conditions,
347
+ :joins => joins_for_finder,
348
+ :outer_joins => active_scaffold_outer_joins,
349
+ :preload => active_scaffold_preload,
350
+ :includes => full_includes,
351
+ :select => options[:select]
352
+ }
356
353
  if Rails::VERSION::MAJOR >= 4
357
354
  if options[:sorting].try(:sorts_by_sql?)
358
355
  options[:sorting].each do |col, _|
@@ -368,7 +365,7 @@ module ActiveScaffold
368
365
 
369
366
  def count_items(query, find_options = {}, count_includes = nil)
370
367
  count_includes ||= find_options[:includes] unless find_options[:conditions].blank?
371
- options = find_options.reject{|k,v| [:select, :reorder].include? k}
368
+ options = find_options.reject { |k, _| [:select, :reorder].include? k }
372
369
  # NOTE: we must use includes in the count query, because some conditions may reference other tables
373
370
  options[:includes] = count_includes
374
371
 
@@ -384,7 +381,7 @@ module ActiveScaffold
384
381
  # See finder_options for valid options
385
382
  def find_page(options = {})
386
383
  options.assert_valid_keys :sorting, :per_page, :page, :count_includes, :pagination, :select
387
- options[:per_page] ||= 999999999
384
+ options[:per_page] ||= 999_999_999
388
385
  options[:page] ||= 1
389
386
 
390
387
  find_options = finder_options(options)
@@ -397,7 +394,7 @@ module ActiveScaffold
397
394
 
398
395
  query = append_to_query(query, find_options)
399
396
  # we build the paginator differently for method- and sql-based sorting
400
- if options[:sorting] and options[:sorting].sorts_by_method?
397
+ if options[:sorting] && options[:sorting].sorts_by_method?
401
398
  pager = ::Paginator.new(count, options[:per_page]) do |offset, per_page|
402
399
  calculate_last_modified(query)
403
400
  sorted_collection = sort_collection_by_column(query.to_a, *options[:sorting].first)
@@ -415,9 +412,8 @@ module ActiveScaffold
415
412
  end
416
413
 
417
414
  def calculate_last_modified(query)
418
- if conditional_get_support? && query.klass.columns_hash['updated_at']
419
- @last_modified = query.maximum(:updated_at)
420
- end
415
+ return unless conditional_get_support? && query.klass.columns_hash['updated_at']
416
+ @last_modified = query.maximum(:updated_at)
421
417
  end
422
418
 
423
419
  def calculate_query
@@ -428,28 +424,29 @@ module ActiveScaffold
428
424
  outer_joins += includes if includes
429
425
  primary_key = active_scaffold_config.model.primary_key
430
426
  subquery = append_to_query(beginning_of_chain, :conditions => conditions, :joins => joins_for_finder, :outer_joins => outer_joins, :select => active_scaffold_config.columns[primary_key].field)
427
+ subquery = subquery.unscope(:order) if Rails::VERSION::MAJOR >= 4
431
428
  active_scaffold_config.model.where(primary_key => subquery)
432
429
  end
433
430
 
434
- def append_to_query(query, options)
431
+ def append_to_query(relation, options)
435
432
  options.assert_valid_keys :where, :select, :group, :reorder, :limit, :offset, :joins, :outer_joins, :includes, :lock, :readonly, :from, :conditions, :preload, (:references if Rails::VERSION::MAJOR >= 4)
436
- query = options.reject{|k,v| v.blank?}.inject(query) do |query, (k, v)|
437
- k == :conditions ? apply_conditions(query, *v) : query.send(k, v)
433
+ relation = options.reject { |_, v| v.blank? }.inject(relation) do |rel, (k, v)|
434
+ k == :conditions ? apply_conditions(rel, *v) : rel.send(k, v)
438
435
  end
439
436
  if options[:outer_joins].present?
440
437
  if Rails::VERSION::MAJOR >= 4
441
- query.distinct_value = true
438
+ relation.distinct_value = true
442
439
  else
443
- query = query.uniq
440
+ relation = relation.uniq
444
441
  end
445
442
  end
446
- query
443
+ relation
447
444
  end
448
445
 
449
446
  def joins_for_finder
450
447
  case joins_for_collection
451
448
  when String
452
- [ joins_for_collection ]
449
+ [joins_for_collection]
453
450
  when Array
454
451
  joins_for_collection
455
452
  else
@@ -457,12 +454,12 @@ module ActiveScaffold
457
454
  end + active_scaffold_habtm_joins
458
455
  end
459
456
 
460
- def apply_conditions(query, *conditions)
461
- conditions.reject(&:blank?).inject(query) do |query, condition|
457
+ def apply_conditions(relation, *conditions)
458
+ conditions.reject(&:blank?).inject(relation) do |rel, condition|
462
459
  if condition.is_a?(Array) && !condition.first.is_a?(String) # multiple conditions
463
- apply_conditions(query, *condition)
460
+ apply_conditions(rel, *condition)
464
461
  else
465
- query.where(condition)
462
+ rel.where(condition)
466
463
  end
467
464
  end
468
465
  end
@@ -470,11 +467,11 @@ module ActiveScaffold
470
467
  # TODO: this should reside on the column, not the controller
471
468
  def sort_collection_by_column(collection, column, order)
472
469
  sorter = column.sort[:method]
473
- collection = collection.sort_by { |record|
470
+ collection = collection.sort_by do |record|
474
471
  value = (sorter.is_a? Proc) ? record.instance_eval(&sorter) : record.instance_eval(sorter.to_s)
475
472
  value = '' if value.nil?
476
473
  value
477
- }
474
+ end
478
475
  collection.reverse! if order.downcase == 'desc'
479
476
  collection
480
477
  end