active_scaffold 3.3.3 → 3.4.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/README.md +5 -3
- data/app/assets/images/active_scaffold/refresh.png +0 -0
- data/app/assets/javascripts/jquery/active_scaffold.js +182 -91
- data/app/assets/javascripts/jquery/date_picker_bridge.js.erb +14 -16
- data/app/assets/javascripts/jquery/draggable_lists.js +33 -26
- data/app/assets/javascripts/jquery/jquery.editinplace.js +3 -3
- data/app/assets/javascripts/prototype/active_scaffold.js +61 -19
- data/app/assets/stylesheets/active_scaffold_colors.css.scss +4 -0
- data/app/assets/stylesheets/active_scaffold_images.css.scss +3 -0
- data/app/assets/stylesheets/active_scaffold_layout.css +23 -2
- data/app/views/active_scaffold_overrides/_add_existing_form.html.erb +1 -3
- data/app/views/active_scaffold_overrides/_base_form.html.erb +7 -5
- data/app/views/active_scaffold_overrides/_field_search.html.erb +1 -2
- data/app/views/active_scaffold_overrides/_form.html.erb +6 -4
- data/app/views/active_scaffold_overrides/_form_association.html.erb +4 -3
- data/app/views/active_scaffold_overrides/_form_association_footer.html.erb +5 -5
- data/app/views/active_scaffold_overrides/_form_association_record.html.erb +8 -6
- data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +3 -2
- data/app/views/active_scaffold_overrides/_list.html.erb +8 -6
- data/app/views/active_scaffold_overrides/_list_column_headings.html.erb +1 -4
- data/app/views/active_scaffold_overrides/_list_pagination.html.erb +4 -4
- data/app/views/active_scaffold_overrides/_list_pagination_links.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_list_record.html.erb +3 -3
- data/app/views/active_scaffold_overrides/_refresh_list.js.erb +8 -1
- data/app/views/active_scaffold_overrides/_search.html.erb +7 -13
- data/app/views/active_scaffold_overrides/_show_columns.html.erb +1 -1
- data/app/views/active_scaffold_overrides/on_create.js.erb +4 -4
- data/app/views/active_scaffold_overrides/render_field_inplace.html.erb +1 -1
- data/app/views/active_scaffold_overrides/row.js.erb +1 -1
- data/config/locales/de.yml +106 -95
- data/config/locales/en.yml +108 -97
- data/config/locales/es.yml +109 -98
- data/config/locales/fr.yml +108 -97
- data/config/locales/hu.yml +109 -98
- data/config/locales/ja.yml +100 -89
- data/config/locales/ru.yml +115 -104
- data/lib/active_scaffold.rb +18 -294
- data/lib/active_scaffold/actions/common_search.rb +50 -17
- data/lib/active_scaffold/actions/core.rb +93 -22
- data/lib/active_scaffold/actions/create.rb +15 -6
- data/lib/active_scaffold/actions/field_search.rb +68 -60
- data/lib/active_scaffold/actions/list.rb +49 -28
- data/lib/active_scaffold/actions/nested.rb +14 -6
- data/lib/active_scaffold/actions/search.rb +36 -35
- data/lib/active_scaffold/actions/show.rb +9 -4
- data/lib/active_scaffold/actions/subform.rb +1 -1
- data/lib/active_scaffold/actions/update.rb +22 -7
- data/lib/active_scaffold/active_record_permissions.rb +125 -118
- data/lib/active_scaffold/attribute_params.rb +84 -66
- data/lib/active_scaffold/bridges.rb +3 -3
- data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +10 -5
- data/lib/active_scaffold/bridges/cancan.rb +2 -1
- data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +13 -2
- data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +11 -6
- data/lib/active_scaffold/bridges/chosen/helpers.rb +2 -2
- data/lib/active_scaffold/bridges/country_helper/country_helper_bridge.rb +45 -29
- data/lib/active_scaffold/bridges/date_picker/ext.rb +11 -6
- data/lib/active_scaffold/bridges/date_picker/helper.rb +5 -1
- data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +10 -5
- data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +6 -1
- data/lib/active_scaffold/bridges/file_column/form_ui.rb +12 -11
- data/lib/active_scaffold/bridges/paperclip/form_ui.rb +14 -6
- data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
- data/lib/active_scaffold/bridges/record_select/helpers.rb +15 -12
- data/lib/active_scaffold/bridges/shared/date_bridge.rb +7 -8
- data/lib/active_scaffold/bridges/tiny_mce.rb +5 -3
- data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +4 -5
- data/lib/active_scaffold/config/base.rb +4 -0
- data/lib/active_scaffold/config/core.rb +12 -5
- data/lib/active_scaffold/config/delete.rb +0 -2
- data/lib/active_scaffold/config/field_search.rb +1 -4
- data/lib/active_scaffold/config/form.rb +0 -2
- data/lib/active_scaffold/config/list.rb +31 -1
- data/lib/active_scaffold/config/search.rb +0 -3
- data/lib/active_scaffold/config/show.rb +0 -6
- data/lib/active_scaffold/config/subform.rb +1 -0
- data/lib/active_scaffold/configurable.rb +2 -2
- data/lib/active_scaffold/constraints.rb +11 -14
- data/lib/active_scaffold/core.rb +277 -0
- data/lib/active_scaffold/data_structures/action_columns.rb +18 -2
- data/lib/active_scaffold/data_structures/action_link.rb +25 -6
- data/lib/active_scaffold/data_structures/action_links.rb +9 -4
- data/lib/active_scaffold/data_structures/actions.rb +1 -1
- data/lib/active_scaffold/data_structures/column.rb +6 -6
- data/lib/active_scaffold/data_structures/columns.rb +2 -2
- data/lib/active_scaffold/data_structures/nested_info.rb +5 -1
- data/lib/active_scaffold/data_structures/sorting.rb +15 -5
- data/lib/active_scaffold/delayed_setup.rb +30 -0
- data/lib/active_scaffold/engine.rb +25 -0
- data/lib/active_scaffold/extensions/action_view_rendering.rb +1 -1
- data/lib/active_scaffold/extensions/left_outer_joins.rb +61 -21
- data/lib/active_scaffold/extensions/localize.rb +1 -1
- data/lib/active_scaffold/extensions/name_option_for_datetime.rb +13 -8
- data/lib/active_scaffold/extensions/paginator_extensions.rb +5 -1
- data/lib/active_scaffold/extensions/reverse_associations.rb +1 -0
- data/lib/active_scaffold/extensions/routing_mapper.rb +1 -1
- data/lib/active_scaffold/extensions/unsaved_record.rb +4 -6
- data/lib/active_scaffold/finder.rb +79 -27
- data/lib/active_scaffold/helpers/association_helpers.rb +48 -18
- data/lib/active_scaffold/helpers/controller_helpers.rb +19 -10
- data/lib/active_scaffold/helpers/form_column_helpers.rb +185 -87
- data/lib/active_scaffold/helpers/human_condition_helpers.rb +2 -1
- data/lib/active_scaffold/helpers/id_helpers.rb +14 -8
- data/lib/active_scaffold/helpers/list_column_helpers.rb +65 -56
- data/lib/active_scaffold/helpers/pagination_helpers.rb +5 -1
- data/lib/active_scaffold/helpers/search_column_helpers.rb +21 -18
- data/lib/active_scaffold/helpers/view_helpers.rb +102 -64
- data/lib/active_scaffold/responds_to_parent.rb +39 -64
- data/lib/active_scaffold/tableless.rb +129 -10
- data/lib/active_scaffold/version.rb +2 -2
- data/test/bridges/bridge_test.rb +1 -1
- data/test/bridges/date_picker_test.rb +2 -2
- data/test/bridges/paperclip_test.rb +10 -8
- data/test/bridges/tiny_mce_test.rb +2 -2
- data/test/company.rb +22 -10
- data/test/config/base_test.rb +1 -1
- data/test/config/core_test.rb +8 -6
- data/test/config/create_test.rb +6 -6
- data/test/config/delete_test.rb +4 -4
- data/test/config/field_search_test.rb +6 -6
- data/test/config/list_test.rb +7 -7
- data/test/config/nested_test.rb +8 -7
- data/test/config/search_test.rb +7 -7
- data/test/config/show_test.rb +5 -5
- data/test/config/subform_test.rb +1 -1
- data/test/config/update_test.rb +5 -4
- data/test/data_structures/action_columns_test.rb +15 -16
- data/test/data_structures/action_link_test.rb +10 -10
- data/test/data_structures/action_links_test.rb +6 -6
- data/test/data_structures/actions_test.rb +4 -4
- data/test/data_structures/association_column_test.rb +4 -4
- data/test/data_structures/column_test.rb +9 -9
- data/test/data_structures/columns_test.rb +7 -7
- data/test/data_structures/error_message_test.rb +2 -4
- data/test/data_structures/set_test.rb +13 -13
- data/test/data_structures/sorting_test.rb +8 -8
- data/test/data_structures/standard_column_test.rb +2 -2
- data/test/data_structures/validation_reflection_test.rb +8 -8
- data/test/data_structures/virtual_column_test.rb +5 -5
- data/test/extensions/active_record_test.rb +1 -1
- data/test/helpers/form_column_helpers_test.rb +5 -5
- data/test/helpers/list_column_helpers_test.rb +2 -1
- data/test/helpers/pagination_helpers_test.rb +1 -1
- data/test/misc/active_record_permissions_test.rb +23 -4
- data/test/misc/attribute_params_test.rb +304 -136
- data/test/misc/calculation_test.rb +55 -0
- data/test/misc/configurable_test.rb +22 -21
- data/test/misc/constraints_test.rb +10 -7
- data/test/misc/convert_numbers_format_test.rb +149 -0
- data/test/misc/finder_test.rb +17 -13
- data/test/misc/lang_test.rb +1 -1
- data/test/misc/tableless_test.rb +18 -0
- data/test/mock_app/app/controllers/addresses_controller.rb +4 -0
- data/test/mock_app/app/controllers/buildings_controller.rb +4 -0
- data/test/mock_app/app/controllers/cars_controller.rb +4 -0
- data/test/mock_app/app/controllers/contacts_controller.rb +4 -0
- data/test/mock_app/app/controllers/floors_controller.rb +6 -0
- data/test/mock_app/app/controllers/people_controller.rb +4 -0
- data/test/mock_app/app/models/address.rb +3 -0
- data/test/mock_app/app/models/building.rb +8 -0
- data/test/mock_app/app/models/car.rb +3 -0
- data/test/mock_app/app/models/contact.rb +3 -0
- data/test/mock_app/app/models/file_model.rb +19 -0
- data/test/mock_app/app/models/floor.rb +8 -0
- data/test/mock_app/app/models/person.rb +11 -0
- data/test/mock_app/config/application.rb +2 -0
- data/test/mock_app/config/environments/test.rb +1 -1
- data/test/mock_app/config/initializers/secret_token.rb +5 -1
- data/test/mock_app/config/routes.rb +1 -1
- data/test/mock_app/db/schema.rb +51 -0
- data/test/model_stub.rb +3 -3
- data/test/test_helper.rb +15 -12
- metadata +51 -50
- data/lib/active_scaffold/extensions/array.rb +0 -7
- data/lib/active_scaffold/extensions/cache_association.rb +0 -16
- data/lib/active_scaffold/extensions/usa_state.rb +0 -46
- data/lib/active_scaffold_env.rb +0 -13
- data/test/extensions/array_test.rb +0 -12
- data/test/mock_app/public/blank.html +0 -33
- data/test/mock_app/public/images/active_scaffold/DO_NOT_EDIT +0 -2
- data/test/mock_app/public/images/active_scaffold/default/add.gif +0 -0
- data/test/mock_app/public/images/active_scaffold/default/arrow_down.gif +0 -0
- data/test/mock_app/public/images/active_scaffold/default/arrow_up.gif +0 -0
- data/test/mock_app/public/images/active_scaffold/default/close.gif +0 -0
- data/test/mock_app/public/images/active_scaffold/default/cross.png +0 -0
- data/test/mock_app/public/images/active_scaffold/default/indicator-small.gif +0 -0
- data/test/mock_app/public/images/active_scaffold/default/indicator.gif +0 -0
- data/test/mock_app/public/images/active_scaffold/default/magnifier.png +0 -0
- data/test/mock_app/public/javascripts/active_scaffold/DO_NOT_EDIT +0 -2
- data/test/mock_app/public/javascripts/active_scaffold/default/active_scaffold.js +0 -532
- data/test/mock_app/public/javascripts/active_scaffold/default/dhtml_history.js +0 -867
- data/test/mock_app/public/javascripts/active_scaffold/default/form_enhancements.js +0 -117
- data/test/mock_app/public/javascripts/active_scaffold/default/rico_corner.js +0 -370
- data/test/mock_app/public/stylesheets/active_scaffold/DO_NOT_EDIT +0 -2
- data/test/mock_app/public/stylesheets/active_scaffold/default/stylesheet-ie.css +0 -35
- data/test/mock_app/public/stylesheets/active_scaffold/default/stylesheet.css +0 -848
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
class Object
|
|
2
2
|
def as_(key, options = {})
|
|
3
3
|
unless key.blank?
|
|
4
|
-
text = I18n.translate
|
|
4
|
+
text = I18n.translate("#{key}", {:scope => [:active_scaffold, *options.delete(:scope)], :default => key.is_a?(String) ? key : key.to_s.titleize}.merge(options)).html_safe
|
|
5
5
|
# text = nil if text.include?('translation missing:')
|
|
6
6
|
end
|
|
7
7
|
text ||= key
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
module
|
|
2
|
-
module
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
module ActiveScaffold
|
|
2
|
+
module DateSelectExtension
|
|
3
|
+
def datetime_selector_with_name(options, html_options)
|
|
4
|
+
options.merge!(:prefix => options[:name].gsub(/\[[^\[]*\]$/,'')) if options[:name]
|
|
5
|
+
datetime_selector_without_name(options, html_options)
|
|
6
|
+
end
|
|
7
|
+
def self.included(base)
|
|
8
|
+
base.class_eval do
|
|
9
|
+
alias_method_chain :datetime_selector, :name
|
|
10
|
+
private :datetime_selector_without_name, :datetime_selector_with_name, :datetime_selector
|
|
8
11
|
end
|
|
9
|
-
alias_method_chain :datetime_selector, :name
|
|
10
12
|
end
|
|
11
13
|
end
|
|
12
14
|
end
|
|
15
|
+
(defined?(ActionView::Helpers::Tags::DateSelect) ? ActionView::Helpers::Tags::DateSelect : ActionView::Helpers::InstanceTag).class_eval do
|
|
16
|
+
include ActiveScaffold::DateSelectExtension
|
|
17
|
+
end
|
|
@@ -4,7 +4,7 @@ class Paginator
|
|
|
4
4
|
|
|
5
5
|
# Total number of pages
|
|
6
6
|
def number_of_pages_with_infinite
|
|
7
|
-
number_of_pages_without_infinite
|
|
7
|
+
number_of_pages_without_infinite if @count
|
|
8
8
|
end
|
|
9
9
|
alias_method_chain :number_of_pages, :infinite
|
|
10
10
|
|
|
@@ -12,6 +12,10 @@ class Paginator
|
|
|
12
12
|
def infinite?
|
|
13
13
|
@count.nil?
|
|
14
14
|
end
|
|
15
|
+
|
|
16
|
+
def count
|
|
17
|
+
@count || first.items.size
|
|
18
|
+
end
|
|
15
19
|
|
|
16
20
|
class Page
|
|
17
21
|
# Checks to see if there's a page after this one
|
|
@@ -28,6 +28,7 @@ module ActiveRecord
|
|
|
28
28
|
|
|
29
29
|
# stage 1 filter: collect associations that point back to this model and use the same foreign_key
|
|
30
30
|
klass.reflect_on_all_associations.each do |assoc|
|
|
31
|
+
next if assoc == self
|
|
31
32
|
if self.options[:through]
|
|
32
33
|
# only iterate has_many :through associations
|
|
33
34
|
next unless assoc.options[:through]
|
|
@@ -2,7 +2,7 @@ module ActionDispatch
|
|
|
2
2
|
module Routing
|
|
3
3
|
ACTIVE_SCAFFOLD_CORE_ROUTING = {
|
|
4
4
|
:collection => {:show_search => :get, :render_field => :post, :mark => :post},
|
|
5
|
-
:member => {:
|
|
5
|
+
:member => {:update_column => :post, :render_field => [:get, :post], :mark => :post}
|
|
6
6
|
}
|
|
7
7
|
ACTIVE_SCAFFOLD_ASSOCIATION_ROUTING = {
|
|
8
8
|
:collection => {:edit_associated => :get, :new_existing => :get, :add_existing => :post},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# a simple (manual) unsaved? flag and method. at least it automatically reverts after a save!
|
|
2
|
-
|
|
2
|
+
module ActiveScaffold::UnsavedRecord
|
|
3
3
|
# acts like a dirty? flag, manually thrown during update_record_from_params.
|
|
4
4
|
def unsaved=(val)
|
|
5
5
|
@unsaved = (val) ? true : false
|
|
@@ -11,10 +11,8 @@ class ActiveRecord::Base
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
# automatically unsets the unsaved flag
|
|
14
|
-
def
|
|
15
|
-
|
|
16
|
-
self.unsaved = false
|
|
17
|
-
return result
|
|
14
|
+
def save(*)
|
|
15
|
+
super.tap { self.unsaved = false }
|
|
18
16
|
end
|
|
19
|
-
alias_method_chain :save, :unsaved_flag
|
|
20
17
|
end
|
|
18
|
+
ActiveRecord::Base.class_eval { include ActiveScaffold::UnsavedRecord }
|
|
@@ -76,7 +76,7 @@ module ActiveScaffold
|
|
|
76
76
|
conditions += values*column.search_sql.size if values.present?
|
|
77
77
|
conditions
|
|
78
78
|
rescue Exception => e
|
|
79
|
-
logger.error
|
|
79
|
+
logger.error "#{e.class.name}: #{e.message} -- on the ActiveScaffold column :#{column.name}, search_ui = #{search_ui} in #{self.name}"
|
|
80
80
|
raise e
|
|
81
81
|
end
|
|
82
82
|
end
|
|
@@ -270,9 +270,19 @@ module ActiveScaffold
|
|
|
270
270
|
@active_scaffold_conditions ||= []
|
|
271
271
|
end
|
|
272
272
|
|
|
273
|
-
attr_writer :
|
|
273
|
+
attr_writer :active_scaffold_preload
|
|
274
|
+
def active_scaffold_preload
|
|
275
|
+
@active_scaffold_preload ||= []
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def active_scaffold_includes=(value)
|
|
279
|
+
ActiveSupport::Deprecation.warn "active_scaffold_includes doesn't exist anymore, use active_scaffold_preload, active_scaffold_outer_joins or active_scaffold_references"
|
|
280
|
+
self.active_scaffold_preload = value
|
|
281
|
+
end
|
|
282
|
+
|
|
274
283
|
def active_scaffold_includes
|
|
275
|
-
|
|
284
|
+
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
|
|
276
286
|
end
|
|
277
287
|
|
|
278
288
|
attr_writer :active_scaffold_habtm_joins
|
|
@@ -284,9 +294,28 @@ module ActiveScaffold
|
|
|
284
294
|
def active_scaffold_outer_joins
|
|
285
295
|
@active_scaffold_outer_joins ||= []
|
|
286
296
|
end
|
|
297
|
+
|
|
298
|
+
attr_writer :active_scaffold_references
|
|
299
|
+
def active_scaffold_references
|
|
300
|
+
@active_scaffold_references ||= []
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
# 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.
|
|
304
|
+
def conditions_for_collection
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# 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.
|
|
308
|
+
def joins_for_collection
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# Override this method on your controller to provide custom finder options to the find() call. The return of this method should be a hash.
|
|
312
|
+
def custom_finder_options
|
|
313
|
+
{}
|
|
314
|
+
end
|
|
287
315
|
|
|
288
316
|
def all_conditions
|
|
289
317
|
[
|
|
318
|
+
id_condition, # for list with id (e.g. /users/:id/index)
|
|
290
319
|
active_scaffold_conditions, # from the search modules
|
|
291
320
|
conditions_for_collection, # from the dev
|
|
292
321
|
conditions_from_params, # from the parameters (e.g. /users/list?first_name=Fred)
|
|
@@ -294,11 +323,14 @@ module ActiveScaffold
|
|
|
294
323
|
active_scaffold_session_storage[:conditions] # embedding conditions (weaker constraints)
|
|
295
324
|
].reject(&:blank?)
|
|
296
325
|
end
|
|
326
|
+
|
|
327
|
+
def id_condition
|
|
328
|
+
{:id => params[:id]} if params[:id]
|
|
329
|
+
end
|
|
297
330
|
|
|
298
331
|
# returns a single record (the given id) but only if it's allowed for the specified security options.
|
|
299
332
|
# security options can be a hash for authorized_for? method or a value to check as a :crud_type
|
|
300
333
|
# accomplishes this by checking model.#{action}_authorized?
|
|
301
|
-
# TODO: this should reside on the model, not the controller
|
|
302
334
|
def find_if_allowed(id, security_options, klass = beginning_of_chain)
|
|
303
335
|
record = klass.find(id)
|
|
304
336
|
security_options = {:crud_type => security_options.to_sym} unless security_options.is_a? Hash
|
|
@@ -311,32 +343,40 @@ module ActiveScaffold
|
|
|
311
343
|
# * :page
|
|
312
344
|
def finder_options(options = {})
|
|
313
345
|
search_conditions = all_conditions
|
|
314
|
-
full_includes = (
|
|
346
|
+
full_includes = (active_scaffold_references.blank? ? nil : active_scaffold_references)
|
|
315
347
|
|
|
316
348
|
# create a general-use options array that's compatible with Rails finders
|
|
317
349
|
finder_options = { :reorder => options[:sorting].try(:clause),
|
|
318
350
|
:conditions => search_conditions,
|
|
319
351
|
:joins => joins_for_finder,
|
|
320
352
|
:outer_joins => active_scaffold_outer_joins,
|
|
353
|
+
:preload => active_scaffold_preload,
|
|
321
354
|
:includes => full_includes,
|
|
322
355
|
:select => options[:select]}
|
|
356
|
+
if Rails::VERSION::MAJOR >= 4
|
|
357
|
+
if options[:sorting].try(:sorts_by_sql?)
|
|
358
|
+
options[:sorting].each do |col, _|
|
|
359
|
+
finder_options[:outer_joins] << col.includes if col.includes.present?
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
finder_options.merge!(:references => active_scaffold_references)
|
|
363
|
+
end
|
|
323
364
|
|
|
324
365
|
finder_options.merge! custom_finder_options
|
|
325
366
|
finder_options
|
|
326
367
|
end
|
|
327
368
|
|
|
328
|
-
def count_items(find_options = {}, count_includes = nil)
|
|
369
|
+
def count_items(query, find_options = {}, count_includes = nil)
|
|
329
370
|
count_includes ||= find_options[:includes] unless find_options[:conditions].blank?
|
|
330
371
|
options = find_options.reject{|k,v| [:select, :reorder].include? k}
|
|
372
|
+
# NOTE: we must use includes in the count query, because some conditions may reference other tables
|
|
331
373
|
options[:includes] = count_includes
|
|
332
374
|
|
|
333
|
-
|
|
334
|
-
count_query = append_to_query(beginning_of_chain, options)
|
|
335
|
-
count = count_query.count(:distinct => true)
|
|
375
|
+
count = append_to_query(query, options).count
|
|
336
376
|
|
|
337
377
|
# Converts count to an integer if ActiveRecord returned an OrderedHash
|
|
338
378
|
# that happens when find_options contains a :group key
|
|
339
|
-
count = count.length if count.is_a? ActiveSupport::OrderedHash
|
|
379
|
+
count = count.length if count.is_a?(Hash) || count.is_a?(ActiveSupport::OrderedHash) # TODO remove OrderedHash check when ruby 1.8 or rails3 support is removed
|
|
340
380
|
count
|
|
341
381
|
end
|
|
342
382
|
|
|
@@ -348,50 +388,62 @@ module ActiveScaffold
|
|
|
348
388
|
options[:page] ||= 1
|
|
349
389
|
|
|
350
390
|
find_options = finder_options(options)
|
|
391
|
+
query = beginning_of_chain.where(nil) # where(nil) is needed because we need a relation
|
|
351
392
|
|
|
352
393
|
# NOTE: we must use :include in the count query, because some conditions may reference other tables
|
|
353
394
|
if options[:pagination] && options[:pagination] != :infinite
|
|
354
|
-
count = count_items(find_options, options[:count_includes])
|
|
395
|
+
count = count_items(query, find_options, options[:count_includes])
|
|
355
396
|
end
|
|
356
397
|
|
|
357
|
-
|
|
358
|
-
klass = klass.where(nil).uniq if find_options[:outer_joins].present? # HACK: call where(nil) because calling uniq on associations (nested scaffolds) send SQL to DB
|
|
398
|
+
query = append_to_query(query, find_options)
|
|
359
399
|
# we build the paginator differently for method- and sql-based sorting
|
|
360
400
|
if options[:sorting] and options[:sorting].sorts_by_method?
|
|
361
401
|
pager = ::Paginator.new(count, options[:per_page]) do |offset, per_page|
|
|
362
|
-
|
|
402
|
+
calculate_last_modified(query)
|
|
403
|
+
sorted_collection = sort_collection_by_column(query.to_a, *options[:sorting].first)
|
|
363
404
|
sorted_collection = sorted_collection.slice(offset, per_page) if options[:pagination]
|
|
364
405
|
sorted_collection
|
|
365
406
|
end
|
|
366
407
|
else
|
|
367
408
|
pager = ::Paginator.new(count, options[:per_page]) do |offset, per_page|
|
|
368
|
-
|
|
369
|
-
|
|
409
|
+
query = append_to_query(query, :offset => offset, :limit => per_page) if options[:pagination]
|
|
410
|
+
calculate_last_modified(query)
|
|
411
|
+
query
|
|
370
412
|
end
|
|
371
413
|
end
|
|
372
414
|
pager.page(options[:page])
|
|
373
415
|
end
|
|
374
416
|
|
|
417
|
+
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
|
|
421
|
+
end
|
|
422
|
+
|
|
375
423
|
def calculate_query
|
|
376
424
|
conditions = all_conditions
|
|
377
425
|
includes = active_scaffold_config.list.count_includes
|
|
378
|
-
includes ||=
|
|
426
|
+
includes ||= active_scaffold_references unless conditions.blank?
|
|
427
|
+
outer_joins = active_scaffold_outer_joins
|
|
428
|
+
outer_joins += includes if includes
|
|
379
429
|
primary_key = active_scaffold_config.model.primary_key
|
|
380
|
-
subquery = append_to_query(beginning_of_chain, :conditions => conditions, :joins => joins_for_finder, :outer_joins =>
|
|
381
|
-
subquery = subquery.select(active_scaffold_config.columns[primary_key].field)
|
|
382
|
-
if includes
|
|
383
|
-
includes_relation = beginning_of_chain.includes(includes)
|
|
384
|
-
subquery = subquery.send(:apply_join_dependency, subquery, includes_relation.send(:construct_join_dependency_for_association_find))
|
|
385
|
-
end
|
|
430
|
+
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)
|
|
386
431
|
active_scaffold_config.model.where(primary_key => subquery)
|
|
387
432
|
end
|
|
388
433
|
|
|
389
434
|
def append_to_query(query, options)
|
|
390
|
-
options.assert_valid_keys :where, :select, :group, :reorder, :limit, :offset, :joins, :outer_joins, :includes, :lock, :readonly, :from, :conditions
|
|
391
|
-
query =
|
|
392
|
-
|
|
393
|
-
|
|
435
|
+
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)
|
|
438
|
+
end
|
|
439
|
+
if options[:outer_joins].present?
|
|
440
|
+
if Rails::VERSION::MAJOR >= 4
|
|
441
|
+
query.distinct_value = true
|
|
442
|
+
else
|
|
443
|
+
query = query.uniq
|
|
444
|
+
end
|
|
394
445
|
end
|
|
446
|
+
query
|
|
395
447
|
end
|
|
396
448
|
|
|
397
449
|
def joins_for_finder
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module ActiveScaffold
|
|
2
2
|
module Helpers
|
|
3
3
|
module AssociationHelpers
|
|
4
|
-
# Cache the
|
|
4
|
+
# Cache the options for select
|
|
5
5
|
def cache_association_options(association, conditions, klass, cache = true)
|
|
6
6
|
if active_scaffold_config.cache_association_options && cache
|
|
7
7
|
@_associations_cache ||= Hash.new { |h,k| h[k] = {} }
|
|
@@ -13,9 +13,11 @@ module ActiveScaffold
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
# Provides a way to honor the :conditions on an association while searching the association's klass
|
|
16
|
-
def association_options_find(association, conditions = nil, klass = nil)
|
|
16
|
+
def association_options_find(association, conditions = nil, klass = nil, record = nil)
|
|
17
|
+
ActiveSupport::Deprecation.warn "Relying on @record is deprecated, call with record.", caller if record.nil? # TODO Remove when relying on @record is removed
|
|
18
|
+
record ||= @record # TODO Remove when relying on @record is removed
|
|
17
19
|
if klass.nil? && association.options[:polymorphic]
|
|
18
|
-
class_name =
|
|
20
|
+
class_name = record.send(association.foreign_type)
|
|
19
21
|
if class_name.present?
|
|
20
22
|
klass = class_name.constantize
|
|
21
23
|
else
|
|
@@ -27,45 +29,73 @@ module ActiveScaffold
|
|
|
27
29
|
klass ||= association.klass
|
|
28
30
|
end
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
if conditions.nil?
|
|
33
|
+
if method(:options_for_association_conditions).arity.abs == 2
|
|
34
|
+
conditions = options_for_association_conditions(association, record)
|
|
35
|
+
else
|
|
36
|
+
ActiveSupport::Deprecation.warn "Relying on @record is deprecated, include record in your options_for_association_conditions overrided method.", caller if record.nil? # TODO Remove when relying on @record is removed
|
|
37
|
+
conditions = options_for_association_conditions(association)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
31
40
|
cache_association_options(association, conditions, klass, cache) do
|
|
41
|
+
klass = association_klass_scoped(association, klass, record)
|
|
32
42
|
relation = klass.where(conditions).where(association.options[:conditions])
|
|
33
43
|
relation = relation.includes(association.options[:include]) if association.options[:include]
|
|
44
|
+
column = column_for_association(association, record)
|
|
45
|
+
if column && column.try(:sort) && column.sort[:sql]
|
|
46
|
+
if column.includes
|
|
47
|
+
include_assoc = column.includes.find { |assoc| assoc.is_a?(Hash) && assoc.include?(association.name) }
|
|
48
|
+
relation = relation.includes(include_assoc[association.name]) if include_assoc
|
|
49
|
+
end
|
|
50
|
+
relation = relation.order(column.sort[:sql])
|
|
51
|
+
end
|
|
34
52
|
relation = yield(relation) if block_given?
|
|
35
53
|
relation.to_a
|
|
36
54
|
end
|
|
37
55
|
end
|
|
38
56
|
|
|
57
|
+
def column_for_association(association, record)
|
|
58
|
+
active_scaffold_config_for(record.class).columns[association.name] rescue nil
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def association_klass_scoped(association, klass, record)
|
|
62
|
+
klass
|
|
63
|
+
end
|
|
64
|
+
|
|
39
65
|
# Sorts the options for select
|
|
40
|
-
def sorted_association_options_find(association, conditions = nil)
|
|
41
|
-
association_options_find(association, conditions)
|
|
66
|
+
def sorted_association_options_find(association, conditions = nil, record = nil)
|
|
67
|
+
options = association_options_find(association, conditions, nil, record)
|
|
68
|
+
column = column_for_association(association, record)
|
|
69
|
+
unless column && column.try(:sort) && column.sort[:sql]
|
|
70
|
+
method = column.options[:label_method] if column
|
|
71
|
+
options = options.sort_by(&(method || :to_label).to_sym)
|
|
72
|
+
end
|
|
73
|
+
options
|
|
42
74
|
end
|
|
43
75
|
|
|
44
76
|
def association_options_count(association, conditions = nil)
|
|
45
77
|
association.klass.where(conditions).where(association.options[:conditions]).count
|
|
46
78
|
end
|
|
47
79
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def options_for_association_count(association)
|
|
57
|
-
association_options_count(association, options_for_association_conditions(association))
|
|
80
|
+
def options_for_association_count(association, record)
|
|
81
|
+
if method(:options_for_association_conditions).arity.abs == 2
|
|
82
|
+
conditions = options_for_association_conditions(association, record)
|
|
83
|
+
else
|
|
84
|
+
ActiveSupport::Deprecation.warn "Relying on @record is deprecated, include record in your options_for_association_conditions overrided method.", caller if record.nil? # TODO Remove when relying on @record is removed
|
|
85
|
+
conditions = options_for_association_conditions(association)
|
|
86
|
+
end
|
|
87
|
+
association_options_count(association, conditions)
|
|
58
88
|
end
|
|
59
89
|
|
|
60
90
|
# A useful override for customizing the records present in an association dropdown.
|
|
61
91
|
# Should work in both the subform and form_ui=>:select modes.
|
|
62
92
|
# Check association.name to specialize the conditions per-column.
|
|
63
|
-
def options_for_association_conditions(association)
|
|
93
|
+
def options_for_association_conditions(association, record = nil)
|
|
64
94
|
return nil if association.options[:through]
|
|
65
95
|
case association.macro
|
|
66
96
|
when :has_one, :has_many
|
|
67
97
|
# Find only orphaned objects
|
|
68
|
-
|
|
98
|
+
{association.foreign_key => nil}
|
|
69
99
|
when :belongs_to, :has_and_belongs_to_many
|
|
70
100
|
# Find all
|
|
71
101
|
nil
|
|
@@ -22,7 +22,7 @@ module ActiveScaffold
|
|
|
22
22
|
# :sort, :sort_direction, and :page are arguments that stored in the session. they need not propagate.
|
|
23
23
|
# and wow. no we don't want to propagate :record.
|
|
24
24
|
# :commit is a special rails variable for form buttons
|
|
25
|
-
blacklist = [:adapter, :position, :sort, :sort_direction, :page, :record, :commit, :_method, :authenticity_token, :iframe, :associated_id, :dont_close]
|
|
25
|
+
blacklist = [:adapter, :position, :sort, :sort_direction, :page, :auto_pagination, :record, :commit, :_method, :authenticity_token, :iframe, :associated_id, :dont_close]
|
|
26
26
|
unless @params_for
|
|
27
27
|
@params_for = {}
|
|
28
28
|
params.except(*blacklist).each {|key, value| @params_for[key.to_sym] = value.duplicable? ? value.clone : value}
|
|
@@ -65,10 +65,10 @@ module ActiveScaffold
|
|
|
65
65
|
|
|
66
66
|
def render_parent_options
|
|
67
67
|
if nested_singular_association?
|
|
68
|
-
{:controller => nested.parent_scaffold.controller_path, :action => :
|
|
68
|
+
{:controller => nested.parent_scaffold.controller_path, :action => :index, :id => nested.parent_id}
|
|
69
69
|
elsif params[:parent_sti]
|
|
70
70
|
options = params_for(:controller => params[:parent_sti], :action => render_parent_action, :parent_sti => nil)
|
|
71
|
-
options.merge(:id => @record.
|
|
71
|
+
options.merge(:action => :index, :id => @record.to_param) if render_parent_action == :row
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
74
|
|
|
@@ -86,15 +86,24 @@ module ActiveScaffold
|
|
|
86
86
|
@parent_action
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
# build an associated record for association
|
|
90
|
+
def build_associated(association, parent_record)
|
|
91
|
+
if association.options[:through]
|
|
92
|
+
# build full chain, only check create_associated on initial parent_record
|
|
93
|
+
parent_record = build_associated(association.through_reflection, parent_record)
|
|
94
|
+
build_associated(association.source_reflection, parent_record).tap do |record|
|
|
95
|
+
save_record_to_association(record, association.source_reflection.reverse, parent_record) # set inverse
|
|
95
96
|
end
|
|
97
|
+
elsif association.collection?
|
|
98
|
+
parent_record.send(association.name).build
|
|
99
|
+
elsif association.belongs_to? || parent_record.new_record? || parent_record.send(association.name).nil?
|
|
100
|
+
# avoid use build_association in has_one when record is saved and had associated record
|
|
101
|
+
# because associated record would be changed in DB
|
|
102
|
+
parent_record.send("build_#{association.name}")
|
|
96
103
|
else
|
|
97
|
-
|
|
104
|
+
association.klass.new.tap do |record|
|
|
105
|
+
save_record_to_association(record, association.reverse, parent_record) # set inverse
|
|
106
|
+
end
|
|
98
107
|
end
|
|
99
108
|
end
|
|
100
109
|
end
|