active_scaffold-sequel 0.3.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.
- data/CHANGELOG +179 -0
- data/MIT-LICENSE +20 -0
- data/README +36 -0
- data/app/assets/images/active_scaffold/add.gif +0 -0
- data/app/assets/images/active_scaffold/arrow_down.gif +0 -0
- data/app/assets/images/active_scaffold/arrow_up.gif +0 -0
- data/app/assets/images/active_scaffold/close.gif +0 -0
- data/app/assets/images/active_scaffold/close_touch.png +0 -0
- data/app/assets/images/active_scaffold/config.png +0 -0
- data/app/assets/images/active_scaffold/cross.png +0 -0
- data/app/assets/images/active_scaffold/gears.png +0 -0
- data/app/assets/images/active_scaffold/indicator-small.gif +0 -0
- data/app/assets/images/active_scaffold/indicator.gif +0 -0
- data/app/assets/images/active_scaffold/magnifier.png +0 -0
- data/app/assets/javascripts/active_scaffold.js.erb +19 -0
- data/app/assets/javascripts/jquery/active_scaffold.js +1057 -0
- data/app/assets/javascripts/jquery/date_picker_bridge.js.erb +24 -0
- data/app/assets/javascripts/jquery/draggable_lists.js +27 -0
- data/app/assets/javascripts/jquery/jquery.editinplace.js +743 -0
- data/app/assets/javascripts/jquery/tiny_mce_bridge.js +7 -0
- data/app/assets/javascripts/prototype/active_scaffold.js +1052 -0
- data/app/assets/javascripts/prototype/dhtml_history.js +870 -0
- data/app/assets/javascripts/prototype/form_enhancements.js +117 -0
- data/app/assets/javascripts/prototype/rico_corner.js +370 -0
- data/app/assets/javascripts/prototype/tiny_mce_bridge.js +7 -0
- data/app/assets/stylesheets/active_scaffold-ie.css +35 -0
- data/app/assets/stylesheets/active_scaffold.css.scss +14 -0
- data/app/assets/stylesheets/active_scaffold_colors.css.scss +395 -0
- data/app/assets/stylesheets/active_scaffold_extensions.css.erb +2 -0
- data/app/assets/stylesheets/active_scaffold_images.css.scss +43 -0
- data/app/assets/stylesheets/active_scaffold_layout.css +912 -0
- data/app/assets/stylesheets/blue-theme.css +74 -0
- data/config/locales/de.yml +114 -0
- data/config/locales/en.yml +118 -0
- data/config/locales/es.yml +120 -0
- data/config/locales/fr.yml +121 -0
- data/config/locales/hu.yml +74 -0
- data/config/locales/ja.yml +73 -0
- data/config/locales/ru.yml +123 -0
- data/frontends/default/views/_action_group.html.erb +24 -0
- data/frontends/default/views/_add_existing_form.html.erb +30 -0
- data/frontends/default/views/_base_form.html.erb +51 -0
- data/frontends/default/views/_create_form.html.erb +8 -0
- data/frontends/default/views/_create_form_on_list.html.erb +6 -0
- data/frontends/default/views/_field_search.html.erb +32 -0
- data/frontends/default/views/_form.html.erb +24 -0
- data/frontends/default/views/_form_association.html.erb +15 -0
- data/frontends/default/views/_form_association_footer.html.erb +47 -0
- data/frontends/default/views/_form_attribute.html.erb +20 -0
- data/frontends/default/views/_form_hidden_attribute.html.erb +2 -0
- data/frontends/default/views/_form_messages.html.erb +5 -0
- data/frontends/default/views/_horizontal_subform.html.erb +28 -0
- data/frontends/default/views/_horizontal_subform_footer.html.erb +0 -0
- data/frontends/default/views/_horizontal_subform_header.html.erb +11 -0
- data/frontends/default/views/_horizontal_subform_record.html.erb +38 -0
- data/frontends/default/views/_human_conditions.html.erb +1 -0
- data/frontends/default/views/_list.html.erb +18 -0
- data/frontends/default/views/_list_actions.html.erb +15 -0
- data/frontends/default/views/_list_calculations.html.erb +16 -0
- data/frontends/default/views/_list_column_headings.html.erb +12 -0
- data/frontends/default/views/_list_header.html.erb +10 -0
- data/frontends/default/views/_list_inline_adapter.html.erb +10 -0
- data/frontends/default/views/_list_messages.html.erb +30 -0
- data/frontends/default/views/_list_pagination.html.erb +11 -0
- data/frontends/default/views/_list_pagination_links.html.erb +9 -0
- data/frontends/default/views/_list_record.html.erb +14 -0
- data/frontends/default/views/_list_record_columns.html.erb +8 -0
- data/frontends/default/views/_list_with_header.html.erb +36 -0
- data/frontends/default/views/_messages.html.erb +10 -0
- data/frontends/default/views/_render_field.js.erb +20 -0
- data/frontends/default/views/_row.html.erb +6 -0
- data/frontends/default/views/_search.html.erb +34 -0
- data/frontends/default/views/_search_attribute.html.erb +10 -0
- data/frontends/default/views/_show.html.erb +8 -0
- data/frontends/default/views/_show_columns.html.erb +15 -0
- data/frontends/default/views/_update_actions.html.erb +9 -0
- data/frontends/default/views/_update_form.html.erb +6 -0
- data/frontends/default/views/_vertical_subform.html.erb +12 -0
- data/frontends/default/views/_vertical_subform_record.html.erb +38 -0
- data/frontends/default/views/action_confirmation.html.erb +13 -0
- data/frontends/default/views/add_existing.js.erb +18 -0
- data/frontends/default/views/add_existing_form.html.erb +5 -0
- data/frontends/default/views/create.html.erb +5 -0
- data/frontends/default/views/delete.html.erb +13 -0
- data/frontends/default/views/destroy.js.erb +24 -0
- data/frontends/default/views/edit_associated.js.erb +12 -0
- data/frontends/default/views/field_search.html.erb +5 -0
- data/frontends/default/views/form_messages.js.erb +1 -0
- data/frontends/default/views/list.html.erb +1 -0
- data/frontends/default/views/on_action_update.js.erb +13 -0
- data/frontends/default/views/on_create.js.erb +47 -0
- data/frontends/default/views/on_mark_all.js.erb +12 -0
- data/frontends/default/views/on_update.js.erb +31 -0
- data/frontends/default/views/refresh_list.js.erb +1 -0
- data/frontends/default/views/render_field.js.erb +1 -0
- data/frontends/default/views/search.html.erb +5 -0
- data/frontends/default/views/show.html.erb +5 -0
- data/frontends/default/views/update.html.erb +8 -0
- data/frontends/default/views/update_column.js.erb +16 -0
- data/frontends/default/views/update_row.js.erb +1 -0
- data/lib/active_scaffold/actions/common_search.rb +25 -0
- data/lib/active_scaffold/actions/core.rb +197 -0
- data/lib/active_scaffold/actions/create.rb +148 -0
- data/lib/active_scaffold/actions/delete.rb +76 -0
- data/lib/active_scaffold/actions/field_search.rb +82 -0
- data/lib/active_scaffold/actions/list.rb +196 -0
- data/lib/active_scaffold/actions/mark.rb +75 -0
- data/lib/active_scaffold/actions/nested.rb +245 -0
- data/lib/active_scaffold/actions/search.rb +48 -0
- data/lib/active_scaffold/actions/show.rb +61 -0
- data/lib/active_scaffold/actions/subform.rb +23 -0
- data/lib/active_scaffold/actions/update.rb +150 -0
- data/lib/active_scaffold/active_record_permissions.rb +136 -0
- data/lib/active_scaffold/attribute_params.rb +208 -0
- data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +39 -0
- data/lib/active_scaffold/bridges/ancestry.rb +5 -0
- data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +67 -0
- data/lib/active_scaffold/bridges/calendar_date_select.rb +24 -0
- data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +107 -0
- data/lib/active_scaffold/bridges/cancan.rb +15 -0
- data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +31 -0
- data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge_helpers.rb +10 -0
- data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +45 -0
- data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +17 -0
- data/lib/active_scaffold/bridges/carrierwave.rb +12 -0
- data/lib/active_scaffold/bridges/country_helper/country_helper_bridge.rb +358 -0
- data/lib/active_scaffold/bridges/country_helper.rb +9 -0
- data/lib/active_scaffold/bridges/date_picker/ext.rb +45 -0
- data/lib/active_scaffold/bridges/date_picker/helper.rb +180 -0
- data/lib/active_scaffold/bridges/date_picker.rb +23 -0
- data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge.rb +34 -0
- data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge_helpers.rb +10 -0
- data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +27 -0
- data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +16 -0
- data/lib/active_scaffold/bridges/dragonfly.rb +9 -0
- data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +48 -0
- data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +57 -0
- data/lib/active_scaffold/bridges/file_column/form_ui.rb +34 -0
- data/lib/active_scaffold/bridges/file_column/list_ui.rb +26 -0
- data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +43 -0
- data/lib/active_scaffold/bridges/file_column/test/mock_model.rb +9 -0
- data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +15 -0
- data/lib/active_scaffold/bridges/file_column.rb +11 -0
- data/lib/active_scaffold/bridges/paperclip/form_ui.rb +27 -0
- data/lib/active_scaffold/bridges/paperclip/list_ui.rb +16 -0
- data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +36 -0
- data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +24 -0
- data/lib/active_scaffold/bridges/paperclip.rb +12 -0
- data/lib/active_scaffold/bridges/record_select/helpers.rb +86 -0
- data/lib/active_scaffold/bridges/record_select.rb +11 -0
- data/lib/active_scaffold/bridges/semantic_attributes/column.rb +20 -0
- data/lib/active_scaffold/bridges/semantic_attributes.rb +5 -0
- data/lib/active_scaffold/bridges/shared/date_bridge.rb +209 -0
- data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +46 -0
- data/lib/active_scaffold/bridges/tiny_mce.rb +17 -0
- data/lib/active_scaffold/bridges.rb +61 -0
- data/lib/active_scaffold/config/base.rb +71 -0
- data/lib/active_scaffold/config/core.rb +219 -0
- data/lib/active_scaffold/config/create.rb +44 -0
- data/lib/active_scaffold/config/delete.rb +33 -0
- data/lib/active_scaffold/config/field_search.rb +76 -0
- data/lib/active_scaffold/config/form.rb +48 -0
- data/lib/active_scaffold/config/list.rb +196 -0
- data/lib/active_scaffold/config/mark.rb +35 -0
- data/lib/active_scaffold/config/nested.rb +42 -0
- data/lib/active_scaffold/config/search.rb +73 -0
- data/lib/active_scaffold/config/show.rb +32 -0
- data/lib/active_scaffold/config/subform.rb +35 -0
- data/lib/active_scaffold/config/update.rb +41 -0
- data/lib/active_scaffold/configurable.rb +29 -0
- data/lib/active_scaffold/constraints.rb +170 -0
- data/lib/active_scaffold/data_structures/action_columns.rb +140 -0
- data/lib/active_scaffold/data_structures/action_link.rb +179 -0
- data/lib/active_scaffold/data_structures/action_links.rb +185 -0
- data/lib/active_scaffold/data_structures/actions.rb +45 -0
- data/lib/active_scaffold/data_structures/bridge.rb +22 -0
- data/lib/active_scaffold/data_structures/column.rb +389 -0
- data/lib/active_scaffold/data_structures/columns.rb +75 -0
- data/lib/active_scaffold/data_structures/error_message.rb +24 -0
- data/lib/active_scaffold/data_structures/nested_info.rb +130 -0
- data/lib/active_scaffold/data_structures/set.rb +57 -0
- data/lib/active_scaffold/data_structures/sorting.rb +172 -0
- data/lib/active_scaffold/engine.rb +4 -0
- data/lib/active_scaffold/extensions/action_controller_rendering.rb +22 -0
- data/lib/active_scaffold/extensions/action_view_rendering.rb +115 -0
- data/lib/active_scaffold/extensions/active_record_offset.rb +12 -0
- data/lib/active_scaffold/extensions/array.rb +7 -0
- data/lib/active_scaffold/extensions/cache_association.rb +16 -0
- data/lib/active_scaffold/extensions/localize.rb +10 -0
- data/lib/active_scaffold/extensions/name_option_for_datetime.rb +12 -0
- data/lib/active_scaffold/extensions/nil_id_in_url_params.rb +7 -0
- data/lib/active_scaffold/extensions/paginator_extensions.rb +26 -0
- data/lib/active_scaffold/extensions/routing_mapper.rb +48 -0
- data/lib/active_scaffold/extensions/to_label.rb +8 -0
- data/lib/active_scaffold/extensions/unsaved_associated.rb +60 -0
- data/lib/active_scaffold/extensions/unsaved_record.rb +20 -0
- data/lib/active_scaffold/extensions/usa_state.rb +46 -0
- data/lib/active_scaffold/finder.rb +372 -0
- data/lib/active_scaffold/helpers/association_helpers.rb +48 -0
- data/lib/active_scaffold/helpers/controller_helpers.rb +88 -0
- data/lib/active_scaffold/helpers/form_column_helpers.rb +321 -0
- data/lib/active_scaffold/helpers/human_condition_helpers.rb +62 -0
- data/lib/active_scaffold/helpers/id_helpers.rb +127 -0
- data/lib/active_scaffold/helpers/list_column_helpers.rb +340 -0
- data/lib/active_scaffold/helpers/pagination_helpers.rb +55 -0
- data/lib/active_scaffold/helpers/search_column_helpers.rb +267 -0
- data/lib/active_scaffold/helpers/show_column_helpers.rb +50 -0
- data/lib/active_scaffold/helpers/view_helpers.rb +342 -0
- data/lib/active_scaffold/marked_model.rb +38 -0
- data/lib/active_scaffold/paginator.rb +136 -0
- data/lib/active_scaffold/responds_to_parent.rb +70 -0
- data/lib/active_scaffold/version.rb +9 -0
- data/lib/active_scaffold.rb +368 -0
- data/lib/active_scaffold_env.rb +11 -0
- data/lib/generators/active_scaffold/USAGE +29 -0
- data/lib/generators/active_scaffold/active_scaffold_generator.rb +20 -0
- data/lib/generators/active_scaffold_controller/USAGE +19 -0
- data/lib/generators/active_scaffold_controller/active_scaffold_controller_generator.rb +29 -0
- data/lib/generators/active_scaffold_controller/templates/controller.rb +4 -0
- data/lib/generators/active_scaffold_controller/templates/helper.rb +2 -0
- data/public/blank.html +33 -0
- data/shoulda_macros/macros.rb +136 -0
- data/test/bridges/active_scaffold_dependent_protect_test.rb +34 -0
- data/test/bridges/bridge_test.rb +90 -0
- data/test/bridges/company.rb +81 -0
- data/test/bridges/paperclip_test.rb +68 -0
- data/test/bridges/tiny_mce_test.rb +27 -0
- data/test/bridges/unobtrusive_date_picker_test.rb +49 -0
- data/test/bridges/validation_reflection_test.rb +57 -0
- data/test/config/base_test.rb +15 -0
- data/test/config/core_test.rb +58 -0
- data/test/config/create_test.rb +58 -0
- data/test/config/delete_test.rb +33 -0
- data/test/config/field_search_test.rb +47 -0
- data/test/config/list_test.rb +129 -0
- data/test/config/nested_test.rb +62 -0
- data/test/config/search_test.rb +60 -0
- data/test/config/show_test.rb +43 -0
- data/test/config/subform_test.rb +17 -0
- data/test/config/update_test.rb +40 -0
- data/test/const_mocker.rb +36 -0
- data/test/data_structures/action_columns_test.rb +113 -0
- data/test/data_structures/action_link_test.rb +78 -0
- data/test/data_structures/action_links_test.rb +78 -0
- data/test/data_structures/actions_test.rb +25 -0
- data/test/data_structures/association_column_test.rb +42 -0
- data/test/data_structures/column_test.rb +185 -0
- data/test/data_structures/columns_test.rb +69 -0
- data/test/data_structures/error_message_test.rb +28 -0
- data/test/data_structures/set_test.rb +86 -0
- data/test/data_structures/sorting_test.rb +126 -0
- data/test/data_structures/standard_column_test.rb +24 -0
- data/test/data_structures/virtual_column_test.rb +23 -0
- data/test/extensions/active_record_test.rb +45 -0
- data/test/extensions/array_test.rb +12 -0
- data/test/helpers/form_column_helpers_test.rb +31 -0
- data/test/helpers/list_column_helpers_test.rb +42 -0
- data/test/helpers/pagination_helpers_test.rb +59 -0
- data/test/misc/active_record_permissions_test.rb +154 -0
- data/test/misc/attribute_params_test.rb +146 -0
- data/test/misc/configurable_test.rb +96 -0
- data/test/misc/constraints_test.rb +193 -0
- data/test/misc/finder_test.rb +92 -0
- data/test/misc/lang_test.rb +11 -0
- data/test/mock_app/app/controllers/application_controller.rb +10 -0
- data/test/mock_app/app/helpers/application_helper.rb +3 -0
- data/test/mock_app/config/boot.rb +110 -0
- data/test/mock_app/config/database.yml +16 -0
- data/test/mock_app/config/environment.rb +43 -0
- data/test/mock_app/config/environments/development.rb +17 -0
- data/test/mock_app/config/environments/production.rb +28 -0
- data/test/mock_app/config/environments/test.rb +28 -0
- data/test/mock_app/config/initializers/backtrace_silencers.rb +7 -0
- data/test/mock_app/config/initializers/inflections.rb +10 -0
- data/test/mock_app/config/initializers/mime_types.rb +5 -0
- data/test/mock_app/config/initializers/new_rails_defaults.rb +19 -0
- data/test/mock_app/config/initializers/session_store.rb +15 -0
- data/test/mock_app/config/locales/en.yml +5 -0
- data/test/mock_app/config/routes.rb +43 -0
- data/test/mock_app/db/test.sqlite3 +1 -0
- data/test/mock_app/public/blank.html +33 -0
- data/test/mock_app/public/images/active_scaffold/DO_NOT_EDIT +2 -0
- 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 +2 -0
- data/test/mock_app/public/javascripts/active_scaffold/default/active_scaffold.js +532 -0
- data/test/mock_app/public/javascripts/active_scaffold/default/dhtml_history.js +867 -0
- data/test/mock_app/public/javascripts/active_scaffold/default/form_enhancements.js +117 -0
- data/test/mock_app/public/javascripts/active_scaffold/default/rico_corner.js +370 -0
- data/test/mock_app/public/stylesheets/active_scaffold/DO_NOT_EDIT +2 -0
- data/test/mock_app/public/stylesheets/active_scaffold/default/stylesheet-ie.css +35 -0
- data/test/mock_app/public/stylesheets/active_scaffold/default/stylesheet.css +848 -0
- data/test/model_stub.rb +55 -0
- data/test/run_all.rb +8 -0
- data/test/test_helper.rb +39 -0
- data/vendor/assets/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/vendor/assets/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/vendor/assets/images/ui-bg_flat_10_000000_40x100.png +0 -0
- data/vendor/assets/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/vendor/assets/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/vendor/assets/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/vendor/assets/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/vendor/assets/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/vendor/assets/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/vendor/assets/images/ui-icons_222222_256x240.png +0 -0
- data/vendor/assets/images/ui-icons_228ef1_256x240.png +0 -0
- data/vendor/assets/images/ui-icons_ef8c08_256x240.png +0 -0
- data/vendor/assets/images/ui-icons_ffd27a_256x240.png +0 -0
- data/vendor/assets/images/ui-icons_ffffff_256x240.png +0 -0
- data/vendor/assets/javascripts/jquery-ui-timepicker-addon.js +1276 -0
- data/vendor/assets/stylesheets/jquery-ui.css +568 -0
- metadata +502 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
module ActiveScaffold::Config
|
|
2
|
+
class Search < Base
|
|
3
|
+
self.crud_type = :read
|
|
4
|
+
|
|
5
|
+
def initialize(core_config)
|
|
6
|
+
super
|
|
7
|
+
@text_search = self.class.text_search
|
|
8
|
+
@live = self.class.live?
|
|
9
|
+
@split_terms = self.class.split_terms
|
|
10
|
+
|
|
11
|
+
# start with the ActionLink defined globally
|
|
12
|
+
@link = self.class.link.clone
|
|
13
|
+
@action_group = self.class.action_group.clone if self.class.action_group
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# global level configuration
|
|
18
|
+
# --------------------------
|
|
19
|
+
# the ActionLink for this action
|
|
20
|
+
cattr_accessor :link
|
|
21
|
+
@@link = ActiveScaffold::DataStructures::ActionLink.new('show_search', :label => :search, :type => :collection, :security_method => :search_authorized?, :ignore_method => :search_ignore?)
|
|
22
|
+
|
|
23
|
+
# A flag for how the search should do full-text searching in the database:
|
|
24
|
+
# * :full: LIKE %?%
|
|
25
|
+
# * :start: LIKE ?%
|
|
26
|
+
# * :end: LIKE %?
|
|
27
|
+
# * false: LIKE ?
|
|
28
|
+
# Default is :full
|
|
29
|
+
cattr_accessor :text_search
|
|
30
|
+
@@text_search = :full
|
|
31
|
+
|
|
32
|
+
# whether submits the search as you type
|
|
33
|
+
cattr_writer :live
|
|
34
|
+
def self.live?
|
|
35
|
+
@@live
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# instance-level configuration
|
|
39
|
+
# ----------------------------
|
|
40
|
+
|
|
41
|
+
# provides access to the list of columns specifically meant for the Search to use
|
|
42
|
+
def columns
|
|
43
|
+
# we want to delay initializing to the @core.columns set for as long as possible. Too soon and .search_sql will not be available to .searchable?
|
|
44
|
+
unless @columns
|
|
45
|
+
self.columns = @core.columns.collect{|c| c.name if @core.columns._inheritable.include?(c.name) and c.searchable? and c.column and c.column[:type] == :string}.compact
|
|
46
|
+
end
|
|
47
|
+
@columns
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
public :columns=
|
|
51
|
+
|
|
52
|
+
# A flag for how the search should do full-text searching in the database:
|
|
53
|
+
# * :full: LIKE %?%
|
|
54
|
+
# * :start: LIKE ?%
|
|
55
|
+
# * :end: LIKE %?
|
|
56
|
+
# * false: LIKE ?
|
|
57
|
+
# Default is :full
|
|
58
|
+
attr_accessor :text_search
|
|
59
|
+
|
|
60
|
+
@@split_terms = " "
|
|
61
|
+
cattr_accessor :split_terms
|
|
62
|
+
attr_accessor :split_terms
|
|
63
|
+
|
|
64
|
+
# the ActionLink for this action
|
|
65
|
+
attr_accessor :link
|
|
66
|
+
|
|
67
|
+
# whether submits the search as you type
|
|
68
|
+
attr_writer :live
|
|
69
|
+
def live?
|
|
70
|
+
@live
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module ActiveScaffold::Config
|
|
2
|
+
class Show < Base
|
|
3
|
+
self.crud_type = :read
|
|
4
|
+
|
|
5
|
+
def initialize(core_config)
|
|
6
|
+
super
|
|
7
|
+
# start with the ActionLink defined globally
|
|
8
|
+
@link = self.class.link.clone
|
|
9
|
+
@action_group = self.class.action_group.clone if self.class.action_group
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# global level configuration
|
|
13
|
+
# --------------------------
|
|
14
|
+
cattr_accessor :link
|
|
15
|
+
@@link = ActiveScaffold::DataStructures::ActionLink.new('show', :label => :show, :type => :member, :security_method => :show_authorized?)
|
|
16
|
+
# instance-level configuration
|
|
17
|
+
# ----------------------------
|
|
18
|
+
|
|
19
|
+
# the ActionLink for this action
|
|
20
|
+
attr_accessor :link
|
|
21
|
+
# the label for this action. used for the header.
|
|
22
|
+
attr_writer :label
|
|
23
|
+
|
|
24
|
+
# provides access to the list of columns specifically meant for this action to use
|
|
25
|
+
def columns
|
|
26
|
+
self.columns = @core.columns._inheritable unless @columns # lazy evaluation
|
|
27
|
+
@columns
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
public :columns=
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module ActiveScaffold::Config
|
|
2
|
+
class Subform < Base
|
|
3
|
+
def initialize(core_config)
|
|
4
|
+
super
|
|
5
|
+
@layout = self.class.layout # default layout
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# global level configuration
|
|
9
|
+
# --------------------------
|
|
10
|
+
|
|
11
|
+
cattr_accessor :layout
|
|
12
|
+
@@layout = :horizontal
|
|
13
|
+
|
|
14
|
+
# instance-level configuration
|
|
15
|
+
# ----------------------------
|
|
16
|
+
|
|
17
|
+
attr_accessor :layout
|
|
18
|
+
|
|
19
|
+
# provides access to the list of columns specifically meant for the Sub-Form to use
|
|
20
|
+
def columns
|
|
21
|
+
# we want to delay initializing to the @core.update.columns set for as long as possible. but we have to eventually clone, or else have a configuration "leak"
|
|
22
|
+
unless @columns
|
|
23
|
+
if @core.actions.include? :update
|
|
24
|
+
@columns = @core.update.columns.clone
|
|
25
|
+
else
|
|
26
|
+
self.columns = @core.columns._inheritable
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
@columns
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
public :columns=
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module ActiveScaffold::Config
|
|
2
|
+
class Update < ActiveScaffold::Config::Form
|
|
3
|
+
self.crud_type = :update
|
|
4
|
+
def initialize(core_config)
|
|
5
|
+
super
|
|
6
|
+
self.nested_links = self.class.nested_links
|
|
7
|
+
self.refresh_list = self.class.refresh_list
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# global level configuration
|
|
11
|
+
# --------------------------
|
|
12
|
+
# the ActionLink for this action
|
|
13
|
+
def self.link
|
|
14
|
+
@@link
|
|
15
|
+
end
|
|
16
|
+
def self.link=(val)
|
|
17
|
+
@@link = val
|
|
18
|
+
end
|
|
19
|
+
@@link = ActiveScaffold::DataStructures::ActionLink.new('edit', :label => :edit, :type => :member, :security_method => :update_authorized?)
|
|
20
|
+
|
|
21
|
+
# whether we should refresh list after update or not
|
|
22
|
+
cattr_accessor :refresh_list
|
|
23
|
+
@@refresh_list = false
|
|
24
|
+
|
|
25
|
+
# instance-level configuration
|
|
26
|
+
# ----------------------------
|
|
27
|
+
|
|
28
|
+
attr_accessor :nested_links
|
|
29
|
+
cattr_accessor :nested_links
|
|
30
|
+
@@nested_links = false
|
|
31
|
+
|
|
32
|
+
attr_writer :hide_nested_column
|
|
33
|
+
def hide_nested_column
|
|
34
|
+
@hide_nested_column.nil? ? true : @hide_nested_column
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# whether we should refresh list after update or not
|
|
38
|
+
attr_accessor :refresh_list
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module ActiveScaffold
|
|
2
|
+
# Exposes a +configure+ method that accepts a block and runs all contents of the block in two contexts, as opposed to the normal one. First, everything gets evaluated as part of the object including Configurable. Then, as a failover, missing methods and variables are evaluated in the original binding of the block.
|
|
3
|
+
#
|
|
4
|
+
# Note that this only works with "barewords". Constants, instance variables, and class variables are not currently supported in both contexts.
|
|
5
|
+
#
|
|
6
|
+
# May add the given functionality at both the class and instance level. For the former, use +extend+, and for the latter, use +include+.
|
|
7
|
+
module Configurable
|
|
8
|
+
def configure(&configuration_block)
|
|
9
|
+
return unless configuration_block
|
|
10
|
+
@configuration_binding = configuration_block.binding
|
|
11
|
+
ret = instance_exec self, &configuration_block
|
|
12
|
+
@configuration_binding = nil
|
|
13
|
+
return ret
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# this method will surely need tweaking. for example, i'm not sure if it should call super before or after it tries to eval with the binding.
|
|
17
|
+
def method_missing(name, *args)
|
|
18
|
+
begin
|
|
19
|
+
super
|
|
20
|
+
rescue NoMethodError, NameError
|
|
21
|
+
if @configuration_binding.nil?
|
|
22
|
+
raise $!
|
|
23
|
+
else
|
|
24
|
+
eval("self", @configuration_binding).send(name, *args)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
module ActiveScaffold
|
|
2
|
+
module Constraints
|
|
3
|
+
|
|
4
|
+
protected
|
|
5
|
+
|
|
6
|
+
# Returns the current constraints
|
|
7
|
+
def active_scaffold_constraints
|
|
8
|
+
@active_scaffold_constraints ||= active_scaffold_session_storage[:constraints] || {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def set_active_scaffold_constraints
|
|
12
|
+
associations_by_params = {}
|
|
13
|
+
active_scaffold_config.model.association_reflections.each do |name,association|
|
|
14
|
+
associations_by_params[association[:class_name].foreign_key] = association[:name]
|
|
15
|
+
end
|
|
16
|
+
params.each do |key, value|
|
|
17
|
+
active_scaffold_constraints[associations_by_params[key]] = value if associations_by_params.include? key
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# For each enabled action, adds the constrained columns to the ActionColumns object (if it exists).
|
|
22
|
+
# This lets the ActionColumns object skip constrained columns.
|
|
23
|
+
#
|
|
24
|
+
# If the constraint value is a Hash, then we assume the constraint is a multi-level association constraint (the reverse of a has_many :through) and we do NOT register the constraint column.
|
|
25
|
+
def register_constraints_with_action_columns(association_constrained_fields = [], exclude_actions = [])
|
|
26
|
+
constrained_fields = active_scaffold_constraints.reject{|k, v| v.is_a? Hash}.keys.collect{|k| k.to_sym}
|
|
27
|
+
constrained_fields = constrained_fields | association_constrained_fields
|
|
28
|
+
if self.class.uses_active_scaffold?
|
|
29
|
+
# we actually want to do this whether constrained_fields exist or not, so that we can reset the array when they don't
|
|
30
|
+
active_scaffold_config.actions.each do |action_name|
|
|
31
|
+
next if exclude_actions.include?(action_name)
|
|
32
|
+
action = active_scaffold_config.send(action_name)
|
|
33
|
+
next unless action.respond_to? :columns
|
|
34
|
+
action.columns.constraint_columns = constrained_fields
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Returns search conditions based on the current scaffold constraints.
|
|
40
|
+
#
|
|
41
|
+
# Supports constraints based on either a column name (in which case it checks for an association
|
|
42
|
+
# or just uses the search_sql) or a database field name.
|
|
43
|
+
#
|
|
44
|
+
# All of this work is primarily to support nested scaffolds in a manner generally useful for other
|
|
45
|
+
# embedded scaffolds.
|
|
46
|
+
def conditions_from_constraints
|
|
47
|
+
conditions = nil
|
|
48
|
+
active_scaffold_constraints.each do |k, v|
|
|
49
|
+
column = active_scaffold_config.columns[k]
|
|
50
|
+
constraint_condition = if column
|
|
51
|
+
# Assume this is a multi-level association constraint.
|
|
52
|
+
# example:
|
|
53
|
+
# data model: Park -> Den -> Bear
|
|
54
|
+
# constraint: :den => {:park => 5}
|
|
55
|
+
if v.is_a? Hash
|
|
56
|
+
far_association_klass = column.association.associated_class.association_reflection(v.keys.first).associated_class
|
|
57
|
+
field = far_association_klass.primary_key
|
|
58
|
+
table = far_association_klass.table_name
|
|
59
|
+
|
|
60
|
+
active_scaffold_includes.concat([{k => v.keys.first}]) # e.g. {:den => :park}
|
|
61
|
+
constraint_condition_for("#{table}__#{field}".to_sym, v.values.first)
|
|
62
|
+
|
|
63
|
+
# association column constraint
|
|
64
|
+
elsif column.association
|
|
65
|
+
if column.association[:type] == :many_to_many
|
|
66
|
+
active_scaffold_habtm_joins.concat column.includes
|
|
67
|
+
else
|
|
68
|
+
active_scaffold_includes.concat column.includes
|
|
69
|
+
end
|
|
70
|
+
condition_from_association_constraint(column.association, v)
|
|
71
|
+
|
|
72
|
+
# regular column constraints
|
|
73
|
+
elsif column.searchable?
|
|
74
|
+
active_scaffold_includes.concat column.includes
|
|
75
|
+
constraint_condition_for(column.search_sql, v)
|
|
76
|
+
end
|
|
77
|
+
# unknown-to-activescaffold-but-real-database-column constraint
|
|
78
|
+
elsif active_scaffold_config.model.columns.include? k
|
|
79
|
+
constraint_condition_for(k, v)
|
|
80
|
+
else
|
|
81
|
+
raise ActiveScaffold::MalformedConstraint, constraint_error(active_scaffold_config.model, k), caller
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
conditions = merge_conditions(conditions, constraint_condition)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
conditions
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# We do NOT want to use .search_sql. If anything, search_sql will refer
|
|
91
|
+
# to a human-searchable value on the associated record.
|
|
92
|
+
def condition_from_association_constraint(association, value)
|
|
93
|
+
# when the reverse association is a :belongs_to, the id for the associated object only exists as
|
|
94
|
+
# the primary_key on the other table. so for :has_one and :has_many (when the reverse is :belongs_to),
|
|
95
|
+
# we have to use the other model's primary_key.
|
|
96
|
+
#
|
|
97
|
+
# please see the relevant tests for concrete examples.
|
|
98
|
+
field = if [:one_to_one, :one_to_many].include?(association[:type])
|
|
99
|
+
association.associated_class.primary_key
|
|
100
|
+
elsif [:many_to_many].include?(association[:type])
|
|
101
|
+
association[:class_name].foreign_key
|
|
102
|
+
else
|
|
103
|
+
association[:name].to_s.foreign_key
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
table = case association[:type]
|
|
107
|
+
when :many_to_many
|
|
108
|
+
association[:join_table]
|
|
109
|
+
|
|
110
|
+
when :many_to_one
|
|
111
|
+
active_scaffold_config.model.table_name
|
|
112
|
+
|
|
113
|
+
else
|
|
114
|
+
association.associated_class.table_name
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# XXX no idea what this is supposed to do, in my setup are all association.options[:primary_key] nils
|
|
118
|
+
# if association.options[:primary_key]
|
|
119
|
+
# value = association.klass.find(value).send(association.options[:primary_key])
|
|
120
|
+
# end
|
|
121
|
+
|
|
122
|
+
constraint_condition_for("#{table}__#{field}".to_sym, value)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def constraint_error(klass, column_name)
|
|
126
|
+
"Malformed constraint `#{klass}##{column_name}'. If it's a legitimate column, and you are using a nested scaffold, please specify or double-check the reverse association name."
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Applies constraints to the given record.
|
|
130
|
+
#
|
|
131
|
+
# Searches through the known columns for association columns. If the given constraint is an association,
|
|
132
|
+
# it assumes that the constraint value is an id. It then does a association.klass.find with the value
|
|
133
|
+
# and adds the associated object to the record.
|
|
134
|
+
#
|
|
135
|
+
# For some operations ActiveRecord will automatically update the database. That's not always ok.
|
|
136
|
+
# If it *is* ok (e.g. you're in a transaction), then set :allow_autosave to true.
|
|
137
|
+
def apply_constraints_to_record(record, options = {})
|
|
138
|
+
options[:allow_autosave] = false if options[:allow_autosave].nil?
|
|
139
|
+
|
|
140
|
+
active_scaffold_constraints.each do |k, v|
|
|
141
|
+
column = active_scaffold_config.columns[k]
|
|
142
|
+
if column and column.association
|
|
143
|
+
if column.plural_association?
|
|
144
|
+
record.send("add_#{k.to_s.singularize}", column.association.associated_class.filter(v))
|
|
145
|
+
else # regular singular association
|
|
146
|
+
record.send("#{k}=", column.association.associated_class.filter(v))
|
|
147
|
+
|
|
148
|
+
# setting the belongs_to side of a has_one isn't safe. if the has_one was already
|
|
149
|
+
# specified, rails won't automatically clear out the previous associated record.
|
|
150
|
+
#
|
|
151
|
+
# note that we can't take the extra step to correct this unless we're permitted to
|
|
152
|
+
# run operations where activerecord auto-saves the object.
|
|
153
|
+
reverse = column.association.associated_class.association_reflection(column.association.reciprocal)
|
|
154
|
+
if reverse[:type] == :one_to_one and options[:allow_autosave]
|
|
155
|
+
record.send(k).send("#{column.association.reciprocal}=", record)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
else
|
|
159
|
+
record.send("#{k}=", v)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
private
|
|
165
|
+
|
|
166
|
+
def constraint_condition_for(sql, value)
|
|
167
|
+
{sql => value}
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
module ActiveScaffold::DataStructures
|
|
2
|
+
# A set of columns. These structures can be nested for organization.
|
|
3
|
+
class ActionColumns < ActiveScaffold::DataStructures::Set
|
|
4
|
+
include ActiveScaffold::Configurable
|
|
5
|
+
|
|
6
|
+
# this lets us refer back to the action responsible for this link, if it exists.
|
|
7
|
+
# the immediate need here is to get the crud_type so we can dynamically filter columns from the set.
|
|
8
|
+
attr_accessor :action
|
|
9
|
+
|
|
10
|
+
# labels are useful for the Create/Update forms, when we display columns in a grouped fashion and want to name them separately
|
|
11
|
+
attr_writer :label
|
|
12
|
+
def label
|
|
13
|
+
as_(@label) if @label
|
|
14
|
+
end
|
|
15
|
+
def css_class
|
|
16
|
+
@label.to_s.underscore
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Whether this column set is collapsed by default in contexts where collapsing is supported
|
|
20
|
+
attr_accessor :collapsed
|
|
21
|
+
|
|
22
|
+
# nests a subgroup in the column set
|
|
23
|
+
def add_subgroup(label, &proc)
|
|
24
|
+
columns = ActiveScaffold::DataStructures::ActionColumns.new
|
|
25
|
+
columns.label = label
|
|
26
|
+
columns.action = self.action
|
|
27
|
+
columns.configure &proc
|
|
28
|
+
self.exclude columns.collect_columns
|
|
29
|
+
self.add columns
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def include?(item)
|
|
33
|
+
@set.each do |c|
|
|
34
|
+
return true if !c.is_a? Symbol and c.include? item
|
|
35
|
+
return true if c == item.to_sym
|
|
36
|
+
end
|
|
37
|
+
return false
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def names
|
|
41
|
+
self.collect(&:name)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def names_without_auth_check
|
|
45
|
+
Array(@set)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
protected
|
|
49
|
+
|
|
50
|
+
def collect_columns
|
|
51
|
+
@set.collect {|col| col.is_a?(ActiveScaffold::DataStructures::ActionColumns) ? col.collect_columns : col}
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# called during clone or dup. makes the clone/dup deeper.
|
|
55
|
+
def initialize_copy(from)
|
|
56
|
+
@set = from.instance_variable_get('@set').clone
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# A package of stuff to add after the configuration block. This is an attempt at making a certain level of functionality inaccessible during configuration, to reduce possible breakage from misuse.
|
|
60
|
+
# The bulk of the package is a means of connecting the referential column set (ActionColumns) with the actual column objects (Columns). This lets us iterate over the set and yield real column objects.
|
|
61
|
+
module AfterConfiguration
|
|
62
|
+
# Redefine the each method to yield actual Column objects.
|
|
63
|
+
# It will skip constrained and unauthorized columns.
|
|
64
|
+
#
|
|
65
|
+
# Options:
|
|
66
|
+
# * :flatten - whether to recursively iterate on nested sets. default is false.
|
|
67
|
+
# * :for - the record (or class) being iterated over. used for column-level security. default is the class.
|
|
68
|
+
def each(options = {}, &proc)
|
|
69
|
+
options[:for] ||= @columns.active_record_class
|
|
70
|
+
self.unauthorized_columns = []
|
|
71
|
+
@set.each do |item|
|
|
72
|
+
unless item.is_a? ActiveScaffold::DataStructures::ActionColumns
|
|
73
|
+
item = (@columns[item] || ActiveScaffold::DataStructures::Column.new(item.to_sym, @columns.active_record_class))
|
|
74
|
+
next if self.skip_column?(item, options)
|
|
75
|
+
end
|
|
76
|
+
if item.is_a? ActiveScaffold::DataStructures::ActionColumns and options.has_key?(:flatten) and options[:flatten]
|
|
77
|
+
item.each(options, &proc)
|
|
78
|
+
else
|
|
79
|
+
yield item
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def collect_visible(options = {}, &proc)
|
|
85
|
+
columns = []
|
|
86
|
+
options[:for] ||= @columns.active_record_class
|
|
87
|
+
self.unauthorized_columns = []
|
|
88
|
+
@set.each do |item|
|
|
89
|
+
unless item.is_a? ActiveScaffold::DataStructures::ActionColumns
|
|
90
|
+
item = (@columns[item] || ActiveScaffold::DataStructures::Column.new(item.to_sym, @columns.active_record_class))
|
|
91
|
+
next if self.skip_column?(item, options)
|
|
92
|
+
end
|
|
93
|
+
if item.is_a? ActiveScaffold::DataStructures::ActionColumns and options.has_key?(:flatten) and options[:flatten]
|
|
94
|
+
columns = columns + item.collect(options, &proc)
|
|
95
|
+
else
|
|
96
|
+
columns << item
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
columns
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def skip_column?(column, options)
|
|
103
|
+
result = false
|
|
104
|
+
# skip if this matches a constrained column
|
|
105
|
+
result = true if constraint_columns.include?(column.name)
|
|
106
|
+
# skip if this matches the field_name of a constrained column
|
|
107
|
+
result = true if column.field_name and constraint_columns.include?(column.field_name)
|
|
108
|
+
# skip this field if it's not authorized
|
|
109
|
+
unless options[:for].authorized_for?(:action => options[:action], :crud_type => options[:crud_type] || self.action.crud_type, :column => column.name)
|
|
110
|
+
self.unauthorized_columns << column.name
|
|
111
|
+
result = true
|
|
112
|
+
end
|
|
113
|
+
return result
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# registers a set of column objects (recursively, for all nested ActionColumns)
|
|
117
|
+
def set_columns(columns)
|
|
118
|
+
@columns = columns
|
|
119
|
+
# iterate over @set instead of self to avoid dealing with security queries
|
|
120
|
+
@set.each do |item|
|
|
121
|
+
item.set_columns(columns) if item.respond_to? :set_columns
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
attr_writer :constraint_columns
|
|
126
|
+
def constraint_columns
|
|
127
|
+
@constraint_columns ||= []
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
attr_writer :unauthorized_columns
|
|
131
|
+
def unauthorized_columns
|
|
132
|
+
@unauthorized_columns ||= []
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def length
|
|
136
|
+
((@set - self.constraint_columns) - self.unauthorized_columns).length
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|