serum-rails 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +6 -0
- data/.rspec +3 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +42 -0
- data/LICENSE +22 -0
- data/README.md +40 -0
- data/bin/serum-rails +13 -0
- data/lib/serum/rails/app.rb +50 -0
- data/lib/serum/rails/code_scanner.rb +49 -0
- data/lib/serum/rails/metrics.rb +118 -0
- data/lib/serum/rails/type_selection.rb +31 -0
- data/lib/serum/rails/version.rb +7 -0
- data/lib/serum-rails.rb +5 -0
- data/serum-rails.gemspec +23 -0
- data/spec/serum/rails/metrics_spec.rb +87 -0
- data/spec/spec_helper.rb +80 -0
- data/spec/test_app/Capfile +4 -0
- data/spec/test_app/Gemfile +54 -0
- data/spec/test_app/Gemfile.lock +163 -0
- data/spec/test_app/Rakefile +11 -0
- data/spec/test_app/app/controllers/admin/categories_controller.rb +17 -0
- data/spec/test_app/app/controllers/admin/users_controller.rb +30 -0
- data/spec/test_app/app/controllers/application_controller/i18n_trait.rb +24 -0
- data/spec/test_app/app/controllers/application_controller/navigation_trait.rb +19 -0
- data/spec/test_app/app/controllers/application_controller/security_trait/disabled_clearance_accounts_trait.rb +41 -0
- data/spec/test_app/app/controllers/application_controller/security_trait.rb +65 -0
- data/spec/test_app/app/controllers/application_controller.rb +13 -0
- data/spec/test_app/app/controllers/conferences_controller.rb +67 -0
- data/spec/test_app/app/controllers/friendship_requests_controller.rb +31 -0
- data/spec/test_app/app/controllers/invitations_controller.rb +39 -0
- data/spec/test_app/app/controllers/members_controller.rb +21 -0
- data/spec/test_app/app/controllers/passwords_controller.rb +33 -0
- data/spec/test_app/app/controllers/sessions_controller.rb +17 -0
- data/spec/test_app/app/controllers/shared/boring_controller_trait/deletable_trait.rb +23 -0
- data/spec/test_app/app/controllers/shared/boring_controller_trait/flash_trait.rb +23 -0
- data/spec/test_app/app/controllers/shared/boring_controller_trait/helpers_trait.rb +35 -0
- data/spec/test_app/app/controllers/shared/boring_controller_trait/index_trait.rb +39 -0
- data/spec/test_app/app/controllers/shared/boring_controller_trait/log_changes_trait.rb +18 -0
- data/spec/test_app/app/controllers/shared/boring_controller_trait.rb +16 -0
- data/spec/test_app/app/controllers/users_controller.rb +49 -0
- data/spec/test_app/app/controllers/ws/api_controller/formatters_trait.rb +91 -0
- data/spec/test_app/app/controllers/ws/api_controller/parsers_trait.rb +59 -0
- data/spec/test_app/app/controllers/ws/api_controller.rb +70 -0
- data/spec/test_app/app/controllers/ws/attendees_controller.rb +43 -0
- data/spec/test_app/app/controllers/ws/categories_controller.rb +30 -0
- data/spec/test_app/app/controllers/ws/conferences_controller.rb +62 -0
- data/spec/test_app/app/controllers/ws/contacts_controller.rb +41 -0
- data/spec/test_app/app/controllers/ws/factory_controller.rb +45 -0
- data/spec/test_app/app/controllers/ws/members_controller.rb +34 -0
- data/spec/test_app/app/controllers/ws/series_controller.rb +19 -0
- data/spec/test_app/app/controllers/ws/tests_controller.rb +23 -0
- data/spec/test_app/app/helpers/application_helper.rb +180 -0
- data/spec/test_app/app/helpers/mail_helper.rb +9 -0
- data/spec/test_app/app/helpers/tags_helper.rb +16 -0
- data/spec/test_app/app/helpers/user_helper.rb +23 -0
- data/spec/test_app/app/models/attendance.rb +11 -0
- data/spec/test_app/app/models/category/ancestry_trait.rb +23 -0
- data/spec/test_app/app/models/category.rb +25 -0
- data/spec/test_app/app/models/conference/attendance_trait.rb +23 -0
- data/spec/test_app/app/models/conference/categories_trait.rb +26 -0
- data/spec/test_app/app/models/conference/icalendar_trait.rb +36 -0
- data/spec/test_app/app/models/conference/search_trait.rb +44 -0
- data/spec/test_app/app/models/conference.rb +24 -0
- data/spec/test_app/app/models/conference_category.rb +6 -0
- data/spec/test_app/app/models/conference_search.rb +51 -0
- data/spec/test_app/app/models/error.rb +25 -0
- data/spec/test_app/app/models/friendship.rb +14 -0
- data/spec/test_app/app/models/friendship_request.rb +19 -0
- data/spec/test_app/app/models/invitation.rb +38 -0
- data/spec/test_app/app/models/member_search.rb +18 -0
- data/spec/test_app/app/models/navigation.rb +38 -0
- data/spec/test_app/app/models/patterns.rb +14 -0
- data/spec/test_app/app/models/permissions.rb +106 -0
- data/spec/test_app/app/models/shared/afterlife_trait.rb +18 -0
- data/spec/test_app/app/models/shared/choice_trait.rb +37 -0
- data/spec/test_app/app/models/shared/deletable_trait.rb +8 -0
- data/spec/test_app/app/models/shared/flag_trait.rb +30 -0
- data/spec/test_app/app/models/shared/indestructible_trait.rb +19 -0
- data/spec/test_app/app/models/shared/list_field_trait.rb +70 -0
- data/spec/test_app/app/models/shared/person_name_trait.rb +25 -0
- data/spec/test_app/app/models/shared/searchable_trait.rb +71 -0
- data/spec/test_app/app/models/shared/sortable_trait.rb +24 -0
- data/spec/test_app/app/models/user/authentication_trait.rb +33 -0
- data/spec/test_app/app/models/user/authorization_trait.rb +17 -0
- data/spec/test_app/app/models/user/friends_trait.rb +42 -0
- data/spec/test_app/app/models/user/search_trait.rb +43 -0
- data/spec/test_app/app/models/user.rb +61 -0
- data/spec/test_app/app/models/util.rb +19 -0
- data/spec/test_app/app/views/admin/categories/_form.html.haml +18 -0
- data/spec/test_app/app/views/admin/categories/_list.html.haml +17 -0
- data/spec/test_app/app/views/admin/categories/edit.html.haml +6 -0
- data/spec/test_app/app/views/admin/categories/index.html.haml +6 -0
- data/spec/test_app/app/views/admin/categories/new.html.haml +6 -0
- data/spec/test_app/app/views/admin/categories/show.html.haml +27 -0
- data/spec/test_app/app/views/admin/users/_form.html.haml +49 -0
- data/spec/test_app/app/views/admin/users/_head.html.haml +5 -0
- data/spec/test_app/app/views/admin/users/_list.html.haml +20 -0
- data/spec/test_app/app/views/admin/users/_search.html.haml +9 -0
- data/spec/test_app/app/views/admin/users/deleted.html.haml +5 -0
- data/spec/test_app/app/views/admin/users/edit.html.haml +5 -0
- data/spec/test_app/app/views/admin/users/index.html.haml +7 -0
- data/spec/test_app/app/views/admin/users/new.html.haml +6 -0
- data/spec/test_app/app/views/clearance_mailer/change_password.erb +9 -0
- data/spec/test_app/app/views/conferences/_categories_list.html.haml +8 -0
- data/spec/test_app/app/views/conferences/_form.html.haml +32 -0
- data/spec/test_app/app/views/conferences/_head.html.haml +4 -0
- data/spec/test_app/app/views/conferences/_list.html.haml +22 -0
- data/spec/test_app/app/views/conferences/_search.html.haml +24 -0
- data/spec/test_app/app/views/conferences/edit.html.haml +8 -0
- data/spec/test_app/app/views/conferences/index.html.haml +22 -0
- data/spec/test_app/app/views/conferences/new.html.haml +9 -0
- data/spec/test_app/app/views/conferences/search.html.haml +7 -0
- data/spec/test_app/app/views/conferences/show.html.haml +78 -0
- data/spec/test_app/app/views/invitations/index.html.haml +26 -0
- data/spec/test_app/app/views/invitations/new.html.haml +22 -0
- data/spec/test_app/app/views/layouts/_flashes.html.haml +13 -0
- data/spec/test_app/app/views/layouts/_javascript_requirement.html.haml +8 -0
- data/spec/test_app/app/views/layouts/_javascripts.html.haml +4 -0
- data/spec/test_app/app/views/layouts/_notifications.html.haml +11 -0
- data/spec/test_app/app/views/layouts/_session_navigation.html.haml +12 -0
- data/spec/test_app/app/views/layouts/_stylesheets.html.haml +6 -0
- data/spec/test_app/app/views/layouts/screen.html.haml +30 -0
- data/spec/test_app/app/views/members/index.html.haml +40 -0
- data/spec/test_app/app/views/passwords/edit.html.haml +21 -0
- data/spec/test_app/app/views/passwords/new.html.haml +14 -0
- data/spec/test_app/app/views/sessions/new.html.haml +19 -0
- data/spec/test_app/app/views/users/_form.html.haml +45 -0
- data/spec/test_app/app/views/users/_head.html.haml +3 -0
- data/spec/test_app/app/views/users/edit.html.haml +5 -0
- data/spec/test_app/app/views/users/new.html.haml +6 -0
- data/spec/test_app/app/views/users/show.html.haml +49 -0
- data/spec/test_app/assets/data.json +981 -0
- data/spec/test_app/config/boot.rb +125 -0
- data/spec/test_app/config/cucumber.yml +8 -0
- data/spec/test_app/config/database.sample.yml +24 -0
- data/spec/test_app/config/deploy/production.rb +9 -0
- data/spec/test_app/config/deploy.rb +100 -0
- data/spec/test_app/config/environment.rb +27 -0
- data/spec/test_app/config/environments/cucumber.rb +28 -0
- data/spec/test_app/config/environments/development.rb +22 -0
- data/spec/test_app/config/environments/production.rb +35 -0
- data/spec/test_app/config/environments/test.rb +30 -0
- data/spec/test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/test_app/config/initializers/clearance.rb +5 -0
- data/spec/test_app/config/initializers/collect_hash.rb +23 -0
- data/spec/test_app/config/initializers/collection_path_with_params.rb +18 -0
- data/spec/test_app/config/initializers/cookie_verification_secret.rb +10 -0
- data/spec/test_app/config/initializers/form_builder.rb +166 -0
- data/spec/test_app/config/initializers/inflections.rb +10 -0
- data/spec/test_app/config/initializers/invert_ordered_hash.rb +12 -0
- data/spec/test_app/config/initializers/localize_textfield_input_for_numbers.rb +30 -0
- data/spec/test_app/config/initializers/mime_types.rb +7 -0
- data/spec/test_app/config/initializers/new_rails_defaults.rb +21 -0
- data/spec/test_app/config/initializers/preload_associations.rb +7 -0
- data/spec/test_app/config/initializers/query_diet.rb +6 -0
- data/spec/test_app/config/initializers/saner_field_with_errors.rb +5 -0
- data/spec/test_app/config/initializers/session_store.rb +18 -0
- data/spec/test_app/config/locales/en.yml +231 -0
- data/spec/test_app/config/preinitializer.rb +22 -0
- data/spec/test_app/config/routes.rb +47 -0
- data/spec/test_app/db/migrate/20110114164517_initial_tables.rb +52 -0
- data/spec/test_app/db/migrate/20110118090858_add_profile_fields_to_user.rb +15 -0
- data/spec/test_app/db/migrate/20110118092741_create_conference.rb +20 -0
- data/spec/test_app/db/migrate/20110118093503_create_category.rb +17 -0
- data/spec/test_app/db/migrate/20110118104438_create_conference_category.rb +16 -0
- data/spec/test_app/db/migrate/20110118105959_create_attendance.rb +17 -0
- data/spec/test_app/db/migrate/20110118122324_create_friendship_requests.rb +15 -0
- data/spec/test_app/db/migrate/20110118162436_create_invitation.rb +16 -0
- data/spec/test_app/db/migrate/20110118170347_create_friendships.rb +15 -0
- data/spec/test_app/db/migrate/20110118193528_add_timestamps_to_conference.rb +12 -0
- data/spec/test_app/db/migrate/20110119075012_set_unique_index_on_username_for_user.rb +11 -0
- data/spec/test_app/db/migrate/20110119093458_remove_first_and_last_name_from_user.rb +12 -0
- data/spec/test_app/db/migrate/20110119110857_add_missing_indexes.rb +23 -0
- data/spec/test_app/db/migrate/20110119115751_add_uniqueness_of_name_to_category.rb +9 -0
- data/spec/test_app/db/seeds.rb +5 -0
- data/spec/test_app/lib/scripts/create_many_users_sql.rb +14 -0
- data/spec/test_app/lib/tasks/cucumber.rake +53 -0
- data/spec/test_app/lib/tasks/pending_migrations.rake +24 -0
- data/spec/test_app/lib/tasks/rcov.rake +42 -0
- data/spec/test_app/lib/tasks/rspec.rake +144 -0
- data/spec/test_app/public/404.html +30 -0
- data/spec/test_app/public/422.html +30 -0
- data/spec/test_app/public/500.html +30 -0
- data/spec/test_app/public/favicon.ico +0 -0
- data/spec/test_app/public/images/ajax-loader.gif +0 -0
- data/spec/test_app/public/images/icons/balloon-quotation.png +0 -0
- data/spec/test_app/public/images/icons/balloon-sound.png +0 -0
- data/spec/test_app/public/images/icons/balloon.png +0 -0
- data/spec/test_app/public/images/icons/bell.png +0 -0
- data/spec/test_app/public/images/icons/bin.png +0 -0
- data/spec/test_app/public/images/icons/bookmark.png +0 -0
- data/spec/test_app/public/images/icons/cake.png +0 -0
- data/spec/test_app/public/images/icons/calendar-blue.png +0 -0
- data/spec/test_app/public/images/icons/calendar-month.png +0 -0
- data/spec/test_app/public/images/icons/calendar-month_light.png +0 -0
- data/spec/test_app/public/images/icons/calendar-select.png +0 -0
- data/spec/test_app/public/images/icons/card-address.png +0 -0
- data/spec/test_app/public/images/icons/cards-address.png +0 -0
- data/spec/test_app/public/images/icons/cross-script.png +0 -0
- data/spec/test_app/public/images/icons/cross-small.png +0 -0
- data/spec/test_app/public/images/icons/cross.png +0 -0
- data/spec/test_app/public/images/icons/crown-silver.png +0 -0
- data/spec/test_app/public/images/icons/crown.png +0 -0
- data/spec/test_app/public/images/icons/dashboard.png +0 -0
- data/spec/test_app/public/images/icons/document-list.png +0 -0
- data/spec/test_app/public/images/icons/document-node.png +0 -0
- data/spec/test_app/public/images/icons/document-number.png +0 -0
- data/spec/test_app/public/images/icons/document-stamp.png +0 -0
- data/spec/test_app/public/images/icons/document-task.png +0 -0
- data/spec/test_app/public/images/icons/document-text.png +0 -0
- data/spec/test_app/public/images/icons/fire.png +0 -0
- data/spec/test_app/public/images/icons/folder-medium.png +0 -0
- data/spec/test_app/public/images/icons/folder.png +0 -0
- data/spec/test_app/public/images/icons/gear.png +0 -0
- data/spec/test_app/public/images/icons/globe-green.png +0 -0
- data/spec/test_app/public/images/icons/globe-green_light.png +0 -0
- data/spec/test_app/public/images/icons/globe-medium-green.png +0 -0
- data/spec/test_app/public/images/icons/heart-break.png +0 -0
- data/spec/test_app/public/images/icons/heart.png +0 -0
- data/spec/test_app/public/images/icons/images-flickr.png +0 -0
- data/spec/test_app/public/images/icons/information-balloon.png +0 -0
- data/spec/test_app/public/images/icons/key.png +0 -0
- data/spec/test_app/public/images/icons/light-bulb.png +0 -0
- data/spec/test_app/public/images/icons/lock--exclamation.png +0 -0
- data/spec/test_app/public/images/icons/lock.png +0 -0
- data/spec/test_app/public/images/icons/magnifier-medium.png +0 -0
- data/spec/test_app/public/images/icons/magnifier.png +0 -0
- data/spec/test_app/public/images/icons/mail.png +0 -0
- data/spec/test_app/public/images/icons/paper-clip-small.png +0 -0
- data/spec/test_app/public/images/icons/paper-clip.png +0 -0
- data/spec/test_app/public/images/icons/pencil.png +0 -0
- data/spec/test_app/public/images/icons/plus-circle.png +0 -0
- data/spec/test_app/public/images/icons/plus-small.png +0 -0
- data/spec/test_app/public/images/icons/plus.png +0 -0
- data/spec/test_app/public/images/icons/printer.png +0 -0
- data/spec/test_app/public/images/icons/question-balloon.png +0 -0
- data/spec/test_app/public/images/icons/question-white.png +0 -0
- data/spec/test_app/public/images/icons/question.png +0 -0
- data/spec/test_app/public/images/icons/quill.png +0 -0
- data/spec/test_app/public/images/icons/robot.png +0 -0
- data/spec/test_app/public/images/icons/ruby_16.png +0 -0
- data/spec/test_app/public/images/icons/ruby_2_16.png +0 -0
- data/spec/test_app/public/images/icons/ruby_32.png +0 -0
- data/spec/test_app/public/images/icons/show.png +0 -0
- data/spec/test_app/public/images/icons/star.png +0 -0
- data/spec/test_app/public/images/icons/sticky-note-text.png +0 -0
- data/spec/test_app/public/images/icons/telephone-fax.png +0 -0
- data/spec/test_app/public/images/icons/telephone-fax_light.png +0 -0
- data/spec/test_app/public/images/icons/telephone.png +0 -0
- data/spec/test_app/public/images/icons/telephone_light.png +0 -0
- data/spec/test_app/public/images/icons/thumb-up.png +0 -0
- data/spec/test_app/public/images/icons/thumb.png +0 -0
- data/spec/test_app/public/images/icons/tick.png +0 -0
- data/spec/test_app/public/images/icons/trophy-silver.png +0 -0
- data/spec/test_app/public/images/icons/trophy.png +0 -0
- data/spec/test_app/public/images/icons/user-gray.png +0 -0
- data/spec/test_app/public/images/icons/user-gray_gray.png +0 -0
- data/spec/test_app/public/images/icons/user-medium.png +0 -0
- data/spec/test_app/public/images/icons/user-red.png +0 -0
- data/spec/test_app/public/images/icons/users.png +0 -0
- data/spec/test_app/public/images/icons/users_gray.png +0 -0
- data/spec/test_app/public/images/icons/xfn.png +0 -0
- data/spec/test_app/public/images/legend_bg.png +0 -0
- data/spec/test_app/public/images/poshytip/tip-deepgray.png +0 -0
- data/spec/test_app/public/images/poshytip/tip-deepgray_arrows.png +0 -0
- data/spec/test_app/public/images/stripes_bottom_dark.png +0 -0
- data/spec/test_app/public/images/stripes_top_dark.png +0 -0
- data/spec/test_app/public/images/ui/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/spec/test_app/public/images/ui/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/spec/test_app/public/images/ui/ui-bg_flat_10_000000_40x100.png +0 -0
- data/spec/test_app/public/images/ui/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/spec/test_app/public/images/ui/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/spec/test_app/public/images/ui/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/spec/test_app/public/images/ui/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/spec/test_app/public/images/ui/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/spec/test_app/public/images/ui/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/spec/test_app/public/images/ui/ui-icons_222222_256x240.png +0 -0
- data/spec/test_app/public/images/ui/ui-icons_228ef1_256x240.png +0 -0
- data/spec/test_app/public/images/ui/ui-icons_ef8c08_256x240.png +0 -0
- data/spec/test_app/public/images/ui/ui-icons_ffd27a_256x240.png +0 -0
- data/spec/test_app/public/images/ui/ui-icons_ffffff_256x240.png +0 -0
- data/spec/test_app/public/javascripts/application.js +175 -0
- data/spec/test_app/public/javascripts/lib/jquery-1.4.2.min.js +154 -0
- data/spec/test_app/public/javascripts/lib/jquery-ui-1.8.5.custom.min.js +249 -0
- data/spec/test_app/public/javascripts/lib/jquery-ui-1.8.5.custom.min.txt +9 -0
- data/spec/test_app/public/javascripts/lib/jquery-ui-timepicker-addon.js +682 -0
- data/spec/test_app/public/javascripts/lib/jquery-ui-timepicker-addon.min.js +22 -0
- data/spec/test_app/public/javascripts/lib/jquery.elastic.js +6 -0
- data/spec/test_app/public/javascripts/lib/jquery.elastic.performance.js +128 -0
- data/spec/test_app/public/javascripts/lib/jquery.elastic.source.js +117 -0
- data/spec/test_app/public/javascripts/lib/jquery.poshytip.js +414 -0
- data/spec/test_app/public/javascripts/lib/jquery.poshytip.min.js +7 -0
- data/spec/test_app/public/javascripts/lib/jquery.ui.datepicker-de.js +23 -0
- data/spec/test_app/public/javascripts/lib/jrails.js +1 -0
- data/spec/test_app/public/javascripts/lib/multiple-autocomplete.js +39 -0
- data/spec/test_app/public/javascripts/lib/underscore-min.js +17 -0
- data/spec/test_app/public/javascripts/lib/underscore.js +704 -0
- data/spec/test_app/public/robots.txt +5 -0
- data/spec/test_app/public/stylesheets/lib/PIE.htc +77 -0
- data/spec/test_app/public/stylesheets/lib/PIE_uncompressed.htc +3064 -0
- data/spec/test_app/public/stylesheets/lib/jquery-ui-timepicker-addon.css +11 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-darkgray/tip-darkgray.css +62 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-darkgray/tip-darkgray.png +0 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-darkgray/tip-darkgray_arrows.png +0 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-deepgray/tip-deepgray.css +64 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-green/tip-green.css +57 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-green/tip-green_arrows.gif +0 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-skyblue/tip-skyblue.css +58 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-skyblue/tip-skyblue.png +0 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-skyblue/tip-skyblue_arrows.png +0 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-twitter/tip-twitter.css +59 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-twitter/tip-twitter_arrows.gif +0 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-violet/tip-violet.css +60 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-violet/tip-violet.png +0 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-violet/tip-violet_arrows.png +0 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-yellow/tip-yellow.css +60 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-yellow/tip-yellow.png +0 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-yellow/tip-yellow_arrows.png +0 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-yellowsimple/tip-yellowsimple.css +60 -0
- data/spec/test_app/public/stylesheets/lib/poshytip/tip-yellowsimple/tip-yellowsimple_arrows.gif +0 -0
- data/spec/test_app/public/stylesheets/lib/ui-lightness/jquery-ui-1.8.5.custom.css +459 -0
- data/spec/test_app/public/stylesheets/sass/_mixins.sass +79 -0
- data/spec/test_app/public/stylesheets/sass/_reset.sass +40 -0
- data/spec/test_app/public/stylesheets/sass/print.sass +22 -0
- data/spec/test_app/public/stylesheets/sass/screen.sass +866 -0
- data/spec/test_app/script/about +4 -0
- data/spec/test_app/script/autospec +6 -0
- data/spec/test_app/script/console +3 -0
- data/spec/test_app/script/cucumber +10 -0
- data/spec/test_app/script/dbconsole +3 -0
- data/spec/test_app/script/destroy +3 -0
- data/spec/test_app/script/generate +3 -0
- data/spec/test_app/script/performance/benchmarker +3 -0
- data/spec/test_app/script/performance/profiler +3 -0
- data/spec/test_app/script/plugin +3 -0
- data/spec/test_app/script/runner +3 -0
- data/spec/test_app/script/server +3 -0
- data/spec/test_app/script/spec +10 -0
- metadata +748 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
# Utility class to provide common regular expressions.
|
2
|
+
# origin: RM
|
3
|
+
class Patterns
|
4
|
+
|
5
|
+
EMAIL = /\A[a-z0-9\+\-_\.]+@[a-z0-9]+[a-z0-9\-\.]*[a-z0-9]+\z/i
|
6
|
+
HOST = /\A[a-z0-9]+[a-z0-9\-\.]*[a-z0-9]+\z/i
|
7
|
+
URL = /(http|https):\/\/[\w\-_]+(\.[\w\-_]+)*([\w\-\.,@?^=%&:\/~\+#]*[\w\-\@?^=%&\/~\+#])?/
|
8
|
+
|
9
|
+
# Returns a regexp without start-of-string and end-of-string assertions
|
10
|
+
def self.partial(pattern)
|
11
|
+
Regexp.compile(pattern.source.sub(/^(\\A|\^)/, '').sub(/(\\z|\$)$/, ''))
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# Describes what a user is allowed to do in the application.
|
2
|
+
# origin: M
|
3
|
+
class Permissions < Aegis::Permissions
|
4
|
+
|
5
|
+
role :admin
|
6
|
+
role :user
|
7
|
+
role :guest
|
8
|
+
|
9
|
+
missing_user_means { User.guest }
|
10
|
+
missing_action_means :error
|
11
|
+
|
12
|
+
namespace :admin do
|
13
|
+
resources :users do
|
14
|
+
action :deleted, :collection => true
|
15
|
+
allow :admin
|
16
|
+
end
|
17
|
+
resources :categories do
|
18
|
+
allow :admin
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
resource :categories do
|
23
|
+
writing do
|
24
|
+
allow :admin
|
25
|
+
end
|
26
|
+
reading do
|
27
|
+
allow :everyone
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
resources :conferences do
|
32
|
+
action :index, :search, :collection => true do
|
33
|
+
allow :everyone
|
34
|
+
end
|
35
|
+
action :show do
|
36
|
+
allow :everyone
|
37
|
+
end
|
38
|
+
action :update, :destroy do
|
39
|
+
allow :user, :admin do
|
40
|
+
object.user == user
|
41
|
+
end
|
42
|
+
end
|
43
|
+
action :create do
|
44
|
+
allow :user, :admin
|
45
|
+
end
|
46
|
+
action :attend, :cancel_attendance do
|
47
|
+
allow :user, :admin
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
resources :invitations do
|
52
|
+
action :create, :index do
|
53
|
+
allow :user, :admin
|
54
|
+
end
|
55
|
+
action :accept, :dismiss do
|
56
|
+
allow :user, :admin do
|
57
|
+
object.recipient == user
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
resources :users do
|
63
|
+
action :create do
|
64
|
+
allow :everyone
|
65
|
+
end
|
66
|
+
action :show do
|
67
|
+
allow :everyone
|
68
|
+
end
|
69
|
+
action :update do
|
70
|
+
allow :admin, :user do
|
71
|
+
user == object
|
72
|
+
end
|
73
|
+
end
|
74
|
+
action :request_friendship do
|
75
|
+
allow :user, :admin
|
76
|
+
end
|
77
|
+
action :search_all_fields, :collection => true do
|
78
|
+
allow :admin
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
resources :members do
|
83
|
+
action :request_friendships, :collection => true
|
84
|
+
allow :user, :admin
|
85
|
+
end
|
86
|
+
|
87
|
+
resources :friends do
|
88
|
+
allow :user, :admin
|
89
|
+
action :accept, :deny do
|
90
|
+
allow :user, :admin do
|
91
|
+
object.user == user
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
resource :own_profile do
|
97
|
+
action :access do
|
98
|
+
allow :user, :admin
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
action :reset_application_state do
|
103
|
+
allow :admin
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Trait to provide an inactive state to any ActiveRecord model, e.g. a class supporting soft-deletion or archival.
|
2
|
+
# origin: RM
|
3
|
+
module AfterlifeTrait
|
4
|
+
|
5
|
+
as_trait do |*options|
|
6
|
+
options = options.first || {}
|
7
|
+
adjective = options.delete(:as) || 'deleted'
|
8
|
+
|
9
|
+
with_adjective ="with_#{adjective}"
|
10
|
+
|
11
|
+
does "flag", adjective, :default => false
|
12
|
+
named_scope :active, :conditions => { adjective => false }
|
13
|
+
named_scope with_adjective, lambda { |show_perished|
|
14
|
+
{ :conditions => (show_perished ? nil : { adjective => false }) }
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Models the pattern of a string attribute that has a fixed number of allowed choices with additional human labels.
|
2
|
+
# origin: RM
|
3
|
+
module ChoiceTrait
|
4
|
+
|
5
|
+
as_trait do |field, options|
|
6
|
+
|
7
|
+
options[:choices] = options[:choices].zip(options[:choices]).flatten if options[:no_hash]
|
8
|
+
choices = ActiveSupport::OrderedHash[*options[:choices]]
|
9
|
+
|
10
|
+
available_values = "available_#{field.to_s.pluralize}"
|
11
|
+
|
12
|
+
metaclass ||= singleton_class
|
13
|
+
metaclass.send(:define_method, available_values) do
|
14
|
+
choices
|
15
|
+
end
|
16
|
+
|
17
|
+
validates_inclusion_of field.to_sym, :in => send(available_values).keys, :allow_blank => !!options[:allow_blank]
|
18
|
+
|
19
|
+
if options.has_key?(:default)
|
20
|
+
has_defaults field.to_sym => options[:default]
|
21
|
+
end
|
22
|
+
|
23
|
+
define_method "humanized_#{field}" do
|
24
|
+
choices[send(field)]
|
25
|
+
end
|
26
|
+
|
27
|
+
if options[:query_methods]
|
28
|
+
choices.keys.each do |key|
|
29
|
+
define_method "#{key}?" do
|
30
|
+
send(field) == key
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Models the pattern of a boolean attribute that must be true or false, but never nil.
|
2
|
+
# origin: RM
|
3
|
+
module FlagTrait
|
4
|
+
|
5
|
+
as_trait do |field, options|
|
6
|
+
|
7
|
+
options ||= {}
|
8
|
+
|
9
|
+
default = options[:default]
|
10
|
+
virtual = options[:virtual]
|
11
|
+
field_var = "@#{field}"
|
12
|
+
set_field = "#{field}="
|
13
|
+
|
14
|
+
validates_inclusion_of field.to_sym, :in => [true, false], :allow_nil => !!virtual
|
15
|
+
has_defaults field.to_sym => default
|
16
|
+
|
17
|
+
if virtual
|
18
|
+
|
19
|
+
attr_reader field
|
20
|
+
|
21
|
+
define_method set_field do |value|
|
22
|
+
value = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
|
23
|
+
instance_variable_set(field_var, value)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Changes an ActiveRecord class so its instances cannot be destroyed.
|
2
|
+
# origin: RM
|
3
|
+
module IndestructibleTrait
|
4
|
+
as_trait do |*options|
|
5
|
+
|
6
|
+
options = options[0] || {}
|
7
|
+
|
8
|
+
before_destroy(options) do
|
9
|
+
false
|
10
|
+
end
|
11
|
+
|
12
|
+
# Allow others to check whether this is an indestructible record.
|
13
|
+
# This is not an ActiveRecord method.
|
14
|
+
def destructible?
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# Provides a virtual attribute that can be get and set like an array, but is realized into other data structure upon saving.
|
2
|
+
# origin: RM
|
3
|
+
module ListFieldTrait
|
4
|
+
|
5
|
+
# This is an array that stringifies with comma separators, so we can
|
6
|
+
# have a text field in the form for it.
|
7
|
+
class CommaSeparatedArray
|
8
|
+
|
9
|
+
include Enumerable
|
10
|
+
|
11
|
+
def initialize(list)
|
12
|
+
@list = list
|
13
|
+
end
|
14
|
+
|
15
|
+
def each(&block)
|
16
|
+
@list.each(&block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def <<(element)
|
20
|
+
@list << element
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
@list.join(', ')
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_a
|
28
|
+
@list
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.wrap(list)
|
32
|
+
list.is_a?(self) ? list : new(list)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
as_trait do |*args|
|
38
|
+
|
39
|
+
list = args[0]
|
40
|
+
options = args[1] || {}
|
41
|
+
|
42
|
+
cast_to_integer = options[:integer]
|
43
|
+
list_variable = "@#{list}"
|
44
|
+
set_list = "#{list}="
|
45
|
+
read_list = "read_#{list}"
|
46
|
+
write_list = "write_#{list}"
|
47
|
+
write_list_if_changed = "write_#{list}_if_changed"
|
48
|
+
|
49
|
+
after_save write_list_if_changed
|
50
|
+
|
51
|
+
define_method list do
|
52
|
+
CommaSeparatedArray.wrap(instance_variable_get(list_variable) || send(read_list))
|
53
|
+
end
|
54
|
+
|
55
|
+
define_method write_list_if_changed do
|
56
|
+
list = instance_variable_get(list_variable)
|
57
|
+
send(write_list, list) if list
|
58
|
+
true
|
59
|
+
end
|
60
|
+
|
61
|
+
define_method set_list do |new_list|
|
62
|
+
new_list = new_list.split(/\s*,\s*/) if new_list.is_a?(String)
|
63
|
+
new_list.reject!(&:blank?)
|
64
|
+
new_list.collect!(&:to_i) if cast_to_integer
|
65
|
+
instance_variable_set(list_variable, new_list)
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Provides an attribute #full_name that is composed from #first_name and #last_name.
|
2
|
+
# origin: RM
|
3
|
+
module PersonNameTrait
|
4
|
+
as_trait do
|
5
|
+
|
6
|
+
# validates_presence_of :last_name
|
7
|
+
|
8
|
+
before_validation :store_full_name
|
9
|
+
|
10
|
+
def full_name
|
11
|
+
[first_name, last_name].select(&:present?).join(" ")
|
12
|
+
end
|
13
|
+
|
14
|
+
def name
|
15
|
+
full_name
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def store_full_name
|
21
|
+
self.full_name = full_name
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# Provides a search scope with Google-esque syntax for ActiveRecord models, e.g. "foo bar date:20090511 baz"
|
2
|
+
# origin: RM
|
3
|
+
module SearchableTrait
|
4
|
+
|
5
|
+
TEXT_QUERY = /(?:"([^"]+)"|([\w\-@\._]+))/
|
6
|
+
FIELD_QUERY = /(\w+)\:#{TEXT_QUERY}/
|
7
|
+
|
8
|
+
as_trait do |options|
|
9
|
+
|
10
|
+
text_field = options[:text_means] || :text # the field we're searching when no field is given
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_accessor :defined_searchers
|
14
|
+
end
|
15
|
+
|
16
|
+
singleton_class.send :define_method, :search do |query|
|
17
|
+
query = query.dup # we are going to delete substrings in-place
|
18
|
+
scope = scoped({})
|
19
|
+
scope = filter_by_field_queries(scope, query)
|
20
|
+
scope = filter_by_text_queries(scope, query)
|
21
|
+
scope
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
singleton_class.send :define_method, :search_by do |*fields, &searcher|
|
27
|
+
self.defined_searchers ||= {}
|
28
|
+
fields.each do |field|
|
29
|
+
defined_searchers[field.to_s.downcase] = true
|
30
|
+
# we need to define the searcher as an actual method because of the way scopes delegate methods to the AR class
|
31
|
+
singleton_class.send :define_method, "search_by_#{field}", &searcher
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
singleton_class.send :define_method, :filter_by_field_queries do |scope, query|
|
36
|
+
while query.sub!(SearchableTrait::FIELD_QUERY, '')
|
37
|
+
field = $1
|
38
|
+
value = "#{$2}#{$3}"
|
39
|
+
scope = search_by_field(scope, field, value)
|
40
|
+
end
|
41
|
+
scope
|
42
|
+
end
|
43
|
+
|
44
|
+
singleton_class.send :define_method, :filter_by_text_queries do |scope, query|
|
45
|
+
while query.sub!(SearchableTrait::TEXT_QUERY, '')
|
46
|
+
value = "#{$1}#{$2}"
|
47
|
+
scope = search_by_field(scope, text_field, value)
|
48
|
+
end
|
49
|
+
scope
|
50
|
+
end
|
51
|
+
|
52
|
+
singleton_class.send :define_method, :search_by_field do |scope, field, value|
|
53
|
+
normalized_field = field.to_s.downcase
|
54
|
+
if defined_searchers[normalized_field]
|
55
|
+
scope = scope.send("search_by_#{normalized_field}", value)
|
56
|
+
else
|
57
|
+
scope = scope.find_nothing
|
58
|
+
end
|
59
|
+
scope
|
60
|
+
end
|
61
|
+
|
62
|
+
singleton_class.send :define_method, :find_nothing do
|
63
|
+
scoped(:conditions => "1=2")
|
64
|
+
end
|
65
|
+
|
66
|
+
search_by text_field do |text|
|
67
|
+
scoped(:conditions => Util.like_query(text_field, text))
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Macro to implement a comparison method for Ruby classes.
|
2
|
+
# origin: RM
|
3
|
+
module SortableTrait
|
4
|
+
|
5
|
+
as_trait do |options|
|
6
|
+
|
7
|
+
send(:define_method, :"<=>") do |other|
|
8
|
+
fields = Array(options[:by])
|
9
|
+
cmp = 0
|
10
|
+
for field in fields
|
11
|
+
left = send(field)
|
12
|
+
left = left.downcase if left.respond_to?(:downcase)
|
13
|
+
right = other.send(field)
|
14
|
+
right = right.downcase if right.respond_to?(:downcase)
|
15
|
+
cmp = left <=> right
|
16
|
+
break unless cmp == 0
|
17
|
+
end
|
18
|
+
cmp *= -1 if options[:descending]
|
19
|
+
cmp
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Code to authenticate against a user database.
|
2
|
+
# origin: RM
|
3
|
+
module User::AuthenticationTrait
|
4
|
+
as_trait do
|
5
|
+
|
6
|
+
include Clearance::User
|
7
|
+
|
8
|
+
validates_length_of :password, :minimum => 3, :allow_blank => true
|
9
|
+
validates_format_of :username, :with => /^[a-z][a-z0-9\.\-_öÖüÜäÄß]+$/mi
|
10
|
+
validates_uniqueness_of :username, :case_sensitive => false
|
11
|
+
|
12
|
+
does 'flag', :locked, :default => false
|
13
|
+
|
14
|
+
# Allow to login with either email or screen_name
|
15
|
+
def self.authenticate(username_or_email, password)
|
16
|
+
return nil unless user = find(:first, :conditions => ['email = ? OR username = ?', username_or_email, username_or_email])
|
17
|
+
return user if user.authenticated?(password)
|
18
|
+
end
|
19
|
+
|
20
|
+
def email_confirmed?
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
def account_disabled?
|
25
|
+
locked? || deleted?
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.guest
|
29
|
+
@guest ||= User.new(:role_name => 'guest')
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Hooks up the aegis gem so users can be given roles and be queried for permissions.
|
2
|
+
# origin: RM
|
3
|
+
module User::AuthorizationTrait
|
4
|
+
as_trait do
|
5
|
+
|
6
|
+
has_role :default => 'user'
|
7
|
+
validates_role
|
8
|
+
|
9
|
+
def self.available_roles
|
10
|
+
labeler = lambda { |role| I18n.t("roles.#{role.name}") }
|
11
|
+
Permissions.roles.sort_by(&labeler).collect_ordered_hash do |role|
|
12
|
+
[role.name, labeler.call(role)]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# Manages friends and friendship requests for users.
|
2
|
+
# origin: M
|
3
|
+
module User::FriendsTrait
|
4
|
+
as_trait do
|
5
|
+
|
6
|
+
has_many :sent_friendship_requests, :class_name => 'FriendshipRequest', :foreign_key => 'requesting_user_id'
|
7
|
+
has_many :friendship_requests
|
8
|
+
|
9
|
+
has_many :friendships
|
10
|
+
has_many :friends, :through => :friendships, :order => 'username'
|
11
|
+
|
12
|
+
def in_contact_with?(other_user)
|
13
|
+
friends_with?(other_user) or sent_friendship_requests.collect(&:user_id).include?(other_user.id)
|
14
|
+
end
|
15
|
+
|
16
|
+
def friends_with?(other_user)
|
17
|
+
friendships.collect(&:friend_id).include? other_user.id
|
18
|
+
end
|
19
|
+
|
20
|
+
def can_become_friends_with?(other_user)
|
21
|
+
self != other_user and not in_contact_with? other_user
|
22
|
+
end
|
23
|
+
|
24
|
+
def status_towards(other_user)
|
25
|
+
if friends_with?(other_user)
|
26
|
+
'in_contact'
|
27
|
+
elsif sent_friendship_requests.collect(&:user_id).include?(other_user.id)
|
28
|
+
'RCD_sent'
|
29
|
+
elsif friendship_requests.collect(&:requesting_user_id).include?(other_user.id)
|
30
|
+
'RCD_received'
|
31
|
+
else
|
32
|
+
'no_contact'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def contacts
|
37
|
+
user_ids = (friend_ids + sent_friendship_requests.collect(&:user_id) + friendship_requests.collect(&:requesting_user_id)).uniq
|
38
|
+
User.all(:conditions => {:id => user_ids})
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Provides search for user records.
|
2
|
+
# origin: M
|
3
|
+
module User::SearchTrait
|
4
|
+
as_trait do
|
5
|
+
|
6
|
+
TEXT_QUERY = /(?:"([^"]+)"|([\w\-@\._]+))/
|
7
|
+
|
8
|
+
# Returns users matching the given query.
|
9
|
+
# Users may search additional fields of a user they are friends with.
|
10
|
+
# Admins may search all fields.
|
11
|
+
def self.search(query, searching_user)
|
12
|
+
friend_ids = searching_user.friend_ids
|
13
|
+
like_username = find_words_in_field('users.username', query)
|
14
|
+
like_full_name = find_words_in_field('users.full_name', query)
|
15
|
+
like_email = find_words_in_field('users.email', query)
|
16
|
+
conditions = if searching_user.may_search_all_fields_users?
|
17
|
+
"(#{like_username}) OR (#{like_full_name}) OR (#{like_email})"
|
18
|
+
elsif friend_ids.any?
|
19
|
+
is_friend = "users.id IN (#{friend_ids.join ', '})"
|
20
|
+
"(#{is_friend}) AND (#{like_full_name}) OR (#{like_username})"
|
21
|
+
else
|
22
|
+
like_username
|
23
|
+
end
|
24
|
+
scoped :conditions => conditions
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def self.find_words_in_field(field, query)
|
30
|
+
collect_words(query) do |word|
|
31
|
+
sanitize_sql_for_conditions(Util.like_query(field, word))
|
32
|
+
end.join(' AND ')
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.collect_words(query, &block)
|
36
|
+
query.scan(TEXT_QUERY).collect do |phrase_match, word_match|
|
37
|
+
word = "#{phrase_match}#{word_match}"
|
38
|
+
block.call(word)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# Models a registered user.
|
2
|
+
# origin: RM
|
3
|
+
class User < ActiveRecord::Base
|
4
|
+
does 'user/authentication'
|
5
|
+
does 'user/authorization'
|
6
|
+
does 'user/friends'
|
7
|
+
does 'user/search'
|
8
|
+
does 'deletable'
|
9
|
+
does 'sortable', :by => :username
|
10
|
+
named_scope :by_username, :order => :username
|
11
|
+
|
12
|
+
has_many :attendances
|
13
|
+
has_many :conferences, :through => :attendances
|
14
|
+
|
15
|
+
validates_presence_of :full_name, :town, :country, :username
|
16
|
+
has_many :received_invitations, :class_name => 'Invitation', :foreign_key => 'recipient_id'
|
17
|
+
has_many :sent_invitations, :class_name => 'Invitation', :foreign_key => 'sender_id'
|
18
|
+
|
19
|
+
has_attached_file :avatar
|
20
|
+
|
21
|
+
|
22
|
+
def sees_details_of?(other_user, force_visible = false)
|
23
|
+
force_visible || self == other_user || friends_with?(other_user)
|
24
|
+
end
|
25
|
+
|
26
|
+
def username_with_full_name
|
27
|
+
"#{username} (#{full_name})"
|
28
|
+
end
|
29
|
+
|
30
|
+
def name_for(other_user, force_visible = false)
|
31
|
+
if sees_details_of?(other_user, force_visible)
|
32
|
+
other_user.username_with_full_name
|
33
|
+
else
|
34
|
+
other_user.username
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def email_for(other_user, force_visible = false)
|
39
|
+
if sees_details_of?(other_user, force_visible)
|
40
|
+
other_user.email
|
41
|
+
else
|
42
|
+
'–'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.create_admin!
|
47
|
+
create! :username => 'admin',
|
48
|
+
:password => 'admin',
|
49
|
+
:password_confirmation => 'admin',
|
50
|
+
:email => 'admin@plat-forms.org',
|
51
|
+
:full_name => 'Plat_Forms 2011',
|
52
|
+
:town => 'Nürnberg',
|
53
|
+
:country => 'Germany',
|
54
|
+
:role_name => 'admin'
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.import(path)
|
58
|
+
YAML.load(path)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Utility methods.
|
2
|
+
# origin: RM
|
3
|
+
module Util
|
4
|
+
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def collect_ids(records_or_ids)
|
8
|
+
Array(records_or_ids).collect { |o| o.is_a?(ActiveRecord::Base) ? o.id : o }
|
9
|
+
end
|
10
|
+
|
11
|
+
def like_query(field, query)
|
12
|
+
["#{field} LIKE ?", "%#{escape_for_like_query(query)}%"]
|
13
|
+
end
|
14
|
+
|
15
|
+
def escape_for_like_query(word)
|
16
|
+
word.gsub("%", "\\%").gsub("_", "\\_")
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
-# Partial for a category form as shown to admins.
|
2
|
+
-# origin: M
|
3
|
+
|
4
|
+
- form_for [:admin, @category] do |form|
|
5
|
+
%dl
|
6
|
+
%dt
|
7
|
+
= form.label :name
|
8
|
+
%dd
|
9
|
+
= form.error_message_on :name
|
10
|
+
= form.text_field :name
|
11
|
+
%dt
|
12
|
+
= form.label :parent_id
|
13
|
+
%dd
|
14
|
+
= form.error_message_on :parent_id
|
15
|
+
= form.select :parent_id, form.object.available_parents, :include_blank => true
|
16
|
+
|
17
|
+
= boring_save_cancel_buttons
|
18
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
-# Partial for a category list as shown to admins.
|
2
|
+
-# origin: M
|
3
|
+
|
4
|
+
- categories = local_assigns[:categories] || @categories
|
5
|
+
|
6
|
+
- if categories.present?
|
7
|
+
%table.grid
|
8
|
+
%tr
|
9
|
+
%th= Category.human_attribute_name :name
|
10
|
+
- for category in categories
|
11
|
+
%tr
|
12
|
+
%td= link_to(icon(:category, category.name), [:admin, category])
|
13
|
+
= pagination categories
|
14
|
+
- else
|
15
|
+
.none
|
16
|
+
No categories found.
|
17
|
+
|