lanes 0.0.1
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 +7 -0
- data/.gitignore +19 -0
- data/.jshintrc +3 -0
- data/Gemfile +9 -0
- data/Guardfile +15 -0
- data/LICENSE-MIT.txt +21 -0
- data/README.md +15 -0
- data/Rakefile +74 -0
- data/bin/lanes +5 -0
- data/client/images/ajax-loader.gif +0 -0
- data/client/images/dataTables/Sorting icons.psd +0 -0
- data/client/images/dataTables/back_disabled.png +0 -0
- data/client/images/dataTables/back_enabled.png +0 -0
- data/client/images/dataTables/back_enabled_hover.png +0 -0
- data/client/images/dataTables/favicon.ico +0 -0
- data/client/images/dataTables/forward_disabled.png +0 -0
- data/client/images/dataTables/forward_enabled.png +0 -0
- data/client/images/dataTables/forward_enabled_hover.png +0 -0
- data/client/images/dataTables/loading-background.png +0 -0
- data/client/images/dataTables/sort_asc.png +0 -0
- data/client/images/dataTables/sort_asc_disabled.png +0 -0
- data/client/images/dataTables/sort_both.png +0 -0
- data/client/images/dataTables/sort_desc.png +0 -0
- data/client/images/dataTables/sort_desc_disabled.png +0 -0
- data/client/images/logo-sm.png +0 -0
- data/client/javascripts/component/Base.coffee +39 -0
- data/client/javascripts/component/ChoicesInput.coffee +47 -0
- data/client/javascripts/component/Grid.coffee +199 -0
- data/client/javascripts/component/ModalDialog.coffee +44 -0
- data/client/javascripts/component/PopOver.coffee +52 -0
- data/client/javascripts/component/RadioGroup.coffee +59 -0
- data/client/javascripts/component/RecordFinder.coffee +143 -0
- data/client/javascripts/component/SelectField.coffee +43 -0
- data/client/javascripts/component/TaggedField.coffee +27 -0
- data/client/javascripts/component/grid/Editor.coffee +65 -0
- data/client/javascripts/component/grid/PopOverEditor.coffee +29 -0
- data/client/javascripts/component/grid/RowEditor.coffee +31 -0
- data/client/javascripts/component/grid/popover-editor.html +18 -0
- data/client/javascripts/component/grid/row-editor.html +16 -0
- data/client/javascripts/component/grid.html +4 -0
- data/client/javascripts/component/index.js +5 -0
- data/client/javascripts/component/modal.html +17 -0
- data/client/javascripts/component/popover.html +5 -0
- data/client/javascripts/component/record-finder/clause.skr +35 -0
- data/client/javascripts/component/record-finder/dialog.skr +4 -0
- data/client/javascripts/component/record-finder/field.skr +8 -0
- data/client/javascripts/data/Bootstrap.coffee +8 -0
- data/client/javascripts/data/ChangeSet.coffee +50 -0
- data/client/javascripts/data/Collection.coffee +111 -0
- data/client/javascripts/data/Config.coffee +15 -0
- data/client/javascripts/data/Model.coffee +269 -0
- data/client/javascripts/data/PubSub.coffee +68 -0
- data/client/javascripts/data/Query.coffee +184 -0
- data/client/javascripts/data/Roles.coffee +91 -0
- data/client/javascripts/data/Screens.coffee +157 -0
- data/client/javascripts/data/Sync.coffee +62 -0
- data/client/javascripts/data/User.coffee +70 -0
- data/client/javascripts/data/index.js +7 -0
- data/client/javascripts/data/mixins/HasCodeField.coffee +13 -0
- data/client/javascripts/extension/Base.coffee +9 -0
- data/client/javascripts/extension/Extensions.coffee +17 -0
- data/client/javascripts/extension/GlAccounts.coffee +9 -0
- data/client/javascripts/extension/index.js +6 -0
- data/client/javascripts/extension/load.js.erb +3 -0
- data/client/javascripts/lanes-complete.js +3 -0
- data/client/javascripts/lanes-workspace.js +1 -0
- data/client/javascripts/lib/MakeBaseClass.coffee +55 -0
- data/client/javascripts/lib/ModuleSupport.coffee +22 -0
- data/client/javascripts/lib/Templates.coffee +47 -0
- data/client/javascripts/lib/create-namespace.js +0 -0
- data/client/javascripts/lib/debounce.coffee +15 -0
- data/client/javascripts/lib/defer.coffee +7 -0
- data/client/javascripts/lib/el.js +115 -0
- data/client/javascripts/lib/index.js +9 -0
- data/client/javascripts/lib/loader.coffee +95 -0
- data/client/javascripts/lib/namespace.coffee +9 -0
- data/client/javascripts/lib/noConflict.coffee +14 -0
- data/client/javascripts/lib/promise_helpers.coffee +4 -0
- data/client/javascripts/lib/results.coffee +15 -0
- data/client/javascripts/lib/underscore.inflection.js +210 -0
- data/client/javascripts/lib/utilFunctions.coffee +51 -0
- data/client/javascripts/plugins/ResizeSensor.js +144 -0
- data/client/javascripts/plugins/index.js +4 -0
- data/client/javascripts/plugins/overlay.coffee +41 -0
- data/client/javascripts/plugins/trigger.coffee +15 -0
- data/client/javascripts/vendor/bootstrap/affix.js +142 -0
- data/client/javascripts/vendor/bootstrap/alert.js +92 -0
- data/client/javascripts/vendor/bootstrap/button.js +110 -0
- data/client/javascripts/vendor/bootstrap/carousel.js +223 -0
- data/client/javascripts/vendor/bootstrap/collapse.js +170 -0
- data/client/javascripts/vendor/bootstrap/dropdown.js +151 -0
- data/client/javascripts/vendor/bootstrap/modal.js +280 -0
- data/client/javascripts/vendor/bootstrap/popover.js +113 -0
- data/client/javascripts/vendor/bootstrap/scrollspy.js +170 -0
- data/client/javascripts/vendor/bootstrap/tab.js +128 -0
- data/client/javascripts/vendor/bootstrap/tooltip.js +457 -0
- data/client/javascripts/vendor/bootstrap/transition.js +59 -0
- data/client/javascripts/vendor/dataTables/dataTables.bootstrap.js +156 -0
- data/client/javascripts/vendor/dataTables/dataTables.scroller.js +1185 -0
- data/client/javascripts/vendor/dataTables/datatables.responsive.js +666 -0
- data/client/javascripts/vendor/dataTables/index.js +2 -0
- data/client/javascripts/vendor/dataTables/jquery.dataTables.js +14380 -0
- data/client/javascripts/vendor/jquery-2.js +9190 -0
- data/client/javascripts/vendor/jquery.tap.js +401 -0
- data/client/javascripts/vendor/magicsuggest.js +1565 -0
- data/client/javascripts/vendor/message-bus.js +285 -0
- data/client/javascripts/vendor/modern-stack.js +14 -0
- data/client/javascripts/vendor/packaged.js +13769 -0
- data/client/javascripts/view/Assets.coffee +9 -0
- data/client/javascripts/view/Base.coffee +231 -0
- data/client/javascripts/view/FormBindings.coffee +98 -0
- data/client/javascripts/view/Functions.coffee +13 -0
- data/client/javascripts/view/Helpers.coffee +77 -0
- data/client/javascripts/view/InterfaceState.coffee +88 -0
- data/client/javascripts/view/Keys.coffee +59 -0
- data/client/javascripts/view/ModelObserver.coffee +31 -0
- data/client/javascripts/view/ModelUpdate.coffee +8 -0
- data/client/javascripts/view/PubSub.coffee +29 -0
- data/client/javascripts/view/RenderContext.coffee +32 -0
- data/client/javascripts/view/SaveNotify.coffee +30 -0
- data/client/javascripts/view/Screen.coffee +30 -0
- data/client/javascripts/view/TimedHighlight.coffee +38 -0
- data/client/javascripts/view/TimedMask.coffee +65 -0
- data/client/javascripts/view/_button.html +3 -0
- data/client/javascripts/view/_toolbar.html +27 -0
- data/client/javascripts/view/index.js +10 -0
- data/client/javascripts/view/mixins/ScreenChangeListener.coffee +43 -0
- data/client/javascripts/view/model-update.html +13 -0
- data/client/javascripts/view/screen-definitions.js.erb +7 -0
- data/client/javascripts/workspace/ActiveScreensSwitcher.coffee +117 -0
- data/client/javascripts/workspace/Instance.es6 +60 -0
- data/client/javascripts/workspace/Layout.coffee +18 -0
- data/client/javascripts/workspace/LoginDialog.coffee +33 -0
- data/client/javascripts/workspace/Navbar.coffee +44 -0
- data/client/javascripts/workspace/Pages.coffee +46 -0
- data/client/javascripts/workspace/ScreensMenu.coffee +126 -0
- data/client/javascripts/workspace/index.js +12 -0
- data/client/javascripts/workspace/layout.html +4 -0
- data/client/javascripts/workspace/login-dialog.html +16 -0
- data/client/javascripts/workspace/menu.html +356 -0
- data/client/javascripts/workspace/menu_toggle.html +9 -0
- data/client/javascripts/workspace/navbar.html +19 -0
- data/client/javascripts/workspace/pages.html +6 -0
- data/client/javascripts/workspace/screens-menu.html +11 -0
- data/client/javascripts/workspace/screens-switcher.html +7 -0
- data/client/javascripts/workspace/tab.html +0 -0
- data/client/screens/user-management/UserEditScreen.coffee +21 -0
- data/client/screens/user-management/UserManagement.coffee +24 -0
- data/client/screens/user-management/grid-popover-editor.html +33 -0
- data/client/screens/user-management/index.css +4 -0
- data/client/screens/user-management/index.js +2 -0
- data/client/screens/user-management/user-management-styles.scss +7 -0
- data/client/screens/user-management/user-management.html +8 -0
- data/client/stylesheets/compoonents/all.scss +6 -0
- data/client/stylesheets/compoonents/changes-notification.scss +44 -0
- data/client/stylesheets/compoonents/grid-editors.scss +65 -0
- data/client/stylesheets/compoonents/grid.scss +301 -0
- data/client/stylesheets/compoonents/modal-dialog.scss +23 -0
- data/client/stylesheets/compoonents/record-finder.scss +71 -0
- data/client/stylesheets/compoonents/suggest.scss +266 -0
- data/client/stylesheets/fonts/icomoon.eot +0 -0
- data/client/stylesheets/fonts/icomoon.svg +160 -0
- data/client/stylesheets/fonts/icomoon.ttf +0 -0
- data/client/stylesheets/fonts/icomoon.woff +0 -0
- data/client/stylesheets/fonts/selection.json +3565 -0
- data/client/stylesheets/fonts/style.css +451 -0
- data/client/stylesheets/fonts.scss +38 -0
- data/client/stylesheets/forms.scss +75 -0
- data/client/stylesheets/index.css +4 -0
- data/client/stylesheets/keybindings.scss +6 -0
- data/client/stylesheets/lanes-workspace.scss +17 -0
- data/client/stylesheets/layout.scss +272 -0
- data/client/stylesheets/plugins/all.scss +2 -0
- data/client/stylesheets/plugins/overlay.scss +63 -0
- data/client/stylesheets/plugins/resize-sensor.scss +24 -0
- data/client/stylesheets/screens.scss +66 -0
- data/client/stylesheets/tabs.scss +148 -0
- data/client/stylesheets/vendor/bootstrap/_alerts.scss +68 -0
- data/client/stylesheets/vendor/bootstrap/_badges.scss +57 -0
- data/client/stylesheets/vendor/bootstrap/_breadcrumbs.scss +26 -0
- data/client/stylesheets/vendor/bootstrap/_button-groups.scss +240 -0
- data/client/stylesheets/vendor/bootstrap/_buttons.scss +157 -0
- data/client/stylesheets/vendor/bootstrap/_carousel.scss +243 -0
- data/client/stylesheets/vendor/bootstrap/_close.scss +35 -0
- data/client/stylesheets/vendor/bootstrap/_code.scss +68 -0
- data/client/stylesheets/vendor/bootstrap/_component-animations.scss +35 -0
- data/client/stylesheets/vendor/bootstrap/_dropdowns.scss +215 -0
- data/client/stylesheets/vendor/bootstrap/_forms.scss +538 -0
- data/client/stylesheets/vendor/bootstrap/_glyphicons.scss +237 -0
- data/client/stylesheets/vendor/bootstrap/_grid.scss +84 -0
- data/client/stylesheets/vendor/bootstrap/_input-groups.scss +166 -0
- data/client/stylesheets/vendor/bootstrap/_jumbotron.scss +48 -0
- data/client/stylesheets/vendor/bootstrap/_labels.scss +66 -0
- data/client/stylesheets/vendor/bootstrap/_list-group.scss +132 -0
- data/client/stylesheets/vendor/bootstrap/_media.scss +56 -0
- data/client/stylesheets/vendor/bootstrap/_mixins.scss +39 -0
- data/client/stylesheets/vendor/bootstrap/_modals.scss +150 -0
- data/client/stylesheets/vendor/bootstrap/_navbar.scss +659 -0
- data/client/stylesheets/vendor/bootstrap/_navs.scss +242 -0
- data/client/stylesheets/vendor/bootstrap/_normalize.scss +425 -0
- data/client/stylesheets/vendor/bootstrap/_pager.scss +55 -0
- data/client/stylesheets/vendor/bootstrap/_pagination.scss +88 -0
- data/client/stylesheets/vendor/bootstrap/_panels.scss +243 -0
- data/client/stylesheets/vendor/bootstrap/_popovers.scss +133 -0
- data/client/stylesheets/vendor/bootstrap/_print.scss +101 -0
- data/client/stylesheets/vendor/bootstrap/_progress-bars.scss +105 -0
- data/client/stylesheets/vendor/bootstrap/_responsive-embed.scss +34 -0
- data/client/stylesheets/vendor/bootstrap/_responsive-utilities.scss +174 -0
- data/client/stylesheets/vendor/bootstrap/_scaffolding.scss +150 -0
- data/client/stylesheets/vendor/bootstrap/_tables.scss +233 -0
- data/client/stylesheets/vendor/bootstrap/_theme.scss +258 -0
- data/client/stylesheets/vendor/bootstrap/_thumbnails.scss +38 -0
- data/client/stylesheets/vendor/bootstrap/_tooltip.scss +95 -0
- data/client/stylesheets/vendor/bootstrap/_type.scss +304 -0
- data/client/stylesheets/vendor/bootstrap/_utilities.scss +57 -0
- data/client/stylesheets/vendor/bootstrap/_variables.scss +850 -0
- data/client/stylesheets/vendor/bootstrap/_wells.scss +29 -0
- data/client/stylesheets/vendor/bootstrap/bootstrap.scss +50 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_alerts.scss +14 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_background-variant.scss +11 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_border-radius.scss +18 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_buttons.scss +50 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_center-block.scss +7 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_clearfix.scss +22 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_forms.scss +84 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_gradients.scss +58 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_grid-framework.scss +81 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_grid.scss +122 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_hide-text.scss +21 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_image.scss +34 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_labels.scss +12 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_list-group.scss +31 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_nav-divider.scss +10 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_nav-vertical-align.scss +9 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_opacity.scss +8 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_pagination.scss +23 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_panels.scss +24 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_progress-bar.scss +10 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_reset-filter.scss +8 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_resize.scss +6 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_responsive-visibility.scss +21 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_size.scss +10 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_tab-focus.scss +9 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_table-row.scss +28 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_text-emphasis.scss +11 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_text-overflow.scss +8 -0
- data/client/stylesheets/vendor/bootstrap/mixins/_vendor-prefixes.scss +219 -0
- data/client/stylesheets/vendor/bootstrap-custom-grid.scss +85 -0
- data/client/stylesheets/vendor/bootstrap-custom-modals.scss +150 -0
- data/client/stylesheets/vendor/bootstrap.scss +69 -0
- data/client/stylesheets/vendor/dataTables.scss +4 -0
- data/config/database.yml +9 -0
- data/config/puma.rb +7 -0
- data/config.ru +4 -0
- data/db/migrate/20140615031600_create_hip_users.rb +17 -0
- data/db/seed.rb +37 -0
- data/foo/Gemfile +5 -0
- data/foo/Guardfile +13 -0
- data/foo/foo/Gemfile +5 -0
- data/foo/foo/lib/foo.rb +7 -0
- data/foo/lib/foo/version.rb +3 -0
- data/foo/lib/foo.rb +8 -0
- data/lanes.gemspec +54 -0
- data/lib/generators/lanes/migrations/install_generator.rb +42 -0
- data/lib/lanes/access/locked_fields.rb +43 -0
- data/lib/lanes/access/role.rb +58 -0
- data/lib/lanes/access/role_collection.rb +75 -0
- data/lib/lanes/access/roles/administrator.rb +25 -0
- data/lib/lanes/access/roles/support.rb +13 -0
- data/lib/lanes/access/user_maint_screen.rb +32 -0
- data/lib/lanes/access.rb +50 -0
- data/lib/lanes/api/asset_pipeline.rb +59 -0
- data/lib/lanes/api/authentication_helper.rb +21 -0
- data/lib/lanes/api/authentication_provider.rb +45 -0
- data/lib/lanes/api/controller.rb +290 -0
- data/lib/lanes/api/default_routes.rb +35 -0
- data/lib/lanes/api/eco.js +516 -0
- data/lib/lanes/api/error_formatter.rb +37 -0
- data/lib/lanes/api/helper_methods.rb +32 -0
- data/lib/lanes/api/javascript_processor.rb +116 -0
- data/lib/lanes/api/pub_sub.rb +33 -0
- data/lib/lanes/api/request_wrapper.rb +42 -0
- data/lib/lanes/api/root.rb +103 -0
- data/lib/lanes/api/skr_templates.rb +60 -0
- data/lib/lanes/api/test_specs.rb +59 -0
- data/lib/lanes/api/updates.rb +38 -0
- data/lib/lanes/api.rb +27 -0
- data/lib/lanes/cli.rb +13 -0
- data/lib/lanes/concerns/all.rb +16 -0
- data/lib/lanes/concerns/api_path.rb +21 -0
- data/lib/lanes/concerns/association_extensions.rb +85 -0
- data/lib/lanes/concerns/attr_accessor_with_default.rb +62 -0
- data/lib/lanes/concerns/code_identifier.rb +43 -0
- data/lib/lanes/concerns/export_associations.rb +52 -0
- data/lib/lanes/concerns/export_join_tables.rb +39 -0
- data/lib/lanes/concerns/export_methods.rb +104 -0
- data/lib/lanes/concerns/export_scope.rb +66 -0
- data/lib/lanes/concerns/exported_limit_evaluator.rb +17 -0
- data/lib/lanes/concerns/immutable_model.rb +32 -0
- data/lib/lanes/concerns/locked_fields.rb +84 -0
- data/lib/lanes/concerns/pub_sub.rb +105 -0
- data/lib/lanes/concerns/queries.rb +20 -0
- data/lib/lanes/concerns/random_hash_code.rb +40 -0
- data/lib/lanes/concerns/sanitize_api_data.rb +15 -0
- data/lib/lanes/concerns/set_attribute_data.rb +154 -0
- data/lib/lanes/concerns/track_modifications.rb +51 -0
- data/lib/lanes/concerns/visible_id_identifier.rb +53 -0
- data/lib/lanes/configuration.rb +85 -0
- data/lib/lanes/db/migration_helpers.rb +178 -0
- data/lib/lanes/db/migrations.rb +13 -0
- data/lib/lanes/db/seed.rb +27 -0
- data/lib/lanes/db.rb +86 -0
- data/lib/lanes/environment.rb +19 -0
- data/lib/lanes/extension.rb +72 -0
- data/lib/lanes/generators/app/Gemfile +5 -0
- data/lib/lanes/generators/app/Guardfile +13 -0
- data/lib/lanes/generators/app/Rakefile +9 -0
- data/lib/lanes/generators/app/config/database.yml +9 -0
- data/lib/lanes/generators/app/config.ru +4 -0
- data/lib/lanes/generators/app/lib/main_class/version.rb +3 -0
- data/lib/lanes/generators/app/lib/main_class.rb +8 -0
- data/lib/lanes/generators/app.rb +36 -0
- data/lib/lanes/guard_tasks.rb +44 -0
- data/lib/lanes/logger.rb +37 -0
- data/lib/lanes/model.rb +26 -0
- data/lib/lanes/numbers.rb +72 -0
- data/lib/lanes/rails_engine.rb +5 -0
- data/lib/lanes/screens.rb +126 -0
- data/lib/lanes/spec_asset_expander.rb +43 -0
- data/lib/lanes/strings.rb +56 -0
- data/lib/lanes/user.rb +127 -0
- data/lib/lanes/validators/all.rb +2 -0
- data/lib/lanes/validators/email.rb +17 -0
- data/lib/lanes/validators/set.rb +18 -0
- data/lib/lanes/version.rb +5 -0
- data/lib/lanes.rb +22 -0
- data/npm-build/README +1 -0
- data/npm-build/compile.coffee +15 -0
- data/npm-build/package.json +59 -0
- data/npm-build/shims/underscore.js +1416 -0
- data/npm-build/template.js +33 -0
- data/public/javascripts/jasmine_examples/Player.js +22 -0
- data/public/javascripts/jasmine_examples/Song.js +7 -0
- data/spec/api/javascript_processor_spec.rb +107 -0
- data/spec/api/user_spec.rb +52 -0
- data/spec/client/component/ChoicesInputSpec.coffee +12 -0
- data/spec/client/component/foo_spec.coffee +4 -0
- data/spec/client/foo_spec.js +0 -0
- data/spec/client/jasmine_examples/PlayerSpec.js +0 -0
- data/spec/client/support/jasmine.yml +128 -0
- data/spec/client/support/jasmine_helper.rb +15 -0
- data/spec/concerns/api_path_spec.rb +14 -0
- data/spec/concerns/association_extensions_spec.rb +30 -0
- data/spec/concerns/attr_accessor_with_default_spec.rb +57 -0
- data/spec/concerns/code_identifier_spec.rb +45 -0
- data/spec/concerns/export_associations_spec.rb +7 -0
- data/spec/concerns/export_methods_spec.rb +43 -0
- data/spec/concerns/export_scope_spec.rb +15 -0
- data/spec/concerns/exported_limits_spec.rb +47 -0
- data/spec/concerns/pub_sub_spec.rb +83 -0
- data/spec/concerns/set_attribute_data_spec.rb +66 -0
- data/spec/configuration_spec.rb +26 -0
- data/spec/fixtures/lanes/users.yml +13 -0
- data/spec/helpers/.gitkeep +0 -0
- data/spec/helpers/SpecHelper.js +18 -0
- data/spec/locked_fields_spec.rb +27 -0
- data/spec/numbers_spec.rb +26 -0
- data/spec/role_collection_spec.rb +19 -0
- data/spec/spec_helper.rb +163 -0
- data/spec/strings_spec.rb +41 -0
- data/spec/testing_models.rb +54 -0
- data/spec/user_role_spec.rb +7 -0
- data/spec/user_spec.rb +53 -0
- data/tasks/migrations.rake +22 -0
- data/tasks/publish.rake +8 -0
- data/views/index.erb +29 -0
- data/views/specs.erb +25 -0
- data/yard_ext/all.rb +9 -0
- data/yard_ext/code_identifier_handler.rb +33 -0
- data/yard_ext/concern_meta_methods.rb +60 -0
- data/yard_ext/config_options.rb +27 -0
- data/yard_ext/exported_scope.rb +4 -0
- data/yard_ext/immutable_handler.rb +17 -0
- data/yard_ext/json_attr_accessor.rb +22 -0
- data/yard_ext/locked_fields_handler.rb +21 -0
- data/yard_ext/templates/default/layout/html/layout.erb +20 -0
- data/yard_ext/templates/default/method_details/html/github_link.erb +1 -0
- data/yard_ext/templates/default/method_details/setup.rb +3 -0
- data/yard_ext/validators.rb +1 -0
- data/yard_ext/visible_id_handler.rb +38 -0
- metadata +772 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require_relative "../lanes"
|
|
2
|
+
require 'guard'
|
|
3
|
+
|
|
4
|
+
module Lanes
|
|
5
|
+
module GuardTasks
|
|
6
|
+
|
|
7
|
+
class CustomMatchers
|
|
8
|
+
attr_reader :client_matches, :server_matches
|
|
9
|
+
|
|
10
|
+
def client(&block)
|
|
11
|
+
@client_matches = block
|
|
12
|
+
end
|
|
13
|
+
def server(&block)
|
|
14
|
+
@server_matches = block
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.run(dsl, options, &block)
|
|
19
|
+
app_name = options[:name] || Pathname.getwd.basename.to_s
|
|
20
|
+
matchers = CustomMatchers.new
|
|
21
|
+
yield matchers
|
|
22
|
+
|
|
23
|
+
jasmine_options = {
|
|
24
|
+
server_mount: '/spec', server_env: 'test', server: :puma, spec_dir: 'spec/client', debug: false
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
dsl.guard :jasmine, jasmine_options do
|
|
28
|
+
dsl.watch(%r{^client/javascripts/(.+?)\.(js|coffee)$}){ |m| "spec/client/#{m[1]}_spec.#{m[2]}" }
|
|
29
|
+
dsl.watch(%r{^spec/client/.*(?:_s|S)pec\.coffee$})
|
|
30
|
+
matchers.client_matches.call if matchers.client_matches
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
dsl.guard :minitest, :all_on_start => true do
|
|
34
|
+
dsl.watch(%r{^spec/spec_helper\.rb}) { 'test' }
|
|
35
|
+
dsl.watch(%r{^spec/.+_spec\.rb})
|
|
36
|
+
dsl.watch(%r{^spec/fixtures/#{app_name}/(.+)s\.yml}) { |m| "spec/#{m[1]}_spec.rb" }
|
|
37
|
+
dsl.watch(%r{^lib/#{app_name}/(.+)\.rb}) { |m| "spec/#{m[1]}_spec.rb" }
|
|
38
|
+
matchers.server_matches.call if matchers.server_matches
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
end
|
data/lib/lanes/logger.rb
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
require 'logger'
|
|
3
|
+
|
|
4
|
+
module Lanes
|
|
5
|
+
|
|
6
|
+
class << self
|
|
7
|
+
def logger
|
|
8
|
+
@logger ||= (
|
|
9
|
+
if defined?(::Rails)
|
|
10
|
+
Rails.logger
|
|
11
|
+
else
|
|
12
|
+
Logger.new(STDOUT)
|
|
13
|
+
end
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def logger=( logger )
|
|
18
|
+
@logger = logger
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def silence_logs( &block )
|
|
22
|
+
old_logger = Lanes.logger
|
|
23
|
+
begin
|
|
24
|
+
Lanes.logger=Logger.new( StringIO.new )
|
|
25
|
+
yield
|
|
26
|
+
ensure
|
|
27
|
+
Lanes.logger=old_logger
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def logger_debug( output )
|
|
32
|
+
logger.debug '⚡ '*40
|
|
33
|
+
logger.debug '⚡ ' + output
|
|
34
|
+
logger.debug '⚡ '*40
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/lanes/model.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require_relative 'concerns/all'
|
|
2
|
+
|
|
3
|
+
module Lanes
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Model < ::ActiveRecord::Base
|
|
7
|
+
self.abstract_class = true
|
|
8
|
+
|
|
9
|
+
include Concerns::PubSub
|
|
10
|
+
include Concerns::ApiAttributeAccess
|
|
11
|
+
include Concerns::LockedFields
|
|
12
|
+
include Concerns::CodeIdentifier
|
|
13
|
+
include Concerns::RandomHashCode
|
|
14
|
+
include Concerns::VisibleIdIdentifier
|
|
15
|
+
include Concerns::ImmutableModel
|
|
16
|
+
include Concerns::ExportMethods
|
|
17
|
+
include Concerns::ExportScope
|
|
18
|
+
include Concerns::ExportAssociations
|
|
19
|
+
include Concerns::ExportJoinTables
|
|
20
|
+
include Concerns::SanitizeApiData
|
|
21
|
+
include Concerns::AssociationExtensions
|
|
22
|
+
include Concerns::ApiPath
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# * Utility methods that manipulate Numbers
|
|
2
|
+
|
|
3
|
+
module Lanes
|
|
4
|
+
module Numbers
|
|
5
|
+
# Document the responsibility of the class
|
|
6
|
+
#
|
|
7
|
+
# == Heading
|
|
8
|
+
#
|
|
9
|
+
# Use headings to break up descriptions
|
|
10
|
+
#
|
|
11
|
+
# == Formatting
|
|
12
|
+
#
|
|
13
|
+
# Embody +parameters+ or +options+ in Teletype Text tags. You can also use
|
|
14
|
+
# *bold* or *italics* but must use HTML tags for <b>multiple words</b>,
|
|
15
|
+
# <i>like this</i> and <tt>like this</tt>.
|
|
16
|
+
# - See more at: http://blog.firsthand.ca/2010/09/ruby-rdoc-example.html#sthash.q9Jkcjrl.dpuf
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# ### PercNum
|
|
20
|
+
#
|
|
21
|
+
#
|
|
22
|
+
# A "percnum" is a Stockor invention *(or abomination, depending on your POV)*.
|
|
23
|
+
# It's a string that contains a number and an optional percent sign.
|
|
24
|
+
# If the percent sign is present, the number is treated as a percentage.
|
|
25
|
+
# If desired the user may also input negative numbers which will invert the sense of the method.
|
|
26
|
+
#
|
|
27
|
+
# It's intended to be a user-friendly method to provide one input box for "discount" or "surcharge",
|
|
28
|
+
# and allow the user to input either a flat amount such as 4.50, or a percentage like 20%
|
|
29
|
+
#
|
|
30
|
+
class PercNum
|
|
31
|
+
# @param perc_or_num [BigDecimal,String, Integer] any value that BigDecimal will accept
|
|
32
|
+
def initialize( perc_or_num )
|
|
33
|
+
@is_perc = !! perc_or_num.to_s.match( /\%\s*$/ )
|
|
34
|
+
@right_side = BigDecimal.new( perc_or_num, 5 )
|
|
35
|
+
if is_percentage?
|
|
36
|
+
@right_side *= 0.01
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Adds the PercNum to the specified amount.
|
|
41
|
+
# @param amount[BigDecimal] the amount that should be added to the PercNum
|
|
42
|
+
# @return [BigDecimal] The result of either adding (non percent) or multiplying by (percent) the amount
|
|
43
|
+
# @example
|
|
44
|
+
# PercNum.new( '23.42' ).credit_to( 33 ).to_s #=> '56.42'
|
|
45
|
+
# PercNum.new( '25%' ).credit_to( 100 ).to_s #=> '125.0'
|
|
46
|
+
def credit_to( amount )
|
|
47
|
+
is_percentage? ? ( 1 + @right_side ) * amount : amount += @right_side
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Subtracts the PercNum to the specified amount.
|
|
51
|
+
# @param amount[BigDecimal] the amount that should be added to the PercNum
|
|
52
|
+
# @return [BigDecimal] The result of either adding (non percent) or multiplying by (percent) the amount
|
|
53
|
+
# @example
|
|
54
|
+
# PercNum.new( '23.42' ).debit_from( 42.42 ).to_s #=> '19.00'
|
|
55
|
+
# PercNum.new( '25%' ).debit_from( 100 ).to_s #=> '75.0'
|
|
56
|
+
def debit_from( amount )
|
|
57
|
+
is_percentage? ? ( 1 - @right_side ) * amount : amount -= @right_side
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
## If PercNum was initialized with a blank string
|
|
61
|
+
def present?
|
|
62
|
+
! @right_side.zero?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Is the PercNum percentage based or absolute
|
|
66
|
+
def is_percentage?
|
|
67
|
+
@is_perc
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
|
|
3
|
+
module Lanes
|
|
4
|
+
|
|
5
|
+
module Screens
|
|
6
|
+
class << self
|
|
7
|
+
|
|
8
|
+
def each_directory
|
|
9
|
+
root = Pathname.new(__FILE__).dirname.join('../../assets/screens')
|
|
10
|
+
root.each_child do | path |
|
|
11
|
+
yield path if path.directory?
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def assets_for_directory(directory)
|
|
16
|
+
path = "skr/screens/#{directory.basename}"
|
|
17
|
+
assets = []
|
|
18
|
+
unless Pathname.glob([ directory.join('*.js'), directory.join('*.coffee')] ).empty?
|
|
19
|
+
assets << "#{path}.js"
|
|
20
|
+
end
|
|
21
|
+
unless Pathname.glob([ directory.join('*.css'), directory.join('*.scss')] ).empty?
|
|
22
|
+
assets << "#{path}.css"
|
|
23
|
+
end
|
|
24
|
+
assets
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# def groups(sprockets)
|
|
28
|
+
# groups = []
|
|
29
|
+
# each_definition(sprockets) do | spec |
|
|
30
|
+
# unless groups.detect{ |group| group['id'] == spec.group_id }
|
|
31
|
+
# groups << spec.group_definition
|
|
32
|
+
# end
|
|
33
|
+
# groups
|
|
34
|
+
# end
|
|
35
|
+
# end
|
|
36
|
+
|
|
37
|
+
# def each_definition(sprockets)
|
|
38
|
+
# ScreenDefinition.each(sprockets) do | definition |
|
|
39
|
+
# spec = definition.specification
|
|
40
|
+
# spec['files'] = definition.asset_file_names.map{ |file| "/assets/#{file}" }
|
|
41
|
+
# yield spec
|
|
42
|
+
# end
|
|
43
|
+
# end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class Group
|
|
47
|
+
include Concerns::AttrAccessorWithDefault
|
|
48
|
+
|
|
49
|
+
attr_accessor_with_default :identifier
|
|
50
|
+
attr_accessor_with_default :title
|
|
51
|
+
attr_accessor_with_default :description
|
|
52
|
+
attr_accessor_with_default :icon
|
|
53
|
+
|
|
54
|
+
def self.each(config)
|
|
55
|
+
self.descendants.each{ |klass| yield klass.new(config) }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def initialize(sprockets)
|
|
59
|
+
@sprockets=sprockets
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def to_json
|
|
63
|
+
Oj.dump({
|
|
64
|
+
id: identifier,
|
|
65
|
+
title: title,
|
|
66
|
+
description: description,
|
|
67
|
+
icon: icon
|
|
68
|
+
}, mode: :compat)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
class Definition
|
|
73
|
+
include Concerns::AttrAccessorWithDefault
|
|
74
|
+
|
|
75
|
+
attr_accessor_with_default :identifier
|
|
76
|
+
attr_accessor_with_default :title
|
|
77
|
+
attr_accessor_with_default :description
|
|
78
|
+
attr_accessor_with_default :icon
|
|
79
|
+
attr_accessor_with_default :group_id
|
|
80
|
+
attr_accessor_with_default :view_class
|
|
81
|
+
attr_accessor_with_default :model_class
|
|
82
|
+
attr_accessor_with_default :files
|
|
83
|
+
|
|
84
|
+
def self.each(config)
|
|
85
|
+
self.descendants.each{ |klass| yield klass.new(config) }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def initialize(sprockets)
|
|
89
|
+
@sprockets=sprockets
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def to_json
|
|
93
|
+
Oj.dump({
|
|
94
|
+
id: identifier,
|
|
95
|
+
title: title,
|
|
96
|
+
icon: icon,
|
|
97
|
+
model: model_class,
|
|
98
|
+
view: view_class,
|
|
99
|
+
files: files,
|
|
100
|
+
group_id: group_id,
|
|
101
|
+
description: description
|
|
102
|
+
}, mode: :compat)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
class SystemGroup < Group
|
|
107
|
+
identifier "system-settings"
|
|
108
|
+
title "System Settings"
|
|
109
|
+
description "Modify system settings"
|
|
110
|
+
icon "icon-wrench"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
class UserMaintScreen < Definition
|
|
114
|
+
identifier "user-maintenance"
|
|
115
|
+
title "User Maintenance"
|
|
116
|
+
description "Add/Remove/Modify User Accounts"
|
|
117
|
+
icon "icon-group"
|
|
118
|
+
group_id "system-settings"
|
|
119
|
+
model_class "User"
|
|
120
|
+
view_class "UserManagement"
|
|
121
|
+
files ['/assets/user-management.js','/assets/user-management.css']
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Lanes
|
|
2
|
+
class SpecAssetExpander
|
|
3
|
+
|
|
4
|
+
def expand(src_dir, src_path)
|
|
5
|
+
pathname = src_path.gsub(/^\/?assets\//, '').gsub(/\.js$/, '')
|
|
6
|
+
|
|
7
|
+
asset_bundle.assets(pathname).flat_map { |asset|
|
|
8
|
+
"/#{asset.gsub(/^\//, '')}?body=true"
|
|
9
|
+
}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def asset_bundle
|
|
15
|
+
return AssetBundle.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class AssetBundle
|
|
19
|
+
def assets(pathname)
|
|
20
|
+
context.get_original_assets(pathname)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def context
|
|
26
|
+
@context ||= ActionView::Base.new.extend(GetOriginalAssetsHelper)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
module GetOriginalAssetsHelper
|
|
30
|
+
def get_original_assets(pathname)
|
|
31
|
+
assets_environment.find_asset(pathname).to_a.map do |processed_asset|
|
|
32
|
+
case processed_asset.content_type
|
|
33
|
+
when "text/css"
|
|
34
|
+
path_to_stylesheet(processed_asset.logical_path, debug: true)
|
|
35
|
+
when "application/javascript"
|
|
36
|
+
path_to_javascript(processed_asset.logical_path, debug: true)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module Lanes
|
|
2
|
+
|
|
3
|
+
module Strings
|
|
4
|
+
|
|
5
|
+
# list of characters that should not be used
|
|
6
|
+
BAD_RAND_CHARS = %w{ B 8 o O 0 i l I 1 }
|
|
7
|
+
|
|
8
|
+
# characters that should be randomly chosen from
|
|
9
|
+
RAND_CHARS = ( ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a ) - BAD_RAND_CHARS
|
|
10
|
+
|
|
11
|
+
# Generates a random string without using commonly confused numbers and letters.
|
|
12
|
+
# It's intended for use in situations where the code will have to be
|
|
13
|
+
# read and re-entered later.
|
|
14
|
+
#
|
|
15
|
+
# The characters in BAD_RAND_CHARS are avoided since they can be confused with one another:
|
|
16
|
+
# @return [String] a random string <length> characters long.
|
|
17
|
+
def self.random( length = 12 )
|
|
18
|
+
1.upto(length).each_with_object(''){|i,s| s << RAND_CHARS[ rand(RAND_CHARS.length) ] }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Attempts to shorten a string while keeping it somewhat
|
|
22
|
+
# like it's original self.
|
|
23
|
+
# Useful for suggesting a code for a given entity name.
|
|
24
|
+
# @param string [String] the string to shorten.
|
|
25
|
+
# @param length [Integer] how long the returned code should be
|
|
26
|
+
# @param padding [String] What to pad the code with if it is shorter than length. False indicates no padding should be performed
|
|
27
|
+
# @return [String] a shortened version of the name with:
|
|
28
|
+
# * Upper cased
|
|
29
|
+
# * Spaces stripped
|
|
30
|
+
# * Made up of a proportional number of chars from each word
|
|
31
|
+
# #### Examples:
|
|
32
|
+
# Lanes::Strings.to_code_identifier('General Acme Corp') #=> 'GENACMCORP'
|
|
33
|
+
# Lanes::Strings.code_identifier('General I B', padding:false) #=> 'GENERALIB' *(no trailing X)*
|
|
34
|
+
# Lanes::Strings.to_code_identifier('Top Cat', maxlen: 5 ) #=> 'TOCAT'
|
|
35
|
+
def self.code_identifier( string, length:10, padding: 'X' )
|
|
36
|
+
stripped = string.gsub(/\W/, '').upcase
|
|
37
|
+
if stripped.length < length
|
|
38
|
+
return padding.present? ? stripped.ljust( length, padding ) : stripped
|
|
39
|
+
end
|
|
40
|
+
result = ''
|
|
41
|
+
words = string.gsub(/[^\w\s-]/,'').split(/\s+|-|_/)
|
|
42
|
+
0.upto(words.length + 1).each_with_index do | attempt_num |
|
|
43
|
+
remainder = length
|
|
44
|
+
result = ''
|
|
45
|
+
string = words.each_with_index do | word, index |
|
|
46
|
+
chars = ( remainder / (words.length-index) + attempt_num )
|
|
47
|
+
result << word[0...chars]
|
|
48
|
+
remainder = length - result.length
|
|
49
|
+
end
|
|
50
|
+
break if result.length >= length
|
|
51
|
+
end
|
|
52
|
+
result[0...length].upcase
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
end
|
data/lib/lanes/user.rb
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
module Lanes
|
|
2
|
+
|
|
3
|
+
class User < Lanes::Model
|
|
4
|
+
has_secure_password
|
|
5
|
+
|
|
6
|
+
validates :login, :name, :email, presence: true
|
|
7
|
+
validates :email, email: true, uniqueness: { case_sensitive: false }
|
|
8
|
+
validates :password, length: { minimum: 6 }, allow_nil: true
|
|
9
|
+
|
|
10
|
+
whitelist_attributes :password
|
|
11
|
+
|
|
12
|
+
def roles
|
|
13
|
+
@cached_roles ||= Access::RoleCollection.new(self)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def workspace_data
|
|
17
|
+
my_data = attributes.slice('id','login','name','email','created_at',
|
|
18
|
+
'created_by','updated_at','updated_by','role_names')
|
|
19
|
+
{ user: my_data, access: Access.for_user(self) }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @param model [Lanes::Model]
|
|
23
|
+
# @param attribute [Symbol]
|
|
24
|
+
# @return [Boolean] Can the User view the model?
|
|
25
|
+
def can_read?(model, attribute = nil)
|
|
26
|
+
roles.can_read?(model, attribute)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @param model [Lanes::Model]
|
|
30
|
+
# @param attribute [Symbol]
|
|
31
|
+
# @return [Boolean] Can the User create and update the model?
|
|
32
|
+
def can_write?(model, attribute = nil)
|
|
33
|
+
roles.can_write?(model, attribute)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @param model [Lanes::Model]
|
|
37
|
+
# @param id [Numberic] the id for the model
|
|
38
|
+
# @return [Boolean] Can the User delete the model?
|
|
39
|
+
def can_delete?(model, id)
|
|
40
|
+
roles.can_delete?(model, id)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# We override the default implementation so that we can gaurantee
|
|
44
|
+
# that the current user can always update their own information
|
|
45
|
+
USER_EDITABLE_ATTRIBUTES=[:name, :email, :password]
|
|
46
|
+
def setting_attribute_is_allowed?(name, user)
|
|
47
|
+
( !new_record? && user.id == self.id && USER_EDITABLE_ATTRIBUTES.include?(name) ) ? true : super
|
|
48
|
+
end
|
|
49
|
+
def can_write_attributes?( attr, user )
|
|
50
|
+
( !new_record? && user.id == self.id ) ? true : super
|
|
51
|
+
end
|
|
52
|
+
def self.can_write_attributes?( attr, user )
|
|
53
|
+
( attr[:id] && attr[:id].to_i == user.id ) ? true : super
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# If all that's needed is the user's id, see `current_id`,
|
|
59
|
+
# that method does not not attempt to instantiate a User
|
|
60
|
+
# Defaults to nil
|
|
61
|
+
# @return [User] The user who's currently interacting with Lanes.
|
|
62
|
+
def self.current
|
|
63
|
+
uid = Thread.current[:lanes_current_user]
|
|
64
|
+
if uid.is_a?(User)
|
|
65
|
+
uid
|
|
66
|
+
else
|
|
67
|
+
user = Thread.current[:lanes_current_user] = User.find_by_id(uid)
|
|
68
|
+
return user ? user.id : nil
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Retrieve the current id of the user we're proxying for.
|
|
73
|
+
# get's a bit complicated since we can proxy both for a user object
|
|
74
|
+
# or just the user's id
|
|
75
|
+
# @return [Fixnum] current user's ID. If the current user is not set, returns 0
|
|
76
|
+
def self.current_id
|
|
77
|
+
uid = Thread.current[:lanes_current_user]
|
|
78
|
+
if uid.nil?
|
|
79
|
+
0
|
|
80
|
+
elsif uid.is_a?(User)
|
|
81
|
+
uid.id
|
|
82
|
+
else
|
|
83
|
+
uid
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# sets the user for the duration of the block
|
|
88
|
+
# @example Inside a Rails controller
|
|
89
|
+
#
|
|
90
|
+
# class DocumentsController < ApplicationController
|
|
91
|
+
# around_filter :set_lanes_user
|
|
92
|
+
#
|
|
93
|
+
# # update's the Document's owner to current
|
|
94
|
+
# # But sets all the notes to be owned by admin
|
|
95
|
+
# def update_owner
|
|
96
|
+
# doc = Document.find(params[:id])
|
|
97
|
+
# doc.current_owner = Lanes::User.current
|
|
98
|
+
# Lanes::User.scoped_to( admin_user ) do
|
|
99
|
+
# doc.notes.each{ |note| note.set_owner_to_current! } # will set to Lanese::User.current
|
|
100
|
+
# end
|
|
101
|
+
# end
|
|
102
|
+
#
|
|
103
|
+
# private
|
|
104
|
+
#
|
|
105
|
+
# def set_lanes_user
|
|
106
|
+
# Lanes::User.scoped_to( session[:user_id] ) do
|
|
107
|
+
# yield
|
|
108
|
+
# end
|
|
109
|
+
# end
|
|
110
|
+
# end
|
|
111
|
+
#
|
|
112
|
+
# @return [UserProxy] self
|
|
113
|
+
def self.scoped_to( user )
|
|
114
|
+
prev_user, Thread.current[:lanes_current_user] = self.current, user
|
|
115
|
+
yield user
|
|
116
|
+
ensure
|
|
117
|
+
Thread.current[:lanes_current_user] = prev_user
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
require_relative "concerns/track_modifications"
|
|
123
|
+
|
|
124
|
+
# We can only use the TrackModifications concern after the User model is defined
|
|
125
|
+
Model.send(:include, Concerns::TrackModifications )
|
|
126
|
+
|
|
127
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# A custom validator "email".
|
|
2
|
+
# Doesn't really validate an email completely
|
|
3
|
+
# It simply asserts that the email string has one (and only one)
|
|
4
|
+
# @ (at symbol). This is mainly
|
|
5
|
+
# to give user feedback and not to assert the e-mail validity.
|
|
6
|
+
|
|
7
|
+
class EmailValidator < ActiveModel::EachValidator
|
|
8
|
+
|
|
9
|
+
# Regex originated from the Devise gem
|
|
10
|
+
REGEX = /\A[^@]+@([^@\.]+\.)+[^@\.]+\z/
|
|
11
|
+
|
|
12
|
+
def validate_each( rec, attr, value)
|
|
13
|
+
unless value.present? && value.match( REGEX )
|
|
14
|
+
rec.errors.add attr, options[:message] || 'does not appear to be a valid email'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# A custom validator "set". It's similar to :presence validator
|
|
2
|
+
# Unlike :presence, :set doesn't care whether the associated record is valid or not, just that it is present
|
|
3
|
+
# Also unlike :presence, it only works on belongs_to
|
|
4
|
+
class SetValidator < ActiveModel::EachValidator
|
|
5
|
+
|
|
6
|
+
def validate_each( record, attribute, value)
|
|
7
|
+
association = record.class.reflect_on_association( attribute )
|
|
8
|
+
|
|
9
|
+
if association.nil? || !association.belongs_to?
|
|
10
|
+
raise ArgumentError, "Cannot validate existence on #{record.class} #{attribute}, not a :belongs_to association"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
if record.send( attribute ).nil?
|
|
14
|
+
record.errors.add( attribute, "is not set")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|
data/lib/lanes.rb
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'active_record'
|
|
2
|
+
|
|
3
|
+
require_relative "lanes/version"
|
|
4
|
+
require_relative "lanes/logger"
|
|
5
|
+
require_relative "lanes/environment"
|
|
6
|
+
require_relative "lanes/configuration"
|
|
7
|
+
if defined?(::Rails)
|
|
8
|
+
require_relative "lanes/rails_engine"
|
|
9
|
+
end
|
|
10
|
+
require_relative "lanes/db"
|
|
11
|
+
|
|
12
|
+
require_relative "lanes/strings"
|
|
13
|
+
require_relative "lanes/numbers"
|
|
14
|
+
require_relative "lanes/concerns/all"
|
|
15
|
+
require_relative "lanes/validators/all"
|
|
16
|
+
require_relative "lanes/model"
|
|
17
|
+
require_relative "lanes/user"
|
|
18
|
+
|
|
19
|
+
require_relative "lanes/access"
|
|
20
|
+
|
|
21
|
+
require_relative "lanes/extension"
|
|
22
|
+
require_relative "lanes/screens"
|
data/npm-build/README
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
no comment
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env coffee
|
|
2
|
+
|
|
3
|
+
browserify = require 'browserify'
|
|
4
|
+
fs = require 'fs'
|
|
5
|
+
path = require 'path'
|
|
6
|
+
#exposify = require 'exposify'
|
|
7
|
+
|
|
8
|
+
# configure what we want to expose
|
|
9
|
+
#exposify.config = { jquery: 'jQuery', underscore: '_' }
|
|
10
|
+
|
|
11
|
+
browserify({ debug: true })
|
|
12
|
+
# .transform(exposify)
|
|
13
|
+
.require(require.resolve('./template.js'), { entry: true })
|
|
14
|
+
.bundle()
|
|
15
|
+
.pipe(fs.createWriteStream(path.join(__dirname, '../assets/javascripts/vendor/packaged.js'), 'utf8'))
|