community_engine 2.0.0.beta1
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/.gitignore +15 -0
- data/.gitmodules +0 -0
- data/.travis.yml +9 -0
- data/CHANGELOG +118 -0
- data/Gemfile +3 -0
- data/LICENSE +30 -0
- data/README.markdown +188 -0
- data/Rakefile +54 -0
- data/UPGRADING.markdown +93 -0
- data/about.yml +7 -0
- data/app/assets/images/auth/facebook_32.png +0 -0
- data/app/assets/images/auth/facebook_64.png +0 -0
- data/app/assets/images/auth/google_32.png +0 -0
- data/app/assets/images/auth/google_64.png +0 -0
- data/app/assets/images/auth/linked_in_32.png +0 -0
- data/app/assets/images/auth/linked_in_64.png +0 -0
- data/app/assets/images/auth/open_id_32.png +0 -0
- data/app/assets/images/auth/remove.png +0 -0
- data/app/assets/images/auth/twitter_32.png +0 -0
- data/app/assets/images/auth/twitter_64.png +0 -0
- data/app/assets/images/bg_h6btn.gif +0 -0
- data/app/assets/images/bg_navbar.gif +0 -0
- data/app/assets/images/clearbits/bg_rounded.gif +0 -0
- data/app/assets/images/clearbits/comment.gif +0 -0
- data/app/assets/images/clearbits/lock.gif +0 -0
- data/app/assets/images/clearbits/smile.gif +0 -0
- data/app/assets/images/close.gif +0 -0
- data/app/assets/images/cropper/marqueeHoriz.gif +0 -0
- data/app/assets/images/cropper/marqueeVert.gif +0 -0
- data/app/assets/images/feed.png +0 -0
- data/app/assets/images/icon_missing_medium.gif +0 -0
- data/app/assets/images/icon_missing_thumb.gif +0 -0
- data/app/assets/images/icons/31.png +0 -0
- data/app/assets/images/icons/52.png +0 -0
- data/app/assets/images/icons/accept.png +0 -0
- data/app/assets/images/icons/activity_default.png +0 -0
- data/app/assets/images/icons/add.png +0 -0
- data/app/assets/images/icons/book.png +0 -0
- data/app/assets/images/icons/bullet_arrow_down.png +0 -0
- data/app/assets/images/icons/bullet_arrow_down_50.png +0 -0
- data/app/assets/images/icons/clipping.png +0 -0
- data/app/assets/images/icons/comment.png +0 -0
- data/app/assets/images/icons/comments.png +0 -0
- data/app/assets/images/icons/date.png +0 -0
- data/app/assets/images/icons/delete.png +0 -0
- data/app/assets/images/icons/email.png +0 -0
- data/app/assets/images/icons/email_edit.png +0 -0
- data/app/assets/images/icons/email_go.png +0 -0
- data/app/assets/images/icons/email_open.png +0 -0
- data/app/assets/images/icons/group_go.png +0 -0
- data/app/assets/images/icons/heart.png +0 -0
- data/app/assets/images/icons/heart_add.png +0 -0
- data/app/assets/images/icons/heart_off.png +0 -0
- data/app/assets/images/icons/ical.gif +0 -0
- data/app/assets/images/icons/page_white.png +0 -0
- data/app/assets/images/icons/page_white_magnify.png +0 -0
- data/app/assets/images/icons/picture.png +0 -0
- data/app/assets/images/icons/poll.png +0 -0
- data/app/assets/images/icons/post.png +0 -0
- data/app/assets/images/icons/printer.png +0 -0
- data/app/assets/images/icons/rss.png +0 -0
- data/app/assets/images/icons/slides.png +0 -0
- data/app/assets/images/icons/tag_blue.png +0 -0
- data/app/assets/images/icons/user.png +0 -0
- data/app/assets/images/icons/user_add.png +0 -0
- data/app/assets/images/icons/user_edit.png +0 -0
- data/app/assets/images/icons/user_go.png +0 -0
- data/app/assets/images/icons/vote.png +0 -0
- data/app/assets/images/icons/world.png +0 -0
- data/app/assets/images/icons/wrench.png +0 -0
- data/app/assets/images/logo.gif +0 -0
- data/app/assets/images/reply_background.png +0 -0
- data/app/assets/images/search.gif +0 -0
- data/app/assets/images/spinner.gif +0 -0
- data/app/assets/images/spinner_black.gif +0 -0
- data/app/assets/images/spinner_bounce.gif +0 -0
- data/app/assets/images/swf/choose.png +0 -0
- data/app/assets/images/swf/line_grapher.swf +0 -0
- data/app/assets/images/swf/swfupload.swf +0 -0
- data/app/assets/images/thumb.gif +0 -0
- data/app/assets/javascripts/builder.js +136 -0
- data/app/assets/javascripts/calendarview.js +839 -0
- data/app/assets/javascripts/community_engine.js +20 -0
- data/app/assets/javascripts/cropper.css +182 -0
- data/app/assets/javascripts/cropper.js +566 -0
- data/app/assets/javascripts/forum.js +73 -0
- data/app/assets/javascripts/lightbox.js +151 -0
- data/app/assets/javascripts/prototip-min.js +27 -0
- data/app/assets/javascripts/rails.js +202 -0
- data/app/assets/javascripts/tinymce/plugins/curblyadvimage/css/advimage.css +84 -0
- data/app/assets/javascripts/tinymce/plugins/curblyadvimage/editor_plugin.js +52 -0
- data/app/assets/javascripts/tinymce/plugins/curblyadvimage/editor_plugin_src.js +45 -0
- data/app/assets/javascripts/tinymce/plugins/curblyadvimage/image.htm +180 -0
- data/app/assets/javascripts/tinymce/plugins/curblyadvimage/img/sample.gif +0 -0
- data/app/assets/javascripts/tinymce/plugins/curblyadvimage/js/functions.js +508 -0
- data/app/assets/javascripts/tinymce/plugins/curblyadvimage/langs/en.js +3 -0
- data/app/assets/javascripts/tinymce/plugins/curblyadvimage/langs/en_dlg.js +43 -0
- data/app/assets/stylesheets/community_engine.css +6 -0
- data/app/assets/stylesheets/forum.css +605 -0
- data/app/assets/stylesheets/lightbox.css +38 -0
- data/app/assets/stylesheets/prototip.css +73 -0
- data/app/assets/stylesheets/reset-fonts-grids.css +8 -0
- data/app/assets/stylesheets/screen.css +977 -0
- data/app/controllers/activities_controller.rb +38 -0
- data/app/controllers/admin_controller.rb +80 -0
- data/app/controllers/ads_controller.rb +85 -0
- data/app/controllers/albums_controller.rb +106 -0
- data/app/controllers/authorizations_controller.rb +41 -0
- data/app/controllers/base_controller.rb +151 -0
- data/app/controllers/categories_controller.rb +118 -0
- data/app/controllers/clippings_controller.rb +192 -0
- data/app/controllers/comment_sweeper.rb +35 -0
- data/app/controllers/comments_controller.rb +179 -0
- data/app/controllers/event_sweeper.rb +24 -0
- data/app/controllers/events_controller.rb +173 -0
- data/app/controllers/favorite_sweeper.rb +29 -0
- data/app/controllers/favorites_controller.rb +36 -0
- data/app/controllers/forums_controller.rb +71 -0
- data/app/controllers/friendships_controller.rb +126 -0
- data/app/controllers/homepage_features_controller.rb +68 -0
- data/app/controllers/invitations_controller.rb +46 -0
- data/app/controllers/messages_controller.rb +95 -0
- data/app/controllers/metro_areas_controller.rb +68 -0
- data/app/controllers/moderators_controller.rb +26 -0
- data/app/controllers/monitorships_controller.rb +20 -0
- data/app/controllers/page_sweeper.rb +33 -0
- data/app/controllers/pages_controller.rb +70 -0
- data/app/controllers/password_resets_controller.rb +52 -0
- data/app/controllers/photo_manager_controller.rb +11 -0
- data/app/controllers/photos_controller.rb +189 -0
- data/app/controllers/post_sweeper.rb +36 -0
- data/app/controllers/posts_controller.rb +252 -0
- data/app/controllers/rsvps_controller.rb +77 -0
- data/app/controllers/sb_posts_controller.rb +149 -0
- data/app/controllers/sessions_controller.rb +34 -0
- data/app/controllers/sitemap_controller.rb +21 -0
- data/app/controllers/statistics_controller.rb +34 -0
- data/app/controllers/taggable_sweeper.rb +38 -0
- data/app/controllers/tags_controller.rb +104 -0
- data/app/controllers/theme_controller.rb +60 -0
- data/app/controllers/topics_controller.rb +122 -0
- data/app/controllers/users_controller.rb +426 -0
- data/app/controllers/vote_sweeper.rb +16 -0
- data/app/controllers/votes_controller.rb +24 -0
- data/app/helpers/base_helper.rb +290 -0
- data/app/helpers/forums_helper.rb +31 -0
- data/app/helpers/friendships_helper.rb +16 -0
- data/app/helpers/monitorships_helper.rb +2 -0
- data/app/helpers/posts_helper.rb +17 -0
- data/app/helpers/sitemap_helper.rb +7 -0
- data/app/helpers/users_helper.rb +6 -0
- data/app/models/ad.rb +43 -0
- data/app/models/album.rb +12 -0
- data/app/models/asset.rb +3 -0
- data/app/models/authorization.rb +60 -0
- data/app/models/category.rb +20 -0
- data/app/models/choice.rb +13 -0
- data/app/models/clipping.rb +78 -0
- data/app/models/clipping_image.rb +9 -0
- data/app/models/comment.rb +122 -0
- data/app/models/country.rb +24 -0
- data/app/models/event.rb +61 -0
- data/app/models/facebook_profile.rb +32 -0
- data/app/models/facebook_publisher.rb +45 -0
- data/app/models/favorite.rb +47 -0
- data/app/models/forum.rb +22 -0
- data/app/models/friendship.rb +64 -0
- data/app/models/friendship_status.rb +3 -0
- data/app/models/homepage_feature.rb +15 -0
- data/app/models/invitation.rb +36 -0
- data/app/models/message.rb +84 -0
- data/app/models/message_thread.rb +33 -0
- data/app/models/metro_area.rb +16 -0
- data/app/models/moderatorship.rb +8 -0
- data/app/models/monitorship.rb +6 -0
- data/app/models/page.rb +8 -0
- data/app/models/photo.rb +83 -0
- data/app/models/poll.rb +39 -0
- data/app/models/post.rb +201 -0
- data/app/models/role.rb +5 -0
- data/app/models/rsvp.rb +24 -0
- data/app/models/sb_post.rb +67 -0
- data/app/models/state.rb +4 -0
- data/app/models/topic.rb +72 -0
- data/app/models/twitter_profile.rb +20 -0
- data/app/models/user.rb +483 -0
- data/app/models/user_notifier.rb +140 -0
- data/app/models/user_session.rb +14 -0
- data/app/models/vote.rb +19 -0
- data/app/views/activities/_activity.html.haml +56 -0
- data/app/views/activities/_icon.html.haml +14 -0
- data/app/views/activities/_unhandled_item.html.haml +1 -0
- data/app/views/activities/destroy.js.rjs +1 -0
- data/app/views/activities/index.html.haml +16 -0
- data/app/views/activities/network.html.haml +14 -0
- data/app/views/admin/comments.html.haml +71 -0
- data/app/views/admin/events.html.haml +33 -0
- data/app/views/admin/messages.html.haml +4 -0
- data/app/views/admin/users.html.haml +69 -0
- data/app/views/ads/edit.html.haml +46 -0
- data/app/views/ads/index.html.haml +43 -0
- data/app/views/ads/new.html.haml +44 -0
- data/app/views/ads/show.html.haml +36 -0
- data/app/views/albums/_form.html.haml +14 -0
- data/app/views/albums/edit.html.haml +16 -0
- data/app/views/albums/new.html.haml +15 -0
- data/app/views/albums/show.html.haml +32 -0
- data/app/views/base/_homepage_banner_message.html.haml +19 -0
- data/app/views/base/advertise.html.haml +8 -0
- data/app/views/base/plaxo.html.haml +5 -0
- data/app/views/base/site_index.html.haml +35 -0
- data/app/views/categories/_tips.html.haml +11 -0
- data/app/views/categories/edit.html.haml +34 -0
- data/app/views/categories/index.html.haml +30 -0
- data/app/views/categories/new.html.haml +9 -0
- data/app/views/categories/show.html.haml +45 -0
- data/app/views/clippings/_clipping.html.haml +18 -0
- data/app/views/clippings/_images.html.haml +3 -0
- data/app/views/clippings/_meta.html.haml +26 -0
- data/app/views/clippings/edit.html.haml +26 -0
- data/app/views/clippings/index.html.haml +35 -0
- data/app/views/clippings/load_images_from_uri.js.rjs +1 -0
- data/app/views/clippings/new.html.haml +29 -0
- data/app/views/clippings/new_clipping.html.haml +91 -0
- data/app/views/clippings/show.html.haml +56 -0
- data/app/views/clippings/site_index.html.haml +34 -0
- data/app/views/comments/_comment.html.haml +42 -0
- data/app/views/comments/_comment_form.html.haml +50 -0
- data/app/views/comments/_edit_form.html.haml +29 -0
- data/app/views/comments/create.js.rjs +20 -0
- data/app/views/comments/edit.js.rjs +7 -0
- data/app/views/comments/index.html.haml +23 -0
- data/app/views/comments/update.js.rjs +9 -0
- data/app/views/events/_event.html.haml +32 -0
- data/app/views/events/_subscribe.html.haml +7 -0
- data/app/views/events/edit.html.haml +34 -0
- data/app/views/events/index.html.haml +22 -0
- data/app/views/events/new.html.haml +32 -0
- data/app/views/events/show.html.haml +29 -0
- data/app/views/facebook/_fb_require.html.haml +11 -0
- data/app/views/favorites/_favorite.html.haml +5 -0
- data/app/views/favorites/create.js.rjs +17 -0
- data/app/views/favorites/destroy.js.rjs +14 -0
- data/app/views/favorites/index.html.haml +10 -0
- data/app/views/favorites/show.html.haml +13 -0
- data/app/views/forums/_form.html.haml +21 -0
- data/app/views/forums/edit.html.haml +11 -0
- data/app/views/forums/index.html.haml +70 -0
- data/app/views/forums/new.html.haml +9 -0
- data/app/views/forums/show.html.haml +85 -0
- data/app/views/friendships/_friendship.html.haml +16 -0
- data/app/views/friendships/_friendships.html.erb +14 -0
- data/app/views/friendships/accepted.html.haml +13 -0
- data/app/views/friendships/denied.html.haml +8 -0
- data/app/views/friendships/index.html.erb +3 -0
- data/app/views/friendships/index.xml.builder +29 -0
- data/app/views/friendships/pending.html.haml +7 -0
- data/app/views/friendships/show.html.haml +12 -0
- data/app/views/homepage_features/edit.html.haml +31 -0
- data/app/views/homepage_features/index.html.haml +30 -0
- data/app/views/homepage_features/new.html.haml +30 -0
- data/app/views/homepage_features/show.html.haml +29 -0
- data/app/views/invitations/index.html.erb +16 -0
- data/app/views/invitations/new.html.haml +33 -0
- data/app/views/layouts/application.html.haml +59 -0
- data/app/views/messages/_form.html.haml +24 -0
- data/app/views/messages/_inbox.html.haml +41 -0
- data/app/views/messages/_sent.html.haml +34 -0
- data/app/views/messages/_sidebar_nav.html.haml +9 -0
- data/app/views/messages/index.html.haml +8 -0
- data/app/views/messages/new.html.haml +10 -0
- data/app/views/messages/show.html.haml +40 -0
- data/app/views/metro_areas/edit.html.haml +16 -0
- data/app/views/metro_areas/index.html.haml +28 -0
- data/app/views/metro_areas/new.html.haml +16 -0
- data/app/views/metro_areas/show.html.haml +22 -0
- data/app/views/moderators/_toggle.html.erb +14 -0
- data/app/views/moderators/create.js.rjs +5 -0
- data/app/views/moderators/destroy.js.rjs +1 -0
- data/app/views/monitorships/create.js.rjs +4 -0
- data/app/views/monitorships/destroy.js.rjs +4 -0
- data/app/views/pages/_form.html.haml +25 -0
- data/app/views/pages/edit.html.haml +16 -0
- data/app/views/pages/edit.html.haml~ +16 -0
- data/app/views/pages/index.html.haml +34 -0
- data/app/views/pages/index.html.haml~ +28 -0
- data/app/views/pages/new.html.haml +14 -0
- data/app/views/pages/show.html.haml +8 -0
- data/app/views/pages/show.html.haml~ +6 -0
- data/app/views/password_resets/edit.html.haml +16 -0
- data/app/views/password_resets/new.html.haml +13 -0
- data/app/views/photo_manager/index.html.haml +49 -0
- data/app/views/photos/_manage_photos.html.haml +14 -0
- data/app/views/photos/_show_image_list.html.haml +24 -0
- data/app/views/photos/edit.html.haml +39 -0
- data/app/views/photos/index.html.haml +28 -0
- data/app/views/photos/index.xml.builder +9 -0
- data/app/views/photos/manage_photos.js.rjs +5 -0
- data/app/views/photos/new.html.haml +51 -0
- data/app/views/photos/recent.html.haml +8 -0
- data/app/views/photos/show.html.haml +53 -0
- data/app/views/polls/_edit.html.haml +15 -0
- data/app/views/polls/_excerpt.html.haml +4 -0
- data/app/views/polls/_new.html.haml +10 -0
- data/app/views/polls/_poll_ui.html.haml +37 -0
- data/app/views/polls/_polls_sidebar.html.haml +8 -0
- data/app/views/posts/_author_profile.html.haml +21 -0
- data/app/views/posts/_favorited_post.html.haml +10 -0
- data/app/views/posts/_post.html.haml +29 -0
- data/app/views/posts/_send_to_friend.html.erb +29 -0
- data/app/views/posts/_sidebar_post.html.haml +1 -0
- data/app/views/posts/edit.html.haml +48 -0
- data/app/views/posts/featured.html.haml +19 -0
- data/app/views/posts/index.html.haml +23 -0
- data/app/views/posts/manage.html.haml +66 -0
- data/app/views/posts/new.html.haml +67 -0
- data/app/views/posts/popular.html.haml +35 -0
- data/app/views/posts/preview.html.haml +27 -0
- data/app/views/posts/recent.html.haml +29 -0
- data/app/views/posts/show.html.haml +85 -0
- data/app/views/rsvps/edit.html.haml +9 -0
- data/app/views/rsvps/new.html.haml +9 -0
- data/app/views/sb_posts/_dummy_forum_post.html.erb +13 -0
- data/app/views/sb_posts/_edit.html.erb +31 -0
- data/app/views/sb_posts/_post.xml.builder +10 -0
- data/app/views/sb_posts/_reply_form.html.haml +37 -0
- data/app/views/sb_posts/_sb_post.html.haml +34 -0
- data/app/views/sb_posts/create.js.rjs +16 -0
- data/app/views/sb_posts/edit.html.erb +13 -0
- data/app/views/sb_posts/edit.js.rjs +6 -0
- data/app/views/sb_posts/index.html.haml +55 -0
- data/app/views/sb_posts/index.xml.builder +20 -0
- data/app/views/sb_posts/monitored.html.erb +55 -0
- data/app/views/sb_posts/monitored.xml.builder +15 -0
- data/app/views/sb_posts/update.js.rjs +5 -0
- data/app/views/sessions/new.html.haml +27 -0
- data/app/views/shared/_admin_nav.html.haml +19 -0
- data/app/views/shared/_bio_help.html.haml +4 -0
- data/app/views/shared/_box.html.haml +3 -0
- data/app/views/shared/_contact.html.haml +5 -0
- data/app/views/shared/_explore.html.haml +9 -0
- data/app/views/shared/_footer_content.html.haml +13 -0
- data/app/views/shared/_header.html.haml +42 -0
- data/app/views/shared/_location_chooser.html.haml +21 -0
- data/app/views/shared/_login_sidebar.html.haml +14 -0
- data/app/views/shared/_messages.html.haml +8 -0
- data/app/views/shared/_scripts_and_styles.html.haml +12 -0
- data/app/views/shared/_user_menu.html.haml +21 -0
- data/app/views/sitemap/index.html.haml +21 -0
- data/app/views/sitemap/index.xml.builder +28 -0
- data/app/views/statistics/activities.xml.builder +33 -0
- data/app/views/statistics/index.html.haml +56 -0
- data/app/views/tags/edit.html.haml +19 -0
- data/app/views/tags/index.html.haml +25 -0
- data/app/views/tags/manage.html.haml +37 -0
- data/app/views/tags/show.html.haml +65 -0
- data/app/views/topics/_form.html.haml +28 -0
- data/app/views/topics/_recent_topics_sidebar.haml +22 -0
- data/app/views/topics/edit.html.haml +10 -0
- data/app/views/topics/new.html.haml +21 -0
- data/app/views/topics/show.html.haml +107 -0
- data/app/views/topics/show.xml.builder +15 -0
- data/app/views/user_notifier/activation.text.erb +11 -0
- data/app/views/user_notifier/comment_notice.text.erb +8 -0
- data/app/views/user_notifier/follow_up_comment_notice.text.erb +15 -0
- data/app/views/user_notifier/follow_up_comment_notice_anonymous.text.erb +18 -0
- data/app/views/user_notifier/forgot_username.text.erb +8 -0
- data/app/views/user_notifier/friendship_accepted.text.erb +8 -0
- data/app/views/user_notifier/friendship_request.text.erb +8 -0
- data/app/views/user_notifier/message_notification.text.erb +14 -0
- data/app/views/user_notifier/new_forum_post_notice.text.erb +14 -0
- data/app/views/user_notifier/password_reset_instructions.text.erb +10 -0
- data/app/views/user_notifier/post_recommendation.text.erb +32 -0
- data/app/views/user_notifier/signup_invitation.text.erb +14 -0
- data/app/views/user_notifier/signup_notification.text.erb +16 -0
- data/app/views/users/_dashboard_nav.html.haml +40 -0
- data/app/views/users/_omniauth_connect.html.haml +21 -0
- data/app/views/users/_profile_completeness.html.haml +21 -0
- data/app/views/users/_profile_user_info_sidebar.html.haml +50 -0
- data/app/views/users/_search_options.html.haml +10 -0
- data/app/views/users/_sidebar_user.html.haml +8 -0
- data/app/views/users/_user.html.haml +31 -0
- data/app/views/users/crop_profile_photo.html.haml +40 -0
- data/app/views/users/dashboard.html.haml +44 -0
- data/app/views/users/edit.html.haml +75 -0
- data/app/views/users/edit_account.html.haml +64 -0
- data/app/views/users/forgot_username.html.haml +13 -0
- data/app/views/users/index.html.haml +18 -0
- data/app/views/users/invite.html.haml +31 -0
- data/app/views/users/new.html.haml +54 -0
- data/app/views/users/resend_activation.html.haml +13 -0
- data/app/views/users/show.html.haml +103 -0
- data/app/views/users/signup_completed.html.haml +8 -0
- data/app/views/users/statistics.html.haml +28 -0
- data/app/views/users/upload_profile_photo.html.haml +15 -0
- data/app/views/users/welcome_about.html.haml +66 -0
- data/app/views/users/welcome_invite.html.haml +33 -0
- data/app/views/users/welcome_photo.html.haml +29 -0
- data/app/views/votes/create.js.rjs +6 -0
- data/community_engine.gemspec +55 -0
- data/config/application_config.rb +162 -0
- data/config/initializers/cropper.rb +19 -0
- data/config/initializers/mce_options.rb +40 -0
- data/config/initializers/recaptcha_constants.rb +6 -0
- data/config/initializers/white_list.rb +7 -0
- data/config/locales/de-DE.yml +1271 -0
- data/config/locales/en.yml +1658 -0
- data/config/locales/es-AR.yml +758 -0
- data/config/locales/es-ES.yml +340 -0
- data/config/locales/es-MX.yml +672 -0
- data/config/locales/fr-FR.yml +1509 -0
- data/config/locales/ja-JP.yml +1321 -0
- data/config/locales/ru-RU.yml +97 -0
- data/config/locales/sr-CP.yml +89 -0
- data/config/locales/sv-SE.yml +1320 -0
- data/config/routes.rb +242 -0
- data/db/migrate/001_create_users.rb +26 -0
- data/db/migrate/002_add_activation_code_to_user.rb +11 -0
- data/db/migrate/003_create_photos.rb +22 -0
- data/db/migrate/004_add_tag_support.rb +21 -0
- data/db/migrate/005_create_friendships.rb +14 -0
- data/db/migrate/006_add_comments_tables.rb +18 -0
- data/db/migrate/007_create_friendship_statuses.rb +13 -0
- data/db/migrate/008_add_friendship_statuses.rb +14 -0
- data/db/migrate/009_create_clippings.rb +16 -0
- data/db/migrate/010_create_invitations.rb +14 -0
- data/db/migrate/011_create_homepage_features.rb +22 -0
- data/db/migrate/012_create_posts.rb +19 -0
- data/db/migrate/013_create_states.rb +13 -0
- data/db/migrate/014_add_states.rb +11 -0
- data/db/migrate/015_create_metro_areas.rb +15 -0
- data/db/migrate/016_add_metro_areas.rb +295 -0
- data/db/migrate/017_add_sessions_table.rb +20 -0
- data/db/migrate/018_create_categories.rb +11 -0
- data/db/migrate/019_change_comment_to_text_field.rb +10 -0
- data/db/migrate/020_create_login_slug.rb +9 -0
- data/db/migrate/021_add_category_names.rb +8 -0
- data/db/migrate/023_add_denied_friendship_status.rb +13 -0
- data/db/migrate/024_add_notification_preferences.rb +13 -0
- data/db/migrate/025_create_countries.rb +11 -0
- data/db/migrate/026_add_countries.rb +230 -0
- data/db/migrate/027_add_us_to_existing_metro_areas.rb +9 -0
- data/db/migrate/028_add_country_id_to_users.rb +9 -0
- data/db/migrate/029_add_us_to_users_with_states.rb +14 -0
- data/db/migrate/030_add_users_counter_cache.rb +9 -0
- data/db/migrate/031_news_to_talk.rb +10 -0
- data/db/migrate/033_featured_users.rb +9 -0
- data/db/migrate/034_add_last_login.rb +9 -0
- data/db/migrate/035_track_emailed.rb +9 -0
- data/db/migrate/036_create_skills.rb +11 -0
- data/db/migrate/037_create_offerings.rb +12 -0
- data/db/migrate/038_add_zag_to_users.rb +13 -0
- data/db/migrate/039_create_activities_table.rb +17 -0
- data/db/migrate/040_add_category_tips.rb +9 -0
- data/db/migrate/041_create_events_table.rb +19 -0
- data/db/migrate/042_add_privacy_to_users.rb +10 -0
- data/db/migrate/043_sql_session_store_setup.rb +39 -0
- data/db/migrate/044_category_improvements.rb +11 -0
- data/db/migrate/045_adding_indexes.rb +39 -0
- data/db/migrate/046_adding_ads.rb +20 -0
- data/db/migrate/047_add_polls.rb +30 -0
- data/db/migrate/049_add_activities_count.rb +9 -0
- data/db/migrate/050_create_initial_schema.rb +73 -0
- data/db/migrate/051_add_audience_limitation_to_ads.rb +9 -0
- data/db/migrate/052_create_assets.rb +21 -0
- data/db/migrate/053_create_favoritables.rb +23 -0
- data/db/migrate/054_add_published_as_to_posts.rb +13 -0
- data/db/migrate/055_add_published_at_to_posts.rb +15 -0
- data/db/migrate/056_create_roles.rb +28 -0
- data/db/migrate/057_add_more_indexes.rb +19 -0
- data/db/migrate/058_add_anonymous_commenting_fields.rb +15 -0
- data/db/migrate/059_create_messages.rb +16 -0
- data/db/migrate/060_still_more_indexes.rb +19 -0
- data/db/migrate/061_postgres_compatibility_changes.rb +9 -0
- data/db/migrate/062_add_notify_to_comments.rb +11 -0
- data/db/migrate/063_create_albums.rb +15 -0
- data/db/migrate/064_add_album_id_to_photos.rb +9 -0
- data/db/migrate/065_add_view_count_to_albums.rb +9 -0
- data/db/migrate/066_add_view_count_to_photos.rb +9 -0
- data/db/migrate/067_create_static_pages.rb +22 -0
- data/db/migrate/068_create_rsvps.rb +13 -0
- data/db/migrate/069_create_pages.rb +29 -0
- data/db/migrate/070_add_pages.rb +11 -0
- data/db/migrate/071_authlogic_compatibility_changes.rb +43 -0
- data/db/migrate/072_add_allow_rsvp_to_events.rb +9 -0
- data/db/migrate/073_add_taggings_count_to_tags.rb +9 -0
- data/db/migrate/074_add_threading_to_messages.rb +19 -0
- data/db/migrate/075_add_anonymous_forum_posting.rb +16 -0
- data/db/migrate/076_add_comment_notification_toggle.rb +9 -0
- data/db/migrate/077_paperclip_changes.rb +36 -0
- data/db/migrate/078_create_authorizations.rb +20 -0
- data/db/migrate/079_create_slugs.rb +18 -0
- data/db/sample/users.rb +55 -0
- data/generators/ce_plugin/USAGE +7 -0
- data/generators/ce_plugin/ce_plugin_generator.rb +25 -0
- data/generators/ce_plugin/templates/README +13 -0
- data/generators/ce_plugin/templates/desert_routes.rb +3 -0
- data/generators/ce_plugin/templates/init.rb +8 -0
- data/generators/ce_plugin/templates/plugin.rb +1 -0
- data/generators/plugin_migration/plugin_migration_generator.rb +101 -0
- data/generators/plugin_migration/templates/plugin_migration.erb +13 -0
- data/lang/TRANSLATION.markdown +32 -0
- data/lib/community_engine/authenticated_system.rb +167 -0
- data/lib/community_engine/authenticated_test_helper.rb +113 -0
- data/lib/community_engine/community_engine_sha1_crypto_method.rb +12 -0
- data/lib/community_engine/engine.rb +39 -0
- data/lib/community_engine/engines_extensions.rb +7 -0
- data/lib/community_engine/i18n_extensions.rb +31 -0
- data/lib/community_engine/localized_application.rb +83 -0
- data/lib/community_engine/rails_asset_extensions.rb +131 -0
- data/lib/community_engine/url_upload.rb +15 -0
- data/lib/community_engine/version.rb +10 -0
- data/lib/community_engine/viewable.rb +12 -0
- data/lib/community_engine.rb +34 -0
- data/lib/tag_hacks.rb +24 -0
- data/lib/tasks/community_engine_tasks.rake +87 -0
- data/public/favicon.ico +0 -0
- data/sample_files/s3.yml +17 -0
- data/test/fixtures/ads.yml +13 -0
- data/test/fixtures/albums.yml +16 -0
- data/test/fixtures/categories.yml +16 -0
- data/test/fixtures/clippings.yml +15 -0
- data/test/fixtures/comments.yml +55 -0
- data/test/fixtures/countries.yml +13 -0
- data/test/fixtures/events.yml +61 -0
- data/test/fixtures/files/Granite.bmp +0 -0
- data/test/fixtures/files/library.jpg +0 -0
- data/test/fixtures/forums.yml +10 -0
- data/test/fixtures/friendship_statuses.yml +10 -0
- data/test/fixtures/friendships.yml +15 -0
- data/test/fixtures/homepage_features.yml +13 -0
- data/test/fixtures/invitations.yml +5 -0
- data/test/fixtures/messages.yml +24 -0
- data/test/fixtures/metro_areas.yml +24 -0
- data/test/fixtures/moderatorships.yml +4 -0
- data/test/fixtures/monitorships.yml +10 -0
- data/test/fixtures/pages.yml +26 -0
- data/test/fixtures/photos.yml +29 -0
- data/test/fixtures/posts.yml +49 -0
- data/test/fixtures/roles.yml +9 -0
- data/test/fixtures/rsvps.yml +7 -0
- data/test/fixtures/sb_posts.yml +90 -0
- data/test/fixtures/states.yml +7 -0
- data/test/fixtures/taggings.yml +15 -0
- data/test/fixtures/tags.yml +11 -0
- data/test/fixtures/topics.yml +63 -0
- data/test/fixtures/users.yml +222 -0
- data/test/functional/activities_controller_test.rb +62 -0
- data/test/functional/admin_controller_test.rb +60 -0
- data/test/functional/ads_controller_test.rb +51 -0
- data/test/functional/albums_controller_test.rb +120 -0
- data/test/functional/base_controller_test.rb +27 -0
- data/test/functional/categories_controller_test.rb +51 -0
- data/test/functional/clippings_controller_test.rb +123 -0
- data/test/functional/comments_controller_test.rb +215 -0
- data/test/functional/events_controller_test.rb +104 -0
- data/test/functional/favorites_controller_test.rb +53 -0
- data/test/functional/forums_controller_test.rb +95 -0
- data/test/functional/friendships_controller_test.rb +98 -0
- data/test/functional/homepage_features_controller_test.rb +69 -0
- data/test/functional/invitations_controller_test.rb +45 -0
- data/test/functional/messages_controller_test.rb +154 -0
- data/test/functional/metro_areas_controller_test.rb +63 -0
- data/test/functional/moderators_controller_test.rb +22 -0
- data/test/functional/monitorships_controller_test.rb +72 -0
- data/test/functional/pages_controller_test.rb +95 -0
- data/test/functional/password_reset_controller_test.rb +34 -0
- data/test/functional/photo_manager_controller_test.rb +21 -0
- data/test/functional/photos_controller_test.rb +203 -0
- data/test/functional/posts_controller_test.rb +224 -0
- data/test/functional/rsvps_controller_test.rb +92 -0
- data/test/functional/sb_posts_controller_test.rb +193 -0
- data/test/functional/sessions_controller_test.rb +55 -0
- data/test/functional/sitemap_controller_test.rb +9 -0
- data/test/functional/statistics_controller_test.rb +18 -0
- data/test/functional/tags_controller_test.rb +52 -0
- data/test/functional/theme_controller_test.rb +11 -0
- data/test/functional/topics_controller_test.rb +201 -0
- data/test/functional/users_controller_test.rb +460 -0
- data/test/functional/votes_controller_test.rb +27 -0
- data/test/test_helper.rb +103 -0
- data/test/testapp/.gitignore +4 -0
- data/test/testapp/README +256 -0
- data/test/testapp/Rakefile +7 -0
- data/test/testapp/app/controllers/application_controller.rb +3 -0
- data/test/testapp/app/helpers/application_helper.rb +2 -0
- data/test/testapp/config/application.rb +45 -0
- data/test/testapp/config/application_config.rb +1 -0
- data/test/testapp/config/boot.rb +10 -0
- data/test/testapp/config/database.yml +22 -0
- data/test/testapp/config/environment.rb +6 -0
- data/test/testapp/config/environments/development.rb +25 -0
- data/test/testapp/config/environments/production.rb +49 -0
- data/test/testapp/config/environments/test.rb +35 -0
- data/test/testapp/config/initializers/backtrace_silencers.rb +7 -0
- data/test/testapp/config/initializers/inflections.rb +10 -0
- data/test/testapp/config/initializers/mime_types.rb +5 -0
- data/test/testapp/config/initializers/secret_token.rb +7 -0
- data/test/testapp/config/initializers/session_store.rb +8 -0
- data/test/testapp/config/locales/en.yml +5 -0
- data/test/testapp/config/routes.rb +3 -0
- data/test/testapp/config.ru +4 -0
- data/test/testapp/db/schema.rb +456 -0
- data/test/testapp/db/seeds.rb +7 -0
- data/test/testapp/doc/README_FOR_APP +2 -0
- data/test/testapp/lib/tasks/.gitkeep +0 -0
- data/test/testapp/public/404.html +26 -0
- data/test/testapp/public/422.html +26 -0
- data/test/testapp/public/500.html +26 -0
- data/test/testapp/public/favicon.ico +0 -0
- data/test/testapp/public/images/rails.png +0 -0
- data/test/testapp/public/robots.txt +5 -0
- data/test/testapp/script/rails +6 -0
- data/test/testapp/test/performance/browsing_test.rb +9 -0
- data/test/testapp/test/test_helper.rb +13 -0
- data/test/testapp/vendor/plugins/.gitkeep +0 -0
- data/test/unit/ad_test.rb +34 -0
- data/test/unit/asset_test.rb +15 -0
- data/test/unit/authorization_test.rb +55 -0
- data/test/unit/category_test.rb +22 -0
- data/test/unit/choice_test.rb +9 -0
- data/test/unit/clipping_image_test.rb +17 -0
- data/test/unit/clipping_test.rb +52 -0
- data/test/unit/comment_test.rb +107 -0
- data/test/unit/country_test.rb +15 -0
- data/test/unit/event_test.rb +75 -0
- data/test/unit/favorite_test.rb +71 -0
- data/test/unit/forum_test.rb +23 -0
- data/test/unit/friendship_status_test.rb +10 -0
- data/test/unit/friendship_test.rb +38 -0
- data/test/unit/homepage_feature_test.rb +10 -0
- data/test/unit/invitation_test.rb +27 -0
- data/test/unit/message_test.rb +49 -0
- data/test/unit/message_thread_test.rb +80 -0
- data/test/unit/metro_area_test.rb +10 -0
- data/test/unit/moderatorship_test.rb +30 -0
- data/test/unit/monitorships_test.rb +38 -0
- data/test/unit/page_test.rb +25 -0
- data/test/unit/photo_test.rb +42 -0
- data/test/unit/poll_test.rb +25 -0
- data/test/unit/post_test.rb +212 -0
- data/test/unit/rsvp_test.rb +33 -0
- data/test/unit/sb_post_test.rb +152 -0
- data/test/unit/state_test.rb +10 -0
- data/test/unit/tag_test.rb +22 -0
- data/test/unit/topic_test.rb +111 -0
- data/test/unit/user_notifier_test.rb +108 -0
- data/test/unit/user_test.rb +259 -0
- data/test/unit/vote_test.rb +9 -0
- data/vendor/plugins/activity_tracker/README +4 -0
- data/vendor/plugins/activity_tracker/Rakefile +22 -0
- data/vendor/plugins/activity_tracker/generators/activity_migration/USAGE +13 -0
- data/vendor/plugins/activity_tracker/generators/activity_migration/activity_migration_generator.rb +11 -0
- data/vendor/plugins/activity_tracker/generators/activity_migration/templates/migration.rb +17 -0
- data/vendor/plugins/activity_tracker/init.rb +1 -0
- data/vendor/plugins/activity_tracker/install.rb +1 -0
- data/vendor/plugins/activity_tracker/lib/activity.rb +40 -0
- data/vendor/plugins/activity_tracker/lib/activity_tracker.rb +80 -0
- data/vendor/plugins/activity_tracker/tasks/activity_tracker_tasks.rake +4 -0
- data/vendor/plugins/activity_tracker/test/abstract_unit.rb +47 -0
- data/vendor/plugins/activity_tracker/test/activity_tracker_test.rb +48 -0
- data/vendor/plugins/activity_tracker/test/database.yml +18 -0
- data/vendor/plugins/activity_tracker/test/debug.log +3329 -0
- data/vendor/plugins/activity_tracker/test/fixtures/test_post.rb +5 -0
- data/vendor/plugins/activity_tracker/test/fixtures/test_posts.yml +3 -0
- data/vendor/plugins/activity_tracker/test/fixtures/test_user.rb +4 -0
- data/vendor/plugins/activity_tracker/test/fixtures/test_users.yml +6 -0
- data/vendor/plugins/activity_tracker/test/schema.rb +21 -0
- data/vendor/plugins/activity_tracker/uninstall.rb +1 -0
- data/vendor/plugins/acts_as_list/README +23 -0
- data/vendor/plugins/acts_as_list/init.rb +3 -0
- data/vendor/plugins/acts_as_list/lib/active_record/acts/list.rb +256 -0
- data/vendor/plugins/acts_as_list/test/list_test.rb +332 -0
- data/vendor/plugins/acts_as_publishable/README +3 -0
- data/vendor/plugins/acts_as_publishable/Rakefile +22 -0
- data/vendor/plugins/acts_as_publishable/generators/publishing/publishing_generator.rb +34 -0
- data/vendor/plugins/acts_as_publishable/generators/publishing/templates/migration.rb +13 -0
- data/vendor/plugins/acts_as_publishable/init.rb +3 -0
- data/vendor/plugins/acts_as_publishable/install.rb +3 -0
- data/vendor/plugins/acts_as_publishable/lib/acts_as_publishable.rb +81 -0
- data/vendor/plugins/acts_as_publishable/test/acts_as_publishable_test.rb +8 -0
- data/vendor/plugins/acts_as_publishable/uninstall.rb +1 -0
- data/vendor/plugins/auto_complete/README +23 -0
- data/vendor/plugins/auto_complete/Rakefile +22 -0
- data/vendor/plugins/auto_complete/init.rb +2 -0
- data/vendor/plugins/auto_complete/lib/auto_complete.rb +47 -0
- data/vendor/plugins/auto_complete/lib/auto_complete_macros_helper.rb +143 -0
- data/vendor/plugins/auto_complete/test/auto_complete_test.rb +67 -0
- data/vendor/plugins/enumerations_mixin/LICENSE +20 -0
- data/vendor/plugins/enumerations_mixin/README_ENUMERATIONS +163 -0
- data/vendor/plugins/enumerations_mixin/init.rb +21 -0
- data/vendor/plugins/enumerations_mixin/lib/active_record/acts/enumerated.rb +177 -0
- data/vendor/plugins/enumerations_mixin/lib/active_record/aggregations/has_enumerated.rb +60 -0
- data/vendor/plugins/enumerations_mixin/lib/active_record/virtual_enumerations.rb +68 -0
- data/vendor/plugins/enumerations_mixin/virtual_enumerations_sample.rb +76 -0
- data/vendor/plugins/prototype_legacy_helper/README.markdown +13 -0
- data/vendor/plugins/prototype_legacy_helper/init.rb +1 -0
- data/vendor/plugins/prototype_legacy_helper/lib/prototype_legacy_helper.rb +432 -0
- data/vendor/plugins/prototype_legacy_helper/test/test_prototype_helper.rb +297 -0
- data/vendor/plugins/resource_feeder/README +4 -0
- data/vendor/plugins/resource_feeder/Rakefile +22 -0
- data/vendor/plugins/resource_feeder/init.rb +2 -0
- data/vendor/plugins/resource_feeder/lib/resource_feeder/atom.rb +71 -0
- data/vendor/plugins/resource_feeder/lib/resource_feeder/rss.rb +71 -0
- data/vendor/plugins/resource_feeder/lib/resource_feeder.rb +2 -0
- data/vendor/plugins/resource_feeder/test/atom_feed_test.rb +85 -0
- data/vendor/plugins/resource_feeder/test/rss_feed_test.rb +61 -0
- data/vendor/plugins/resource_feeder/test/test_helper.rb +60 -0
- data/vendor/plugins/respond_to_parent/MIT-LICENSE +20 -0
- data/vendor/plugins/respond_to_parent/README +47 -0
- data/vendor/plugins/respond_to_parent/Rakefile +22 -0
- data/vendor/plugins/respond_to_parent/init.rb +1 -0
- data/vendor/plugins/respond_to_parent/install.rb +1 -0
- data/vendor/plugins/respond_to_parent/lib/responds_to_parent.rb +70 -0
- data/vendor/plugins/respond_to_parent/test/responds_to_parent_test.rb +10 -0
- data/vendor/plugins/respond_to_parent/test/test_helper.rb +6 -0
- data/vendor/plugins/respond_to_parent/uninstall.rb +1 -0
- data/vendor/plugins/tiny_mce/CHANGELOG_PLUGIN.rdoc +91 -0
- data/vendor/plugins/tiny_mce/CHANGELOG_TINYMCE +1226 -0
- data/vendor/plugins/tiny_mce/DEV_UPGRADE_NOTES.rdoc +12 -0
- data/vendor/plugins/tiny_mce/init.rb +2 -0
- data/vendor/plugins/tiny_mce/install.rb +18 -0
- data/vendor/plugins/tiny_mce/lib/tiny_mce/base.rb +33 -0
- data/vendor/plugins/tiny_mce/lib/tiny_mce/configuration.rb +114 -0
- data/vendor/plugins/tiny_mce/lib/tiny_mce/exceptions.rb +14 -0
- data/vendor/plugins/tiny_mce/lib/tiny_mce/helpers.rb +43 -0
- data/vendor/plugins/tiny_mce/lib/tiny_mce/railtie.rb +13 -0
- data/vendor/plugins/tiny_mce/lib/tiny_mce/spell_checker.rb +67 -0
- data/vendor/plugins/tiny_mce/lib/tiny_mce/valid_tinymce_langs.yml +25 -0
- data/vendor/plugins/tiny_mce/lib/tiny_mce/valid_tinymce_options.yml +167 -0
- data/vendor/plugins/tiny_mce/lib/tiny_mce.rb +24 -0
- data/vendor/plugins/white_list/README +35 -0
- data/vendor/plugins/white_list/Rakefile +22 -0
- data/vendor/plugins/white_list/init.rb +35 -0
- data/vendor/plugins/white_list/lib/white_list_helper.rb +61 -0
- data/vendor/plugins/white_list/test/white_list_test.rb +120 -0
- metadata +1073 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
class PublishingGenerator < Rails::Generator::Base
|
|
2
|
+
|
|
3
|
+
attr_reader :publishing_class
|
|
4
|
+
attr_reader :publishing_table_name
|
|
5
|
+
|
|
6
|
+
def initialize(args, options = {})
|
|
7
|
+
klass = args.last
|
|
8
|
+
|
|
9
|
+
begin; valid_klass = klass.camelcase.constantize; rescue; end
|
|
10
|
+
|
|
11
|
+
if valid_klass
|
|
12
|
+
@publishing_table_name = klass.to_s.downcase.pluralize
|
|
13
|
+
@publishing_class = klass.to_s.capitalize
|
|
14
|
+
else
|
|
15
|
+
raise "#{klass} is not a valid class in this application."
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def manifest
|
|
22
|
+
record do |m|
|
|
23
|
+
unless options[:skip_migration]
|
|
24
|
+
m.migration_template 'migration.rb', 'db/migrate',
|
|
25
|
+
:migration_file_name => "add_published_as_to_#{@publishing_table_name}"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
protected
|
|
31
|
+
def usage
|
|
32
|
+
puts "Usage: #{$0} publishing [ModelName]"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class AddPublishedAsTo<%= publishing_class.pluralize %> < ActiveRecord::Migration
|
|
2
|
+
|
|
3
|
+
# Add the new tables.
|
|
4
|
+
def self.up
|
|
5
|
+
add_column :<%= publishing_table_name %>, :published_as, :string, :limit => 16, :default => 'draft'
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# Remove the tables.
|
|
9
|
+
def self.down
|
|
10
|
+
remove_column :<%= publishing_table_name %>, :published_as
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module Acts
|
|
2
|
+
module As
|
|
3
|
+
module Publishable
|
|
4
|
+
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.extend(ClassMethods)
|
|
7
|
+
|
|
8
|
+
# All ActiveRecords will now respond to publishable? with false
|
|
9
|
+
def publishable?; false; end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module ClassMethods
|
|
13
|
+
def acts_as_publishable(*args)
|
|
14
|
+
unless args.include?(:draft) && args.include?(:live)
|
|
15
|
+
raise "you must specify :draft and :live in list of publish_states for acts_as_publishable"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
cattr_accessor :publish_states
|
|
19
|
+
self.publish_states = args.collect{|state| state.to_s.downcase.to_sym }
|
|
20
|
+
include InstanceMethods
|
|
21
|
+
|
|
22
|
+
scope :live, where(:published_as => 'live')
|
|
23
|
+
scope :draft, where(:published_as => 'draft')
|
|
24
|
+
default_scope live
|
|
25
|
+
|
|
26
|
+
# class << self
|
|
27
|
+
# alias_method_chain :find, :published_as
|
|
28
|
+
# end
|
|
29
|
+
|
|
30
|
+
# create methods for each publish state
|
|
31
|
+
self.publish_states.each do |status|
|
|
32
|
+
|
|
33
|
+
define_method("is_#{status}?") do
|
|
34
|
+
self.published_as == status.to_s
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
define_method("save_as_#{status}") do
|
|
38
|
+
self.published_as = status.to_s
|
|
39
|
+
save
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# def find_with_published_as(*args)
|
|
46
|
+
# # hacked to filter out unpublished items by default, when using find(:all)
|
|
47
|
+
# # to really find all items, use Class.find_without_published_as
|
|
48
|
+
# state = args.first
|
|
49
|
+
# state = state.eql?(:all) ? :live : state
|
|
50
|
+
#
|
|
51
|
+
# if self.publish_states.include?(state)
|
|
52
|
+
# args.shift
|
|
53
|
+
# # find_all_by_published_as(state.to_s.downcase, *args)
|
|
54
|
+
# # again, hacked
|
|
55
|
+
# with_scope(:find => {:conditions => ["published_as = ?", state.to_s.downcase] }) do
|
|
56
|
+
# find_without_published_as(:all, *args)
|
|
57
|
+
# end
|
|
58
|
+
# else
|
|
59
|
+
# find_without_published_as(*args)
|
|
60
|
+
# end
|
|
61
|
+
# end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
module InstanceMethods
|
|
66
|
+
|
|
67
|
+
# All ActiveRecords using this plugin will now respond to publishable? with true
|
|
68
|
+
def publishable?; true; end
|
|
69
|
+
|
|
70
|
+
def publish(should_raise = false)
|
|
71
|
+
if defined?(:save_as_live)
|
|
72
|
+
save_as_live
|
|
73
|
+
else
|
|
74
|
+
raise "Add 'live' to list of acts_as_published for publish method" if should_raise
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Uninstall hook code here
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Example:
|
|
2
|
+
|
|
3
|
+
# Controller
|
|
4
|
+
class BlogController < ApplicationController
|
|
5
|
+
auto_complete_for :post, :title
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# View
|
|
9
|
+
<%= text_field_with_auto_complete :post, title %>
|
|
10
|
+
|
|
11
|
+
By default, auto_complete_for limits the results to 10 entries,
|
|
12
|
+
and sorts by the given field.
|
|
13
|
+
|
|
14
|
+
auto_complete_for takes a third parameter, an options hash to
|
|
15
|
+
the find method used to search for the records:
|
|
16
|
+
|
|
17
|
+
auto_complete_for :post, :title, :limit => 15, :order => 'created_at DESC'
|
|
18
|
+
|
|
19
|
+
For more examples, see script.aculo.us:
|
|
20
|
+
* http://script.aculo.us/demos/ajax/autocompleter
|
|
21
|
+
* http://script.aculo.us/demos/ajax/autocompleter_customized
|
|
22
|
+
|
|
23
|
+
Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'rake'
|
|
2
|
+
require 'rake/testtask'
|
|
3
|
+
require 'rake/rdoctask'
|
|
4
|
+
|
|
5
|
+
desc 'Default: run unit tests.'
|
|
6
|
+
task :default => :test
|
|
7
|
+
|
|
8
|
+
desc 'Test auto_complete plugin.'
|
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
|
10
|
+
t.libs << 'lib'
|
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
|
12
|
+
t.verbose = true
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
desc 'Generate documentation for auto_complete plugin.'
|
|
16
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
18
|
+
rdoc.title = 'Auto Complete'
|
|
19
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
|
20
|
+
rdoc.rdoc_files.include('README')
|
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
22
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module AutoComplete
|
|
2
|
+
|
|
3
|
+
def self.included(base)
|
|
4
|
+
base.extend(ClassMethods)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
#
|
|
8
|
+
# Example:
|
|
9
|
+
#
|
|
10
|
+
# # Controller
|
|
11
|
+
# class BlogController < ApplicationController
|
|
12
|
+
# auto_complete_for :post, :title
|
|
13
|
+
# end
|
|
14
|
+
#
|
|
15
|
+
# # View
|
|
16
|
+
# <%= text_field_with_auto_complete :post, title %>
|
|
17
|
+
#
|
|
18
|
+
# By default, auto_complete_for limits the results to 10 entries,
|
|
19
|
+
# and sorts by the given field.
|
|
20
|
+
#
|
|
21
|
+
# auto_complete_for takes a third parameter, an options hash to
|
|
22
|
+
# the find method used to search for the records:
|
|
23
|
+
#
|
|
24
|
+
# auto_complete_for :post, :title, :limit => 15, :order => 'created_at DESC'
|
|
25
|
+
#
|
|
26
|
+
# For help on defining text input fields with autocompletion,
|
|
27
|
+
# see ActionView::Helpers::JavaScriptHelper.
|
|
28
|
+
#
|
|
29
|
+
# For more examples, see script.aculo.us:
|
|
30
|
+
# * http://script.aculo.us/demos/ajax/autocompleter
|
|
31
|
+
# * http://script.aculo.us/demos/ajax/autocompleter_customized
|
|
32
|
+
module ClassMethods
|
|
33
|
+
def auto_complete_for(object, method, options = {})
|
|
34
|
+
define_method("auto_complete_for_#{object}_#{method}") do
|
|
35
|
+
find_options = {
|
|
36
|
+
:conditions => [ "LOWER(#{method}) LIKE ?", '%' + params[object][method].downcase + '%' ],
|
|
37
|
+
:order => "#{method} ASC",
|
|
38
|
+
:limit => 10 }.merge!(options)
|
|
39
|
+
|
|
40
|
+
@items = object.to_s.camelize.constantize.find(:all, find_options)
|
|
41
|
+
|
|
42
|
+
render :inline => "<%= auto_complete_result @items, '#{method}' %>"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
module AutoCompleteMacrosHelper
|
|
2
|
+
# Adds AJAX autocomplete functionality to the text input field with the
|
|
3
|
+
# DOM ID specified by +field_id+.
|
|
4
|
+
#
|
|
5
|
+
# This function expects that the called action returns an HTML <ul> list,
|
|
6
|
+
# or nothing if no entries should be displayed for autocompletion.
|
|
7
|
+
#
|
|
8
|
+
# You'll probably want to turn the browser's built-in autocompletion off,
|
|
9
|
+
# so be sure to include an <tt>autocomplete="off"</tt> attribute with your text
|
|
10
|
+
# input field.
|
|
11
|
+
#
|
|
12
|
+
# The autocompleter object is assigned to a Javascript variable named <tt>field_id</tt>_auto_completer.
|
|
13
|
+
# This object is useful if you for example want to trigger the auto-complete suggestions through
|
|
14
|
+
# other means than user input (for that specific case, call the <tt>activate</tt> method on that object).
|
|
15
|
+
#
|
|
16
|
+
# Required +options+ are:
|
|
17
|
+
# <tt>:url</tt>:: URL to call for autocompletion results
|
|
18
|
+
# in url_for format.
|
|
19
|
+
#
|
|
20
|
+
# Addtional +options+ are:
|
|
21
|
+
# <tt>:update</tt>:: Specifies the DOM ID of the element whose
|
|
22
|
+
# innerHTML should be updated with the autocomplete
|
|
23
|
+
# entries returned by the AJAX request.
|
|
24
|
+
# Defaults to <tt>field_id</tt> + '_auto_complete'
|
|
25
|
+
# <tt>:with</tt>:: A JavaScript expression specifying the
|
|
26
|
+
# parameters for the XMLHttpRequest. This defaults
|
|
27
|
+
# to 'fieldname=value'.
|
|
28
|
+
# <tt>:frequency</tt>:: Determines the time to wait after the last keystroke
|
|
29
|
+
# for the AJAX request to be initiated.
|
|
30
|
+
# <tt>:indicator</tt>:: Specifies the DOM ID of an element which will be
|
|
31
|
+
# displayed while autocomplete is running.
|
|
32
|
+
# <tt>:tokens</tt>:: A string or an array of strings containing
|
|
33
|
+
# separator tokens for tokenized incremental
|
|
34
|
+
# autocompletion. Example: <tt>:tokens => ','</tt> would
|
|
35
|
+
# allow multiple autocompletion entries, separated
|
|
36
|
+
# by commas.
|
|
37
|
+
# <tt>:min_chars</tt>:: The minimum number of characters that should be
|
|
38
|
+
# in the input field before an Ajax call is made
|
|
39
|
+
# to the server.
|
|
40
|
+
# <tt>:on_hide</tt>:: A Javascript expression that is called when the
|
|
41
|
+
# autocompletion div is hidden. The expression
|
|
42
|
+
# should take two variables: element and update.
|
|
43
|
+
# Element is a DOM element for the field, update
|
|
44
|
+
# is a DOM element for the div from which the
|
|
45
|
+
# innerHTML is replaced.
|
|
46
|
+
# <tt>:on_show</tt>:: Like on_hide, only now the expression is called
|
|
47
|
+
# then the div is shown.
|
|
48
|
+
# <tt>:after_update_element</tt>:: A Javascript expression that is called when the
|
|
49
|
+
# user has selected one of the proposed values.
|
|
50
|
+
# The expression should take two variables: element and value.
|
|
51
|
+
# Element is a DOM element for the field, value
|
|
52
|
+
# is the value selected by the user.
|
|
53
|
+
# <tt>:select</tt>:: Pick the class of the element from which the value for
|
|
54
|
+
# insertion should be extracted. If this is not specified,
|
|
55
|
+
# the entire element is used.
|
|
56
|
+
# <tt>:method</tt>:: Specifies the HTTP verb to use when the autocompletion
|
|
57
|
+
# request is made. Defaults to POST.
|
|
58
|
+
def auto_complete_field(field_id, options = {})
|
|
59
|
+
function = "var #{field_id}_auto_completer = new Ajax.Autocompleter("
|
|
60
|
+
function << "'#{field_id}', "
|
|
61
|
+
function << "'" + (options[:update] || "#{field_id}_auto_complete") + "', "
|
|
62
|
+
function << "'#{url_for(options[:url])}'"
|
|
63
|
+
|
|
64
|
+
js_options = {}
|
|
65
|
+
js_options[:tokens] = array_or_string_for_javascript(options[:tokens]) if options[:tokens]
|
|
66
|
+
js_options[:callback] = "function(element, value) { return #{options[:with]} }" if options[:with]
|
|
67
|
+
js_options[:indicator] = "'#{options[:indicator]}'" if options[:indicator]
|
|
68
|
+
js_options[:select] = "'#{options[:select]}'" if options[:select]
|
|
69
|
+
js_options[:paramName] = "'#{options[:param_name]}'" if options[:param_name]
|
|
70
|
+
js_options[:frequency] = "#{options[:frequency]}" if options[:frequency]
|
|
71
|
+
js_options[:method] = "'#{options[:method].to_s}'" if options[:method]
|
|
72
|
+
|
|
73
|
+
{ :after_update_element => :afterUpdateElement,
|
|
74
|
+
:on_show => :onShow, :on_hide => :onHide, :min_chars => :minChars }.each do |k,v|
|
|
75
|
+
js_options[v] = options[k] if options[k]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
function << (', ' + options_for_javascript(js_options) + ')')
|
|
79
|
+
|
|
80
|
+
javascript_tag(function)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Use this method in your view to generate a return for the AJAX autocomplete requests.
|
|
84
|
+
#
|
|
85
|
+
# Example action:
|
|
86
|
+
#
|
|
87
|
+
# def auto_complete_for_item_title
|
|
88
|
+
# @items = Item.find(:all,
|
|
89
|
+
# :conditions => [ 'LOWER(description) LIKE ?',
|
|
90
|
+
# '%' + request.raw_post.downcase + '%' ])
|
|
91
|
+
# render :inline => "<%= auto_complete_result(@items, 'description') %>"
|
|
92
|
+
# end
|
|
93
|
+
#
|
|
94
|
+
# The auto_complete_result can of course also be called from a view belonging to the
|
|
95
|
+
# auto_complete action if you need to decorate it further.
|
|
96
|
+
def auto_complete_result(entries, field, phrase = nil)
|
|
97
|
+
return unless entries
|
|
98
|
+
items = entries.map { |entry| content_tag("li", phrase ? highlight(entry[field], phrase) : h(entry[field])) }
|
|
99
|
+
content_tag("ul", items.uniq)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Wrapper for text_field with added AJAX autocompletion functionality.
|
|
103
|
+
#
|
|
104
|
+
# In your controller, you'll need to define an action called
|
|
105
|
+
# auto_complete_for to respond the AJAX calls,
|
|
106
|
+
#
|
|
107
|
+
def text_field_with_auto_complete(object, method, tag_options = {}, completion_options = {})
|
|
108
|
+
(completion_options[:skip_style] ? "" : auto_complete_stylesheet) +
|
|
109
|
+
text_field(object, method, tag_options) +
|
|
110
|
+
content_tag("div", "", :id => "#{object}_#{method}_auto_complete", :class => "auto_complete") +
|
|
111
|
+
auto_complete_field("#{object}_#{method}", { :url => { :action => "auto_complete_for_#{object}_#{method}" } }.update(completion_options))
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
private
|
|
115
|
+
def auto_complete_stylesheet
|
|
116
|
+
content_tag('style', <<-EOT, :type => Mime::CSS)
|
|
117
|
+
div.auto_complete {
|
|
118
|
+
width: 350px;
|
|
119
|
+
background: #fff;
|
|
120
|
+
}
|
|
121
|
+
div.auto_complete ul {
|
|
122
|
+
border:1px solid #888;
|
|
123
|
+
margin:0;
|
|
124
|
+
padding:0;
|
|
125
|
+
width:100%;
|
|
126
|
+
list-style-type:none;
|
|
127
|
+
}
|
|
128
|
+
div.auto_complete ul li {
|
|
129
|
+
margin:0;
|
|
130
|
+
padding:3px;
|
|
131
|
+
}
|
|
132
|
+
div.auto_complete ul li.selected {
|
|
133
|
+
background-color: #ffb;
|
|
134
|
+
}
|
|
135
|
+
div.auto_complete ul strong.highlight {
|
|
136
|
+
color: #800;
|
|
137
|
+
margin:0;
|
|
138
|
+
padding:0;
|
|
139
|
+
}
|
|
140
|
+
EOT
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../../../../test/test_helper'))
|
|
2
|
+
|
|
3
|
+
class AutoCompleteTest < Test::Unit::TestCase
|
|
4
|
+
include AutoComplete
|
|
5
|
+
include AutoCompleteMacrosHelper
|
|
6
|
+
|
|
7
|
+
include ActionView::Helpers::UrlHelper
|
|
8
|
+
include ActionView::Helpers::TagHelper
|
|
9
|
+
include ActionView::Helpers::TextHelper
|
|
10
|
+
include ActionView::Helpers::FormHelper
|
|
11
|
+
include ActionView::Helpers::CaptureHelper
|
|
12
|
+
|
|
13
|
+
def setup
|
|
14
|
+
@controller = Class.new do
|
|
15
|
+
def url_for(options)
|
|
16
|
+
url = "http://www.example.com/"
|
|
17
|
+
url << options[:action].to_s if options and options[:action]
|
|
18
|
+
url
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
@controller = @controller.new
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_auto_complete_field
|
|
26
|
+
assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {})\n//]]>\n</script>),
|
|
27
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" });
|
|
28
|
+
assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {tokens:','})\n//]]>\n</script>),
|
|
29
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :tokens => ',');
|
|
30
|
+
assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {tokens:[',']})\n//]]>\n</script>),
|
|
31
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :tokens => [',']);
|
|
32
|
+
assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {minChars:3})\n//]]>\n</script>),
|
|
33
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :min_chars => 3);
|
|
34
|
+
assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {onHide:function(element, update){alert('me');}})\n//]]>\n</script>),
|
|
35
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :on_hide => "function(element, update){alert('me');}");
|
|
36
|
+
assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {frequency:2})\n//]]>\n</script>),
|
|
37
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :frequency => 2);
|
|
38
|
+
assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {afterUpdateElement:function(element,value){alert('You have chosen: '+value)}})\n//]]>\n</script>),
|
|
39
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" },
|
|
40
|
+
:after_update_element => "function(element,value){alert('You have chosen: '+value)}");
|
|
41
|
+
assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {paramName:'huidriwusch'})\n//]]>\n</script>),
|
|
42
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :param_name => 'huidriwusch');
|
|
43
|
+
assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {method:'get'})\n//]]>\n</script>),
|
|
44
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :method => :get);
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def test_auto_complete_result
|
|
48
|
+
result = [ { :title => 'test1' }, { :title => 'test2' } ]
|
|
49
|
+
assert_equal %(<ul><li>test1</li><li>test2</li></ul>),
|
|
50
|
+
auto_complete_result(result, :title)
|
|
51
|
+
assert_equal %(<ul><li>t<strong class=\"highlight\">est</strong>1</li><li>t<strong class=\"highlight\">est</strong>2</li></ul>),
|
|
52
|
+
auto_complete_result(result, :title, "est")
|
|
53
|
+
|
|
54
|
+
resultuniq = [ { :title => 'test1' }, { :title => 'test1' } ]
|
|
55
|
+
assert_equal %(<ul><li>t<strong class=\"highlight\">est</strong>1</li></ul>),
|
|
56
|
+
auto_complete_result(resultuniq, :title, "est")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_text_field_with_auto_complete
|
|
60
|
+
assert_match %(<style type="text/css">),
|
|
61
|
+
text_field_with_auto_complete(:message, :recipient)
|
|
62
|
+
|
|
63
|
+
assert_dom_equal %(<input id=\"message_recipient\" name=\"message[recipient]\" size=\"30\" type=\"text\" /><div class=\"auto_complete\" id=\"message_recipient_auto_complete\"></div><script type=\"text/javascript\">\n//<![CDATA[\nvar message_recipient_auto_completer = new Ajax.Autocompleter('message_recipient', 'message_recipient_auto_complete', 'http://www.example.com/auto_complete_for_message_recipient', {})\n//]]>\n</script>),
|
|
64
|
+
text_field_with_auto_complete(:message, :recipient, {}, :skip_style => true)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2005 Trevor Squires
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject
|
|
9
|
+
to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
17
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
|
18
|
+
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
19
|
+
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
Enumerations Mixin
|
|
2
|
+
Copyright (c) 2005 Trevor Squires
|
|
3
|
+
Released under the MIT License. See the LICENSE file for more details.
|
|
4
|
+
|
|
5
|
+
What is this?:
|
|
6
|
+
|
|
7
|
+
The enumerations mixin allows you to treat instances of your
|
|
8
|
+
ActiveRecord models as though they were an enumeration of values.
|
|
9
|
+
|
|
10
|
+
At it's most basic level, it allows you to say things along the lines of:
|
|
11
|
+
|
|
12
|
+
booking = Booking.new(:status => BookingStatus[:provisional])
|
|
13
|
+
booking.update_attribute(:status, BookingStatus[:confirmed])
|
|
14
|
+
|
|
15
|
+
Booking.find :first,
|
|
16
|
+
:conditions => ['status_id = ?', BookingStatus[:provisional].id]
|
|
17
|
+
|
|
18
|
+
BookingStatus.all.collect {|status|, [status.name, status.id]}
|
|
19
|
+
|
|
20
|
+
See "How to use it" below for more information.
|
|
21
|
+
|
|
22
|
+
Package Contents:
|
|
23
|
+
|
|
24
|
+
This package adds two mixins and a helper to Rails' ActiveRecord:
|
|
25
|
+
|
|
26
|
+
acts_as_enumerated provides capabilities to treat your model and
|
|
27
|
+
its records as an enumeration. At a minimum, the database table for
|
|
28
|
+
an acts_as_enumerated must contain an 'id' column and a 'name'
|
|
29
|
+
column. All instances for the acts_as_enumerated model are cached
|
|
30
|
+
in memory.
|
|
31
|
+
|
|
32
|
+
has_enumerated adds methods to your ActiveRecord model for setting
|
|
33
|
+
and retrieving enumerated values using an associated acts_as_enumerated
|
|
34
|
+
model.
|
|
35
|
+
|
|
36
|
+
There is also an ActiveRecord::VirtualEnumerations helper module
|
|
37
|
+
to create 'virtual' acts_as_enumerated models which helps to avoid
|
|
38
|
+
cluttering up your models directory with acts_as_enumerated classes.
|
|
39
|
+
|
|
40
|
+
How to use it:
|
|
41
|
+
|
|
42
|
+
* acts_as_enumerated
|
|
43
|
+
|
|
44
|
+
class BookingStatus < ActiveRecord::Base
|
|
45
|
+
acts_as_enumerated :conditions => 'optional_sql_conditions',
|
|
46
|
+
:order => 'optional_sql_orderby',
|
|
47
|
+
:on_lookup_failure => :optional_class_method
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
With that, your BookingStatus class will have the following methods defined:
|
|
51
|
+
|
|
52
|
+
* BookingStatus[arg] : lookup the BookingStatus instance for arg.
|
|
53
|
+
The arg value can be a 'string' or a :symbol, in which case the
|
|
54
|
+
lookup will be against the BookingStatus.name field. Alternatively
|
|
55
|
+
arg can be a Fixnum, in which case the lookup will be against the
|
|
56
|
+
BookingStatus.id field.
|
|
57
|
+
|
|
58
|
+
The :on_lookup_failure option specifies the name of a class method
|
|
59
|
+
to invoke when the [] method is unable to locate a BookingStatus
|
|
60
|
+
record for arg. The defeault is the built-in :enforce_strict_literals
|
|
61
|
+
which causes an exception to be raised when no record is found and
|
|
62
|
+
the arg is a Fixnum or Symbol, otherwise it returns nil. There are
|
|
63
|
+
also built-ins for :enforce_strict (raise and exception regardless
|
|
64
|
+
of the type for arg) and :enforce_none which just returns nil.
|
|
65
|
+
|
|
66
|
+
The whole point of the :on_lookup_failure option is that I'm pretty
|
|
67
|
+
opinionated that a) if the value can't be looked-up for a :symbol
|
|
68
|
+
that I've passed, it's probably a typo so I want a *big* hint that
|
|
69
|
+
something is wrong and b) it's likely that my opinion isn't shared
|
|
70
|
+
by everyone so it should be configurable.
|
|
71
|
+
|
|
72
|
+
* BookingStatus.all : returns an array of all BookingStatus records
|
|
73
|
+
that match the :conditions specified in acts_as_enumerated, in the
|
|
74
|
+
order specified by :order.
|
|
75
|
+
|
|
76
|
+
NOTE: acts_as_enumerated records are considered immutable. By
|
|
77
|
+
default you cannot create/alter/destroy instances because they are
|
|
78
|
+
cached in memory. Because of Rails' process-based model it is not
|
|
79
|
+
safe to allow updating acts_as_enumerated records as the caches
|
|
80
|
+
will get out of sync.
|
|
81
|
+
|
|
82
|
+
However, one instance where updating the models *should* be allowed
|
|
83
|
+
is if you are using ActiveRecord Migrations.
|
|
84
|
+
|
|
85
|
+
Using the above example you would do the following:
|
|
86
|
+
|
|
87
|
+
BookingStatus.enumeration_model_updates_permitted = true
|
|
88
|
+
BookingStatus.create(:name => 'newname')
|
|
89
|
+
|
|
90
|
+
* has_enumerated
|
|
91
|
+
|
|
92
|
+
First of all, note that you *could* specify the relationship
|
|
93
|
+
to an acts_as_enumerated class using the belongs_to association.
|
|
94
|
+
However, has_enumerated is preferable because you aren't really
|
|
95
|
+
associated to the enumerated value, you are *aggregating* it.
|
|
96
|
+
As such, the has_enumerated macro behaves more like an aggregation
|
|
97
|
+
than an association.
|
|
98
|
+
|
|
99
|
+
class Booking < ActiveRecord::Base
|
|
100
|
+
has_enumerated :status, :class_name => 'BookingStatus',
|
|
101
|
+
:foreign_key => 'status_id',
|
|
102
|
+
:on_lookup_failure => :optional_instance_method
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
By default, the foreign key is interpreted to be the name of your
|
|
106
|
+
has_enumerated field (in this case 'status') plus '_id'. Additionally,
|
|
107
|
+
the default value for :class_name is the camel-ized version of the
|
|
108
|
+
name for your has_enumerated field. :on_lookup_failure is explained
|
|
109
|
+
below.
|
|
110
|
+
|
|
111
|
+
With that, your Booking class will have the following methods defined:
|
|
112
|
+
|
|
113
|
+
* status : returns the BookingStatus with an id that matches the
|
|
114
|
+
value in the Booking.status_id.
|
|
115
|
+
|
|
116
|
+
* status= : sets the value for Booking.status_id using the id of
|
|
117
|
+
the BookingStatus instance passed as an argument. As a short-hand,
|
|
118
|
+
you can also pass it the 'name' of a BookingStatus instance, either
|
|
119
|
+
as a 'string' or :symbol.
|
|
120
|
+
|
|
121
|
+
I.e. mybooking.status = :confirmed or mybooking.update_attribute(:status,
|
|
122
|
+
:confirmed)
|
|
123
|
+
|
|
124
|
+
The :on_lookup_failure option in has_enumerated is there because
|
|
125
|
+
(again) I'm opinionated about what should happen. By default, if
|
|
126
|
+
booking.status_id contains an id that isn't a valid BookingStatus.id
|
|
127
|
+
I just want booking.status to return nil rather than throw an
|
|
128
|
+
exception. This ensures I can edit my Booking instances without
|
|
129
|
+
having to put rescue blocks around all my booking.status calls.
|
|
130
|
+
However, if I call booking.status = :bogus I want noisy hints about
|
|
131
|
+
the bug.
|
|
132
|
+
|
|
133
|
+
Of course, you may not agree with that in which case you can specify
|
|
134
|
+
an *instance* method to be called in the case of a lookup failure.
|
|
135
|
+
The method signature is as follows:
|
|
136
|
+
|
|
137
|
+
your_lookup_handler(operation, name, name_foreign_key,
|
|
138
|
+
acts_enumerated_class_name, lookup_value)
|
|
139
|
+
|
|
140
|
+
The 'operation' arg will be either :read or :write. In the case
|
|
141
|
+
of :read you are expected to return something or raise an exception,
|
|
142
|
+
while in the case of a :write you don't have to return anything.
|
|
143
|
+
|
|
144
|
+
Note that there's enough information in the method signature that
|
|
145
|
+
you can specify one method to handle all lookup failures for all
|
|
146
|
+
has_enumerated fields if you happen to have more than one defined
|
|
147
|
+
in your model.
|
|
148
|
+
|
|
149
|
+
* ActiveRecord::VirtualEnumerations
|
|
150
|
+
|
|
151
|
+
For the most part, your acts_as_enumerated classes will do nothing
|
|
152
|
+
more than just act as enumerated.
|
|
153
|
+
|
|
154
|
+
In that case there isn't much point cluttering up your models
|
|
155
|
+
directory with those class files. You can use
|
|
156
|
+
ActiveRecord::VirtualEnumerations to reduce that clutter.
|
|
157
|
+
|
|
158
|
+
Copy virtual_enumerations_sample.rb to
|
|
159
|
+
Rails.root/config/virtual_enumerations.rb and configure it accordingly.
|
|
160
|
+
|
|
161
|
+
See virtual_enumerations_sample.rb in this directory for a full
|
|
162
|
+
description.
|
|
163
|
+
|