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.
- checksums.yaml +4 -4
- data/CHANGELOG +39 -0
- data/{LICENSE → LICENSE.md} +1 -1
- data/README.md +27 -19
- data/app/assets/javascripts/active_scaffold.js.erb +1 -1
- data/app/assets/javascripts/jquery/active_scaffold.js +95 -43
- data/app/assets/javascripts/jquery/tiny_mce_bridge.js +30 -6
- data/app/assets/javascripts/prototype/tiny_mce_bridge.js +11 -1
- data/app/assets/stylesheets/active_scaffold_colors.scss +2 -2
- data/app/assets/stylesheets/active_scaffold_layout.css +36 -28
- data/app/views/active_scaffold_overrides/_base_form.html.erb +2 -3
- data/app/views/active_scaffold_overrides/_field_search.html.erb +8 -7
- data/app/views/active_scaffold_overrides/_form_association.html.erb +9 -9
- data/app/views/active_scaffold_overrides/_form_association_footer.html.erb +6 -6
- data/app/views/active_scaffold_overrides/_form_association_record.html.erb +52 -50
- data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_human_conditions.html.erb +3 -1
- data/app/views/active_scaffold_overrides/_list_calculations.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_list_column_headings.html.erb +2 -0
- data/app/views/active_scaffold_overrides/_list_messages.html.erb +5 -3
- data/app/views/active_scaffold_overrides/_list_record.html.erb +3 -1
- data/app/views/active_scaffold_overrides/_list_with_header.html.erb +9 -9
- data/app/views/active_scaffold_overrides/_messages.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_refresh_list.js.erb +18 -10
- data/app/views/active_scaffold_overrides/_render_field.js.erb +3 -3
- data/app/views/active_scaffold_overrides/_search.html.erb +7 -6
- data/app/views/active_scaffold_overrides/_show_actions.html.erb +14 -0
- data/app/views/active_scaffold_overrides/_show_association.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_update_actions.html.erb +6 -2
- data/app/views/active_scaffold_overrides/_update_column.js.erb +1 -1
- data/app/views/active_scaffold_overrides/_update_form.html.erb +1 -1
- data/app/views/active_scaffold_overrides/destroy.js.erb +2 -3
- data/app/views/active_scaffold_overrides/edit_associated.js.erb +4 -3
- data/app/views/active_scaffold_overrides/on_action_update.js.erb +5 -3
- data/app/views/active_scaffold_overrides/on_create.js.erb +4 -4
- data/app/views/active_scaffold_overrides/on_update.js.erb +6 -6
- data/app/views/active_scaffold_overrides/show.html.erb +6 -0
- data/app/views/active_scaffold_overrides/update.html.erb +1 -1
- data/app/views/active_scaffold_overrides/update_column.js.erb +1 -1
- data/config/brakeman.ignore +26 -0
- data/config/brakeman.yml +3 -0
- data/config/i18n-tasks.yml +121 -0
- data/config/locales/de.yml +81 -70
- data/config/locales/en.yml +83 -74
- data/config/locales/es.yml +82 -73
- data/config/locales/fr.yml +86 -75
- data/config/locales/hu.yml +81 -70
- data/config/locales/ja.yml +71 -60
- data/config/locales/ru.yml +85 -74
- data/lib/active_scaffold.rb +3 -0
- data/lib/active_scaffold/actions/common_search.rb +11 -7
- data/lib/active_scaffold/actions/core.rb +119 -47
- data/lib/active_scaffold/actions/create.rb +1 -1
- data/lib/active_scaffold/actions/delete.rb +11 -8
- data/lib/active_scaffold/actions/field_search.rb +104 -6
- data/lib/active_scaffold/actions/list.rb +25 -21
- data/lib/active_scaffold/actions/mark.rb +12 -4
- data/lib/active_scaffold/actions/nested.rb +26 -26
- data/lib/active_scaffold/actions/search.rb +2 -2
- data/lib/active_scaffold/actions/show.rb +4 -5
- data/lib/active_scaffold/actions/subform.rb +9 -7
- data/lib/active_scaffold/actions/update.rb +20 -13
- data/lib/active_scaffold/active_record_permissions.rb +24 -5
- data/lib/active_scaffold/attribute_params.rb +68 -49
- data/lib/active_scaffold/bridges.rb +1 -1
- data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +15 -19
- data/lib/active_scaffold/bridges/bitfields.rb +1 -1
- data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +10 -14
- data/lib/active_scaffold/bridges/calendar_date_select.rb +0 -7
- data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +19 -22
- data/lib/active_scaffold/bridges/cancan.rb +4 -3
- data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +11 -21
- data/lib/active_scaffold/bridges/carrierwave.rb +2 -1
- data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +2 -6
- data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +6 -39
- data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +1 -1
- data/lib/active_scaffold/bridges/chosen.rb +4 -1
- data/lib/active_scaffold/bridges/chosen/helpers.rb +3 -2
- data/lib/active_scaffold/bridges/country_select/country_select_bridge_helper.rb +2 -2
- data/lib/active_scaffold/bridges/date_picker.rb +3 -0
- data/lib/active_scaffold/bridges/date_picker/ext.rb +43 -38
- data/lib/active_scaffold/bridges/date_picker/helper.rb +24 -23
- data/lib/active_scaffold/bridges/dragonfly.rb +1 -1
- data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge.rb +3 -7
- data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +3 -25
- data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +2 -2
- data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +6 -8
- data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +1 -1
- data/lib/active_scaffold/bridges/file_column/form_ui.rb +0 -2
- data/lib/active_scaffold/bridges/file_column/list_ui.rb +2 -1
- data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +1 -1
- data/lib/active_scaffold/bridges/paper_trail/actions.rb +1 -1
- data/lib/active_scaffold/bridges/paper_trail/helper.rb +1 -2
- data/lib/active_scaffold/bridges/paper_trail/paper_trail_bridge.rb +3 -7
- data/lib/active_scaffold/bridges/paperclip.rb +1 -1
- data/lib/active_scaffold/bridges/paperclip/form_ui.rb +3 -28
- data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
- data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +3 -7
- data/lib/active_scaffold/bridges/record_select.rb +2 -0
- data/lib/active_scaffold/bridges/record_select/helpers.rb +14 -18
- data/lib/active_scaffold/bridges/semantic_attributes/column.rb +4 -8
- data/lib/active_scaffold/bridges/shared/date_bridge.rb +20 -20
- data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +7 -22
- data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +14 -14
- data/lib/active_scaffold/config/base.rb +9 -6
- data/lib/active_scaffold/config/core.rb +30 -21
- data/lib/active_scaffold/config/create.rb +2 -1
- data/lib/active_scaffold/config/delete.rb +2 -2
- data/lib/active_scaffold/config/field_search.rb +9 -3
- data/lib/active_scaffold/config/form.rb +4 -4
- data/lib/active_scaffold/config/list.rb +27 -23
- data/lib/active_scaffold/config/nested.rb +4 -4
- data/lib/active_scaffold/config/search.rb +6 -6
- data/lib/active_scaffold/config/show.rb +11 -1
- data/lib/active_scaffold/config/subform.rb +1 -1
- data/lib/active_scaffold/config/update.rb +4 -2
- data/lib/active_scaffold/constraints.rb +39 -36
- data/lib/active_scaffold/core.rb +36 -15
- data/lib/active_scaffold/data_structures/action_columns.rb +14 -9
- data/lib/active_scaffold/data_structures/action_link.rb +4 -5
- data/lib/active_scaffold/data_structures/action_links.rb +5 -4
- data/lib/active_scaffold/data_structures/actions.rb +2 -2
- data/lib/active_scaffold/data_structures/association.rb +8 -0
- data/lib/active_scaffold/data_structures/association/abstract.rb +147 -0
- data/lib/active_scaffold/data_structures/association/active_mongoid.rb +42 -0
- data/lib/active_scaffold/data_structures/association/active_record.rb +94 -0
- data/lib/active_scaffold/data_structures/association/mongoid.rb +45 -0
- data/lib/active_scaffold/data_structures/bridge.rb +3 -6
- data/lib/active_scaffold/data_structures/column.rb +100 -82
- data/lib/active_scaffold/data_structures/columns.rb +21 -3
- data/lib/active_scaffold/data_structures/nested_info.rb +22 -37
- data/lib/active_scaffold/data_structures/set.rb +4 -4
- data/lib/active_scaffold/data_structures/sorting.rb +29 -15
- data/lib/active_scaffold/engine.rb +3 -1
- data/lib/active_scaffold/extensions/action_controller_rendering.rb +10 -5
- data/lib/active_scaffold/extensions/action_view_rendering.rb +65 -59
- data/lib/active_scaffold/extensions/left_outer_joins.rb +48 -53
- data/lib/active_scaffold/extensions/localize.rb +3 -4
- data/lib/active_scaffold/extensions/name_option_for_datetime.rb +7 -11
- data/lib/active_scaffold/extensions/paginator_extensions.rb +20 -18
- data/lib/active_scaffold/extensions/routing_mapper.rb +104 -40
- data/lib/active_scaffold/extensions/to_label.rb +1 -1
- data/lib/active_scaffold/extensions/unsaved_associated.rb +4 -13
- data/lib/active_scaffold/extensions/unsaved_record.rb +12 -1
- data/lib/active_scaffold/finder.rb +200 -134
- data/lib/active_scaffold/helpers/action_link_helpers.rb +398 -0
- data/lib/active_scaffold/helpers/association_helpers.rb +12 -30
- data/lib/active_scaffold/helpers/controller_helpers.rb +74 -24
- data/lib/active_scaffold/helpers/form_column_helpers.rb +205 -112
- data/lib/active_scaffold/helpers/human_condition_helpers.rb +21 -11
- data/lib/active_scaffold/helpers/id_helpers.rb +1 -1
- data/lib/active_scaffold/helpers/list_column_helpers.rb +117 -39
- data/lib/active_scaffold/helpers/pagination_helpers.rb +11 -14
- data/lib/active_scaffold/helpers/search_column_helpers.rb +69 -32
- data/lib/active_scaffold/helpers/show_column_helpers.rb +9 -3
- data/lib/active_scaffold/helpers/view_helpers.rb +41 -426
- data/lib/active_scaffold/orm_checks.rb +109 -0
- data/lib/active_scaffold/paginator.rb +1 -1
- data/lib/active_scaffold/responds_to_parent.rb +12 -10
- data/lib/active_scaffold/tableless.rb +81 -43
- data/lib/active_scaffold/version.rb +2 -2
- data/lib/generators/active_scaffold/controller_generator.rb +49 -0
- data/lib/generators/active_scaffold/install_generator.rb +45 -0
- data/lib/generators/active_scaffold/resource_generator.rb +56 -0
- data/lib/generators/{active_scaffold_controller/templates → templates}/controller.rb +0 -0
- data/lib/generators/{active_scaffold_controller/templates → templates}/helper.rb +0 -0
- data/shoulda_macros/macros.rb +3 -3
- data/test/active_scaffold_config_mock.rb +33 -0
- data/test/bridges/bridge_test.rb +9 -9
- data/test/bridges/date_picker_test.rb +3 -1
- data/test/bridges/paper_trail_test.rb +2 -3
- data/test/bridges/paperclip_test.rb +21 -10
- data/test/bridges/tiny_mce_test.rb +20 -21
- data/test/class_with_finder.rb +42 -0
- data/test/company.rb +6 -4
- data/test/config/core_test.rb +1 -1
- data/test/config/create_test.rb +1 -1
- data/test/config/list_test.rb +3 -3
- data/test/config/update_test.rb +3 -3
- data/test/data_structures/action_columns_test.rb +3 -3
- data/test/data_structures/association_column_test.rb +5 -5
- data/test/data_structures/column_test.rb +14 -14
- data/test/data_structures/columns_test.rb +2 -2
- data/test/data_structures/set_test.rb +2 -2
- data/test/data_structures/sorting_test.rb +6 -4
- data/test/extensions/active_record_test.rb +1 -1
- data/test/extensions/routing_mapper_test.rb +64 -13
- data/test/helpers/form_column_helpers_test.rb +6 -6
- data/test/helpers/list_column_helpers_test.rb +9 -5
- data/test/helpers/pagination_helpers_test.rb +1 -0
- data/test/misc/active_record_permissions_test.rb +18 -1
- data/test/misc/attribute_params_test.rb +26 -17
- data/test/misc/calculation_test.rb +8 -31
- data/test/misc/configurable_test.rb +3 -2
- data/test/misc/constraints_test.rb +33 -22
- data/test/misc/convert_numbers_format_test.rb +28 -10
- data/test/misc/finder_test.rb +6 -29
- data/test/misc/parse_datetime_test.rb +160 -0
- data/test/misc/render_test.rb +1 -1
- data/test/misc/tableless_test.rb +24 -0
- data/test/mock_app/app/models/building.rb +2 -1
- data/test/mock_app/config.ru +1 -1
- data/test/mock_app/config/environments/test.rb +1 -1
- data/test/mock_app/config/routes.rb +11 -3
- data/test/model_stub.rb +11 -6
- data/test/run_all.rb +1 -1
- data/test/test_helper.rb +19 -4
- metadata +42 -23
- data/lib/active_scaffold/data_structures/error_message.rb +0 -22
- data/lib/active_scaffold/extensions/reverse_associations.rb +0 -119
- data/lib/generators/active_scaffold/USAGE +0 -29
- data/lib/generators/active_scaffold/active_scaffold_generator.rb +0 -21
- data/lib/generators/active_scaffold_controller/USAGE +0 -19
- data/lib/generators/active_scaffold_controller/active_scaffold_controller_generator.rb +0 -29
- data/test/data_structures/error_message_test.rb +0 -25
@@ -5,31 +5,85 @@ module ActiveScaffold
|
|
5
5
|
end
|
6
6
|
|
7
7
|
module ClassMethods
|
8
|
+
def self.extended(klass)
|
9
|
+
return unless klass.active_scaffold_config
|
10
|
+
if klass.active_scaffold_config.active_record?
|
11
|
+
klass.extend ActiveRecord
|
12
|
+
elsif klass.active_scaffold_config.mongoid?
|
13
|
+
klass.extend Mongoid
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
8
17
|
# Takes a collection of search terms (the tokens) and creates SQL that
|
9
18
|
# searches all specified ActiveScaffold columns. A row will match if each
|
10
19
|
# token is found in at least one of the columns.
|
11
|
-
def
|
20
|
+
def conditions_for_columns(tokens, columns, text_search = :full)
|
12
21
|
# if there aren't any columns, then just return a nil condition
|
13
22
|
return unless columns.any?
|
14
|
-
like_pattern = like_pattern(text_search)
|
15
23
|
|
16
24
|
tokens = [tokens] if tokens.is_a? String
|
25
|
+
tokens = type_casted_tokens(tokens, columns, like_pattern(text_search))
|
26
|
+
create_conditions_for_columns(tokens, columns)
|
27
|
+
end
|
17
28
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
29
|
+
def type_casted_tokens(tokens, columns, like_pattern)
|
30
|
+
tokens.map do |value|
|
31
|
+
columns.each_with_object({}) do |column, column_tokens|
|
32
|
+
column_tokens[column.name] = column.text? ? like_pattern.sub('?', value) : ActiveScaffold::Core.column_type_cast(value, column.column)
|
22
33
|
end
|
23
34
|
end
|
24
|
-
|
35
|
+
end
|
25
36
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
37
|
+
module ActiveRecord
|
38
|
+
def create_conditions_for_columns(tokens, columns)
|
39
|
+
where_clauses = []
|
40
|
+
columns.each do |column|
|
41
|
+
column.search_sql.each do |search_sql|
|
42
|
+
where_clauses << "#{search_sql} #{column.text? ? ActiveScaffold::Finder.like_operator : '='} ?"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
phrase = where_clauses.join(' OR ')
|
46
|
+
|
47
|
+
tokens.map do |columns_token|
|
48
|
+
columns.each_with_object([phrase]) do |column, condition|
|
49
|
+
condition.concat([columns_token[column.name]] * column.search_sql.size)
|
30
50
|
end
|
31
51
|
end
|
32
52
|
end
|
53
|
+
|
54
|
+
def like_pattern(text_search)
|
55
|
+
case text_search
|
56
|
+
when :full then '%?%'
|
57
|
+
when :start then '?%'
|
58
|
+
when :end then '%?'
|
59
|
+
else '?'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
module Mongoid
|
65
|
+
def create_conditions_for_columns(tokens, columns)
|
66
|
+
conditions = tokens.map do |columns_token|
|
67
|
+
token_conditions = columns.map do |column|
|
68
|
+
value = columns_token[column.name]
|
69
|
+
value = /#{value}/ if column.text?
|
70
|
+
column.search_sql.map do |search_sql|
|
71
|
+
{search_sql => value}
|
72
|
+
end
|
73
|
+
end.flatten
|
74
|
+
active_scaffold_config.model.or(token_conditions).selector
|
75
|
+
end
|
76
|
+
[active_scaffold_config.model.and(conditions).selector]
|
77
|
+
end
|
78
|
+
|
79
|
+
def like_pattern(text_search)
|
80
|
+
case text_search
|
81
|
+
when :full then '?'
|
82
|
+
when :start then '^?'
|
83
|
+
when :end then '?$'
|
84
|
+
else '^?$'
|
85
|
+
end
|
86
|
+
end
|
33
87
|
end
|
34
88
|
|
35
89
|
# Generates an SQL condition for the given ActiveScaffold column based on
|
@@ -38,14 +92,14 @@ module ActiveScaffold
|
|
38
92
|
def condition_for_column(column, value, text_search = :full)
|
39
93
|
like_pattern = like_pattern(text_search)
|
40
94
|
value = value.with_indifferent_access if value.is_a? Hash
|
41
|
-
if
|
95
|
+
if respond_to?("condition_for_#{column.name}_column")
|
42
96
|
return send("condition_for_#{column.name}_column", column, value, like_pattern)
|
43
97
|
end
|
44
|
-
return unless column && column.search_sql &&
|
45
|
-
search_ui = column.search_ui || column.
|
98
|
+
return unless column && column.search_sql && value.present?
|
99
|
+
search_ui = column.search_ui || column.column_type
|
46
100
|
begin
|
47
101
|
sql, *values =
|
48
|
-
if search_ui &&
|
102
|
+
if search_ui && respond_to?("condition_for_#{search_ui}_type")
|
49
103
|
send("condition_for_#{search_ui}_type", column, value, like_pattern)
|
50
104
|
else
|
51
105
|
if column.search_sql.instance_of? Proc
|
@@ -60,7 +114,7 @@ module ActiveScaffold
|
|
60
114
|
conditions += values * column.search_sql.size if values.present?
|
61
115
|
conditions
|
62
116
|
rescue StandardError => e
|
63
|
-
logger.error "#{e.class.name}: #{e.message} -- on the ActiveScaffold column :#{column.name}, search_ui = #{search_ui} in #{name}"
|
117
|
+
Rails.logger.error "#{e.class.name}: #{e.message} -- on the ActiveScaffold column :#{column.name}, search_ui = #{search_ui} in #{name}"
|
64
118
|
raise e
|
65
119
|
end
|
66
120
|
end
|
@@ -76,7 +130,8 @@ module ActiveScaffold
|
|
76
130
|
when :date, :time, :datetime, :timestamp
|
77
131
|
condition_for_datetime(column, value)
|
78
132
|
when :select, :multi_select, :country, :usa_state, :chosen, :multi_chosen
|
79
|
-
|
133
|
+
values = Array(value).select(&:present?)
|
134
|
+
['%{search_sql} in (?)', values] if values.present?
|
80
135
|
else
|
81
136
|
if column.text?
|
82
137
|
["%{search_sql} #{ActiveScaffold::Finder.like_operator} ?", like_pattern.sub('?', value)]
|
@@ -120,61 +175,89 @@ module ActiveScaffold
|
|
120
175
|
end
|
121
176
|
end
|
122
177
|
|
123
|
-
def
|
178
|
+
def tables_for_translating_days_and_months(format)
|
124
179
|
keys = {
|
125
180
|
'%A' => 'date.day_names',
|
126
181
|
'%a' => 'date.abbr_day_names',
|
127
182
|
'%B' => 'date.month_names',
|
128
183
|
'%b' => 'date.abbr_month_names'
|
129
184
|
}
|
130
|
-
keys.
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
end
|
185
|
+
key_index = keys.keys.map { |key| [key, format.index(key)] }.to_h
|
186
|
+
keys.select! { |k, _| key_index[k] }
|
187
|
+
keys.sort_by { |k, _| key_index[k] }.map do |_, k|
|
188
|
+
I18n.t(k).compact.zip(I18n.t(k, :locale => :en).compact).to_h
|
135
189
|
end
|
136
|
-
value
|
137
190
|
end
|
138
191
|
|
139
|
-
def
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
value.send(conversion)
|
192
|
+
def translate_days_and_months(value, format)
|
193
|
+
translated = ''
|
194
|
+
tables_for_translating_days_and_months(format).each do |table|
|
195
|
+
regexp = Regexp.union(table.keys)
|
196
|
+
index = value.index(regexp)
|
197
|
+
next unless index
|
198
|
+
translated << value.slice!(0...index)
|
199
|
+
value.sub!(regexp) do |str|
|
200
|
+
translated << table[str]
|
201
|
+
''
|
150
202
|
end
|
151
|
-
|
152
|
-
|
203
|
+
end
|
204
|
+
translated << value
|
205
|
+
end
|
206
|
+
|
207
|
+
def format_for_datetime(column, value)
|
208
|
+
parts = Date._parse(value)
|
209
|
+
if ActiveScaffold.js_framework == :jquery
|
210
|
+
format = I18n.translate "time.formats.#{column.options[:format] || :picker}", :default => ''
|
211
|
+
end
|
212
|
+
|
213
|
+
if format.blank?
|
214
|
+
time_parts = [[:hour, '%H'], [:min, '%M'], [:sec, '%S']].map do |part, format_part|
|
215
|
+
format_part if parts[part].present?
|
216
|
+
end.compact
|
217
|
+
format = "#{I18n.t('date.formats.default')} #{time_parts.join(':')} #{'%z' if parts[:offset].present?}"
|
153
218
|
else
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
219
|
+
[[:hour, '%H'], [:min, ':%M'], [:sec, ':%S']].each do |part, f|
|
220
|
+
format.gsub!(f, '') if parts[part].blank?
|
221
|
+
end
|
222
|
+
format += ' %z' if parts[:offset].present? && format !~ /%z/i
|
223
|
+
end
|
224
|
+
|
225
|
+
format.gsub!(/.*(?=%H)/, '') if !parts[:year] && !parts[:month] && !parts[:mday]
|
226
|
+
[format, parts[:offset]]
|
227
|
+
end
|
228
|
+
|
229
|
+
def condition_value_for_datetime(column, value, conversion = :to_time)
|
230
|
+
unless value.nil? || value.blank?
|
231
|
+
if value.is_a? Hash
|
232
|
+
time = Time.zone.local(*%i[year month day hour minute second].collect { |part| value[part].to_i }) rescue nil
|
233
|
+
time.send(conversion) if time
|
234
|
+
elsif value.respond_to?(:strftime)
|
235
|
+
if conversion == :to_time
|
236
|
+
# Explicitly get the current zone, because TimeWithZone#to_time in rails 3.2.3 returns UTC.
|
237
|
+
# https://github.com/rails/rails/pull/2453
|
238
|
+
value.to_time.in_time_zone
|
162
239
|
else
|
163
|
-
value
|
240
|
+
value.send(conversion)
|
164
241
|
end
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
value =
|
169
|
-
|
170
|
-
value
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
242
|
+
elsif conversion == :to_date
|
243
|
+
format = I18n.t("date.formats.#{column.options[:format] || :default}")
|
244
|
+
format.gsub!(/%-d|%-m|%_m/) { |s| s.gsub(/[-_]/, '') } # strptime fails with %-d, %-m, %_m
|
245
|
+
value = translate_days_and_months(value, format) if I18n.locale != :en
|
246
|
+
Date.strptime(value, format) rescue nil
|
247
|
+
elsif value.include?('T')
|
248
|
+
Time.zone.parse(value)
|
249
|
+
else # datetime
|
250
|
+
format, offset = format_for_datetime(column, value)
|
251
|
+
format.gsub!(/%-d|%-m|%_m/) { |s| s.gsub(/[-_]/, '') } # strptime fails with %-d, %-m, %_m
|
252
|
+
value = translate_days_and_months(value, format) if I18n.locale != :en
|
253
|
+
time = DateTime.strptime(value, format) rescue nil
|
254
|
+
if time
|
255
|
+
time = Time.zone.local_to_utc(time).in_time_zone unless offset
|
256
|
+
time = time.send(conversion) unless conversion == :to_time
|
257
|
+
end
|
258
|
+
time
|
175
259
|
end
|
176
|
-
|
177
|
-
end unless value.nil? || value.blank?
|
260
|
+
end
|
178
261
|
end
|
179
262
|
|
180
263
|
def condition_value_for_numeric(column, value)
|
@@ -185,9 +268,9 @@ module ActiveScaffold
|
|
185
268
|
when :float then value.to_f
|
186
269
|
when :decimal
|
187
270
|
if Rails.version >= '4.2.0'
|
188
|
-
ActiveRecord::Type::Decimal.new.type_cast_from_user(value)
|
271
|
+
::ActiveRecord::Type::Decimal.new.type_cast_from_user(value)
|
189
272
|
else
|
190
|
-
ActiveRecord::ConnectionAdapters::Column.value_to_decimal(value)
|
273
|
+
::ActiveRecord::ConnectionAdapters::Column.value_to_decimal(value)
|
191
274
|
end
|
192
275
|
else
|
193
276
|
value
|
@@ -234,15 +317,6 @@ module ActiveScaffold
|
|
234
317
|
['%{search_sql} is not null', []]
|
235
318
|
end
|
236
319
|
end
|
237
|
-
|
238
|
-
def like_pattern(text_search)
|
239
|
-
case text_search
|
240
|
-
when :full then '%?%'
|
241
|
-
when :start then '?%'
|
242
|
-
when :end then '%?'
|
243
|
-
else '?'
|
244
|
-
end
|
245
|
-
end
|
246
320
|
end
|
247
321
|
|
248
322
|
NUMERIC_COMPARATORS = [
|
@@ -253,13 +327,13 @@ module ActiveScaffold
|
|
253
327
|
'<',
|
254
328
|
'!=',
|
255
329
|
'BETWEEN'
|
256
|
-
]
|
330
|
+
].freeze
|
257
331
|
STRING_COMPARATORS = {
|
258
332
|
:contains => '%?%',
|
259
333
|
:begins_with => '?%',
|
260
334
|
:ends_with => '%?'
|
261
|
-
}
|
262
|
-
NULL_COMPARATORS = %w
|
335
|
+
}.freeze
|
336
|
+
NULL_COMPARATORS = %w[null not_null].freeze
|
263
337
|
|
264
338
|
def self.included(klass)
|
265
339
|
klass.extend ClassMethods
|
@@ -277,16 +351,6 @@ module ActiveScaffold
|
|
277
351
|
@active_scaffold_preload ||= []
|
278
352
|
end
|
279
353
|
|
280
|
-
def active_scaffold_includes=(value)
|
281
|
-
ActiveSupport::Deprecation.warn "active_scaffold_includes doesn't exist anymore, use active_scaffold_preload, active_scaffold_outer_joins or active_scaffold_references"
|
282
|
-
self.active_scaffold_preload = value
|
283
|
-
end
|
284
|
-
|
285
|
-
def active_scaffold_includes
|
286
|
-
ActiveSupport::Deprecation.warn "active_scaffold_includes doesn't exist anymore, use active_scaffold_preload, active_scaffold_outer_joins or active_scaffold_references"
|
287
|
-
active_scaffold_preload
|
288
|
-
end
|
289
|
-
|
290
354
|
attr_writer :active_scaffold_habtm_joins
|
291
355
|
def active_scaffold_habtm_joins
|
292
356
|
@active_scaffold_habtm_joins ||= []
|
@@ -303,18 +367,20 @@ module ActiveScaffold
|
|
303
367
|
end
|
304
368
|
|
305
369
|
# Override this method on your controller to define conditions to be used when querying a recordset (e.g. for List). The return of this method should be any format compatible with the :conditions clause of ActiveRecord::Base's find.
|
306
|
-
def conditions_for_collection
|
307
|
-
end
|
370
|
+
def conditions_for_collection; end
|
308
371
|
|
309
372
|
# Override this method on your controller to define joins to be used when querying a recordset (e.g. for List). The return of this method should be any format compatible with the :joins clause of ActiveRecord::Base's find.
|
310
|
-
def joins_for_collection
|
311
|
-
end
|
373
|
+
def joins_for_collection; end
|
312
374
|
|
313
375
|
# Override this method on your controller to provide custom finder options to the find() call. The return of this method should be a hash.
|
314
376
|
def custom_finder_options
|
315
377
|
{}
|
316
378
|
end
|
317
379
|
|
380
|
+
def active_scaffold_embedded_conditions
|
381
|
+
params_hash active_scaffold_embedded_params[:conditions]
|
382
|
+
end
|
383
|
+
|
318
384
|
def all_conditions
|
319
385
|
[
|
320
386
|
id_condition, # for list with id (e.g. /users/:id/index)
|
@@ -322,12 +388,12 @@ module ActiveScaffold
|
|
322
388
|
conditions_for_collection, # from the dev
|
323
389
|
conditions_from_params, # from the parameters (e.g. /users/list?first_name=Fred)
|
324
390
|
conditions_from_constraints, # from any constraints (embedded scaffolds)
|
325
|
-
|
391
|
+
active_scaffold_embedded_conditions # embedding conditions (weaker constraints)
|
326
392
|
].reject(&:blank?)
|
327
393
|
end
|
328
394
|
|
329
395
|
def id_condition
|
330
|
-
{active_scaffold_config.
|
396
|
+
{active_scaffold_config.primary_key => params[:id]} if params[:id]
|
331
397
|
end
|
332
398
|
|
333
399
|
# returns a single record (the given id) but only if it's allowed for the specified security options.
|
@@ -339,26 +405,30 @@ module ActiveScaffold
|
|
339
405
|
raise ActiveScaffold::RecordNotAllowed, "#{klass} with id = #{id}" unless record.authorized_for? security_options
|
340
406
|
record
|
341
407
|
end
|
408
|
+
|
342
409
|
# valid options may include:
|
343
410
|
# * :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.
|
344
411
|
# * :per_page
|
345
412
|
# * :page
|
346
413
|
def finder_options(options = {})
|
347
414
|
search_conditions = all_conditions
|
348
|
-
full_includes = (active_scaffold_references.blank? ? nil : active_scaffold_references)
|
349
415
|
|
350
416
|
# create a general-use options array that's compatible with Rails finders
|
351
417
|
finder_options = {
|
352
|
-
:reorder => options[:sorting].try(:clause),
|
353
|
-
:conditions => search_conditions
|
354
|
-
:joins => joins_for_finder,
|
355
|
-
:outer_joins => active_scaffold_outer_joins,
|
356
|
-
:preload => active_scaffold_preload,
|
357
|
-
:includes => full_includes,
|
358
|
-
:select => options[:select]
|
418
|
+
:reorder => options[:sorting].try(:clause, (grouped_columns_calculations if grouped_search?)),
|
419
|
+
:conditions => search_conditions
|
359
420
|
}
|
360
|
-
if
|
361
|
-
finder_options
|
421
|
+
if active_scaffold_config.mongoid?
|
422
|
+
finder_options[:includes] = [active_scaffold_references, active_scaffold_preload].compact.flatten.uniq.presence
|
423
|
+
else
|
424
|
+
finder_options.merge!(
|
425
|
+
:joins => joins_for_finder,
|
426
|
+
:left_joins => active_scaffold_outer_joins,
|
427
|
+
:preload => active_scaffold_preload,
|
428
|
+
:includes => active_scaffold_references.presence,
|
429
|
+
:references => active_scaffold_references.presence,
|
430
|
+
:select => options[:select]
|
431
|
+
)
|
362
432
|
end
|
363
433
|
|
364
434
|
finder_options.merge! custom_finder_options
|
@@ -366,8 +436,8 @@ module ActiveScaffold
|
|
366
436
|
end
|
367
437
|
|
368
438
|
def count_items(query, find_options = {}, count_includes = nil)
|
369
|
-
count_includes ||= find_options[:includes]
|
370
|
-
options = find_options.reject { |k, _| [
|
439
|
+
count_includes ||= find_options[:includes] if find_options[:conditions].present?
|
440
|
+
options = find_options.reject { |k, _| %i[select reorder order].include? k }
|
371
441
|
# NOTE: we must use includes in the count query, because some conditions may reference other tables
|
372
442
|
options[:includes] = count_includes
|
373
443
|
|
@@ -396,20 +466,20 @@ module ActiveScaffold
|
|
396
466
|
|
397
467
|
query = append_to_query(query, find_options)
|
398
468
|
# we build the paginator differently for method- and sql-based sorting
|
399
|
-
if options[:sorting] && options[:sorting].sorts_by_method?
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
469
|
+
pager = if options[:sorting] && options[:sorting].sorts_by_method?
|
470
|
+
::Paginator.new(count, options[:per_page]) do |offset, per_page|
|
471
|
+
calculate_last_modified(query)
|
472
|
+
sorted_collection = sort_collection_by_column(query.to_a, *options[:sorting].first)
|
473
|
+
sorted_collection = sorted_collection.slice(offset, per_page) if options[:pagination]
|
474
|
+
sorted_collection
|
475
|
+
end
|
476
|
+
else
|
477
|
+
::Paginator.new(count, options[:per_page]) do |offset, per_page|
|
478
|
+
query = append_to_query(query, :offset => offset, :limit => per_page) if options[:pagination]
|
479
|
+
calculate_last_modified(query)
|
480
|
+
query
|
481
|
+
end
|
482
|
+
end
|
413
483
|
pager.page(options[:page])
|
414
484
|
end
|
415
485
|
|
@@ -421,38 +491,34 @@ module ActiveScaffold
|
|
421
491
|
def calculate_query
|
422
492
|
conditions = all_conditions
|
423
493
|
includes = active_scaffold_config.list.count_includes
|
424
|
-
includes ||= active_scaffold_references
|
425
|
-
|
426
|
-
|
427
|
-
primary_key = active_scaffold_config.
|
428
|
-
subquery = append_to_query(beginning_of_chain, :conditions => conditions, :joins => joins_for_finder, :
|
429
|
-
subquery = subquery.unscope(:order)
|
494
|
+
includes ||= active_scaffold_references if conditions.present?
|
495
|
+
left_joins = active_scaffold_outer_joins
|
496
|
+
left_joins += includes if includes
|
497
|
+
primary_key = active_scaffold_config.primary_key
|
498
|
+
subquery = append_to_query(beginning_of_chain, :conditions => conditions, :joins => joins_for_finder, :left_joins => left_joins, :select => active_scaffold_config.columns[primary_key].field)
|
499
|
+
subquery = subquery.unscope(:order)
|
430
500
|
active_scaffold_config.model.where(primary_key => subquery)
|
431
501
|
end
|
432
502
|
|
433
503
|
def append_to_query(relation, options)
|
434
|
-
options.assert_valid_keys :where, :select, :having, :group, :reorder, :limit, :offset, :joins, :
|
504
|
+
options.assert_valid_keys :where, :select, :having, :group, :reorder, :order, :limit, :offset, :joins, :left_joins, :left_outer_joins, :includes, :lock, :readonly, :from, :conditions, :preload, :references
|
435
505
|
relation = options.reject { |_, v| v.blank? }.inject(relation) do |rel, (k, v)|
|
436
506
|
k == :conditions ? apply_conditions(rel, *v) : rel.send(k, v)
|
437
507
|
end
|
438
|
-
if options[:
|
439
|
-
|
440
|
-
relation.distinct_value = true
|
441
|
-
else
|
442
|
-
relation = relation.uniq
|
443
|
-
end
|
508
|
+
if options[:left_outer_joins].present? || options[:left_joins].present?
|
509
|
+
relation.distinct_value = true
|
444
510
|
end
|
445
511
|
relation
|
446
512
|
end
|
447
513
|
|
448
514
|
def joins_for_finder
|
449
515
|
case joins_for_collection
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
516
|
+
when String
|
517
|
+
[joins_for_collection]
|
518
|
+
when Array
|
519
|
+
joins_for_collection
|
520
|
+
else
|
521
|
+
[]
|
456
522
|
end + active_scaffold_habtm_joins
|
457
523
|
end
|
458
524
|
|
@@ -474,7 +540,7 @@ module ActiveScaffold
|
|
474
540
|
value = '' if value.nil?
|
475
541
|
value
|
476
542
|
end
|
477
|
-
collection.reverse! if order.
|
543
|
+
collection.reverse! if order.casecmp('DESC').zero?
|
478
544
|
collection
|
479
545
|
end
|
480
546
|
end
|