Changesets can be listed by changeset number.
The Git repository is here.
Changeset 15
Attempt to update Typo to a Typo SVN HEAD release from around the
time the prototype installation was set up on the RISC OS Open Limited
web site. Timestamps place this at 04-Jul so a revision from 05-Jul or
earlier was pulled and copied over the 2.6.0 tarball stable code.
- Comitted by: adh
- Date: Saturday July 22 23:27:35 2006 (over 18 years ago)
Affected files:
- rool/rails/typo/trunk/app/views/admin/comments/show.rhtml (diff)
- rool/rails/typo/trunk/app/models/content_state/factory.rb
- rool/rails/typo/trunk/app/helpers/sidebars/
- rool/rails/typo/trunk/app/models/content_state/
- rool/rails/typo/trunk/app/models/content_state/state/
- rool/rails/typo/trunk/app/views/admin/resources/
- rool/rails/typo/trunk/app/views/admin/textfilters/
- rool/rails/typo/trunk/app/views/admin/trackbacks/
- rool/rails/typo/trunk/app/views/notification_mailer/
- rool/rails/typo/trunk/app/views/redirect/
- rool/rails/typo/trunk/app/views/sidebar/
- rool/rails/typo/trunk/app/views/textfilter/
- rool/rails/typo/trunk/components/plugins/sidebars/aimpresence/
- rool/rails/typo/trunk/components/plugins/sidebars/amazon/
- rool/rails/typo/trunk/components/plugins/sidebars/audioscrobbler/
- rool/rails/typo/trunk/components/plugins/sidebars/backpack/
- rool/rails/typo/trunk/components/plugins/sidebars/magnolia/
- rool/rails/typo/trunk/components/plugins/sidebars/recent_comments/
- rool/rails/typo/trunk/components/plugins/sidebars/tag/
- rool/rails/typo/trunk/components/plugins/sidebars/xbox/
- rool/rails/typo/trunk/components/plugins/textfilters/
- rool/rails/typo/trunk/lib/generators/
- rool/rails/typo/trunk/lib/generators/sidebar/
- rool/rails/typo/trunk/lib/generators/sidebar/templates/
- rool/rails/typo/trunk/lib/generators/sidebar/templates/components/
- rool/rails/typo/trunk/lib/generators/sidebar/templates/components/plugins/
- rool/rails/typo/trunk/lib/generators/sidebar/templates/components/plugins/sidebars/
- rool/rails/typo/trunk/lib/generators/sidebar/templates/components/plugins/sidebars/views/
- rool/rails/typo/trunk/lib/rails_patch/
- rool/rails/typo/trunk/lib/sidebars/
- rool/rails/typo/trunk/lib/tasks/
- rool/rails/typo/trunk/script/performance/
- rool/rails/typo/trunk/test/fixtures/notification_mailer/
- rool/rails/typo/trunk/test/unit/content_state/
- rool/rails/typo/trunk/tmp/
- rool/rails/typo/trunk/tmp/cache/
- rool/rails/typo/trunk/tmp/sessions/
- rool/rails/typo/trunk/tmp/sockets/
- rool/rails/typo/trunk/vendor/flickr/
- rool/rails/typo/trunk/vendor/jabber4r/
- rool/rails/typo/trunk/vendor/jabber4r/lib/
- rool/rails/typo/trunk/vendor/jabber4r/lib/jabber4r/
- rool/rails/typo/trunk/vendor/plugins/
- rool/rails/typo/trunk/vendor/plugins/expiring_action_cache/
- rool/rails/typo/trunk/vendor/plugins/expiring_action_cache/lib/
- rool/rails/typo/trunk/vendor/plugins/upload_progress/
- rool/rails/typo/trunk/vendor/plugins/upload_progress/lib/
- rool/rails/typo/trunk/vendor/plugins/upload_progress/public/
- rool/rails/typo/trunk/vendor/plugins/upload_progress/public/stylesheets/
- rool/rails/typo/trunk/vendor/plugins/upload_progress/test/
- rool/rails/typo/trunk/vendor/rails/actionmailer/test/fixtures/path.with.dots/
- rool/rails/typo/trunk/vendor/rails/actionpack/test/activerecord/
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/db_definitions/
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/layout_tests/
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/layout_tests/layouts/
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/layout_tests/layouts/controller_name_space/
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/layout_tests/views/
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/public/
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/public/images/
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/respond_to/
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/respond_to/layouts/
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/test/dot.directory/
- rool/rails/typo/trunk/vendor/rails/actionwebservice/test/fixtures/
- rool/rails/typo/trunk/vendor/rails/actionwebservice/test/fixtures/db_definitions/
- rool/rails/typo/trunk/vendor/rails/activerecord/test/connections/native_openbase/
- rool/rails/typo/trunk/vendor/rails/activerecord/test/connections/native_oracle/
- rool/rails/typo/trunk/vendor/rails/activerecord/test/connections/native_sybase/
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/categories/
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/categories/subsubdir/
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/class/
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/kernel/
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/module/
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/object/
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/pathname/
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/json/
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/json/encoders/
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/vendor/
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/vendor/builder/
- rool/rails/typo/trunk/vendor/rails/activesupport/test/autoloading_fixtures/
- rool/rails/typo/trunk/vendor/rails/activesupport/test/autoloading_fixtures/a/
- rool/rails/typo/trunk/vendor/rails/activesupport/test/autoloading_fixtures/a/c/
- rool/rails/typo/trunk/vendor/rails/activesupport/test/autoloading_fixtures/a/c/e/
- rool/rails/typo/trunk/vendor/rails/activesupport/test/autoloading_fixtures/module_folder/
- rool/rails/typo/trunk/vendor/rails/railties/builtin/rails_info/
- rool/rails/typo/trunk/vendor/rails/railties/builtin/rails_info/rails/
- rool/rails/typo/trunk/vendor/rails/railties/configs/databases/
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails/
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/integration_test/
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/integration_test/templates/
- rool/rails/typo/trunk/vendor/sparklines/
- rool/rails/typo/trunk/vendor/sparklines/lib/
- rool/rails/typo/trunk/vendor/sparklines/samples/
- rool/rails/typo/trunk/vendor/sparklines/templates/
- rool/rails/typo/trunk/vendor/syntax/
- rool/rails/typo/trunk/vendor/syntax/api/
- rool/rails/typo/trunk/vendor/syntax/api/classes/
- rool/rails/typo/trunk/vendor/syntax/api/classes/Syntax/
- rool/rails/typo/trunk/vendor/syntax/api/classes/Syntax/Convertors/
- rool/rails/typo/trunk/vendor/syntax/api/files/
- rool/rails/typo/trunk/vendor/syntax/api/files/lib/
- rool/rails/typo/trunk/vendor/syntax/api/files/lib/syntax/
- rool/rails/typo/trunk/vendor/syntax/api/files/lib/syntax/convertors/
- rool/rails/typo/trunk/vendor/syntax/api/files/lib/syntax/lang/
- rool/rails/typo/trunk/vendor/syntax/doc/
- rool/rails/typo/trunk/vendor/syntax/doc/manual-html/
- rool/rails/typo/trunk/vendor/syntax/doc/manual-html/stylesheets/
- rool/rails/typo/trunk/vendor/syntax/doc/manual/
- rool/rails/typo/trunk/vendor/syntax/doc/manual/parts/
- rool/rails/typo/trunk/vendor/syntax/doc/manual/stylesheets/
- rool/rails/typo/trunk/vendor/syntax/lib/
- rool/rails/typo/trunk/vendor/syntax/lib/syntax/
- rool/rails/typo/trunk/vendor/syntax/lib/syntax/convertors/
- rool/rails/typo/trunk/vendor/syntax/lib/syntax/lang/
- rool/rails/typo/trunk/vendor/syntax/test/
- rool/rails/typo/trunk/vendor/syntax/test/syntax/
- rool/rails/typo/trunk/vendor/uuidtools/
- rool/rails/typo/trunk/vendor/uuidtools/lib/
- rool/rails/typo/trunk/MAINTAINERS
- rool/rails/typo/trunk/app/controllers/admin/resources_controller.rb
- rool/rails/typo/trunk/app/controllers/admin/textfilters_controller.rb
- rool/rails/typo/trunk/app/controllers/content_controller.rb
- rool/rails/typo/trunk/app/controllers/redirect_controller.rb
- rool/rails/typo/trunk/app/controllers/sidebar_controller.rb
- rool/rails/typo/trunk/app/controllers/textfilter_controller.rb
- rool/rails/typo/trunk/app/helpers/admin/blacklist_helper.rb
- rool/rails/typo/trunk/app/helpers/admin/cache_helper.rb
- rool/rails/typo/trunk/app/helpers/admin/comments_helper.rb
- rool/rails/typo/trunk/app/helpers/admin/content_helper.rb
- rool/rails/typo/trunk/app/helpers/admin/general_helper.rb
- rool/rails/typo/trunk/app/helpers/admin/pages_helper.rb
- rool/rails/typo/trunk/app/helpers/admin/resources_helper.rb
- rool/rails/typo/trunk/app/helpers/admin/sidebar_helper.rb
- rool/rails/typo/trunk/app/helpers/admin/textfilters_helper.rb
- rool/rails/typo/trunk/app/helpers/admin/trackbacks_helper.rb
- rool/rails/typo/trunk/app/helpers/admin/users_helper.rb
- rool/rails/typo/trunk/app/helpers/content_helper.rb
- rool/rails/typo/trunk/app/helpers/mail_helper.rb
- rool/rails/typo/trunk/app/helpers/redirect_helper.rb
- rool/rails/typo/trunk/app/helpers/sidebar_helper.rb
- rool/rails/typo/trunk/app/helpers/sidebars/plugin_helper.rb
- rool/rails/typo/trunk/app/helpers/text_filter_plugin_helper.rb
- rool/rails/typo/trunk/app/helpers/textfilter_helper.rb
- rool/rails/typo/trunk/app/helpers/theme_helper.rb
- rool/rails/typo/trunk/app/models/aggregations/audioscrobbler.rb
- rool/rails/typo/trunk/app/models/aggregations/backpack.rb
- rool/rails/typo/trunk/app/models/aggregations/magnolia.rb
- rool/rails/typo/trunk/app/models/blog.rb
- rool/rails/typo/trunk/app/models/content.rb
- rool/rails/typo/trunk/app/models/content_observer.rb
- rool/rails/typo/trunk/app/models/content_state/base.rb
- rool/rails/typo/trunk/app/models/content_state/draft.rb
- rool/rails/typo/trunk/app/models/content_state/just_published.rb
- rool/rails/typo/trunk/app/models/content_state/new.rb
- rool/rails/typo/trunk/app/models/content_state/publication_pending.rb
- rool/rails/typo/trunk/app/models/content_state/published.rb
- rool/rails/typo/trunk/app/models/email_notifier.rb
- rool/rails/typo/trunk/app/models/notification_mailer.rb
- rool/rails/typo/trunk/app/models/redirect.rb
- rool/rails/typo/trunk/app/models/tag.rb
- rool/rails/typo/trunk/app/models/text_filter.rb
- rool/rails/typo/trunk/app/models/trigger.rb
- rool/rails/typo/trunk/app/models/web_notifier.rb
- rool/rails/typo/trunk/app/views/admin/categories/reorder.rhtml
- rool/rails/typo/trunk/app/views/admin/content/_attachment.rhtml
- rool/rails/typo/trunk/app/views/admin/content/_show_categories.rhtml
- rool/rails/typo/trunk/app/views/admin/content/_show_resources.rhtml
- rool/rails/typo/trunk/app/views/admin/resources/_itunes_category_add.rhtml
- rool/rails/typo/trunk/app/views/admin/resources/_itunes_category_edit.rhtml
- rool/rails/typo/trunk/app/views/admin/resources/_metadata_add.rhtml
- rool/rails/typo/trunk/app/views/admin/resources/_metadata_edit.rhtml
- rool/rails/typo/trunk/app/views/admin/resources/_mime_edit.rhtml
- rool/rails/typo/trunk/app/views/admin/resources/_pages.rhtml
- rool/rails/typo/trunk/app/views/admin/resources/_resources.rhtml
- rool/rails/typo/trunk/app/views/admin/resources/destroy.rhtml
- rool/rails/typo/trunk/app/views/admin/resources/list.rhtml
- rool/rails/typo/trunk/app/views/admin/resources/new.rhtml
- rool/rails/typo/trunk/app/views/admin/sidebar/_target.rhtml
- rool/rails/typo/trunk/app/views/admin/sidebar/publish.rjs
- rool/rails/typo/trunk/app/views/admin/sidebar/remove.rjs
- rool/rails/typo/trunk/app/views/admin/sidebar/set_active.rjs
- rool/rails/typo/trunk/app/views/admin/textfilters/_form.rhtml
- rool/rails/typo/trunk/app/views/admin/textfilters/_macros.rhtml
- rool/rails/typo/trunk/app/views/admin/textfilters/_textfilters.rhtml
- rool/rails/typo/trunk/app/views/admin/textfilters/destroy.rhtml
- rool/rails/typo/trunk/app/views/admin/textfilters/edit.rhtml
- rool/rails/typo/trunk/app/views/admin/textfilters/list.rhtml
- rool/rails/typo/trunk/app/views/admin/textfilters/macro_help.rhtml
- rool/rails/typo/trunk/app/views/admin/textfilters/new.rhtml
- rool/rails/typo/trunk/app/views/admin/textfilters/preview.rhtml
- rool/rails/typo/trunk/app/views/admin/textfilters/show.rhtml
- rool/rails/typo/trunk/app/views/admin/textfilters/show_help.rhtml
- rool/rails/typo/trunk/app/views/admin/trackbacks/_form.rhtml
- rool/rails/typo/trunk/app/views/admin/trackbacks/destroy.rhtml
- rool/rails/typo/trunk/app/views/admin/trackbacks/edit.rhtml
- rool/rails/typo/trunk/app/views/admin/trackbacks/list.rhtml
- rool/rails/typo/trunk/app/views/admin/trackbacks/new.rhtml
- rool/rails/typo/trunk/app/views/admin/trackbacks/show.rhtml
- rool/rails/typo/trunk/app/views/articles/comment_preview.rhtml
- rool/rails/typo/trunk/app/views/articles/groupings.rhtml
- rool/rails/typo/trunk/app/views/layouts/sidebar.rhtml
- rool/rails/typo/trunk/app/views/notification_mailer/_mail_footer.rhtml
- rool/rails/typo/trunk/app/views/notification_mailer/_mail_header.rhtml
- rool/rails/typo/trunk/app/views/notification_mailer/article.rhtml
- rool/rails/typo/trunk/app/views/notification_mailer/comment.rhtml
- rool/rails/typo/trunk/app/views/notification_mailer/trackback.rhtml
- rool/rails/typo/trunk/app/views/sidebar/_row.rhtml
- rool/rails/typo/trunk/app/views/sidebar/_sidebar.rhtml
- rool/rails/typo/trunk/app/views/sidebar/display_plugins.rhtml
- rool/rails/typo/trunk/app/views/sidebar/show.rhtml
- rool/rails/typo/trunk/app/views/xml/_atom10_item_article.rxml
- rool/rails/typo/trunk/app/views/xml/_atom10_item_comment.rxml
- rool/rails/typo/trunk/app/views/xml/_atom10_item_trackback.rxml
- rool/rails/typo/trunk/app/views/xml/_itunes_item_resource.rxml
- rool/rails/typo/trunk/app/views/xml/_rss20_item_article.rxml
- rool/rails/typo/trunk/app/views/xml/_rss20_item_comment.rxml
- rool/rails/typo/trunk/app/views/xml/_rss20_item_trackback.rxml
- rool/rails/typo/trunk/app/views/xml/atom10_feed.rxml
- rool/rails/typo/trunk/app/views/xml/itunes_feed.rxml
- rool/rails/typo/trunk/app/views/xml/rss20_feed.rxml
- rool/rails/typo/trunk/components/plugins/sidebars/aimpresence/content.rhtml
- rool/rails/typo/trunk/components/plugins/sidebars/aimpresence_controller.rb
- rool/rails/typo/trunk/components/plugins/sidebars/amazon/content.rhtml
- rool/rails/typo/trunk/components/plugins/sidebars/amazon_controller.rb
- rool/rails/typo/trunk/components/plugins/sidebars/audioscrobbler/content.rhtml
- rool/rails/typo/trunk/components/plugins/sidebars/audioscrobbler_controller.rb
- rool/rails/typo/trunk/components/plugins/sidebars/backpack/content.rhtml
- rool/rails/typo/trunk/components/plugins/sidebars/backpack_controller.rb
- rool/rails/typo/trunk/components/plugins/sidebars/magnolia/content.rhtml
- rool/rails/typo/trunk/components/plugins/sidebars/magnolia_controller.rb
- rool/rails/typo/trunk/components/plugins/sidebars/recent_comments/content.rhtml
- rool/rails/typo/trunk/components/plugins/sidebars/recent_comments_controller.rb
- rool/rails/typo/trunk/components/plugins/sidebars/tag/content.rhtml
- rool/rails/typo/trunk/components/plugins/sidebars/tag_controller.rb
- rool/rails/typo/trunk/components/plugins/sidebars/xbox/content.rhtml
- rool/rails/typo/trunk/components/plugins/sidebars/xbox_controller.rb
- rool/rails/typo/trunk/components/plugins/textfilters/amazon_controller.rb
- rool/rails/typo/trunk/components/plugins/textfilters/code_controller.rb
- rool/rails/typo/trunk/components/plugins/textfilters/flickr_controller.rb
- rool/rails/typo/trunk/components/plugins/textfilters/htmlfilter_controller.rb
- rool/rails/typo/trunk/components/plugins/textfilters/lightbox_controller.rb
- rool/rails/typo/trunk/components/plugins/textfilters/macropost_controller.rb
- rool/rails/typo/trunk/components/plugins/textfilters/macropre_controller.rb
- rool/rails/typo/trunk/components/plugins/textfilters/markdown_controller.rb
- rool/rails/typo/trunk/components/plugins/textfilters/none_controller.rb
- rool/rails/typo/trunk/components/plugins/textfilters/smartypants_controller.rb
- rool/rails/typo/trunk/components/plugins/textfilters/sparkline_controller.rb
- rool/rails/typo/trunk/components/plugins/textfilters/textile_controller.rb
- rool/rails/typo/trunk/config/boot.rb
- rool/rails/typo/trunk/config/database.yml.sqlite
- rool/rails/typo/trunk/config/iTunes.yml
- rool/rails/typo/trunk/config/mail.yml.example
- rool/rails/typo/trunk/db/converters/README
- rool/rails/typo/trunk/db/converters/feed.rb
- rool/rails/typo/trunk/db/migrate/001_initial_schema.rb
- rool/rails/typo/trunk/db/migrate/002_add_user_email.rb
- rool/rails/typo/trunk/db/migrate/003_add_article_user_id.rb
- rool/rails/typo/trunk/db/migrate/004_add_sidebars.rb
- rool/rails/typo/trunk/db/migrate/005_add_cache_table.rb
- rool/rails/typo/trunk/db/migrate/006_add_pages.rb
- rool/rails/typo/trunk/db/migrate/007_add_permalink.rb
- rool/rails/typo/trunk/db/migrate/008_add_page_title.rb
- rool/rails/typo/trunk/db/migrate/009_add_article_guid.rb
- rool/rails/typo/trunk/db/migrate/010_add_tags.rb
- rool/rails/typo/trunk/db/migrate/011_add_article_id.rb
- rool/rails/typo/trunk/db/migrate/012_enlarge_settings.rb
- rool/rails/typo/trunk/db/migrate/013_add_textfilters.rb
- rool/rails/typo/trunk/db/migrate/014_move_text_filter_to_text_filter_id.rb
- rool/rails/typo/trunk/db/migrate/015_convert_mysql_to_innodb.rb
- rool/rails/typo/trunk/db/migrate/016_fix_is_primary_postgres.rb
- rool/rails/typo/trunk/db/migrate/017_add_comment_user_id.rb
- rool/rails/typo/trunk/db/migrate/018_add_guids.rb
- rool/rails/typo/trunk/db/migrate/019_add_whiteboards_to_content.rb
- rool/rails/typo/trunk/db/migrate/020_superclass_articles.rb
- rool/rails/typo/trunk/db/migrate/021_superclass_comments.rb
- rool/rails/typo/trunk/db/migrate/022_superclass_trackbacks.rb
- rool/rails/typo/trunk/db/migrate/023_superclass_pages.rb
- rool/rails/typo/trunk/db/migrate/024_cleanup_contents.rb
- rool/rails/typo/trunk/db/migrate/025_add_itunes_metadata.rb
- rool/rails/typo/trunk/db/migrate/026_add_redirect_table.rb
- rool/rails/typo/trunk/db/migrate/027_set_comment_published_flag.rb
- rool/rails/typo/trunk/db/migrate/028_rename_redirect_to.rb
- rool/rails/typo/trunk/db/migrate/029_add_user_notification.rb
- rool/rails/typo/trunk/db/migrate/030_index_sessions.rb
- rool/rails/typo/trunk/db/migrate/031_add_notifications_table.rb
- rool/rails/typo/trunk/db/migrate/032_add_jabber_notification.rb
- rool/rails/typo/trunk/db/migrate/033_add_count_caching.rb
- rool/rails/typo/trunk/db/migrate/034_boolify_published.rb
- rool/rails/typo/trunk/db/migrate/035_boolify_content_allow_foo.rb
- rool/rails/typo/trunk/db/migrate/036_add_tag_display_name.rb
- rool/rails/typo/trunk/db/migrate/037_enlarge_ip_field.rb
- rool/rails/typo/trunk/db/migrate/038_add_blog_object.rb
- rool/rails/typo/trunk/db/migrate/039_serialize_blog_attributes.rb
- rool/rails/typo/trunk/db/migrate/040_attach_content_to_blog.rb
- rool/rails/typo/trunk/db/migrate/041_fixup_default_sidebars.rb
- rool/rails/typo/trunk/db/migrate/042_remove_sidebar_staged_config.rb
- rool/rails/typo/trunk/db/migrate/043_create_triggers.rb
- rool/rails/typo/trunk/db/migrate/044_add_published_at_to_content.rb
- rool/rails/typo/trunk/db/migrate/045_fix_contents_published_default.rb
- rool/rails/typo/trunk/db/migrate/046_fixup_forthcoming_publications.rb
- rool/rails/typo/trunk/db/schema.mysql-v3.sql
- rool/rails/typo/trunk/db/schema.postgresql.sql
- rool/rails/typo/trunk/db/schema.sqlserver.sql
- rool/rails/typo/trunk/db/schema_version
- rool/rails/typo/trunk/lib/backpack_api.rb
- rool/rails/typo/trunk/lib/bare_migration.rb
- rool/rails/typo/trunk/lib/email_notify.rb
- rool/rails/typo/trunk/lib/generators/sidebar/sidebar_generator.rb
- rool/rails/typo/trunk/lib/generators/sidebar/templates/components/plugins/sidebars/controller_template.rb
- rool/rails/typo/trunk/lib/generators/sidebar/templates/components/plugins/sidebars/views/content_template.rhtml
- rool/rails/typo/trunk/lib/jabber_notify.rb
- rool/rails/typo/trunk/lib/rails_patch/active_record.rb
- rool/rails/typo/trunk/lib/rails_patch/components.rb
- rool/rails/typo/trunk/lib/sidebars/component_plugin.rb
- rool/rails/typo/trunk/lib/sidebars/plugin.rb
- rool/rails/typo/trunk/lib/tasks/release.rake
- rool/rails/typo/trunk/lib/tasks/schemas.rake
- rool/rails/typo/trunk/lib/tasks/sweep_cache.rake
- rool/rails/typo/trunk/lib/text_filter_plugin.rb
- rool/rails/typo/trunk/lib/typo_guid.rb
- rool/rails/typo/trunk/lib/typo_plugins.rb
- rool/rails/typo/trunk/lib/typo_version.rb
- rool/rails/typo/trunk/public/images/loading.gif
- rool/rails/typo/trunk/public/images/overlay.png
- rool/rails/typo/trunk/public/javascripts/application.js
- rool/rails/typo/trunk/public/javascripts/lightbox.js
- rool/rails/typo/trunk/public/javascripts/scriptaculous.js
- rool/rails/typo/trunk/public/javascripts/slider.js
- rool/rails/typo/trunk/public/stylesheets/lightbox.css
- rool/rails/typo/trunk/public/stylesheets/rss.css
- rool/rails/typo/trunk/public/stylesheets/user-styles.css
- rool/rails/typo/trunk/script/about
- rool/rails/typo/trunk/script/logreport
- rool/rails/typo/trunk/script/migrate
- rool/rails/typo/trunk/script/performance/benchmarker
- rool/rails/typo/trunk/script/performance/profiler
- rool/rails/typo/trunk/script/plugin
- rool/rails/typo/trunk/script/spacecheck
- rool/rails/typo/trunk/test/fixtures/articles_tags.yml
- rool/rails/typo/trunk/test/fixtures/blogs.yml
- rool/rails/typo/trunk/test/fixtures/contents.yml
- rool/rails/typo/trunk/test/fixtures/notification_mailer/article
- rool/rails/typo/trunk/test/fixtures/notification_mailer/comment
- rool/rails/typo/trunk/test/fixtures/notification_mailer/trackback
- rool/rails/typo/trunk/test/fixtures/notifications.yml
- rool/rails/typo/trunk/test/fixtures/redirects.yml
- rool/rails/typo/trunk/test/fixtures/tags.yml
- rool/rails/typo/trunk/test/fixtures/text_filters.yml
- rool/rails/typo/trunk/test/fixtures/triggers.yml
- rool/rails/typo/trunk/test/functional/admin/article_preview_test.rb
- rool/rails/typo/trunk/test/functional/admin/pages_controller_test.rb
- rool/rails/typo/trunk/test/functional/admin/resources_controller_test.rb
- rool/rails/typo/trunk/test/functional/admin/textfilters_controller_test.rb
- rool/rails/typo/trunk/test/functional/redirect_controller_test.rb
- rool/rails/typo/trunk/test/functional/textfilter_controller_test.rb
- rool/rails/typo/trunk/test/mocks/test/flickr_mock.rb
- rool/rails/typo/trunk/test/mocks/test/xmlrpc_mock.rb
- rool/rails/typo/trunk/test/mocks/themes/123-numbers-in-path/about.markdown
- rool/rails/typo/trunk/test/mocks/themes/CamelCaseDirectory/about.markdown
- rool/rails/typo/trunk/test/mocks/themes/azure
- rool/rails/typo/trunk/test/mocks/themes/i-have-special-chars/about.markdown
- rool/rails/typo/trunk/test/unit/assumptions_tests.rb
- rool/rails/typo/trunk/test/unit/audioscrobbler_test.rb
- rool/rails/typo/trunk/test/unit/blog_test.rb
- rool/rails/typo/trunk/test/unit/content_state/factory_test.rb
- rool/rails/typo/trunk/test/unit/magnolia_test.rb
- rool/rails/typo/trunk/test/unit/metafragment_test.rb
- rool/rails/typo/trunk/test/unit/notification_mailer_test.rb
- rool/rails/typo/trunk/test/unit/observer_test.rb
- rool/rails/typo/trunk/test/unit/redirect_test.rb
- rool/rails/typo/trunk/test/unit/tag_test.rb
- rool/rails/typo/trunk/test/unit/text_filter_test.rb
- rool/rails/typo/trunk/test/unit/trigger_test.rb
- rool/rails/typo/trunk/themes/azure/stylesheets/print.css
- rool/rails/typo/trunk/vendor/flickr/Rakefile
- rool/rails/typo/trunk/vendor/flickr/flickr.rb
- rool/rails/typo/trunk/vendor/flickr/index.html
- rool/rails/typo/trunk/vendor/flickr/test_flickr.rb
- rool/rails/typo/trunk/vendor/jabber4r/CHANGES
- rool/rails/typo/trunk/vendor/jabber4r/LICENSE.txt
- rool/rails/typo/trunk/vendor/jabber4r/README
- rool/rails/typo/trunk/vendor/jabber4r/Rakefile.rb
- rool/rails/typo/trunk/vendor/jabber4r/lib/jabber4r/jabber4r.rb
- rool/rails/typo/trunk/vendor/jabber4r/lib/jabber4r/jid.rb
- rool/rails/typo/trunk/vendor/jabber4r/lib/jabber4r/protocol.rb
- rool/rails/typo/trunk/vendor/jabber4r/lib/jabber4r/rexml_1.8_patch.rb
- rool/rails/typo/trunk/vendor/jabber4r/lib/jabber4r/roster.rb
- rool/rails/typo/trunk/vendor/jabber4r/lib/jabber4r/session.rb
- rool/rails/typo/trunk/vendor/jabber4r/lib/jabber4r/vcard.rb
- rool/rails/typo/trunk/vendor/plugins/expiring_action_cache/init.rb
- rool/rails/typo/trunk/vendor/plugins/expiring_action_cache/lib/actionparamcache.rb
- rool/rails/typo/trunk/vendor/plugins/expiring_action_cache/lib/metafragment.rb
- rool/rails/typo/trunk/vendor/plugins/upload_progress/CHANGELOG
- rool/rails/typo/trunk/vendor/plugins/upload_progress/MIT-LICENSE
- rool/rails/typo/trunk/vendor/plugins/upload_progress/README
- rool/rails/typo/trunk/vendor/plugins/upload_progress/Rakefile
- rool/rails/typo/trunk/vendor/plugins/upload_progress/init.rb
- rool/rails/typo/trunk/vendor/plugins/upload_progress/lib/multipart_progress.rb
- rool/rails/typo/trunk/vendor/plugins/upload_progress/lib/progress.rb
- rool/rails/typo/trunk/vendor/plugins/upload_progress/lib/upload_progress.rb
- rool/rails/typo/trunk/vendor/plugins/upload_progress/lib/upload_progress_helper.rb
- rool/rails/typo/trunk/vendor/plugins/upload_progress/public/stylesheets/upload_progress.css
- rool/rails/typo/trunk/vendor/plugins/upload_progress/test/multipart_progress_testx.rb
- rool/rails/typo/trunk/vendor/plugins/upload_progress/test/upload_progress_helper_testx.rb
- rool/rails/typo/trunk/vendor/plugins/upload_progress/test/upload_progress_testx.rb
- rool/rails/typo/trunk/vendor/rails/actionmailer/test/fixtures/path.with.dots/multipart_with_template_path_with_dots.rhtml
- rool/rails/typo/trunk/vendor/rails/actionmailer/test/fixtures/raw_email13
- rool/rails/typo/trunk/vendor/rails/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.ignored.rhtml
- rool/rails/typo/trunk/vendor/rails/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.rhtml.bak
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/deprecated_request_methods.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/integration.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/mime_responds.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/mime_type.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/vendor/xml_node.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/prototype_helper.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/scriptaculous_helper.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/test/active_record_unit.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/test/activerecord/active_record_assertions_test.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/test/activerecord/active_record_store_test.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/test/activerecord/pagination_test.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/layout_test.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/mime_responds_test.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/mime_type_test.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/webservice_test.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/companies.yml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/company.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/db_definitions/sqlite.sql
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/developer.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/developers.yml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/developers_projects.yml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/layout_tests/layouts/item.rhtml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/layout_tests/layouts/layout_test.rhtml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/layout_tests/layouts/third_party_template_library.mab
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/layout_tests/views/hello.rhtml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/multipart/mona_lisa.jpg
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/project.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/projects.yml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/public/images/rails.png
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/replies.yml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/reply.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/respond_to/all_types_with_layout.rhtml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/respond_to/all_types_with_layout.rjs
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/respond_to/layouts/standard.rhtml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/respond_to/using_defaults.rhtml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/respond_to/using_defaults.rjs
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/respond_to/using_defaults.rxml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/respond_to/using_defaults_with_type_list.rhtml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/respond_to/using_defaults_with_type_list.rjs
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/respond_to/using_defaults_with_type_list.rxml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/test/block_content_for.rhtml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/test/delete_with_js.rjs
- rool/rails/typo/trunk/vendor/syntax/lib/syntax/common.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/test/dot.directory/render_file_with_ivar.rhtml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/test/enum_rjs_test.rjs
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/test/erb_content_for.rhtml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/test/hello_world.rxml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/test/hello_world_with_layout_false.rhtml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/test/non_erb_block_content_for.rxml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/topic.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/test/fixtures/topics.yml
- rool/rails/typo/trunk/vendor/rails/actionpack/test/template/prototype_helper_test.rb
- rool/rails/typo/trunk/vendor/rails/actionpack/test/template/scriptaculous_helper_test.rb
- rool/rails/typo/trunk/vendor/rails/actionwebservice/test/fixtures/db_definitions/mysql.sql
- rool/rails/typo/trunk/vendor/rails/actionwebservice/test/fixtures/users.yml
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/associations/has_many_through_association.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/calculations.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/openbase_adapter.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/sybase_adapter.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/test/associations_cascaded_eager_loading_test.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/test/associations_join_model_test.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/test/calculations_test.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/test/connections/native_openbase/connection.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/test/connections/native_oracle/connection.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/test/connections/native_sybase/connection.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/test/defaults_test.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/author_favorites.yml
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/categories/special_categories.yml
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/categories/subsubdir/arbitrary_filename.yml
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/categorization.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/categorizations.yml
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/openbase.drop.sql
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/openbase.sql
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/openbase2.drop.sql
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/openbase2.sql
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/oracle.drop.sql
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/oracle.sql
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/oracle2.drop.sql
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/oracle2.sql
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/schema.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/sybase.drop.sql
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/sybase.sql
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/sybase2.drop.sql
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/sybase2.sql
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/funny_jokes.yml
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/joke.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/legacy_thing.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/legacy_things.yml
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/reader.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/readers.yml
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/tag.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/tagging.rb
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/taggings.yml
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/tags.yml
- rool/rails/typo/trunk/vendor/rails/activerecord/test/synonym_test_oracle.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/caching_tools.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/class.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/class/removal.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/hash/conversions.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/hash/diff.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/kernel/agnostics.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/kernel/daemonizing.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/kernel/reporting.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/kernel/requires.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/logger.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/module.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/module/delegation.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/module/inclusion.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/module/introspection.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/module/loading.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/object.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/object/extending.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/object/misc.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/pathname.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/pathname/clean_within.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/proc.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/string/iterators.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/symbol.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/json.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/json/encoders.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/json/encoders/core.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/option_merger.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/reloadable.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/vendor/builder.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/vendor/builder/blankslate.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/vendor/builder/xmlbase.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/vendor/builder/xmlevents.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/vendor/builder/xmlmarkup.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/autoloading_fixtures/a/b.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/autoloading_fixtures/a/c/d.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/autoloading_fixtures/a/c/e/f.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/autoloading_fixtures/e.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/autoloading_fixtures/module_folder/nested_class.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/autoloading_fixtures/module_folder/nested_sibling.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/caching_tools_test.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/class_test.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/module_test.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/pathname_test.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/proc_test.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/symbol_test.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/dependencies/check_warnings.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/dependencies/mutual_one.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/dependencies/mutual_two.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/dependencies/raises_exception.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/json.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/option_merger_test.rb
- rool/rails/typo/trunk/vendor/rails/activesupport/test/reloadable_test.rb
- rool/rails/typo/trunk/vendor/rails/railties/builtin/rails_info/rails/info.rb
- rool/rails/typo/trunk/vendor/rails/railties/builtin/rails_info/rails/info_controller.rb
- rool/rails/typo/trunk/vendor/rails/railties/builtin/rails_info/rails/info_helper.rb
- rool/rails/typo/trunk/vendor/rails/railties/builtin/rails_info/rails_info_controller.rb
- rool/rails/typo/trunk/vendor/rails/railties/configs/databases/mysql.yml
- rool/rails/typo/trunk/vendor/rails/railties/configs/databases/oracle.yml
- rool/rails/typo/trunk/vendor/rails/railties/configs/databases/postgresql.yml
- rool/rails/typo/trunk/vendor/rails/railties/configs/databases/sqlite2.yml
- rool/rails/typo/trunk/vendor/rails/railties/configs/databases/sqlite3.yml
- rool/rails/typo/trunk/vendor/rails/railties/html/javascripts/application.js
- rool/rails/typo/trunk/vendor/rails/railties/lib/console_app.rb
- rool/rails/typo/trunk/vendor/rails/railties/lib/console_with_helpers.rb
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails/version.rb
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/integration_test/USAGE
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/integration_test/integration_test_generator.rb
- rool/rails/typo/trunk/app/views/admin/comments/new.rhtml (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/integration_test/templates/integration_test.rb
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/model/templates/migration.rb
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/plugin/templates/install.rb
- rool/rails/typo/trunk/vendor/rails/railties/lib/ruby_version_check.rb
- rool/rails/typo/trunk/vendor/rails/railties/lib/tasks/log.rake
- rool/rails/typo/trunk/vendor/rails/railties/lib/tasks/pre_namespace_aliases.rake
- rool/rails/typo/trunk/vendor/rails/railties/lib/tasks/tmp.rake
- rool/rails/typo/trunk/vendor/redcloth/setup.rb
- rool/rails/typo/trunk/vendor/redcloth/tests/hard_breaks.yml
- rool/rails/typo/trunk/vendor/sparklines/README.txt
- rool/rails/typo/trunk/vendor/sparklines/USAGE
- rool/rails/typo/trunk/vendor/sparklines/lib/sparklines.rb
- rool/rails/typo/trunk/vendor/sparklines/samples/sparklinestest.rb
- rool/rails/typo/trunk/vendor/sparklines/sparklines_generator.rb
- rool/rails/typo/trunk/vendor/sparklines/templates/sparklines_controller.rb
- rool/rails/typo/trunk/vendor/sparklines/templates/sparklines_helper.rb
- rool/rails/typo/trunk/vendor/syntax/LICENSE
- rool/rails/typo/trunk/vendor/syntax/NEWS
- rool/rails/typo/trunk/vendor/syntax/README
- rool/rails/typo/trunk/vendor/syntax/Rakefile
- rool/rails/typo/trunk/vendor/syntax/api/classes/Syntax.html
- rool/rails/typo/trunk/vendor/syntax/api/classes/Syntax/Convertors.html
- rool/rails/typo/trunk/vendor/syntax/api/classes/Syntax/Convertors/Abstract.html
- rool/rails/typo/trunk/vendor/syntax/api/classes/Syntax/Convertors/HTML.html
- rool/rails/typo/trunk/vendor/syntax/api/classes/Syntax/Default.html
- rool/rails/typo/trunk/vendor/syntax/api/classes/Syntax/Ruby.html
- rool/rails/typo/trunk/vendor/syntax/api/classes/Syntax/Token.html
- rool/rails/typo/trunk/vendor/syntax/api/classes/Syntax/Tokenizer.html
- rool/rails/typo/trunk/vendor/syntax/api/classes/Syntax/Version.html
- rool/rails/typo/trunk/vendor/syntax/api/classes/Syntax/XML.html
- rool/rails/typo/trunk/vendor/syntax/api/classes/Syntax/YAML.html
- rool/rails/typo/trunk/vendor/syntax/api/created.rid
- rool/rails/typo/trunk/vendor/syntax/api/files/README.html
- rool/rails/typo/trunk/vendor/syntax/api/files/lib/syntax/common_rb.html
- rool/rails/typo/trunk/vendor/syntax/api/files/lib/syntax/convertors/abstract_rb.html
- rool/rails/typo/trunk/vendor/syntax/api/files/lib/syntax/convertors/html_rb.html
- rool/rails/typo/trunk/vendor/syntax/api/files/lib/syntax/lang/ruby_rb.html
- rool/rails/typo/trunk/vendor/syntax/api/files/lib/syntax/lang/xml_rb.html
- rool/rails/typo/trunk/vendor/syntax/api/files/lib/syntax/lang/yaml_rb.html
- rool/rails/typo/trunk/vendor/syntax/api/files/lib/syntax/version_rb.html
- rool/rails/typo/trunk/vendor/syntax/api/files/lib/syntax_rb.html
- rool/rails/typo/trunk/vendor/syntax/api/fr_class_index.html
- rool/rails/typo/trunk/vendor/syntax/api/fr_file_index.html
- rool/rails/typo/trunk/vendor/syntax/api/fr_method_index.html
- rool/rails/typo/trunk/vendor/syntax/api/index.html
- rool/rails/typo/trunk/vendor/syntax/api/rdoc-style.css
- rool/rails/typo/trunk/vendor/syntax/doc/manual-html/chapter-1.html
- rool/rails/typo/trunk/vendor/syntax/doc/manual-html/chapter-2.html
- rool/rails/typo/trunk/vendor/syntax/doc/manual-html/chapter-3.html
- rool/rails/typo/trunk/vendor/syntax/doc/manual-html/chapter-4.html
- rool/rails/typo/trunk/vendor/syntax/doc/manual-html/index.html
- rool/rails/typo/trunk/vendor/syntax/doc/manual-html/stylesheets/manual.css
- rool/rails/typo/trunk/vendor/syntax/doc/manual-html/stylesheets/ruby.css
- rool/rails/typo/trunk/vendor/syntax/doc/manual/chapter.erb
- rool/rails/typo/trunk/vendor/syntax/doc/manual/example.erb
- rool/rails/typo/trunk/vendor/syntax/doc/manual/index.erb
- rool/rails/typo/trunk/vendor/syntax/doc/manual/manual.rb
- rool/rails/typo/trunk/vendor/syntax/doc/manual/manual.yml
- rool/rails/typo/trunk/vendor/syntax/doc/manual/page.erb
- rool/rails/typo/trunk/vendor/syntax/doc/manual/parts/0000.txt
- rool/rails/typo/trunk/vendor/syntax/doc/manual/parts/0001.txt
- rool/rails/typo/trunk/vendor/syntax/doc/manual/parts/0002.txt
- rool/rails/typo/trunk/vendor/syntax/doc/manual/parts/0003.txt
- rool/rails/typo/trunk/vendor/syntax/doc/manual/parts/0004.txt
- rool/rails/typo/trunk/vendor/syntax/doc/manual/parts/0005.txt
- rool/rails/typo/trunk/vendor/syntax/doc/manual/parts/0006.txt
- rool/rails/typo/trunk/vendor/syntax/doc/manual/parts/0007.txt
- rool/rails/typo/trunk/vendor/syntax/doc/manual/parts/0008.txt
- rool/rails/typo/trunk/vendor/syntax/doc/manual/parts/0009.txt
- rool/rails/typo/trunk/vendor/syntax/doc/manual/parts/0010.txt
- rool/rails/typo/trunk/vendor/syntax/doc/manual/stylesheets/manual.css
- rool/rails/typo/trunk/vendor/syntax/doc/manual/stylesheets/ruby.css
- rool/rails/typo/trunk/vendor/syntax/doc/manual/tutorial.erb
- rool/rails/typo/trunk/vendor/syntax/lib/syntax.rb
- rool/rails/typo/trunk/vendor/syntax/lib/syntax/convertors/abstract.rb
- rool/rails/typo/trunk/vendor/syntax/lib/syntax/convertors/html.rb
- rool/rails/typo/trunk/vendor/syntax/lib/syntax/lang/ruby.rb
- rool/rails/typo/trunk/vendor/syntax/lib/syntax/lang/xml.rb
- rool/rails/typo/trunk/vendor/syntax/lib/syntax/lang/yaml.rb
- rool/rails/typo/trunk/vendor/syntax/lib/syntax/version.rb
- rool/rails/typo/trunk/vendor/syntax/setup.rb
- rool/rails/typo/trunk/vendor/syntax/syntax.gemspec
- rool/rails/typo/trunk/vendor/syntax/test/ALL-TESTS.rb
- rool/rails/typo/trunk/vendor/syntax/test/syntax/tc_ruby.rb
- rool/rails/typo/trunk/vendor/syntax/test/syntax/tc_xml.rb
- rool/rails/typo/trunk/vendor/syntax/test/syntax/tc_yaml.rb
- rool/rails/typo/trunk/vendor/syntax/test/syntax/tokenizer_testcase.rb
- rool/rails/typo/trunk/vendor/syntax/test/tc_syntax.rb
- rool/rails/typo/trunk/vendor/uuidtools/CHANGELOG
- rool/rails/typo/trunk/vendor/uuidtools/README
- rool/rails/typo/trunk/vendor/uuidtools/install.rb
- rool/rails/typo/trunk/vendor/uuidtools/lib/uuidtools.rb
- rool/rails/typo/trunk/vendor/uuidtools/rakefile
- rool/rails/typo/trunk/README (diff)
- rool/rails/typo/trunk/Rakefile (diff)
- rool/rails/typo/trunk/app/apis/blogger_service.rb (diff)
- rool/rails/typo/trunk/app/apis/meta_weblog_service.rb (diff)
- rool/rails/typo/trunk/app/apis/movable_type_service.rb (diff)
- rool/rails/typo/trunk/app/apis/typo_web_service.rb (diff)
- rool/rails/typo/trunk/app/controllers/accounts_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/admin/base_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/admin/blacklist_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/admin/cache_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/admin/categories_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/admin/comments_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/admin/content_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/admin/general_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/admin/pages_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/admin/sidebar_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/admin/themes_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/admin/trackbacks_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/admin/users_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/application.rb (diff)
- rool/rails/typo/trunk/app/controllers/articles_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/backend_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/live_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/theme_controller.rb (diff)
- rool/rails/typo/trunk/app/controllers/xml_controller.rb (diff)
- rool/rails/typo/trunk/app/helpers/admin/base_helper.rb (diff)
- rool/rails/typo/trunk/app/helpers/application_helper.rb (diff)
- rool/rails/typo/trunk/app/helpers/articles_helper.rb (diff)
- rool/rails/typo/trunk/app/helpers/xml_helper.rb (diff)
- rool/rails/typo/trunk/app/models/aggregations/delicious.rb (diff)
- rool/rails/typo/trunk/app/models/aggregations/flickr.rb (diff)
- rool/rails/typo/trunk/app/models/aggregations/fortythree.rb (diff)
- rool/rails/typo/trunk/app/models/aggregations/tada.rb (diff)
- rool/rails/typo/trunk/app/models/aggregations/technorati.rb (diff)
- rool/rails/typo/trunk/app/models/aggregations/upcoming.rb (diff)
- rool/rails/typo/trunk/app/models/article.rb (diff)
- rool/rails/typo/trunk/app/models/blacklist_pattern.rb (diff)
- rool/rails/typo/trunk/app/models/blog_sweeper.rb (diff)
- rool/rails/typo/trunk/app/models/category.rb (diff)
- rool/rails/typo/trunk/app/models/comment.rb (diff)
- rool/rails/typo/trunk/app/models/config_manager.rb (diff)
- rool/rails/typo/trunk/app/models/page.rb (diff)
- rool/rails/typo/trunk/app/models/page_cache.rb (diff)
- rool/rails/typo/trunk/app/models/ping.rb (diff)
- rool/rails/typo/trunk/app/models/resource.rb (diff)
- rool/rails/typo/trunk/app/models/sidebar.rb (diff)
- rool/rails/typo/trunk/app/models/simple_cache.rb (diff)
- rool/rails/typo/trunk/app/models/theme.rb (diff)
- rool/rails/typo/trunk/app/models/trackback.rb (diff)
- rool/rails/typo/trunk/app/models/user.rb (diff)
- rool/rails/typo/trunk/app/views/accounts/login.rhtml (diff)
- rool/rails/typo/trunk/app/views/accounts/logout.rhtml (diff)
- rool/rails/typo/trunk/app/views/accounts/signup.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/blacklist/_blacklist_patterns.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/blacklist/_quick_post.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/categories/_categories.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/categories/_quick_post.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/categories/destroy.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/categories/list.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/categories/show.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/comments/destroy.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/comments/edit.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/comments/list.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/content/_articles.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/content/_form.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/content/_quick_post.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/content/destroy.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/content/edit.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/content/new.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/content/preview.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/content/show.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/general/index.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/pages/_form.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/pages/_quick_post.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/pages/preview.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/pages/show.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/sidebar/_active.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/sidebar/_actives.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/sidebar/index.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/themes/index.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/users/_form.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/users/_user.rhtml (diff)
- rool/rails/typo/trunk/app/views/admin/users/show.rhtml (diff)
- rool/rails/typo/trunk/app/views/articles/_article.rhtml (diff)
- rool/rails/typo/trunk/app/views/articles/_comment.rhtml (diff)
- rool/rails/typo/trunk/app/views/articles/_comment_box.rhtml (diff)
- rool/rails/typo/trunk/app/views/articles/_trackback.rhtml (diff)
- rool/rails/typo/trunk/app/views/articles/archives.rhtml (diff)
- rool/rails/typo/trunk/app/views/articles/index.rhtml (diff)
- rool/rails/typo/trunk/app/views/articles/read.rhtml (diff)
- rool/rails/typo/trunk/app/views/articles/trackback.rxml (diff)
- rool/rails/typo/trunk/app/views/articles/view_page.rhtml (diff)
- rool/rails/typo/trunk/app/views/layouts/administration.rhtml (diff)
- rool/rails/typo/trunk/app/views/live/search.rhtml (diff)
- rool/rails/typo/trunk/app/views/settings/done.rhtml (diff)
- rool/rails/typo/trunk/app/views/settings/install.rhtml (diff)
- rool/rails/typo/trunk/app/views/xml/rsd.rxml (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/archives/content.rhtml (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/archives_controller.rb (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/category/content.rhtml (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/category_controller.rb (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/delicious/content.rhtml (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/delicious_controller.rb (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/flickr/content.rhtml (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/flickr_controller.rb (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/fortythree/content.rhtml (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/fortythree_controller.rb (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/fortythreeplaces/content.rhtml (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/fortythreeplaces_controller.rb (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/static_controller.rb (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/tada/content.rhtml (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/tada_controller.rb (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/technorati/content.rhtml (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/technorati_controller.rb (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/upcoming_controller.rb (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/xml/content.rhtml (diff)
- rool/rails/typo/trunk/components/plugins/sidebars/xml_controller.rb (diff)
- rool/rails/typo/trunk/config/environment.rb (diff)
- rool/rails/typo/trunk/config/environments/development.rb (diff)
- rool/rails/typo/trunk/config/environments/production.rb (diff)
- rool/rails/typo/trunk/config/environments/test.rb (diff)
- rool/rails/typo/trunk/config/lighttpd.conf (diff)
- rool/rails/typo/trunk/config/routes.rb (diff)
- rool/rails/typo/trunk/db/converters/mt3.rb (diff)
- rool/rails/typo/trunk/db/converters/s9y.rb (diff)
- rool/rails/typo/trunk/db/converters/textpattern.rb (diff)
- rool/rails/typo/trunk/db/converters/wordpress.rb (diff)
- rool/rails/typo/trunk/db/schema.mysql.sql (diff)
- rool/rails/typo/trunk/db/schema.sqlite.sql (diff)
- rool/rails/typo/trunk/db/scripts/fix_permalinks.rb (diff)
- rool/rails/typo/trunk/lib/format.rb (diff)
- rool/rails/typo/trunk/lib/login_system.rb (diff)
- rool/rails/typo/trunk/lib/migrator.rb (diff)
- rool/rails/typo/trunk/lib/spam_protection.rb (diff)
- rool/rails/typo/trunk/lib/transforms.rb (diff)
- rool/rails/typo/trunk/lib/xmlrpc_fix.rb (diff)
- rool/rails/typo/trunk/public/.htaccess (diff)
- rool/rails/typo/trunk/public/404.html (diff)
- rool/rails/typo/trunk/public/500.html (diff)
- rool/rails/typo/trunk/public/dispatch.rb (diff)
- rool/rails/typo/trunk/public/javascripts/controls.js (diff)
- rool/rails/typo/trunk/public/javascripts/cookies.js (diff)
- rool/rails/typo/trunk/public/javascripts/dragdrop.js (diff)
- rool/rails/typo/trunk/public/javascripts/effects.js (diff)
- rool/rails/typo/trunk/public/javascripts/prototype.js (diff)
- rool/rails/typo/trunk/public/javascripts/typo.js (diff)
- rool/rails/typo/trunk/public/stylesheets/administration.css (diff)
- rool/rails/typo/trunk/script/breakpointer (diff)
- rool/rails/typo/trunk/script/console (diff)
- rool/rails/typo/trunk/script/destroy (diff)
- rool/rails/typo/trunk/script/generate (diff)
- rool/rails/typo/trunk/script/process/reaper (diff)
- rool/rails/typo/trunk/script/process/spawner (diff)
- rool/rails/typo/trunk/script/process/spinner (diff)
- rool/rails/typo/trunk/script/runner (diff)
- rool/rails/typo/trunk/script/server (diff)
- rool/rails/typo/trunk/test/fixtures/articles_categories.yml (diff)
- rool/rails/typo/trunk/test/fixtures/categories.yml (diff)
- rool/rails/typo/trunk/test/fixtures/resources.yml (diff)
- rool/rails/typo/trunk/test/fixtures/users.yml (diff)
- rool/rails/typo/trunk/test/functional/accounts_controller_test.rb (diff)
- rool/rails/typo/trunk/test/functional/admin/blacklist_controller_test.rb (diff)
- rool/rails/typo/trunk/test/functional/admin/categories_controller_test.rb (diff)
- rool/rails/typo/trunk/test/functional/admin/comments_controller_test.rb (diff)
- rool/rails/typo/trunk/test/functional/admin/content_controller_test.rb (diff)
- rool/rails/typo/trunk/test/functional/admin/general_controller_test.rb (diff)
- rool/rails/typo/trunk/test/functional/admin/themes_controller_test.rb (diff)
- rool/rails/typo/trunk/test/functional/admin/trackbacks_controller_test.rb (diff)
- rool/rails/typo/trunk/test/functional/admin/users_controller_test.rb (diff)
- rool/rails/typo/trunk/test/functional/articles_controller_test.rb (diff)
- rool/rails/typo/trunk/test/functional/backend_controller_test.rb (diff)
- rool/rails/typo/trunk/test/functional/theme_controller_test.rb (diff)
- rool/rails/typo/trunk/test/functional/xml_controller_test.rb (diff)
- rool/rails/typo/trunk/test/mocks/test/dns_mock.rb (diff)
- rool/rails/typo/trunk/test/mocks/test/http_mock.rb (diff)
- rool/rails/typo/trunk/test/mocks/test/theme_mock.rb (diff)
- rool/rails/typo/trunk/test/test_helper.rb (diff)
- rool/rails/typo/trunk/test/unit/article_test.rb (diff)
- rool/rails/typo/trunk/test/unit/category_test.rb (diff)
- rool/rails/typo/trunk/test/unit/comment_test.rb (diff)
- rool/rails/typo/trunk/test/unit/configuration_test.rb (diff)
- rool/rails/typo/trunk/test/unit/delicious_test.rb (diff)
- rool/rails/typo/trunk/test/unit/flickr_test.rb (diff)
- rool/rails/typo/trunk/test/unit/fortythree_test.rb (diff)
- rool/rails/typo/trunk/test/unit/page_cache_test.rb (diff)
- rool/rails/typo/trunk/test/unit/page_test.rb (diff)
- rool/rails/typo/trunk/test/unit/ping_test.rb (diff)
- rool/rails/typo/trunk/test/unit/resource_test.rb (diff)
- rool/rails/typo/trunk/test/unit/theme_test.rb (diff)
- rool/rails/typo/trunk/test/unit/trackback_test.rb (diff)
- rool/rails/typo/trunk/test/unit/user_test.rb (diff)
- rool/rails/typo/trunk/themes/azure/layouts/default.rhtml (diff)
- rool/rails/typo/trunk/themes/azure/stylesheets/azure.css (diff)
- rool/rails/typo/trunk/vendor/rails/actionmailer/CHANGELOG (diff)
- rool/rails/typo/trunk/vendor/rails/actionmailer/Rakefile (diff)
- rool/rails/typo/trunk/vendor/rails/actionmailer/lib/action_mailer/adv_attr_accessor.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionmailer/lib/action_mailer/base.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionmailer/lib/action_mailer/part.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionmailer/lib/action_mailer/part_container.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/attachments.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/quoting.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionmailer/lib/action_mailer/version.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionmailer/test/fixtures/raw_email7 (diff)
- rool/rails/typo/trunk/vendor/rails/actionmailer/test/mail_service_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/CHANGELOG (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/Rakefile (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/assertions.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/base.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/benchmarking.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/caching.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/cgi_ext/cookie_performance_fix.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/cgi_process.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/components.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/dependencies.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/deprecated_redirects.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/filters.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/flash.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/helpers.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/layout.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/pagination.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/request.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/rescue.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/routing.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/scaffolding.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/session/active_record_store.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/session/mem_cache_store.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/session_management.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/templates/rescues/_trace.rhtml (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/templates/rescues/diagnostics.rhtml (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/templates/scaffolds/layout.rhtml (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/templates/scaffolds/list.rhtml (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/test_process.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/vendor/html-scanner/html/node.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/vendor/html-scanner/html/tokenizer.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/vendor/html-scanner/html/version.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/verification.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_pack/version.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/base.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/compiled_templates.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/active_record_helper.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/asset_tag_helper.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/capture_helper.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/date_helper.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/form_helper.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/form_options_helper.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/form_tag_helper.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/java_script_macros_helper.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/javascript_helper.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/javascripts/controls.js (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/javascripts/dragdrop.js (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/javascripts/effects.js (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/javascripts/prototype.js (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/number_helper.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/pagination_helper.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/text_helper.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/url_helper.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/partials.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/abstract_unit.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/action_pack_assertions_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/base_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/benchmark_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/capture_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/cgi_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/custom_handler_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/fake_controllers.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/filters_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/flash_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/fragment_store_setting_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/new_render_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/redirect_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/render_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/request_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/routing_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/test_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/verification_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/template/active_record_helper_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/template/asset_tag_helper_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/template/date_helper_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/template/form_helper_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/template/form_options_helper_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/template/form_tag_helper_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/template/java_script_macros_helper_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/template/javascript_helper_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/template/number_helper_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/template/text_helper_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionpack/test/template/url_helper_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/CHANGELOG (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/Rakefile (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/api.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/base.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/casting.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/client/soap_client.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/protocol/soap_protocol/marshaler.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/scaffolding.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/struct.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/support/signature_types.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/templates/scaffolds/layout.rhtml (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/templates/scaffolds/parameters.rhtml (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/test_invoke.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/version.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/test/abstract_client.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/test/abstract_unit.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/test/client_soap_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/test/client_xmlrpc_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/test/scaffolded_controller_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/actionwebservice/test/test_invoke_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/CHANGELOG (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/RUNNING_UNIT_TESTS (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/Rakefile (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/acts/list.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/acts/tree.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/aggregations.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/associations.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/associations/belongs_to_association.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/associations/has_many_association.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/associations/has_one_association.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/base.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/callbacks.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/db2_adapter.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/sqlserver_adapter.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/fixtures.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/locking.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/migration.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/observer.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/reflection.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/schema.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/schema_dumper.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/timestamp.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/validations.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/vendor/db2.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/vendor/simple.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/version.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/aaa_create_tables_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/abstract_unit.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/adapter_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/associations_go_eager_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/associations_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/base_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/binary_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/callbacks_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/class_inheritable_attributes_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/column_alias_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/connections/native_mysql/connection.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/connections/native_sqlite/connection.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/connections/native_sqlite3/connection.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/connections/native_sqlite3/in_memory_connection.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/deprecated_associations_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/deprecated_finder_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/finder_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/accounts.yml (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/author.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/categories_posts.yml (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/category.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/company.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/company_in_module.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/customer.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/db2.drop.sql (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/db2.sql (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/db22.sql (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/firebird.drop.sql (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/firebird.sql (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/mysql.drop.sql (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/mysql.sql (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/postgresql.drop.sql (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/postgresql.sql (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/sqlite.drop.sql (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/sqlite.sql (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/sqlserver.drop.sql (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/sqlserver.sql (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/developers.yml (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/developers_projects.yml (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/mixin.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/person.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/post.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/project.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/reply.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/tasks.yml (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/topic.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/topics.yml (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/inheritance_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/locking_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/method_scoping_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/migration_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/mixin_nested_set_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/modules_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/readonly_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/reflection_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/schema_dumper_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/threaded_connections_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/unconnected_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activerecord/test/validations_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/CHANGELOG (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/Rakefile (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/breakpoint.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/clean_logger.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/array.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/array/conversions.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/blank.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/date/conversions.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/enumerable.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/exception.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/hash.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/integer/inflections.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/kernel.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/numeric/time.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/string.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/string/access.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/string/inflections.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/time/calculations.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/time/conversions.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/dependencies.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/inflections.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/inflector.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/ordered_options.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/version.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/test/class_inheritable_attributes_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/test/clean_logger_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/array_ext_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/blank_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/enumerable_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/exception_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/hash_ext_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/kernel_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/object_and_class_ext_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/string_ext_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/time_ext_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/test/dependencies_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/activesupport/test/inflector_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/CHANGELOG (diff)
- rool/rails/typo/trunk/vendor/rails/railties/README (diff)
- rool/rails/typo/trunk/vendor/rails/railties/Rakefile (diff)
- rool/rails/typo/trunk/vendor/rails/railties/bin/rails (diff)
- rool/rails/typo/trunk/vendor/rails/railties/configs/lighttpd.conf (diff)
- rool/rails/typo/trunk/vendor/rails/railties/configs/routes.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/environments/boot.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/environments/development.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/environments/environment.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/environments/production.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/environments/test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/fresh_rakefile (diff)
- rool/rails/typo/trunk/vendor/rails/railties/html/500.html (diff)
- rool/rails/typo/trunk/vendor/rails/railties/html/index.html (diff)
- rool/rails/typo/trunk/vendor/rails/railties/html/javascripts/controls.js (diff)
- rool/rails/typo/trunk/vendor/rails/railties/html/javascripts/dragdrop.js (diff)
- rool/rails/typo/trunk/vendor/rails/railties/html/javascripts/effects.js (diff)
- rool/rails/typo/trunk/vendor/rails/railties/html/javascripts/prototype.js (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/code_statistics.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/commands/console.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/commands/plugin.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/commands/process/reaper.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/commands/process/spawner.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/commands/runner.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/commands/server.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/commands/servers/lighttpd.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/dispatcher.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/fcgi_handler.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/initializer.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/commands.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/applications/app/app_generator.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/mailer/USAGE (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/migration/USAGE (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/model/USAGE (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/model/model_generator.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/model/templates/unit_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/plugin/USAGE (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/plugin/plugin_generator.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/plugin/templates/Rakefile (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/scaffold/templates/style.css (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/session_migration/USAGE (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/options.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/tasks/databases.rake (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/tasks/documentation.rake (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/tasks/framework.rake (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/tasks/misc.rake (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/tasks/statistics.rake (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/tasks/testing.rake (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/test_help.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/lib/webrick_server.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/test/dispatcher_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/railties/test/rails_info_controller_test.rb (diff)
- rool/rails/typo/trunk/vendor/rails/release.rb (diff)
- rool/rails/typo/trunk/vendor/redcloth/bin/redcloth (diff)
- rool/rails/typo/trunk/vendor/redcloth/doc/CHANGELOG (diff)
- rool/rails/typo/trunk/vendor/redcloth/doc/README (diff)
- rool/rails/typo/trunk/vendor/redcloth/doc/REFERENCE (diff)
- rool/rails/typo/trunk/vendor/redcloth/lib/redcloth.rb (diff)
- rool/rails/typo/trunk/vendor/redcloth/run-tests.rb (diff)
- rool/rails/typo/trunk/vendor/redcloth/tests/table.yml (diff)
- rool/rails/typo/trunk/vendor/redcloth/tests/textism.yml (diff)
rool/rails/typo/trunk/app/views/admin/comments/show.rhtml:
prev. | current | |
1 | | |
1 | <% @page_heading = "Comments for #{ link_to h(@article.title), :controller => 'content', :action => 'show', :id => @article }" %> | |
<div class="form"> | ||
<label>Author:</label> <span class="static"><%=h @comment.author %></span><br/> | ||
5 | <label>URL:</label> <span class="static"><%=h @comment.url %></span><br/> | |
6 | <label>Email:</label> <span class="static"><%=h @comment.email %></span><br/> | |
<label>Body:</label> <span class="static"><%=h @comment.body %></span><br/> | ||
<label>IP Address:</label> <span class="static"><%=h @comment.ip %></span><br/> | ||
<label>Created at:</label> <span class="static"><%=h @comment.created_at %></span><br/> |
rool/rails/typo/trunk/app/views/admin/comments/new.rhtml:
prev. | current | |
1 | | |
1 | <% @page_heading = "Comments for #{ link_to h(@article.title), :controller => 'content', :action => 'show', :id => @article }" %> | |
<h3>Creating comment</h3> | ||
rool/rails/typo/trunk/README:
prev. | current | |
What is it? | ||
=========== | ||
4 | ||
5 | ||
6 | ||
7 | ||
8 | ||
4 | Typo is a weblog system written in Ruby using Ruby on Rails. Weblogs are cool, | |
5 | weblogs are "in" and everyone who writes code has an different opinion on how | |
6 | a weblog should be written. Typo is our take on it. Typo is designed to be | |
7 | usable by programmers and non-programmers, while being easy for programmers to | |
8 | extend. | |
Requirements | ||
============ | ||
Currently you need all of those things to get typo to run: | ||
15 | | |
16 | | |
17 | | |
15 | * Ruby 1.8.4 or higher | |
16 | * Rails 1.1.x | |
* A database. Typo supports MySQL, PostgreSQL, and SQLite. | ||
* Ruby drivers for your database. | ||
* For best performance, you should have a web server running either | ||
... | ... | |
but Sqlite doesn't have full support for database migrations in Rails | ||
0.13.1. | ||
34 | | |
35 | | |
36 | | |
37 | | |
33 | * Create a database for typo. You can find schemas in the db/ folder. | |
34 | * Create config/database.yml using database.yml.example to reflect your | |
35 | newly created database configuration | |
* Run script/server -e production and see if it works | ||
* Point your browser to http://your.domain.com:3000/ and follow the | ||
install process | ||
42 | ||
43 | ||
44 | ||
40 | Typo, like all Rails apps, doesn't work well as a CGI. Seriously consider | |
41 | using FastCGI instead. To deploy on FastCGI you will need to follow the setup | |
42 | instructions on the typo page at http://www.typosphere.org/trac/wiki/FastCgi | |
44 | By default, Typo runs in *development* mode. This is very useful for | |
45 | developers, but it can cause horrible performance for users who aren't | |
46 | changing Typo's code. Production mode can easily be 20x as fast as development | |
47 | mode. To change the default, edit the second line of config/environment.rb and | |
48 | change 'development' to 'production', or follow the directions on the FastCGI | |
49 | configuration page on the Typo wiki. | |
50 | ||
Permissions | ||
=========== | ||
... | ... | |
process--in a hosted environment this may be your user; on dedicated | ||
systems it may be something like 'httpd' or 'www-data'. | ||
54 | ||
55 | ||
56 | ||
57 | ||
58 | ||
59 | ||
59 | The specific directories in question are 'log/' (and everything underneath | |
60 | it), 'cache/', and 'public/'. Strictly speaking, Rails will continue to work | |
61 | if public isn't writable, but Typo's page caching code will work properly and | |
62 | this will cause Typo to be slower and use much more CPU time. For the security | |
63 | conscious, Rails really only needs the ability to change a half-dozen files | |
64 | and subdirectories under public/, ask on the Typo mailing list for more | |
65 | details. | |
Usage | ||
====== | ||
... | ... | |
change Typo's configuration settings. For posting new content, you can | ||
either use this administrative web interface or a desktop blog editor | ||
like MarsEdit or Ecto. For a short list of clients which are confirmed | ||
69 | ||
75 | to work please visit http://typosphere.org/trac/wiki/DesktopClients. | |
Client setup | ||
============ | ||
... | ... | |
Tell me about your blog | ||
======================= | ||
80 | ||
81 | ||
86 | Add yourself to the list of typo blogs at http://typosphere.org/trac/wiki/TypoPowered | |
87 | and subscribe to the typo mailing list. | |
Enjoy, | ||
Your typo team | ||
92 |
rool/rails/typo/trunk/Rakefile:
prev. | current | |
1 | # Add your own tasks in files placed in lib/tasks ending in .rake, | |
2 | # for example lib/tasks/switchtower.rake, and they will automatically be available to Rake. | |
3 | ||
4 | require(File.join(File.dirname(__FILE__), 'config', 'boot')) | |
5 | ||
require 'rake' | ||
require 'rake/testtask' | ||
require 'rake/rdoctask' | ||
4 | ||
5 | ||
7 | ||
8 | ||
9 | ||
10 | ||
11 | ||
12 | ||
13 | ||
14 | ||
15 | ||
16 | ||
17 | ||
18 | ||
19 | ||
20 | ||
21 | ||
22 | ||
23 | | |
24 | | |
25 | | |
26 | ||
27 | ||
28 | ||
29 | ||
30 | ||
31 | ||
32 | ||
33 | ||
34 | | |
35 | | |
36 | | |
37 | | |
38 | | |
39 | | |
40 | ||
41 | ||
42 | ||
43 | ||
44 | | |
45 | | |
46 | | |
47 | | |
48 | ||
49 | | |
50 | | |
51 | | |
52 | ||
53 | ||
54 | ||
55 | ||
56 | ||
57 | | |
58 | | |
59 | | |
60 | ||
61 | ||
62 | ||
63 | ||
64 | ||
65 | | |
66 | | |
67 | | |
68 | ||
69 | ||
70 | ||
71 | ||
72 | ||
73 | | |
74 | | |
75 | | |
76 | | |
77 | | |
78 | ||
79 | ||
80 | ||
81 | ||
82 | | |
83 | | |
84 | | |
85 | | |
86 | | |
87 | | |
88 | | |
89 | | |
90 | | |
91 | | |
92 | | |
93 | | |
94 | | |
95 | | |
96 | | |
97 | | |
98 | | |
99 | | |
100 | | |
101 | | |
102 | | |
103 | | |
104 | | |
105 | | |
106 | | |
107 | | |
108 | | |
109 | | |
110 | | |
111 | | |
112 | | |
113 | | |
114 | ||
115 | ||
116 | ||
117 | ||
118 | | |
119 | | |
120 | | |
121 | | |
122 | | |
123 | | |
124 | | |
125 | | |
126 | | |
127 | | |
128 | ||
129 | ||
130 | ||
131 | ||
132 | | |
133 | | |
134 | | |
135 | | |
136 | | |
137 | | |
138 | | |
139 | | |
140 | | |
141 | | |
142 | | |
143 | | |
144 | | |
145 | | |
146 | | |
147 | | |
148 | | |
149 | | |
150 | ||
151 | ||
152 | ||
153 | ||
154 | | |
155 | | |
156 | | |
157 | | |
158 | | |
159 | | |
160 | | |
161 | | |
162 | | |
163 | | |
164 | | |
165 | | |
166 | | |
167 | | |
168 | | |
169 | ||
170 | ||
171 | ||
172 | ||
173 | | |
174 | | |
175 | | |
176 | | |
177 | | |
178 | | |
179 | | |
180 | | |
181 | | |
182 | | |
183 | | |
184 | | |
185 | | |
186 | | |
187 | | |
188 | | |
189 | ||
190 | ||
191 | ||
192 | ||
193 | | |
194 | | |
195 | | |
196 | | |
197 | | |
198 | | |
199 | | |
200 | | |
201 | | |
202 | | |
203 | | |
204 | | |
205 | | |
206 | | |
207 | | |
208 | ||
209 | ||
210 | ||
211 | | |
212 | | |
213 | | |
214 | ||
215 | ||
216 | ||
217 | ||
218 | | |
219 | ||
220 | ||
221 | ||
222 | ||
223 | | |
224 | | |
225 | ||
226 | ||
227 | ||
228 | ||
229 | | |
230 | | |
231 | ||
232 | ||
233 | ||
234 | ||
235 | | |
236 | ||
237 | ||
238 | ||
239 | ||
240 | | |
241 | ||
242 | | |
243 | | |
244 | | |
245 | ||
246 | | |
247 | | |
248 | | |
249 | | |
250 | ||
251 | | |
252 | | |
253 | | |
254 | | |
255 | | |
256 | | |
257 | | |
258 | ||
259 | | |
260 | | |
261 | | |
262 | | |
263 | | |
264 | | |
265 | | |
266 | | |
267 | ||
268 | | |
269 | | |
270 | | |
271 | ||
272 | | |
273 | | |
274 | | |
275 | | |
276 | ||
277 | | |
278 | | |
279 | ||
280 | | |
281 | | |
282 | | |
283 | | |
284 | ||
285 | | |
286 | ||
287 | | |
288 | | |
289 | | |
290 | | |
291 | | |
292 | | |
293 | | |
294 | | |
295 | | |
296 | | |
297 | ||
298 | | |
299 | | |
300 | | |
301 | | |
302 | | |
303 | | |
304 | | |
305 | | |
306 | | |
307 | | |
308 | | |
309 | | |
310 | | |
311 | | |
312 | | |
313 | | |
314 | | |
315 | | |
316 | | |
317 | | |
318 | | |
319 | | |
320 | | |
321 | | |
322 | ||
323 | | |
324 | | |
325 | | |
326 | ||
327 | | |
328 | | |
329 | | |
330 | | |
331 | | |
332 | | |
333 | | |
334 | ||
335 | | |
336 | | |
337 | | |
338 | ||
339 | | |
340 | | |
341 | | |
342 | | |
343 | | |
344 | ||
345 | | |
346 | | |
347 | | |
348 | | |
349 | ||
350 | | |
351 | | |
352 | | |
353 | ||
354 | ||
355 | ||
356 | ||
10 | require 'tasks/rails' | |
rool/rails/typo/trunk/app/apis/blogger_service.rb:
prev. | current | |
api_method :getUserInfo, | ||
:expects => [ {:appkey => :string}, {:username => :string}, {:password => :string} ], | ||
:returns => [BloggerStructs::User] | ||
29 | | |
29 | ||
api_method :getUsersBlogs, | ||
:expects => [ {:appkey => :string}, {:username => :string}, {:password => :string} ], | ||
:returns => [[BloggerStructs::Blog]] | ||
... | ... | |
class BloggerService < TypoWebService | ||
web_service_api BloggerApi | ||
43 | before_invocation :authenticate | |
44 | | |
45 | | |
46 | | |
47 | | |
48 | | |
49 | | |
50 | | |
def deletePost(appkey, postid, username, password, publish) | ||
52 | | |
46 | article = this_blog.articles.find(postid) | |
article.destroy | ||
true | ||
end | ||
56 | | |
50 | ||
def getUserInfo(appkey, username, password) | ||
BloggerStructs::User.new( | ||
:userid => username, | ||
... | ... | |
:url => controller.url_for(:controller => "/") | ||
) | ||
end | ||
67 | | |
61 | ||
def getUsersBlogs(appkey, username, password) | ||
[BloggerStructs::Blog.new( | ||
:url => controller.url_for(:controller => "/"), | ||
:blogid => 1, | ||
72 | | |
66 | :blogName => this_blog.blog_name | |
)] | ||
end | ||
def newPost(appkey, blogid, username, password, content, publish) | ||
title, categories, body = content.match(%r{^<title>(.+?)</title>(?:<category>(.+?)</category>)?(.+)$}mi).captures rescue nil | ||
79 | | |
80 | | |
81 | | |
82 | | |
83 | | |
84 | | |
85 | | |
73 | article = this_blog.articles.build | |
74 | article.body = body || content || '' | |
75 | article.title = title || content.split.slice(0..5).join(' ') || '' | |
76 | article.published = publish | |
77 | article.author = username | |
78 | article.published_at = Time.now | |
79 | article.user = @user | |
80 | article.allow_comments = this_blog.default_allow_comments | |
81 | article.allow_pings = this_blog.default_allow_pings | |
82 | article.text_filter = this_blog.text_filter | |
83 | article.save | |
if categories | ||
categories.split(",").each do |c| | ||
... | ... | |
end | ||
end | ||
93 | | |
article.id | ||
end | ||
rool/rails/typo/trunk/app/apis/meta_weblog_service.rb:
prev. | current | |
class MetaWeblogService < TypoWebService | ||
web_service_api MetaWeblogApi | ||
68 | | |
69 | | |
70 | | |
68 | before_invocation :authenticate | |
72 | | |
73 | | |
74 | | |
75 | ||
def getCategories(blogid, username, password) | ||
77 | | |
71 | Category.find(:all).collect { |c| c.name } | |
end | ||
def getPost(postid, username, password) | ||
81 | | |
82 | | |
75 | article = this_blog.articles.find(postid) | |
76 | ||
article_dto_from(article) | ||
84 | | |
78 | end | |
def getRecentPosts(blogid, username, password, numberOfPosts) | ||
87 | | |
81 | this_blog.articles.find(:all, :order => "created_at DESC", :limit => numberOfPosts).collect{ |c| article_dto_from(c) } | |
end | ||
def newPost(blogid, username, password, struct, publish) | ||
91 | | |
85 | article = this_blog.articles.build | |
article.body = struct['description'] || '' | ||
article.title = struct['title'] || '' | ||
94 | | |
88 | article.published = publish | |
article.author = username | ||
96 | | |
90 | article.published_at = struct['dateCreated'].to_time.getlocal rescue Time.now | |
article.user = @user | ||
# Movable Type API support | ||
100 | | |
101 | | |
94 | article.allow_comments = struct['mt_allow_comments'] || this_blog.default_allow_comments | |
95 | article.allow_pings = struct['mt_allow_pings'] || this_blog.default_allow_pings | |
article.extended = struct['mt_text_more'] || '' | ||
article.excerpt = struct['mt_excerpt'] || '' | ||
article.keywords = struct['mt_keywords'] || '' | ||
105 | | |
106 | | |
99 | article.text_filter = TextFilter.find_by_name(struct['mt_convert_breaks'] || this_blog.text_filter) | |
100 | ||
if struct['categories'] | ||
article.categories.clear | ||
109 | | |
103 | Category.find(:all).each do |c| | |
article.categories << c if struct['categories'].include?(c.name) | ||
end | ||
end | ||
114 | | |
115 | | |
116 | | |
117 | | |
108 | if article.save | |
109 | article.id.to_s | |
110 | else | |
111 | raise article.errors.full_messages * ", " | |
112 | end | |
end | ||
119 | | |
114 | ||
def deletePost(appkey, postid, username, password, publish) | ||
121 | | |
116 | article = this_blog.articles.find(postid) | |
article.destroy | ||
true | ||
end | ||
def editPost(postid, username, password, struct, publish) | ||
127 | | |
122 | article = this_blog.articles.find(postid) | |
article.body = struct['description'] || '' | ||
article.title = struct['title'] || '' | ||
130 | | |
125 | article.published = publish | |
article.author = username | ||
132 | | |
127 | article.published_at = struct['dateCreated'].to_time.getlocal unless struct['dateCreated'].blank? | |
# Movable Type API support | ||
135 | | |
136 | | |
137 | | |
138 | | |
139 | | |
140 | | |
130 | article.allow_comments = struct['mt_allow_comments'] || this_blog.default_allow_comments | |
131 | article.allow_pings = struct['mt_allow_pings'] || this_blog.default_allow_pings | |
132 | article.extended = struct['mt_text_more'] || '' | |
133 | article.excerpt = struct['mt_excerpt'] || '' | |
134 | article.keywords = struct['mt_keywords'] || '' | |
135 | article.text_filter = TextFilter.find_by_name(struct['mt_convert_breaks'] || this_blog.text_filter) | |
if struct['categories'] | ||
article.categories.clear | ||
144 | | |
139 | Category.find(:all).each do |c| | |
article.categories << c if struct['categories'].include?(c.name) | ||
end | ||
end | ||
RAILS_DEFAULT_LOGGER.info(struct['mt_tb_ping_urls']) | ||
149 | | |
150 | ||
151 | | |
144 | article.save | |
true | ||
end | ||
154 | | |
147 | ||
def newMediaObject(blogid, username, password, data) | ||
156 | | |
157 | | |
158 | | |
159 | | |
160 | | |
161 | | |
149 | resource = Resource.create(:filename => data['name'], :mime => data['type'], :created_at => Time.now) | |
150 | resource.write_to_disk(data['bits']) | |
163 | | |
164 | | |
165 | | |
166 | | |
167 | | |
168 | | |
169 | | |
170 | | |
152 | MetaWeblogStructs::Url.new("url" => controller.url_for(:controller => "/files/#{resource.filename}")) | |
153 | end | |
def article_dto_from(article) | ||
MetaWeblogStructs::Article.new( | ||
... | ... | |
:mt_text_more => article.extended.to_s, | ||
:mt_excerpt => article.excerpt.to_s, | ||
:mt_keywords => article.keywords.to_s, | ||
184 | | |
185 | | |
186 | | |
167 | :mt_allow_comments => article.allow_comments? ? 1 : 0, | |
168 | :mt_allow_pings => article.allow_pings? ? 1 : 0, | |
169 | :mt_convert_breaks => (article.text_filter.name.to_s rescue ''), | |
:mt_tb_ping_urls => article.pings.collect { |p| p.url }, | ||
188 | | |
171 | :dateCreated => (article.published_at.to_formatted_s(:db) rescue "") | |
) | ||
end | ||
... | ... | |
def article_url(article) | ||
begin | ||
196 | | |
197 | | |
198 | | |
179 | controller.url_for :controller=>"articles", :action =>"permalink", | |
180 | :year => article.published_at.year, :month => sprintf("%.2d", article.published_at.month), | |
181 | :day => sprintf("%.2d", article.published_at.day), :title => article.stripped_title | |
rescue | ||
183 | created = article.published_at | |
184 | sprintf("/articles/%.4d/%.2d/%.2d/#{article.stripped_title}", created.year, created.month, created.day) | |
# FIXME: rescue is needed for functional tests as the test framework currently doesn't supply fully | ||
# fledged controller instances (yet?) | ||
202 | | |
end | ||
end | ||
190 | def server_url | |
191 | controller.url_for(:only_path => false, :controller => "/") | |
192 | end | |
193 | ||
def pub_date(time) | ||
time.strftime "%a, %e %b %Y %H:%M:%S %Z" | ||
end |
rool/rails/typo/trunk/app/apis/movable_type_service.rb:
prev. | current | |
:expects => [ {:postid => :string}, {:username => :string}, {:password => :string}, {:categories => [MovableTypeStructs::CategoryPerPost]} ], | ||
:returns => [:bool] | ||
52 | api_method :supportedMethods, | |
53 | :expects => [], | |
54 | :returns => [[:string]] | |
55 | ||
api_method :supportedTextFilters, | ||
57 | :expects => [], | |
:returns => [[MovableTypeStructs::TextFilter]] | ||
api_method :getTrackbackPings, | ||
... | ... | |
class MovableTypeService < TypoWebService | ||
web_service_api MovableTypeApi | ||
67 | | |
72 | ||
before_invocation :authenticate, :except => [:getTrackbackPings, :supportedMethods, :supportedTextFilters] | ||
def getRecentPostTitles(blogid, username, password, numberOfPosts) | ||
71 | | |
76 | this_blog.articles.find(:all,:order => "created_at DESC", :limit => numberOfPosts).collect do |article| | |
MovableTypeStructs::ArticleTitle.new( | ||
:dateCreated => article.created_at, | ||
:userid => blogid.to_s, | ||
:postid => article.id.to_s, | ||
:title => article.title | ||
77 | | |
82 | ) | |
end | ||
end | ||
def getCategoryList(blogid, username, password) | ||
82 | | |
87 | Category.find_all.collect do |c| | |
MovableTypeStructs::CategoryList.new( | ||
:categoryId => c.id, | ||
:categoryName => c.name | ||
... | ... | |
end | ||
def getPostCategories(postid, username, password) | ||
91 | | |
96 | this_blog.articles.find(postid).categories.collect do |c| | |
MovableTypeStructs::CategoryPerPost.new( | ||
:categoryName => c.name, | ||
:categoryId => c.id.to_i, | ||
... | ... | |
end | ||
def setPostCategories(postid, username, password, categories) | ||
101 | | |
106 | article = this_blog.articles.find(postid) | |
article.categories.clear if categories != nil | ||
for c in categories | ||
category = Category.find(c['categoryId']) | ||
article.categories.push_with_attributes(category, :is_primary => c['isPrimary']) | ||
end | ||
108 | | |
article.save | ||
end | ||
112 | | |
113 | | |
def supportedMethods() | ||
117 | MovableTypeApi.api_methods.keys.collect { |method| method.to_s } | |
end | ||
117 | | |
120 | # Support for markdown and textile formatting dependant on the relevant | |
# translators being available. | ||
def supportedTextFilters() | ||
120 | | |
121 | | |
122 | | |
123 | | |
124 | | |
125 | | |
123 | TextFilter.find(:all).collect do |filter| | |
124 | MovableTypeStructs::TextFilter.new(:key => filter.name, :label => filter.description) | |
125 | end | |
end | ||
def getTrackbackPings(postid) | ||
129 | | |
129 | article = this_blog.articles.find(postid) | |
article.trackbacks.collect do |t| | ||
MovableTypeStructs::TrackBack.new( | ||
:pingTitle => t.title.to_s, | ||
... | ... | |
end | ||
def publishPost(postid, username, password) | ||
140 | | |
141 | | |
142 | | |
140 | article = this_blog.articles.find(postid) | |
141 | article.published = true | |
142 | article.save | |
end | ||
private |
rool/rails/typo/trunk/app/apis/typo_web_service.rb:
prev. | current | |
class TypoWebService < ActionWebService::Base | ||
2 | attr_accessor :controller | |
4 | def initialize(controller) | |
5 | @controller = controller | |
6 | end | |
7 | ||
8 | def this_blog | |
9 | controller.send(:this_blog) | |
10 | end | |
11 | ||
protected | ||
def authenticate(name, args) | ||
... | ... | |
# Coping with backwards incompatibility change in AWS releases post 0.6.2 | ||
begin | ||
h = method.expects_to_hash(args) | ||
11 | | |
20 | raise "Invalid login" unless @user=User.authenticate(h[:username], h[:password]) | |
rescue NoMethodError | ||
username, password = method[:expects].index(:username=>String), method[:expects].index(:password=>String) | ||
14 | | |
23 | raise "Invalid login" unless @user = User.authenticate(args[username], args[password]) | |
end | ||
end | ||
end |
rool/rails/typo/trunk/app/controllers/accounts_controller.rb:
prev. | current | |
class AccountsController < ApplicationController | ||
3 | before_filter :verify_users, :only => [:login] | |
4 | ||
def login | ||
case request.method | ||
when :post | ||
... | ... | |
flash[:notice] = "Login successful" | ||
cookies[:is_admin] = "yes" | ||
10 | | |
12 | redirect_back_or_default :controller => "admin/content", :action => "index" | |
else | ||
12 | | |
14 | flash.now[:notice] = "Login unsuccessful" | |
@login = params[:user_login] | ||
end | ||
end | ||
end | ||
18 | | |
20 | ||
def signup | ||
20 | | |
21 | | |
22 | redirect_to :action => "login" and return unless User.count.zero? | |
23 | ||
@user = User.new(params[:user]) | ||
23 | | |
25 | ||
if request.post? and @user.save | ||
session[:user] = User.authenticate(@user.login, params[:user][:password]) | ||
flash[:notice] = "Signup successful" | ||
redirect_to :controller => "admin/general", :action => "index" | ||
return | ||
29 | | |
30 | | |
31 | | |
31 | end | |
32 | end | |
33 | ||
def logout | ||
session[:user] = nil | ||
cookies.delete :is_admin | ||
end | ||
36 | | |
38 | ||
def welcome | ||
end | ||
42 | private | |
43 | ||
44 | def verify_users | |
45 | if User.count == 0 | |
46 | redirect_to :controller => "accounts", :action => "signup" | |
47 | else | |
48 | true | |
49 | end | |
50 | end | |
51 | ||
end |
rool/rails/typo/trunk/app/controllers/admin/base_controller.rb:
prev. | current | |
class Admin::BaseController < ApplicationController | ||
cattr_accessor :look_for_migrations | ||
@@look_for_migrations = true | ||
4 | | |
4 | ||
layout 'administration' | ||
before_filter :login_required, :except => [ :login, :signup ] | ||
before_filter :look_for_needed_db_updates, :except => [:login, :signup, :update_database, :migrate] | ||
... | ... | |
cache_sweeper :blog_sweeper | ||
private | ||
12 | | |
12 | ||
def look_for_needed_db_updates | ||
if Migrator.offer_migration_when_available | ||
redirect_to :controller => '/admin/general', :action => 'update_database' if Migrator.current_schema_version != Migrator.max_schema_version | ||
end | ||
end | ||
18 | | |
18 | ||
19 | include_protected ActionView::Helpers::TagHelper, ActionView::Helpers::TextHelper | |
20 | ||
end |
rool/rails/typo/trunk/app/controllers/admin/blacklist_controller.rb:
prev. | current | |
1 | ||
2 | ||
class Admin::BlacklistController < Admin::BaseController | ||
def index | ||
list | ||
... | ... | |
def new | ||
@blacklist_pattern = BlacklistPattern.new | ||
19 | | |
17 | ||
if params[:blacklist_pattern].has_key?('type') | ||
@blacklist_pattern = case params[:blacklist_pattern][:type] | ||
when "StringPattern": StringPattern.new | ||
... | ... | |
end rescue nil | ||
@blacklist_pattern.attributes = params[:blacklist_pattern] | ||
28 | | |
26 | ||
if request.post? and @blacklist_pattern.save | ||
flash[:notice] = 'BlacklistPattern was successfully created.' | ||
redirect_to :action => 'list' | ||
32 | | |
30 | end | |
end | ||
def edit | ||
... | ... | |
if request.post? and @blacklist_pattern.save | ||
flash[:notice] = 'BlacklistPattern was successfully updated.' | ||
redirect_to :action => 'list' | ||
41 | | |
39 | end | |
end | ||
def destroy | ||
... | ... | |
redirect_to :action => 'list' | ||
end | ||
end | ||
51 | | |
49 | ||
end |
rool/rails/typo/trunk/app/controllers/admin/cache_controller.rb:
prev. | current | |
class Admin::CacheController < Admin::BaseController | ||
2 | | |
2 | ||
def index | ||
list | ||
render_action 'list' | ||
... | ... | |
def sweep | ||
PageCache.sweep_all | ||
14 | | |
14 | expire_fragment(/.*/) | |
15 | ||
16 | flash[:notice] = 'Cache was cleared' | |
redirect_to :controller => 'general' | ||
end | ||
17 | | |
19 | ||
20 | def sweep_html | |
21 | Article.transaction do | |
22 | Article.update_all 'body_html = null' | |
23 | Comment.update_all 'body_html = null' | |
24 | Page.update_all 'body_html = null' | |
25 | end | |
26 | ||
27 | flash[:notice] = 'HTML was cleared' | |
28 | redirect_to :controller => 'general' | |
29 | end | |
30 | ||
end |
rool/rails/typo/trunk/app/controllers/admin/categories_controller.rb:
prev. | current | |
class Admin::CategoriesController < Admin::BaseController | ||
2 | | |
2 | ||
def index | ||
list | ||
render_action 'list' | ||
end | ||
def list | ||
9 | | |
9 | @categories = Category.find(:all, :order => :position) | |
end | ||
def show | ||
... | ... | |
def new | ||
@category = Category.new(params[:category]) | ||
18 | | |
18 | ||
if request.post? and @category.save | ||
flash[:notice] = 'Category was successfully created.' | ||
21 | | |
22 | | |
21 | else | |
22 | flash[:error] = 'Category could not be created.' | |
23 | end | |
24 | ||
25 | redirect_to :action => 'list' | |
end | ||
def edit | ||
... | ... | |
if request.post? and @category.save | ||
flash[:notice] = 'Category was successfully updated.' | ||
redirect_to :action => 'list' | ||
31 | | |
34 | end | |
end | ||
def destroy | ||
... | ... | |
redirect_to :action => 'list' | ||
end | ||
end | ||
41 | | |
44 | ||
45 | def order | |
46 | Category.reorder(params[:category_list]) | |
47 | render :nothing => true | |
48 | end | |
49 | ||
50 | def asort | |
51 | Category.reorder_alpha | |
52 | category_container | |
53 | end | |
54 | ||
55 | def category_container | |
56 | @categories = Category.find(:all, :order => :position) | |
57 | render :partial => "categories" | |
58 | end | |
59 | ||
60 | def reorder | |
61 | @categories = Category.find(:all, :order => :position) | |
62 | render :layout => false | |
63 | end | |
end |
rool/rails/typo/trunk/app/controllers/admin/comments_controller.rb:
prev. | current | |
class Admin::CommentsController < Admin::BaseController | ||
2 | | |
2 | ||
before_filter :get_article | ||
4 | | |
5 | | |
4 | ||
def index | ||
list | ||
render_action 'list' | ||
... | ... | |
@comment = @article.comments.build(params[:comment]) | ||
if request.post? and @comment.save | ||
22 | # We should probably wave a spam filter over this, but for now, just mark it as published. | |
23 | @comment.published = true | |
flash[:notice] = 'Comment was successfully created.' | ||
redirect_to :action => 'show', :id => @comment.id | ||
25 | | |
26 | end | |
end | ||
def edit | ||
@comment = @article.comments.find(params[:id]) | ||
@comment.attributes = params[:comment] | ||
32 | ||
if request.post? and @comment.save | ||
flash[:notice] = 'Comment was successfully updated.' | ||
redirect_to :action => 'show', :id => @comment.id | ||
34 | | |
36 | end | |
end | ||
def destroy | ||
... | ... | |
redirect_to :action => 'list' | ||
end | ||
end | ||
44 | | |
46 | ||
private | ||
46 | | |
48 | ||
def get_article | ||
@article = Article.find(params[:article_id]) | ||
... | ... | |
redirect_to '/admin' | ||
end | ||
end | ||
54 | | |
56 | ||
end |
rool/rails/typo/trunk/app/controllers/admin/content_controller.rb:
prev. | current | |
class Admin::ContentController < Admin::BaseController | ||
2 | ||
3 | | |
4 | ||
def index | ||
list | ||
render_action 'list' | ||
end | ||
def list | ||
11 | | |
12 | | |
13 | | |
14 | | |
8 | @articles_pages, @articles = with_blog_scoped_classes do | |
9 | paginate(:article, :per_page => 15, :order_by => "created_at DESC", | |
10 | :parameter => 'id') | |
11 | end | |
12 | setup_categories | |
13 | @article = this_blog.articles.build(params[:article]) | |
end | ||
def show | ||
@article = Article.find(params[:id]) | ||
19 | | |
18 | setup_categories | |
19 | @resources = Resource.find(:all, :order => 'created_at DESC') | |
end | ||
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
30 | | |
22 | def new; new_or_edit; end | |
23 | def edit; new_or_edit; end | |
24 | ||
25 | def destroy | |
26 | @article = Article.find(params[:id]) | |
if request.post? | ||
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | | |
28 | @article.destroy | |
29 | redirect_to :action => 'list' | |
end | ||
end | ||
41 | | |
33 | def category_add; do_add_or_remove_fu; end | |
34 | alias_method :category_remove, :category_add | |
35 | alias_method :resource_add, :category_add | |
36 | alias_method :resource_remove, :category_add | |
37 | ||
38 | def preview | |
39 | @headers["Content-Type"] = "text/html; charset=utf-8" | |
40 | @article = Article.new(params[:article]) | |
41 | render :layout => false | |
42 | end | |
43 | ||
44 | def attachment_box_add | |
45 | render :partial => 'admin/content/attachment', :locals => { :attachment_num => params[:id] } | |
46 | end | |
47 | ||
48 | def attachment_box_remove | |
49 | render :inline => "<%= javascript_tag 'document.getElementById(\"attachments\").removeChild(document.getElementById(\"attachment_#{params[:id]}\")); return false;' -%>" | |
50 | end | |
51 | ||
52 | def attachment_save(attachment) | |
53 | begin | |
54 | Resource.create(:filename => attachment.original_filename, | |
55 | :mime => attachment.content_type.chomp, :created_at => Time.now).write_to_disk(attachment) | |
56 | rescue => e | |
57 | logger.info(e.message) | |
58 | nil | |
59 | end | |
60 | end | |
61 | ||
62 | protected | |
63 | ||
64 | attr_accessor :resources, :categories, :resource, :category | |
65 | ||
66 | def do_add_or_remove_fu | |
67 | attrib, action = params[:action].split('_') | |
@article = Article.find(params[:id]) | ||
43 | | |
44 | | |
45 | | |
46 | | |
47 | | |
48 | | |
49 | | |
50 | | |
69 | self.send("#{attrib}=", self.class.const_get(attrib.classify).find(params["#{attrib}_id"])) | |
70 | send("setup_#{attrib.pluralize}") | |
71 | @article.send(attrib.pluralize).send(real_action_for(action), send(attrib)) | |
72 | @article.save | |
73 | render :partial => "show_#{attrib.pluralize}" | |
74 | end | |
75 | ||
76 | def real_action_for(action); { 'add' => :<<, 'remove' => :delete}[action]; end | |
77 | ||
78 | def new_or_edit | |
79 | get_or_build_article | |
80 | params[:article] ||= {} | |
81 | params[:article].reverse_merge!('allow_comments' => this_blog.default_allow_comments, | |
82 | 'allow_pings' => this_blog.default_allow_pings, | |
83 | 'published' => true) | |
84 | @article.attributes = (params[:article]) | |
85 | setup_categories | |
86 | @selected = @article.categories.collect { |c| c.id } | |
87 | if request.post? | |
88 | set_article_author | |
89 | save_attachments | |
90 | if @article.save | |
91 | set_article_categories | |
92 | set_the_flash | |
redirect_to :action => 'show', :id => @article.id | ||
end | ||
53 | | |
95 | end | |
end | ||
56 | | |
57 | | |
58 | | |
59 | | |
60 | | |
98 | def set_the_flash | |
99 | case params[:action] | |
100 | when 'new' | |
101 | flash[:notice] = 'Article was successfully created' | |
102 | when 'edit' | |
103 | flash[:notice] = 'Article was successfully updated.' | |
104 | else | |
105 | raise "I don't know how to tidy up action: #{params[:action]}" | |
end | ||
end | ||
63 | | |
64 | | |
65 | | |
66 | | |
67 | | |
68 | | |
69 | | |
108 | ||
109 | def set_article_author | |
110 | return if @article.author | |
111 | @article.author = session[:user].login | |
112 | @article.user = session[:user] | |
end | ||
72 | | |
73 | | |
74 | | |
75 | | |
76 | | |
77 | | |
115 | def save_attachments | |
116 | return if params[:attachments].nil? | |
117 | params[:attachments].each do |k,v| | |
118 | a = attachment_save(v) | |
119 | @article.resources << a unless a.nil? | |
120 | end | |
end | ||
79 | | |
80 | | |
81 | | |
82 | | |
83 | | |
122 | ||
123 | def set_article_categories | |
124 | @article.categories.clear | |
125 | @article.categories = Category.find(params[:categories]) if params[:categories] | |
126 | @selected = params[:categories] || [] | |
end | ||
85 | | |
128 | ||
129 | def get_or_build_article | |
130 | @article = case params[:action] | |
131 | when 'new' | |
132 | this_blog.articles.build | |
133 | when 'edit' | |
134 | this_blog.articles.find(params[:id]) | |
135 | else | |
136 | raise "Don't know how to get article for action: #{params[:action]}" | |
137 | end | |
138 | end | |
139 | ||
140 | def setup_categories | |
141 | @categories = Category.find(:all, :order => 'UPPER(name)') | |
142 | end | |
143 | ||
144 | def setup_resources | |
145 | @resources = Resource.find(:all, :order => 'created_at DESC') | |
146 | end | |
end |
rool/rails/typo/trunk/app/controllers/admin/general_controller.rb:
prev. | current | |
class Admin::GeneralController < Admin::BaseController | ||
def index | ||
3 | if this_blog.canonical_server_url.blank? | |
4 | this_blog.canonical_server_url = server_url | |
5 | end | |
@page_cache_size = PageCache.count | ||
end | ||
5 | | |
8 | ||
9 | def redirect | |
10 | flash[:notice] = "Please review and save the settings before continuing" | |
11 | redirect_to :action => "index" | |
12 | end | |
13 | ||
def update_database | ||
@current_version = Migrator.current_schema_version | ||
8 | | |
16 | @needed_version = Migrator.max_schema_version | |
@support = Migrator.db_supports_migrations? | ||
10 | | |
18 | @needed_migrations = Migrator.available_migrations[@current_version..@needed_version].collect do |mig| | |
mig.scan(/\d+\_([\w_]+)\.rb$/).flatten.first.humanize | ||
end | ||
end | ||
14 | | |
22 | ||
def migrate | ||
16 | | |
24 | if request.post? | |
Migrator.migrate | ||
redirect_to :action => 'update_database' | ||
end | ||
end | ||
21 | | |
29 | ||
def update | ||
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
31 | if request.post? | |
32 | Blog.transaction do | |
33 | params[:setting].each { |k,v| this_blog[k] = v} | |
34 | this_blog.save | |
35 | flash[:notice] = 'config updated.' | |
end | ||
31 | | |
redirect_to :action => 'index' | ||
33 | | |
34 | | |
35 | | |
36 | | |
37 | ||
38 | | |
39 | | |
40 | | |
end | ||
42 | | |
end | ||
40 | ||
41 | private | |
end |
rool/rails/typo/trunk/app/controllers/admin/pages_controller.rb:
prev. | current | |
class Admin::PagesController < Admin::BaseController | ||
2 | | |
3 | ||
def index | ||
list | ||
render_action 'list' | ||
... | ... | |
def list | ||
@pages = Page.find(:all, :order => "id DESC") | ||
@page = Page.new(params[:page]) | ||
12 | | |
10 | @page.text_filter ||= this_blog.text_filter | |
end | ||
def show | ||
... | ... | |
def new | ||
@page = Page.new(params[:page]) | ||
@page.user_id = session[:user].id | ||
22 | | |
20 | @page.text_filter ||= this_blog.text_filter | |
if request.post? and @page.save | ||
flash[:notice] = 'Page was successfully created.' | ||
redirect_to :action => 'show', :id => @page.id | ||
... | ... | |
if request.post? and @page.save | ||
flash[:notice] = 'Page was successfully updated.' | ||
redirect_to :action => 'show', :id => @page.id | ||
35 | | |
33 | end | |
end | ||
def destroy | ||
... | ... | |
redirect_to :action => 'list' | ||
end | ||
end | ||
45 | | |
43 | ||
def preview | ||
@headers["Content-Type"] = "text/html; charset=utf-8" | ||
48 | | |
46 | @page = this_blog.pages.build(params[:page]) | |
render :layout => false | ||
end | ||
51 | | |
49 | ||
end |
rool/rails/typo/trunk/app/controllers/admin/sidebar_controller.rb:
prev. | current | |
1 | ||
2 | ||
class Admin::SidebarController < Admin::BaseController | ||
def index | ||
5 | | |
6 | | |
7 | | |
3 | @sidebars = ::SidebarController.available_sidebars.inject({}) do |hash,sb| | |
4 | hash.merge({ sb.short_name => sb }) | |
end | ||
9 | ||
10 | | |
6 | # Reset the staged position based on the active position. | |
7 | Sidebar.delete_all('active_position is null') | |
8 | @active = Sidebar.find(:all, :order => 'active_position').select do |sb| | |
9 | @sidebars[sb.controller] | |
10 | end | |
11 | flash[:sidebars] = @active.map {|sb| sb.id } | |
@available = @sidebars.values.sort { |a,b| a.name <=> b.name } | ||
end | ||
14 | | |
15 | | |
16 | | |
17 | ||
def set_active | ||
19 | | |
# Get all available plugins | ||
21 | | |
22 | | |
23 | | |
24 | | |
18 | defaults_for = available.inject({}) do |hash, item| | |
19 | hash.merge({ item.short_name => item.default_config }) | |
20 | end | |
# Get all already active plugins | ||
27 | | |
28 | | |
29 | | |
22 | activemap = flash[:sidebars].inject({}) do |h, sb_id| | |
23 | sb = Sidebar.find(sb_id.to_i) | |
24 | sb ? h.merge({ sb.html_id => sb_id }) : h | |
end | ||
31 | | |
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | | |
38 | | |
40 | | |
41 | | |
42 | | |
27 | # Figure out which plugins are referenced by the params[:active] array and | |
28 | # lay them out in a easy accessible sequential array | |
29 | flash[:sidebars] = params[:active].inject([]) do |array, name| | |
30 | if defaults_for.has_key?(name) | |
31 | @new_item = Sidebar.create!(:controller => name, | |
32 | :config => defaults_for[name]) | |
33 | @target = name | |
34 | array << @new_item.id | |
35 | elsif activemap.has_key?(name) | |
36 | array << activemap[name] | |
37 | else | |
38 | array | |
end | ||
44 | | |
end | ||
46 | ||
47 | | |
48 | | |
49 | | |
50 | | |
51 | | |
52 | | |
53 | | |
54 | | |
55 | | |
56 | | |
57 | ||
58 | | |
end | ||
61 | | |
62 | | |
63 | | |
64 | | |
65 | ||
66 | | |
67 | | |
68 | ||
69 | | |
70 | | |
71 | | |
72 | | |
def remove | ||
74 | | |
75 | | |
76 | | |
77 | ||
78 | | |
44 | flash[:sidebars] = flash[:sidebars].reject do |sb_id| | |
45 | sb_id == params[:id].to_i | |
46 | end | |
47 | @element_to_remove = params[:element] | |
end | ||
def publish | ||
Sidebar.transaction do | ||
83 | | |
84 | | |
85 | | |
52 | position = 0 | |
53 | params[:configure] ||= [] | |
54 | Sidebar.update_all('active_position = null') | |
55 | flash[:sidebars].each do |id| | |
56 | Sidebar.find(id).update_attributes(:config => params[:configure][id.to_s], | |
57 | :active_position => position) | |
58 | position += 1 | |
end | ||
87 | | |
60 | Sidebar.delete_all('active_position is null') | |
end | ||
89 | | |
62 | index | |
end | ||
92 | | |
65 | protected | |
66 | def show_available | |
67 | render :partial => 'availables', :object => available | |
68 | end | |
def available | ||
95 | | |
71 | ::SidebarController.available_sidebars.sort { |a,b| a.name <=> b.name } | |
end | ||
73 | helper_method :available | |
end |
rool/rails/typo/trunk/app/controllers/admin/themes_controller.rb:
prev. | current | |
class Admin::ThemesController < Admin::BaseController | ||
2 | | |
2 | ||
def index | ||
@themes = Theme.find_all | ||
5 | | |
5 | @themes.each do |theme| | |
6 | theme.description_html = TextFilter.filter_text(theme.description, self, nil, [:markdown,:smartypants]) | |
7 | end | |
8 | @active = this_blog.current_theme | |
end | ||
7 | | |
10 | ||
def preview | ||
send_file "#{Theme.themes_root}/#{params[:theme]}/preview.png", :type => 'image/png', :disposition => 'inline', :stream => false | ||
end | ||
11 | | |
12 | | |
13 | | |
14 | | |
16 | | |
17 | | |
18 | | |
15 | def switchto | |
16 | this_blog.theme = params[:theme] | |
17 | this_blog.save | |
redirect_to :action => 'index' | ||
20 | | |
end | ||
22 | | |
end |
rool/rails/typo/trunk/app/controllers/admin/trackbacks_controller.rb:
prev. | current | |
1 | ||
2 | | |
1 | class Admin::TrackbacksController < Admin::BaseController | |
2 | ||
before_filter :get_article | ||
def index | ||
... | ... | |
def new | ||
@trackback = @article.trackbacks.build(params[:trackback]) | ||
20 | | |
20 | ||
if request.post? and @trackback.save | ||
flash[:notice] = 'Trackback was successfully created.' | ||
redirect_to :action => 'show', :id => @trackback.id | ||
24 | | |
24 | end | |
end | ||
def edit | ||
... | ... | |
if request.post? and @trackback.save | ||
flash[:notice] = 'Trackback was successfully updated.' | ||
redirect_to :action => 'show', :id => @trackback.id | ||
33 | | |
33 | end | |
end | ||
def destroy | ||
... | ... | |
redirect_to :action => 'list' | ||
end | ||
end | ||
43 | | |
43 | ||
private | ||
def get_article |
rool/rails/typo/trunk/app/controllers/admin/users_controller.rb:
prev. | current | |
class Admin::UsersController < Admin::BaseController | ||
2 | | |
2 | ||
def index | ||
list | ||
render_action 'list' | ||
... | ... | |
if request.post? and @user.save | ||
flash[:notice] = 'User was successfully created.' | ||
redirect_to :action => 'list' | ||
21 | | |
21 | end | |
end | ||
def edit | ||
... | ... | |
if request.post? and @user.save | ||
flash[:notice] = 'User was successfully updated.' | ||
redirect_to :action => 'show', :id => @user.id | ||
30 | | |
31 | | |
30 | end | |
end | ||
def destroy | ||
@user = User.find(params[:id]) | ||
if request.post? | ||
37 | | |
36 | @user.destroy if User.count > 1 | |
redirect_to :action => 'list' | ||
end | ||
end | ||
41 | | |
40 | ||
end |
rool/rails/typo/trunk/app/controllers/application.rb:
prev. | current | |
1 | ||
# The filters added to this controller will be run for all controllers in the application. | ||
# Likewise will all the methods added be available for all controllers. | ||
class ApplicationController < ActionController::Base | ||
include LoginSystem | ||
6 | | |
7 | | |
8 | | |
9 | | |
10 | | |
11 | | |
12 | | |
13 | | |
14 | | |
15 | | |
16 | | |
17 | | |
18 | | |
19 | | |
5 | ||
6 | before_filter :get_the_blog_object | |
7 | before_filter :fire_triggers | |
8 | after_filter :flush_the_blog_object | |
9 | ||
10 | around_filter Blog | |
11 | ||
12 | protected | |
13 | ||
14 | def fire_triggers | |
15 | Trigger.fire | |
end | ||
22 | | |
23 | | |
24 | | |
25 | | |
18 | def with_blog_scoped_classes(klasses=[Content, Article, Comment, Page, Trackback], &block) | |
19 | default_id = this_blog.id | |
20 | scope_hash = { :find => { :conditions => "blog_id = #{default_id}"}, | |
21 | :create => { :blog_id => default_id } } | |
22 | klasses.inject(block) do |blk, klass| | |
23 | lambda { klass.with_scope(scope_hash, &blk) } | |
24 | end.call | |
end | ||
27 | def article_url(article, only_path = true, anchor = nil) | |
28 | article.location(anchor, only_path) | |
29 | end | |
30 | ||
31 | def server_url | |
32 | this_blog.server_url | |
33 | end | |
34 | ||
def cache | ||
$cache ||= SimpleCache.new 1.hour | ||
end | ||
31 | | |
32 | | |
33 | | |
38 | ||
39 | def get_the_blog_object | |
40 | @blog = Blog.default || Blog.create! | |
41 | true | |
end | ||
36 | | |
37 | | |
44 | def flush_the_blog_object | |
45 | @blog = nil | |
46 | true | |
end | ||
48 | ||
49 | def this_blog | |
50 | @blog || Blog.default || Blog.new | |
51 | end | |
52 | helper_method :this_blog | |
53 | ||
54 | def self.include_protected(*modules) | |
55 | modules.reverse.each do |mod| | |
56 | included_methods = mod.public_instance_methods.reject do |meth| | |
57 | self.method_defined?(meth) | |
58 | end | |
59 | self.send(:include, mod) | |
60 | included_methods.each do |meth| | |
61 | protected meth | |
62 | end | |
63 | end | |
64 | end | |
end | ||
66 |
rool/rails/typo/trunk/app/controllers/articles_controller.rb:
prev. | current | |
1 | ||
1 | class ArticlesController < ContentController | |
before_filter :verify_config | ||
3 | | |
4 | | |
3 | before_filter :check_page_query_param_for_missing_routes | |
5 | layout :theme_layout, :except => [:comment_preview, :trackback] | |
6 | ||
cache_sweeper :blog_sweeper | ||
7 | | |
9 | | |
10 | | |
9 | cached_pages = [:index, :read, :permalink, :category, :find_by_date, :archives, :view_page, :tag, :author] | |
10 | # If you're really memory-constrained, then consider replacing | |
11 | # caches_action_with_params with caches_page | |
12 | caches_action_with_params *cached_pages | |
13 | session :off, :only => cached_pages | |
14 | ||
15 | verify(:only => [:nuke_comment, :nuke_trackback], | |
16 | :session => :user, :method => :post, | |
17 | :render => { :text => 'Forbidden', :status => 403 }) | |
18 | ||
def index | ||
12 | | |
13 | | |
20 | @pages, @articles = | |
21 | paginate(:article, :per_page => this_blog.limit_article_display, | |
22 | :conditions => | |
23 | ['published = ? AND contents.created_at < ? AND blog_id = ?', | |
24 | true, Time.now, this_blog.id], | |
25 | :order_by => "contents.created_at DESC", | |
26 | :include => [:categories, :tags]) | |
end | ||
15 | | |
28 | ||
def search | ||
17 | | |
30 | @articles = this_blog.published_articles.search(params[:q]) | |
31 | render_paginated_index("No articles found...") | |
end | ||
34 | def comment_preview | |
35 | if params[:comment].blank? or params[:comment][:body].blank? | |
36 | render :nothing => true | |
37 | return | |
38 | end | |
39 | ||
40 | set_headers | |
41 | @comment = this_blog.comments.build(params[:comment]) | |
42 | @controller = self | |
43 | end | |
44 | ||
def archives | ||
21 | | |
46 | @articles = this_blog.published_articles | |
end | ||
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
48 | ||
49 | def read | |
50 | display_article { this_blog.published_articles.find(params[:id]) } | |
end | ||
29 | | |
52 | ||
def permalink | ||
31 | | |
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | | |
38 | | |
39 | | |
54 | display_article(this_blog.published_articles.find_by_permalink(*params.values_at(:year, :month, :day, :title))) | |
end | ||
41 | | |
56 | ||
def find_by_date | ||
43 | | |
44 | | |
58 | @articles = this_blog.published_articles.find_all_by_date(params[:year], params[:month], params[:day]) | |
59 | render_paginated_index | |
60 | end | |
46 | | |
47 | | |
48 | | |
49 | | |
50 | | |
51 | | |
52 | ||
53 | | |
54 | | |
55 | | |
56 | | |
def error(message = "Record not found...") | ||
58 | | |
59 | | |
63 | @message = message.to_s | |
64 | render :action => 'error' | |
end | ||
61 | | |
66 | ||
67 | def author | |
68 | render_grouping(User) | |
69 | end | |
70 | ||
def category | ||
63 | | |
64 | | |
65 | | |
66 | | |
67 | | |
68 | | |
69 | | |
70 | | |
72 | render_grouping(Category) | |
73 | end | |
72 | | |
73 | | |
74 | | |
75 | | |
75 | def tag | |
76 | render_grouping(Tag) | |
77 | end | |
77 | | |
78 | | |
79 | | |
79 | # Receive comments to articles | |
80 | def comment | |
81 | unless @request.xhr? || this_blog.sp_allow_non_ajax_comments | |
82 | render_error("non-ajax commenting is disabled") | |
83 | return | |
end | ||
81 | | |
82 | | |
83 | | |
84 | | |
85 | | |
86 | | |
87 | | |
88 | | |
90 | | |
91 | | |
92 | | |
93 | | |
94 | | |
86 | if request.post? | |
87 | begin | |
88 | params[:comment].merge!({:ip => request.remote_ip, | |
89 | :published => true }) | |
90 | @article = this_blog.published_articles.find(params[:id]) | |
91 | @comment = @article.comments.build(params[:comment]) | |
92 | @comment.user = session[:user] | |
93 | @comment.save! | |
94 | add_to_cookies(:author, @comment.author) | |
95 | add_to_cookies(:url, @comment.url) | |
96 | | |
97 | | |
98 | | |
99 | | |
100 | | |
97 | set_headers | |
98 | render :partial => "comment", :object => @comment | |
99 | rescue ActiveRecord::RecordInvalid | |
100 | STDERR.puts @comment.errors.inspect | |
101 | render_error(@comment) | |
102 | end | |
end | ||
102 | | |
104 | end | |
# Receive trackbacks linked to articles | ||
def trackback | ||
106 | | |
107 | | |
108 | | |
109 | | |
110 | | |
111 | | |
112 | | |
113 | | |
114 | | |
108 | @error_message = catch(:error) do | |
109 | if params[:__mode] == "rss" | |
110 | # Part of the trackback spec... will implement later | |
111 | # XXX. Should this throw an error? | |
112 | elsif !(params.has_key?(:url) && params.has_key?(:id)) | |
113 | throw :error, "A URL is required" | |
else | ||
begin | ||
117 | | |
118 | | |
119 | | |
120 | | |
121 | | |
122 | | |
123 | | |
124 | | |
125 | | |
126 | | |
127 | | |
116 | settings = { :id => params[:id], | |
117 | :url => params[:url], :blog_name => params[:blog_name], | |
118 | :title => params[:title], :excerpt => params[:excerpt], | |
119 | :ip => request.remote_ip, :published => true } | |
120 | this_blog.ping_article!(settings) | |
rescue ActiveRecord::RecordNotFound, ActiveRecord::StatementInvalid | ||
129 | | |
130 | | |
122 | throw :error, "Article id #{params[:id]} not found." | |
123 | rescue ActiveRecord::RecordInvalid | |
124 | throw :error, "Trackback not saved" | |
end | ||
end | ||
127 | nil | |
end | ||
134 | | |
end | ||
136 | | |
130 | ||
def nuke_comment | ||
138 | | |
139 | | |
140 | | |
141 | | |
142 | | |
132 | Comment.find(params[:id]).destroy | |
133 | render :nothing => true | |
end | ||
def nuke_trackback | ||
146 | | |
147 | | |
148 | | |
149 | | |
150 | | |
137 | Trackback.find(params[:id]).destroy | |
138 | render :nothing => true | |
end | ||
def view_page | ||
if(@page = Page.find_by_name(params[:name].to_a.join('/'))) | ||
@page_title = @page.title | ||
156 | | |
else | ||
render :nothing => true, :status => 404 | ||
end | ||
end | ||
161 | | |
148 | ||
private | ||
164 | | |
165 | | |
151 | def add_to_cookies(name, value, path=nil, expires=nil) | |
152 | cookies[name] = { :value => value, :path => path || "/#{controller_name}", | |
153 | :expires => 6.weeks.from_now } | |
154 | end | |
155 | ||
156 | def check_page_query_param_for_missing_routes | |
157 | unless request.path =~ /\/page\// | |
158 | raise "Page param problem" unless params[:page].nil? | |
end | ||
160 | end | |
168 | | |
169 | | |
170 | | |
171 | | |
172 | | |
173 | | |
174 | | |
175 | | |
162 | def verify_config | |
163 | if User.count == 0 | |
164 | redirect_to :controller => "accounts", :action => "signup" | |
165 | elsif ! this_blog.is_ok? | |
166 | redirect_to :controller => "admin/general", :action => "redirect" | |
167 | else | |
168 | return true | |
end | ||
177 | | |
178 | | |
179 | | |
170 | end | |
171 | ||
172 | def display_article(article = nil) | |
173 | begin | |
174 | @article = block_given? ? yield : article | |
175 | @comment = Comment.new | |
176 | @page_title = @article.title | |
177 | auto_discovery_feed :type => 'article', :id => @article.id | |
178 | render :action => 'read' | |
179 | rescue ActiveRecord::RecordNotFound, NoMethodError => e | |
180 | error("Post not found...") | |
end | ||
182 | end | |
184 | alias_method :rescue_action_in_public, :error | |
185 | ||
186 | def render_error(object = '', status = 500) | |
187 | render(:text => (object.errors.full_messages.join(", ") rescue object.to_s), :status => status) | |
188 | end | |
189 | ||
190 | def set_headers | |
191 | @headers["Content-Type"] = "text/html; charset=utf-8" | |
192 | end | |
193 | ||
194 | def list_groupings(klass) | |
195 | @grouping_class = klass | |
196 | @groupings = klass.find_all_with_article_counters(1000) | |
197 | render :action => 'groupings' | |
198 | end | |
199 | ||
200 | def render_grouping(klass) | |
201 | return list_groupings(klass) unless params[:id] | |
202 | ||
203 | @articles = klass.find_by_permalink(params[:id]).articles.find_already_published rescue [] | |
204 | auto_discovery_feed :type => klass.to_s.underscore, :id => params[:id] | |
205 | render_paginated_index("Can't find posts with #{klass.to_prefix} '#{h(params[:id])}'") | |
206 | end | |
207 | ||
208 | def render_paginated_index(on_empty = "No posts found...") | |
209 | return error(on_empty) if @articles.empty? | |
210 | ||
211 | @pages = Paginator.new self, @articles.size, this_blog.limit_article_display, @params[:page] | |
212 | start = @pages.current.offset | |
213 | stop = (@pages.current.next.offset - 1) rescue @articles.size | |
214 | # Why won't this work? @articles.slice!(start..stop) | |
215 | @articles = @articles.slice(start..stop) | |
216 | render :action => 'index' | |
217 | end | |
end |
rool/rails/typo/trunk/app/controllers/backend_controller.rb:
prev. | current | |
1 | ||
1 | class BackendController < ContentController | |
cache_sweeper :blog_sweeper | ||
3 | session :off | |
web_service_dispatching_mode :layered | ||
web_service(:metaWeblog) { MetaWeblogService.new(self) } | ||
6 | | |
7 | web_service(:mt) { MovableTypeService.new(self) } | |
web_service(:blogger) { BloggerService.new(self) } | ||
alias xmlrpc api |
rool/rails/typo/trunk/app/controllers/live_controller.rb:
prev. | current | |
1 | ||
1 | class LiveController < ContentController | |
2 | session :off | |
def search | ||
@search = params[:q] | ||
@articles = Article.search(@search) | ||
@headers["Content-Type"] = "text/html; charset=utf-8" | ||
end | ||
8 | | |
9 | ||
10 | ||
11 | end |
rool/rails/typo/trunk/app/controllers/theme_controller.rb:
prev. | current | |
1 | ||
1 | class ThemeController < ContentController | |
caches_page :stylesheets, :javascript, :images | ||
3 | | |
3 | session :off | |
4 | ||
def stylesheets | ||
render_theme_item(:stylesheets, params[:filename], 'text/css') | ||
end | ||
... | ... | |
end | ||
private | ||
24 | | |
25 | ||
def render_theme_item(type, file, mime = mime_for(file)) | ||
render :text => "Not Found", :status => 404 and return if file.split(%r{[\\/]}).include?("..") | ||
27 | | |
28 | send_file this_blog.current_theme_path + "/#{type}/#{file}", :type => mime, :disposition => 'inline', :stream => false | |
end | ||
29 | | |
30 | ||
def mime_for(filename) | ||
case filename.downcase | ||
when /\.js$/ | ||
... | ... | |
else | ||
'application/binary' | ||
end | ||
47 | | |
48 | | |
48 | end | |
50 | ||
end | ||
rool/rails/typo/trunk/app/controllers/xml_controller.rb:
prev. | current | |
1 | ||
2 | | |
1 | class XmlController < ContentController | |
2 | caches_action_with_params :feed | |
3 | session :off | |
5 | NORMALIZED_FORMAT_FOR = {'atom' => 'atom10', 'rss' => 'rss20', | |
6 | 'atom10' => 'atom10', 'rss20' => 'rss20'} | |
7 | ||
8 | CONTENT_TYPE_FOR = { 'rss20' => 'application/xml', | |
9 | 'atom10' => 'application/atom+xml' } | |
10 | ||
11 | ||
12 | def feed | |
13 | @items = Array.new | |
14 | @format = params[:format] | |
15 | ||
16 | if @format == 'atom03' | |
17 | @headers["Status"] = "301 Moved Permanently" | |
18 | return redirect_to(:format=>'atom') | |
19 | end | |
20 | ||
21 | @feed_title = this_blog.blog_name | |
22 | @link = url_for({:controller => "articles"},{:only_path => false}) | |
23 | ||
24 | @format = NORMALIZED_FORMAT_FOR[@format] | |
25 | ||
26 | if not @format | |
27 | render :text => 'Unsupported format', :status => 404 | |
28 | return | |
29 | end | |
30 | ||
31 | @headers["Content-Type"] = "#{CONTENT_TYPE_FOR[@format]}; charset=utf-8" | |
32 | ||
33 | if respond_to?("prep_#{params[:type]}") | |
34 | self.send("prep_#{params[:type]}") | |
35 | else | |
36 | render :text => 'Unsupported action', :status => 404 | |
37 | return | |
38 | end | |
39 | ||
40 | render :action => "#{@format}_feed" | |
41 | end | |
42 | ||
43 | def itunes | |
44 | @feed_title = "#{this_blog.blog_name} Podcast" | |
45 | @items = Resource.find(:all, :order => 'created_at DESC', | |
46 | :conditions => ['itunes_metadata = ?', true], :limit => this_blog.limit_rss_display) | |
47 | render :action => "itunes_feed" | |
48 | end | |
49 | ||
def articlerss | ||
5 | | |
6 | | |
51 | redirect_to :action => 'feed', :format => 'rss20', :type => 'article', :id => params[:id] | |
end | ||
8 | | |
53 | ||
def commentrss | ||
10 | | |
55 | redirect_to :action => 'feed', :format => 'rss20', :type => 'comments' | |
end | ||
12 | | |
def trackbackrss | ||
14 | | |
58 | redirect_to :action => 'feed', :format => 'rss20', :type => 'trackbacks' | |
end | ||
16 | | |
17 | | |
18 | | |
60 | ||
61 | def rsd | |
end | ||
21 | | |
22 | | |
64 | protected | |
65 | ||
66 | def fetch_items(association, order='created_at DESC', limit=nil) | |
67 | if association.instance_of?(Symbol) | |
68 | association = this_blog.send(association) | |
69 | end | |
70 | limit ||= this_blog.limit_rss_display | |
71 | @items = association.find_already_published(:all, :limit => limit, :order => order) | |
end | ||
25 | | |
74 | def prep_feed | |
75 | fetch_items(:articles) | |
end | ||
78 | def prep_comments | |
79 | fetch_items(:comments) | |
80 | @feed_title << " comments" | |
81 | end | |
82 | ||
83 | def prep_trackbacks | |
84 | fetch_items(:trackbacks) | |
85 | @feed_title << " trackbacks" | |
86 | end | |
87 | ||
88 | def prep_article | |
89 | article = this_blog.articles.find(params[:id]) | |
90 | fetch_items(article.comments, 'created_at DESC', 25) | |
91 | @items.unshift(article) | |
92 | @feed_title << ": #{article.title}" | |
93 | @link = article_url(article, false) | |
94 | end | |
95 | ||
96 | def prep_category | |
97 | category = Category.find_by_permalink(params[:id]) | |
98 | fetch_items(category.articles) | |
99 | @feed_title << ": Category #{category.name}" | |
100 | @link = url_for({:controller => "articles", :action => "category", :id => category.permalink}, | |
101 | {:only_path => false}) | |
102 | end | |
103 | ||
104 | def prep_tag | |
105 | tag = Tag.find_by_name(params[:id]) | |
106 | fetch_items(tag.articles) | |
107 | @feed_title << ": Tag #{tag.display_name}" | |
108 | @link = url_for({:controller => "articles_controller.rb", :action => 'tag', :tag => tag.name}, | |
109 | {:only_path => false}) | |
110 | end | |
end |
rool/rails/typo/trunk/app/helpers/admin/base_helper.rb:
prev. | current | |
def render_flash | ||
output = [] | ||
5 | | |
6 | | |
7 | | |
8 | | |
9 | | |
5 | ||
6 | for key,value in flash | |
7 | output << "<span class=\"#{key.to_s.downcase}\">#{value}</span>" | |
8 | end if flash | |
9 | ||
output.join("<br/>\n") | ||
end | ||
... | ... | |
for key,value in @tasks | ||
output << "<a href=\"#{value}\">#{key}</a>" | ||
end if @tasks | ||
19 | | |
19 | ||
output.join("<br/>\n") | ||
end | ||
22 | | |
22 | ||
def current_user_notice | ||
unless session[:user] | ||
link_to "log in", :controller => "/accounts", :action=>"login" | ||
... | ... | |
end | ||
end | ||
31 | | |
31 | def tab(label, options = {}) | |
if controller.controller_name =~ /#{options[:controller].split('/').last}/ | ||
content_tag :li, link_to(label, options, {"class"=> "active"}), {"class"=> "active"} | ||
else | ||
35 | | |
36 | | |
37 | | |
38 | | |
35 | content_tag :li, link_to(label, options) | |
36 | end | |
37 | end | |
38 | ||
def cancel(url = {:action => 'list'}) | ||
link_to "Cancel", url | ||
end | ||
... | ... | |
def link_to_show(record) | ||
link_to image_tag('go'), :action => 'show', :id => record.id | ||
53 | | |
53 | end | |
def link_to_edit(record) | ||
link_to image_tag('go'), :action => 'edit', :id => record.id | ||
57 | | |
57 | end | |
def link_to_destroy(record) | ||
link_to image_tag('delete'), :action => 'destroy', :id => record.id | ||
61 | | |
61 | end | |
63 | | |
64 | | |
65 | | |
66 | | |
67 | | |
68 | | |
69 | | |
70 | | |
63 | def text_filter_options | |
64 | TextFilter.find(:all).collect do |filter| | |
65 | [ filter.description, filter ] | |
66 | end | |
end | ||
72 | | |
68 | ||
def alternate_class | ||
@class = @class != '' ? '' : 'class="shade"' | ||
end | ||
76 | | |
72 | ||
73 | def reset_alternation | |
74 | @class = nil | |
75 | end | |
76 | ||
def task_quickpost(title) | ||
content_tag :li, link_to_function(title, toggle_effect('quick-post', 'Effect.BlindUp', "duration:0.4", "Effect.BlindDown", "duration:0.4")) | ||
end | ||
80 | | |
80 | ||
def task_quicknav(title) | ||
content_tag :li, link_to_function(title, toggle_effect('quick-navigate', 'Effect.BlindUp', "duration:0.4", "Effect.BlindDown", "duration:0.4")) | ||
end | ||
... | ... | |
task(title, 'show', id) | ||
end | ||
105 | def task_help(title, id) | |
106 | task(title, 'show_help', id) | |
107 | end | |
108 | ||
def task(title, action, id = nil) | ||
content_tag :li, link_to(title, :action => action, :id => id) | ||
end | ||
113 | def task_add_resource_metadata(title,id) | |
114 | link_to_function(title, toggle_effect('add-resource-metadata-' + id.to_s, 'Effect.BlindUp', "duration:0.4", "Effect.BlindDown", "duration:0.4")) | |
115 | end | |
116 | ||
117 | def task_edit_resource_metadata(title,id) | |
118 | link_to_function(title, toggle_effect('edit-resource-metadata-' + id.to_s, 'Effect.BlindUp', "duration:0.4", "Effect.BlindDown", "duration:0.4")) | |
119 | end | |
120 | ||
121 | def task_edit_resource_mime(title,id) | |
122 | link_to_function(title, toggle_effect('edit-resource-mime-' + id.to_s, 'Effect.BlindUp', "duration:0.4", "Effect.BlindDown", "duration:0.4")) | |
123 | end | |
end |
rool/rails/typo/trunk/app/helpers/application_helper.rb:
prev. | current | |
require 'digest/sha1' | ||
module ApplicationHelper | ||
5 | | |
6 | | |
7 | | |
8 | | |
5 | def server_url_for(options = {}) | |
6 | url_for options.update(:only_path => false) | |
end | ||
10 | | |
11 | | |
12 | | |
13 | | |
14 | | |
15 | | |
8 | ||
9 | def config_value(name) | |
10 | this_blog[name] | |
end | ||
18 | | |
19 | | |
20 | | |
21 | | |
22 | | |
13 | def config | |
14 | this_blog | |
end | ||
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
17 | def item_link(title, item, anchor=nil) | |
18 | link_to title, item.location(anchor) | |
end | ||
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | | |
38 | | |
39 | | |
40 | | |
41 | | |
42 | | |
43 | | |
44 | | |
21 | alias_method :article_link, :item_link | |
22 | alias_method :page_link, :item_link | |
23 | alias_method :comment_url_link, :item_link | |
46 | | |
47 | | |
25 | def url_of(item, only_path=true, anchor=nil) | |
26 | item.location(anchor, only_path) | |
end | ||
50 | | |
51 | | |
52 | | |
53 | | |
54 | | |
55 | | |
56 | | |
57 | | |
58 | | |
29 | alias_method :trackback_url, :url_of | |
30 | alias_method :comment_url, :url_of | |
31 | alias_method :article_url, :url_of | |
32 | alias_method :page_url, :url_of | |
60 | | |
61 | | |
34 | def pluralize(size, word) | |
35 | case size | |
36 | when 0 then "no #{word}s" | |
37 | when 1 then "1 #{word}" | |
38 | else "#{size} #{word}s" | |
39 | end | |
end | ||
63 | | |
64 | | |
65 | | |
66 | | |
68 | | |
69 | | |
42 | def comments_link(article) | |
43 | article_link(pluralize(article.comments.size, "comment"), | |
44 | article, 'comments') | |
end | ||
71 | | |
72 | | |
73 | | |
74 | | |
75 | | |
76 | | |
77 | | |
78 | | |
80 | | |
81 | | |
47 | def trackbacks_link(article) | |
48 | article_link(pluralize(article.trackbacks.size, "trackback"), | |
49 | article, 'trackbacks') | |
end | ||
84 | | |
85 | | |
86 | | |
52 | def check_cache(aggregator, *args) | |
53 | hash = "#{aggregator.to_s}_#{args.collect { |arg| Digest::SHA1.hexdigest(arg) }.join('_') }".to_sym | |
54 | controller.cache[hash] ||= aggregator.new(*args) | |
end | ||
88 | | |
89 | | |
90 | | |
91 | | |
92 | | |
93 | | |
94 | | |
95 | | |
96 | | |
97 | | |
98 | | |
99 | | |
100 | | |
101 | | |
102 | | |
103 | | |
104 | | |
105 | | |
106 | | |
107 | | |
109 | | |
110 | | |
111 | | |
112 | | |
113 | | |
114 | | |
115 | | |
116 | | |
117 | | |
def js_distance_of_time_in_words_to_now(date) | ||
time = date.utc.strftime("%a, %d %b %Y %H:%M:%S GMT") | ||
"<span class=\"typo_date\" title=\"#{time}\">#{time}</span>" | ||
end | ||
122 | | |
123 | | |
124 | | |
125 | | |
126 | | |
127 | | |
128 | | |
129 | | |
130 | | |
61 | ||
def meta_tag(name, value) | ||
tag :meta, :name => name, :content => value unless value.blank? | ||
end | ||
134 | | |
65 | ||
def date(date) | ||
"<span class=\"typo_date\">#{date.utc.strftime("%d. %b")}</span>" | ||
end | ||
138 | | |
69 | ||
def render_theme(options) | ||
options[:controller]=Themes::ThemeController.active_theme_name | ||
render_component(options) | ||
... | ... | |
def toggle_effect(domid, true_effect, true_opts, false_effect, false_opts) | ||
"$('#{domid}').style.display == 'none' ? new #{false_effect}('#{domid}', {#{false_opts}}) : new #{true_effect}('#{domid}', {#{true_opts}}); return false;" | ||
end | ||
78 | ||
79 | def article_html(article, what = :all) | |
80 | article.html(@controller, what) | |
81 | end | |
82 | ||
83 | def comment_html(comment) | |
84 | comment.html(@controller, :body) | |
85 | end | |
86 | ||
87 | def page_html(page) | |
88 | page.html(@controller,:body) | |
89 | end | |
90 | ||
91 | def strip_html(text) text.strip_html end | |
end |
rool/rails/typo/trunk/app/helpers/articles_helper.rb:
prev. | current | |
module ArticlesHelper | ||
2 | | |
def admin_tools_for(model) | ||
type = model.class.to_s.downcase | ||
tag = [] | ||
tag << content_tag("div", | ||
link_to_remote('nuke', { | ||
8 | | |
7 | :url => { :action => "nuke_#{type}", :id => model }, | |
:complete => visual_effect(:puff, "#{type}-#{model.id}", :duration => 0.6), | ||
:confirm => "Are you sure you want to delete this #{type}?" | ||
}, :class => "admintools") << | ||
link_to('edit', { | ||
:controller => "admin/#{type.pluralize}/article/#{model.article.id}", | ||
14 | | |
13 | :action => "edit", :id => model | |
}, :class => "admintools"), | ||
:id => "admin_#{type}_#{model.id}", :style => "display: none") | ||
tag.join(" | ") | ||
... | ... | |
tag << %{ onmouseout="Element.hide('admin_#{[type, id].compact.join('_')}');" } | ||
tag | ||
end | ||
26 | | |
25 | ||
def render_errors(obj) | ||
return "" unless obj | ||
tag = String.new | ||
... | ... | |
unless obj.errors.empty? | ||
tag << %{<ul class="objerrors">} | ||
34 | | |
33 | obj.errors.each_full do |message| | |
tag << "<li>#{message}</li>" | ||
end | ||
... | ... | |
end | ||
tag | ||
42 | | |
43 | | |
41 | end | |
42 | ||
def page_title | ||
if @page_title | ||
@page_title | ||
else | ||
48 | | |
49 | | |
47 | this_blog.blog_name || "Typo" | |
48 | end | |
end | ||
51 | | |
50 | ||
51 | def page_header | |
52 | page_header_includes = contents.collect { |c| c.whiteboard }.collect { |w| w.select {|k,v| k =~ /^page_header_/}.collect {|(k,v)| v} }.flatten.uniq | |
53 | ( | |
54 | <<-HTML | |
55 | <meta http-equiv="content-type" content="text/html; charset=utf-8" /> | |
56 | #{ meta_tag 'ICBM', this_blog.geourl_location unless this_blog.geourl_location.empty? } | |
57 | <link rel="EditURI" type="application/rsd+xml" title="RSD" href="#{ server_url_for :controller => 'xml', :action => 'rsd' }" /> | |
58 | <link rel="alternate" type="application/atom+xml" title="Atom" href="#{ @auto_discovery_url_atom }" /> | |
59 | <link rel="alternate" type="application/rss+xml" title="RSS" href="#{ @auto_discovery_url_rss }" /> | |
60 | #{ javascript_include_tag "cookies" } | |
61 | #{ javascript_include_tag "prototype" } | |
62 | #{ javascript_include_tag "effects" } | |
63 | #{ javascript_include_tag "typo" } | |
64 | #{ page_header_includes.join("\n") } | |
65 | <script type="text/javascript">#{ @content_for_script }</script> | |
66 | HTML | |
67 | ).chomp | |
68 | end | |
69 | ||
def article_links(article) | ||
returning code = [] do | ||
code << category_links(article) unless article.categories.empty? | ||
73 | code << tag_links(article) unless article.tags.empty? | |
code << comments_link(article) if article.allow_comments? | ||
code << trackbacks_link(article) if article.allow_pings? | ||
end.join(" <strong>|</strong> ") | ||
end | ||
59 | | |
78 | ||
def category_links(article) | ||
61 | | |
62 | | |
63 | | |
80 | "Posted in " + article.categories.collect { |c| link_to h(c.name), | |
81 | { :controller => "articles", :action => "category", :id => c.permalink }, | |
82 | :rel => "tag" | |
}.join(", ") | ||
end | ||
86 | def tag_links(article) | |
87 | "Tags " + article.tags.collect { |tag| link_to tag.display_name, | |
88 | { :controller => "articles", :action => "tag", :id => tag.name }, | |
89 | :rel => "tag" | |
90 | }.sort.join(", ") | |
91 | end | |
92 | ||
def author_link(article) | ||
68 | | |
69 | | |
94 | if this_blog.link_to_author and article.user and article.user.email.to_s.size>0 | |
95 | "<a href=\"mailto:#{h article.user.email}\">#{h article.user.name}</a>" | |
elsif article.user and article.user.name.to_s.size>0 | ||
71 | | |
97 | h article.user.name | |
else | ||
73 | | |
99 | h article.author | |
end | ||
end | ||
103 | def next_link(article) | |
104 | n = article.next | |
105 | return n ? article_link("#{n.title} »", n) : '' | |
106 | end | |
107 | ||
108 | def prev_link(article) | |
109 | p = article.previous | |
110 | return p ? article_link("« #{p.title}", p) : '' | |
111 | end | |
112 | ||
113 | def render_sidebars | |
114 | # ugly ugly hack to fix the extremely verbose sidebar logging | |
115 | options = { :controller => SidebarController, | |
116 | :action => 'display_plugins', | |
117 | :params => {:contents => contents, | |
118 | :request_params => params} } | |
119 | render_component(options) | |
120 | end | |
121 | ||
122 | # Generate the image tag for a commenters gravatar based on their email address | |
123 | # Valid options are described at http://www.gravatar.com/implement.php | |
124 | def gravatar_tag(email, options={}) | |
125 | options.update(:gravatar_id => Digest::MD5.hexdigest(email.strip)) | |
126 | options[:default] = CGI::escape(options[:default]) if options.include?(:default) | |
127 | options[:size] ||= 60 | |
128 | ||
129 | image_tag("http://www.gravatar.com/avatar.php?" << | |
130 | options.map { |key,value| "#{key}=#{value}" }.sort.join("&"), :class => "gravatar") | |
131 | end | |
132 | ||
133 | def calc_distributed_class(articles, max_articles, grp_class, min_class, max_class) | |
134 | (grp_class.to_prefix rescue grp_class.to_s) + | |
135 | ((max_articles == 0) ? | |
136 | min_class.to_s : | |
137 | (min_class + ((max_class-min_class) * articles.to_f / max_articles).to_i).to_s) | |
138 | end | |
139 | ||
140 | def link_to_grouping(grp) | |
141 | link_to( grp.display_name, urlspec_for_grouping(grp), | |
142 | :rel => "tag", :title => title_for_grouping(grp) ) | |
143 | end | |
144 | ||
145 | def urlspec_for_grouping(grouping) | |
146 | { :controller => "articles", :action => grouping.class.to_prefix, :id => grouping.permalink } | |
147 | end | |
148 | ||
149 | def title_for_grouping(grouping) | |
150 | "#{pluralize(grouping.article_counter, 'post')} with #{grouping.class.to_s.underscore} '#{grouping.display_name}'" | |
151 | end | |
152 | ||
153 | def ul_tag_for(grouping_class) | |
154 | case grouping_class | |
155 | when Tag | |
156 | %{<ul id="taglist" class="tags">} | |
157 | when Category | |
158 | %{<ul class="categorylist">} | |
159 | else | |
160 | '<ul>' | |
161 | end | |
162 | end | |
end |
rool/rails/typo/trunk/app/helpers/xml_helper.rb:
prev. | current | |
module XmlHelper | ||
def pub_date(time) | ||
3 | | |
3 | time.rfc822 | |
end | ||
def post_title(post) | ||
7 | | |
7 | h(post.title) | |
end | ||
10 | | |
11 | | |
10 | def item_link(item) | |
11 | item.location(nil, false) | |
end | ||
13 | | |
14 | | |
15 | | |
16 | | |
17 | | |
18 | | |
19 | | |
20 | | |
21 | | |
13 | ||
14 | alias_method :post_link, :item_link | |
15 | alias_method :comment_link, :item_link | |
16 | alias_method :trackback_link, :item_link | |
17 | ||
def blog_title | ||
23 | | |
19 | this_blog.blog_name || "Unnamed blog" | |
end | ||
end |
rool/rails/typo/trunk/app/models/aggregations/delicious.rb:
prev. | current | |
class Delicious | ||
include REXML | ||
8 | | |
9 | | |
8 | attr_accessor :url, :items, :link, :title, :days | |
9 | ||
# This object holds given information of an item | ||
11 | | |
12 | | |
11 | class DeliciousItem < Struct.new(:link, :title, :description, :description_link, :date) | |
12 | def to_s; title end | |
end | ||
14 | | |
14 | ||
# Pass the url to the RSS feed you would like to keep tabs on | ||
16 | | |
16 | # by default this will request the rss from the server right away and | |
# fill the items array | ||
def initialize(url, refresh = true) | ||
19 | | |
20 | | |
21 | | |
19 | self.items = [] | |
20 | self.url = url | |
21 | self.days = {} | |
22 | self.refresh if refresh | |
end | ||
23 | | |
24 | ||
# This method lets you refresh the items in the items array | ||
25 | | |
26 | # useful if you keep the object cached in memory and | |
def refresh | ||
open(@url) do |http| | ||
parse(http.read) | ||
end | ||
end | ||
31 | | |
32 | ||
private | ||
def parse(body) | ||
35 | | |
36 | ||
xml = Document.new(body) | ||
37 | | |
38 | | |
39 | | |
40 | | |
41 | | |
42 | | |
43 | | |
38 | ||
39 | self.items = [] | |
40 | self.link = XPath.match(xml, "//channel/link/text()").first.value rescue "" | |
41 | self.title = XPath.match(xml, "//channel/title/text()").first.value rescue "" | |
42 | ||
43 | XPath.each(xml, "//item/") do |elem| | |
item = DeliciousItem.new | ||
45 | | |
46 | | |
47 | | |
45 | item.title = XPath.match(elem, "title/text()").first.value rescue "" | |
46 | item.link = XPath.match(elem, "link/text()").first.value rescue "" | |
47 | item.description = XPath.match(elem, "description/text()").first.value rescue "" | |
48 | item.date = Time.mktime(*ParseDate.parsedate(XPath.match(elem, "dc:date/text()").first.value)) rescue Time.now | |
49 | ||
50 | item.description_link = item.description | |
51 | item.description.gsub!(/<\/?a\b.*?>/, "") # remove all <a> tags | |
items << item | ||
end | ||
50 | | |
54 | ||
self.items = items.sort_by { |item| item.date }.reverse | ||
52 | | |
56 | end | |
end |
rool/rails/typo/trunk/app/models/aggregations/flickr.rb:
prev. | current | |
require 'rexml/document' | ||
# Example: | ||
6 | ||
6 | # | |
# flickr = Flickr.new('http://www.flickr.com/services/feeds/photos_public.gne?id=40235412@N00&format=rss_200') | ||
# flickr.pics.each do |pic| | ||
# puts "#{pic.title} @ #{pic.link} updated at #{pic.date}" | ||
# end | ||
# | ||
12 | ||
12 | class FlickrAggregation | |
include REXML | ||
def choose(num) | ||
return pics unless pics.size > num | ||
bag = [] | ||
set = pics.dup | ||
19 | | |
19 | num.times {|x| bag << set.delete_at(rand(set.size))} | |
bag | ||
end | ||
22 | | |
22 | ||
attr_accessor :url, :pics, :link, :title, :description | ||
24 | | |
24 | ||
# This object holds given information of a picture | ||
26 | | |
27 | | |
28 | | |
29 | | |
26 | class Picture | |
27 | attr_accessor :link, :title, :date, :description | |
28 | ||
29 | def to_s | |
30 | title | |
31 | end | |
32 | ||
33 | def date=(value) | |
34 | @date = Time.parse(value) | |
35 | end | |
36 | ||
37 | def image | |
description.scan( /(http:\/\/(static|photos).*?\.jpg)/ ).first.first | ||
end | ||
def thumb | ||
33 | | |
41 | image.gsub( /\_m\./, '_t.' ) | |
end | ||
def square | ||
36 | | |
44 | image.gsub( /\_m\./, '_s.' ) | |
end | ||
end | ||
39 | | |
47 | ||
# Pass the url to the RSS feed you would like to keep tabs on | ||
41 | | |
49 | # by default this will request the rss from the server right away and | |
# fill the tasks array | ||
def initialize(url, refresh = true) | ||
self.pics = [] | ||
self.url = url | ||
self.refresh if refresh | ||
end | ||
48 | | |
56 | ||
# This method lets you refresh the tasks int the tasks array | ||
50 | | |
58 | # useful if you keep the object cached in memory and | |
def refresh | ||
open(@url) do |http| | ||
parse(http.read) | ||
end | ||
end | ||
56 | | |
64 | ||
private | ||
def parse(body) | ||
60 | | |
68 | ||
xml = Document.new(body) | ||
62 | | |
63 | | |
70 | ||
71 | self.pics = [] | |
self.link = XPath.match(xml, "//channel/link/text()").to_s | ||
self.title = XPath.match(xml, "//channel/title/text()").to_s | ||
self.description = XPath.match(xml, "//channel/description/text()").to_s | ||
67 | | |
68 | | |
69 | | |
75 | ||
76 | XPath.each(xml, "//item/") do |elem| | |
77 | ||
picture = Picture.new | ||
71 | | |
79 | picture.title = XPath.match(elem, "title/text()").to_s | |
picture.date = XPath.match(elem, "pubDate/text()").to_s | ||
picture.link = XPath.match(elem, "link/text()").to_s | ||
picture.description = XPath.match(elem, "description/text()").to_s | ||
75 | | |
83 | ||
pics << picture | ||
end | ||
end |
rool/rails/typo/trunk/app/models/aggregations/fortythree.rb:
prev. | current | |
require 'rexml/document' | ||
# Example: | ||
6 | ||
6 | # | |
# fortythree = Fortythree.new('http://www.43things.com/rss/uber/author?username=<user>') | ||
# fortythree.things.each do |thing| | ||
# puts "#{thing.title} @ #{thing.link} updated at #{thing.date}" | ||
... | ... | |
include REXML | ||
attr_accessor :url, :things, :link, :title, :description | ||
16 | | |
16 | ||
# This object holds given information of a thing | ||
class ThingItem < Struct.new(:link, :title, :date) | ||
19 | | |
19 | def to_s; title end | |
def date=(value); super(Time.parse(value)) end | ||
end | ||
22 | | |
22 | ||
# Pass the url to the RSS feed you would like to keep tabs on | ||
24 | | |
24 | # by default this will request the rss from the server right away and | |
# fill the tasks array def initialize(url, refresh = true) | ||
def initialize(url, refresh = true) | ||
self.things = [] | ||
self.url = url | ||
self.refresh if refresh | ||
end | ||
31 | | |
31 | ||
# This method lets you refresh the things into the things array | ||
33 | | |
33 | # useful if you keep the object cached in memory and | |
def refresh | ||
open(@url) do |http| | ||
parse(http.read) | ||
end | ||
end | ||
39 | | |
39 | ||
private | ||
def parse(body) | ||
43 | | |
43 | ||
xml = Document.new(body) | ||
45 | | |
46 | | |
45 | ||
46 | self.things = [] | |
self.link = XPath.match(xml, "//channel/link/text()").to_s | ||
self.title = XPath.match(xml, "//channel/title/text()").to_s | ||
self.description = XPath.match(xml, "//channel/description/text()").to_s | ||
50 | | |
51 | | |
52 | | |
50 | ||
51 | XPath.each(xml, "//item/") do |elem| | |
52 | ||
thing = ThingItem.new | ||
thing.title = XPath.match(elem, "title/text()").to_s | ||
55 | | |
55 | ||
thing.date = XPath.match(elem, "pubDate/text()").to_s | ||
thing.link = XPath.match(elem, "link/text()").to_s | ||
58 | | |
58 | ||
things << thing | ||
end | ||
end | ||
62 | ||
63 | end |
rool/rails/typo/trunk/app/models/aggregations/tada.rb:
prev. | current | |
require 'rexml/document' | ||
# Example: | ||
6 | ||
6 | # | |
# tada = Tada.new('http://<nick>.tadalist.com/lists/feed/<id>?token=<token>') | ||
# tada.tasks.each do |task| | ||
# puts "#{task.title} @ #{task.link} updated at #{task.date}" | ||
... | ... | |
include REXML | ||
attr_accessor :url, :tasks, :link, :title, :description | ||
16 | | |
16 | ||
# This object holds given information of a task | ||
class TaskItem < Struct.new(:link, :title, :date, :status) | ||
19 | | |
19 | def to_s; title end | |
def date=(value); super(Time.parse(value)) end | ||
end | ||
22 | | |
22 | ||
# Pass the url to the RSS feed you would like to keep tabs on | ||
24 | | |
24 | # by default this will request the rss from the server right away and | |
# fill the tasks array def initialize(url, refresh = true) | ||
def initialize(url, refresh = true) | ||
self.tasks = [] | ||
self.url = url | ||
self.refresh if refresh | ||
end | ||
31 | | |
31 | ||
# This method lets you refresh the tasks int the tasks array | ||
33 | | |
33 | # useful if you keep the object cached in memory and | |
def refresh | ||
open(@url) do |http| | ||
parse(http.read) | ||
end | ||
end | ||
39 | | |
39 | ||
private | ||
def parse(body) | ||
43 | | |
43 | ||
xml = Document.new(body) | ||
45 | | |
46 | | |
45 | ||
46 | self.tasks = [] | |
self.link = XPath.match(xml, "//channel/link/text()") | ||
self.title = XPath.match(xml, "//channel/title/text()") | ||
self.description = XPath.match(xml, "//channel/description/text()") | ||
50 | | |
51 | | |
52 | | |
50 | ||
51 | XPath.each(xml, "//item/") do |elem| | |
52 | ||
title = XPath.match(elem, "title/text()").to_s | ||
# extract the status from the title | ||
... | ... | |
task = TaskItem.new | ||
task.title = title | ||
task.status = status | ||
66 | | |
66 | ||
task.date = XPath.match(elem, "pubDate/text()").to_s | ||
task.link = XPath.match(elem, "link/text()").to_s | ||
69 | | |
69 | ||
tasks << task | ||
end | ||
self.tasks = tasks.sort_by { |task| task.status.to_s } | ||
end | ||
75 | ||
76 | end |
rool/rails/typo/trunk/app/models/aggregations/technorati.rb:
prev. | current | |
return cosmos unless cosmos.size > num | ||
bag = [] | ||
set = cosmos.dup | ||
12 | | |
12 | num.times {|x| bag << set.delete_at(rand(set.size))} | |
bag | ||
end | ||
15 | | |
15 | ||
attr_accessor :url, :link, :title, :cosmos | ||
17 | | |
17 | ||
# This object holds given information of a picture | ||
class Inbound < Struct.new(:link, :title) | ||
20 | | |
20 | def to_s; title end | |
end | ||
22 | | |
22 | ||
def initialize(url, refresh = true) | ||
self.cosmos = [] | ||
self.url = url | ||
self.refresh if refresh | ||
end | ||
28 | | |
28 | ||
# This method lets you refresh the tasks int the tasks array | ||
30 | | |
30 | # useful if you keep the object cached in memory and | |
def refresh | ||
open(@url) do |http| | ||
parse(http.read) | ||
end | ||
end | ||
36 | | |
36 | ||
private | ||
def parse(body) | ||
xml = Document.new(body) | ||
41 | | |
42 | | |
41 | self.cosmos = [] | |
42 | XPath.each(xml, "//item/") do |elem| | |
inbound = Inbound.new | ||
44 | | |
44 | inbound.title = XPath.match(elem, "title/text()").to_s | |
inbound.link = XPath.match(elem, "link/text()").to_s | ||
cosmos << inbound | ||
end |
rool/rails/typo/trunk/app/models/aggregations/upcoming.rb:
prev. | current | |
require 'rexml/document' | ||
# Example: | ||
5 | ||
5 | # | |
# upcoming = Upcoming.new('http://upcoming.org/syndicate/my_events/<your_user_id>') | ||
# upcoming.events.each do |event| | ||
# puts "#{event.title} @ #{event.timespan} #{event.link} : #{event.description}" | ||
... | ... | |
include REXML | ||
def choose(num) | ||
16 | | |
17 | | |
18 | | |
19 | | |
20 | | |
16 | events.last(num) | |
end | ||
22 | | |
18 | ||
attr_accessor :events, :link, :title, :description, :url | ||
24 | | |
20 | ||
# This object holds given information for an Event | ||
class Event < Struct.new(:link, :title, :description) | ||
27 | | |
23 | def to_s; title end | |
29 | | |
25 | def timespan | |
description.split(':')[0] | ||
end | ||
def info | ||
description.split(':')[1] | ||
35 | | |
31 | end | |
end | ||
37 | | |
33 | ||
# Pass the url to the RSS feed you would like to keep tabs on | ||
39 | | |
35 | # by default this will request the rss from the server right away and | |
# fill the tasks array | ||
def initialize(url, refresh = true) | ||
self.events = [] | ||
self.url = url | ||
self.refresh if refresh | ||
end | ||
46 | | |
42 | ||
# This method lets you refresh the tasks int the tasks array | ||
48 | | |
44 | # useful if you keep the object cached in memory and | |
def refresh | ||
open(@url) do |http| | ||
parse(http.read) | ||
end | ||
end | ||
54 | | |
50 | ||
private | ||
def parse(body) | ||
58 | | |
54 | ||
xml = Document.new(body) | ||
60 | | |
61 | | |
56 | ||
57 | self.events = [] | |
self.link = XPath.match(xml, "//channel/link/text()").to_s | ||
self.title = XPath.match(xml, "//channel/title/text()").to_s | ||
self.description = XPath.match(xml, "//channel/description/text()").to_s | ||
65 | | |
66 | | |
67 | | |
61 | ||
62 | XPath.each(xml, "//item/") do |elem| | |
63 | ||
event = Event.new | ||
69 | | |
65 | event.title = XPath.match(elem, "title/text()").to_s | |
event.link = XPath.match(elem, "link/text()").to_s | ||
event.description = XPath.match(elem, "description/text()").to_s | ||
event.inspect |
rool/rails/typo/trunk/app/models/article.rb:
prev. | current | |
require 'uri' | ||
require 'net/http' | ||
3 | ||
5 | ||
4 | class Article < Content | |
5 | include TypoGuid | |
6 | ||
7 | content_fields :body, :extended | |
8 | ||
has_many :pings, :dependent => true, :order => "created_at ASC" | ||
has_many :comments, :dependent => true, :order => "created_at ASC" | ||
has_many :trackbacks, :dependent => true, :order => "created_at ASC" | ||
9 | | |
10 | | |
12 | has_many :resources, :order => "created_at DESC", | |
13 | :class_name => "Resource", :foreign_key => 'article_id' | |
14 | has_and_belongs_to_many :categories, :foreign_key => 'article_id' | |
15 | has_and_belongs_to_many :tags, :foreign_key => 'article_id' | |
belongs_to :user | ||
12 | | |
17 | has_many :triggers, :as => :pending_item | |
18 | ||
19 | after_destroy :fix_resources | |
20 | ||
def stripped_title | ||
14 | | |
22 | self.title.gsub(/<[^>]*>/,'').to_url | |
end | ||
16 | | |
17 | | |
18 | | |
19 | | |
20 | | |
21 | | |
22 | | |
23 | | |
24 | ||
25 | def location(anchor=nil, only_path=true) | |
26 | blog.article_url(self, only_path, anchor) | |
27 | end | |
28 | ||
29 | def html_urls | |
30 | urls = Array.new | |
31 | (body_html.to_s + extended_html.to_s).gsub(/<a [^>]*>/) do |tag| | |
32 | if(tag =~ /href="([^"]+)"/) | |
33 | urls.push($1) | |
34 | end | |
35 | end | |
36 | ||
37 | urls | |
38 | end | |
39 | ||
40 | def really_send_pings(serverurl = blog.server_url, articleurl = location(nil, false)) | |
41 | return unless blog.send_outbound_pings | |
42 | ||
43 | weblogupdatesping_urls = blog.ping_urls.gsub(/ +/,'').split(/[\n\r]+/) | |
44 | pingback_or_trackback_urls = self.html_urls | |
45 | ||
46 | ping_urls = weblogupdatesping_urls + pingback_or_trackback_urls | |
47 | ||
48 | ping_urls.uniq.each do |url| | |
begin | ||
25 | | |
50 | unless pings.collect { |p| p.url }.include?(url.strip) | |
ping = pings.build("url" => url) | ||
28 | | |
29 | | |
53 | if weblogupdatesping_urls.include?(url) | |
54 | ping.send_weblogupdatesping(serverurl, articleurl) | |
55 | else pingback_or_trackback_urls.include?(url) | |
56 | ping.send_pingback_or_trackback(articleurl) | |
57 | end | |
end | ||
31 | | |
rescue | ||
33 | | |
60 | # in case the remote server doesn't respond or gives an error, | |
# we should throw an xmlrpc error here. | ||
35 | | |
62 | end | |
end | ||
end | ||
66 | def send_pings | |
67 | state.send_pings(self) | |
68 | end | |
69 | ||
70 | def next | |
71 | Article.find(:first, :conditions => ['published_at > ?', published_at], | |
72 | :order => 'published_at asc') | |
73 | end | |
74 | ||
75 | def previous | |
76 | Article.find(:first, :conditions => ['published_at < ?', published_at], | |
77 | :order => 'published_at desc') | |
78 | end | |
79 | ||
# Count articles on a certain date | ||
40 | | |
81 | def self.count_by_date(year, month = nil, day = nil, limit = nil) | |
from, to = self.time_delta(year, month, day) | ||
42 | | |
83 | Article.count(["published_at BETWEEN ? AND ? AND published = ?", | |
84 | from, to, true]) | |
end | ||
44 | | |
86 | ||
# Find all articles on a certain date | ||
def self.find_all_by_date(year, month = nil, day = nil) | ||
from, to = self.time_delta(year, month, day) | ||
48 | | |
90 | Article.find_published(:all, :conditions => ["published_at BETWEEN ? AND ?", | |
91 | from, to]) | |
end | ||
# Find one article on a certain date | ||
52 | | |
95 | ||
96 | def self.find_by_date(year, month, day) | |
find_all_by_date(year, month, day).first | ||
end | ||
55 | | |
99 | ||
# Finds one article which was posted on a certain date and matches the supplied dashed-title | ||
def self.find_by_permalink(year, month, day, title) | ||
from, to = self.time_delta(year, month, day) | ||
59 | | |
60 | | |
61 | | |
62 | | |
63 | | |
103 | find_published(:first, | |
104 | :conditions => ['permalink = ? AND ' + | |
105 | 'published_at BETWEEN ? AND ?', | |
106 | title, from, to ]) | |
end | ||
# Fulltext searches the body of published articles | ||
def self.search(query) | ||
if !query.to_s.strip.empty? | ||
tokens = query.split.collect {|c| "%#{c.downcase}%"} | ||
70 | | |
113 | find_published(:all, | |
114 | :conditions => [(["(LOWER(body) LIKE ? OR LOWER(extended) LIKE ? OR LOWER(title) LIKE ?)"] * tokens.size).join(" AND "), *tokens.collect { |token| [token] * 3 }.flatten]) | |
else | ||
[] | ||
end | ||
end | ||
75 | | |
76 | | |
77 | | |
78 | | |
119 | ||
120 | def keywords_to_tags | |
121 | Article.transaction do | |
122 | tags.clear | |
123 | keywords.to_s.scan(/((['"]).*?\2|\w+)/).collect do |x| | |
124 | x.first.tr("\"'", '') | |
125 | end.uniq.each do |tagword| | |
126 | tags << Tag.get(tagword) | |
127 | end | |
128 | end | |
end | ||
80 | | |
81 | | |
83 | | |
84 | | |
131 | def interested_users | |
132 | User.find_boolean(:all, :notify_on_new_articles) | |
133 | end | |
134 | ||
135 | def notify_user_via_email(controller, user) | |
136 | if user.notify_via_email? | |
137 | EmailNotify.send_article(controller, self, user) | |
138 | end | |
139 | end | |
140 | ||
141 | def notify_user_via_jabber(controller, user) | |
142 | if user.notify_via_jabber? | |
143 | JabberNotify.send_message(user, "New post", | |
144 | "A new message was posted to #{blog.blog_name}", | |
145 | content.body_html) | |
146 | end | |
147 | end | |
148 | ||
149 | protected | |
150 | ||
151 | before_create :set_defaults, :create_guid, :add_notifications | |
152 | after_save :keywords_to_tags | |
153 | ||
154 | def correct_counts | |
155 | self.comments_count = self.comments_count | |
156 | self.trackbacks_count = self.trackbacks_count | |
157 | end | |
158 | ||
def set_defaults | ||
86 | | |
87 | | |
88 | | |
89 | | |
160 | if self.attributes.include?("permalink") and self.permalink.blank? | |
161 | self.permalink = self.stripped_title | |
162 | end | |
163 | correct_counts | |
164 | if blog && self.allow_comments.nil? | |
165 | self.allow_comments = blog.default_allow_comments | |
166 | end | |
167 | ||
168 | if blog && self.allow_pings.nil? | |
169 | self.allow_pings = blog.default_allow_pings | |
170 | end | |
171 | true | |
end | ||
91 | | |
92 | | |
93 | | |
94 | | |
95 | | |
174 | def add_notifications | |
175 | # Grr, how do I do :conditions => 'notify_on_new_articles = true' when on MySQL boolean DB tables | |
176 | # are integers, Postgres booleans are booleans, and sqlite is basically just a string? | |
177 | # | |
178 | # I'm punting for now and doing the test in Ruby. Feel free to rewrite. | |
179 | ||
180 | self.notify_users = User.find_boolean(:all, :notify_on_new_articles) | |
181 | self.notify_users << self.user if (self.user.notify_watch_my_articles? rescue false) | |
182 | self.notify_users.uniq! | |
183 | end | |
184 | ||
185 | def default_text_filter_config_key | |
186 | 'text_filter' | |
187 | end | |
188 | ||
def self.time_delta(year, month = nil, day = nil) | ||
from = Time.mktime(year, month || 1, day || 1) | ||
99 | | |
100 | | |
101 | | |
102 | | |
103 | | |
191 | ||
192 | to = from.next_year | |
193 | to = from.next_month unless month.blank? | |
194 | to = from + 1.day unless day.blank? | |
195 | to = to - 1 # pull off 1 second so we don't overlap onto the next day | |
return [from, to] | ||
end | ||
199 | ||
validates_uniqueness_of :guid | ||
validates_presence_of :title | ||
202 | ||
203 | private | |
204 | ||
205 | def fix_resources | |
206 | Resource.find(:all, :conditions => "article_id = #{id}").each do |fu| | |
207 | fu.article_id = nil | |
208 | fu.save | |
209 | end | |
210 | end | |
end |
rool/rails/typo/trunk/app/models/blacklist_pattern.rb:
prev. | current | |
end | ||
class RegexPattern < BlacklistPattern | ||
5 | def matches?(string) | |
6 | string.match(/#{pattern}/) | |
7 | end | |
8 | ||
9 | def to_s | |
10 | "Regex /#{pattern}/" | |
11 | end | |
end | ||
class StringPattern < BlacklistPattern | ||
8 | ||
16 | def matches?(string) | |
17 | string.match(/\b#{Regexp.quote(pattern)}\b/) | |
18 | end | |
19 | ||
20 | def to_s | |
21 | "String '#{pattern}'" | |
22 | end | |
23 | end |
rool/rails/typo/trunk/app/models/blog_sweeper.rb:
prev. | current | |
class BlogSweeper < ActionController::Caching::Sweeper | ||
2 | | |
2 | observe Article, Category, Comment, Trackback, Page, Blog, Sidebar, User | |
def after_save(record) | ||
expire_for(record) | ||
... | ... | |
def after_destroy(record) | ||
expire_for(record) | ||
end | ||
11 | | |
11 | ||
def expire_for(record) | ||
case record | ||
14 | | |
14 | when Blog, Sidebar, Category, Comment, Trackback, Article, User | |
PageCache.sweep_all | ||
16 | expire_fragment(/.*/) | |
when Page | ||
PageCache.sweep("/pages/#{record.name}.html") | ||
19 | expire_fragment(/.*\/pages\/.*/) | |
20 | expire_fragment(/.*\/view_page.*/) | |
end | ||
end | ||
end |
rool/rails/typo/trunk/app/models/category.rb:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 |
| |
5 | | |
6 | | |
7 | | |
8 | | |
9 | | |
10 | | |
11 | | |
12 | | |
13 | | |
14 |
| |
15 | | |
16 | | |
17 | | |
18 |
| |
19 | | |
20 |
| |
21 | | |
22 |
| |
23 | | |
24 | | |
25 | | |
26 |
| |
27 | | |
28 | | |
29 | ||
30 |
| |
1 | class Category < ActiveRecord::Base | |
2 | acts_as_list | |
3 | has_and_belongs_to_many(:articles, | |
4 | :order => "published_at DESC, created_at DESC") | |
5 | ||
6 | def self.find_all_with_article_counters(maxcount=nil) | |
7 | self.find_by_sql([%{ | |
8 | SELECT categories.id, categories.name, categories.permalink, categories.position, COUNT(articles.id) AS article_counter | |
9 | FROM #{Category.table_name} categories | |
10 | LEFT OUTER JOIN #{Category.table_name_prefix}articles_categories#{Category.table_name_suffix} articles_categories | |
11 | ON articles_categories.category_id = categories.id | |
12 | LEFT OUTER JOIN #{Article.table_name} articles | |
13 | ON (articles_categories.article_id = articles.id AND articles.published = ?) | |
14 | GROUP BY categories.id, categories.name, categories.position, categories.permalink | |
15 | ORDER BY position | |
16 | }, true]).each {|item| item.article_counter = item.article_counter.to_i } | |
17 | end | |
18 | ||
19 | def self.find_by_permalink(*args) | |
20 | super || new | |
21 | end | |
22 | ||
23 | def self.to_prefix | |
24 | 'category' | |
25 | end | |
26 | ||
27 | def stripped_name | |
28 | self.name.to_url | |
29 | end | |
30 | ||
31 | def self.reorder(serialized_list) | |
32 | self.transaction do | |
33 | serialized_list.each_with_index do |cid,index| | |
34 | find(cid).update_attribute "position", index rescue nil | |
35 | end | |
36 | end | |
37 | end | |
38 | ||
39 | def self.reorder_alpha | |
40 | reorder find(:all, :order => 'UPPER(name)').collect { |c| c.id } | |
41 | end | |
42 | ||
43 | def published_articles | |
44 | self.articles.find_already_published | |
45 | end | |
46 | ||
47 | def display_name | |
48 | name | |
49 | end | |
50 | ||
51 | protected | |
52 | ||
53 | before_save :set_defaults | |
54 | ||
55 | def set_defaults | |
56 | self.permalink ||= self.stripped_name | |
57 | end | |
58 | ||
59 | validates_presence_of :name | |
60 | validates_uniqueness_of :name, :on => :create | |
61 | end | |
62 |
rool/rails/typo/trunk/app/models/comment.rb:
prev. | current | |
1 | ||
1 | require_dependency 'spam_protection' | |
3 | ||
4 | | |
3 | class Comment < Content | |
4 | include TypoGuid | |
6 | content_fields :body | |
7 | ||
8 | belongs_to :article, :counter_cache => true | |
9 | belongs_to :user | |
10 | ||
validates_presence_of :author, :body | ||
validates_against_spamdb :body, :url, :ip | ||
validates_age_of :article_id | ||
9 | | |
14 | validate_on_create :check_article_is_open_to_comments | |
15 | ||
16 | def self.default_order | |
17 | 'created_at ASC' | |
18 | end | |
19 | ||
20 | def notify_user_via_email(controller, user) | |
21 | if user.notify_via_email? | |
22 | EmailNotify.send_comment(controller, self, user) | |
23 | end | |
24 | end | |
25 | ||
26 | def notify_user_via_jabber(controller, user) | |
27 | if user.notify_via_jabber? | |
28 | JabberNotify.send_message(user, "New comment", "A new comment was posted to '#{article.title}' on #{blog.blog_name} by #{author}: #{body}", self.body_html) | |
29 | end | |
30 | end | |
31 | ||
32 | def interested_users | |
33 | users = User.find_boolean(:all, :notify_on_comments) | |
34 | self.notify_users = users | |
35 | users | |
36 | end | |
37 | ||
38 | def location(anchor=:ignored, only_path=true) | |
39 | blog.url_for(article, "comment-#{id}", only_path) | |
40 | end | |
41 | ||
protected | ||
11 | | |
12 | | |
44 | def check_article_is_open_to_comments | |
45 | return unless article | |
46 | unless article.allow_comments? | |
47 | errors.add(:article, "Article is not open to comments") | |
48 | end | |
49 | end | |
50 | ||
51 | ||
52 | ||
53 | def body_html_postprocess(value, controller) | |
54 | controller.send(:sanitize, controller.send(:auto_link, value)) | |
55 | end | |
56 | ||
57 | def default_text_filter_config_key | |
58 | 'comment_text_filter' | |
59 | end | |
60 | ||
61 | before_create :create_guid | |
62 | before_save :correct_url, :make_nofollow | |
63 | ||
def correct_url | ||
unless url.to_s.empty? | ||
unless url =~ /^http\:\/\// | ||
... | ... | |
end | ||
def make_nofollow | ||
23 | | |
24 | | |
73 | self.author = author.nofollowify | |
74 | self.body_html = body_html.to_s.nofollowify | |
end | ||
26 | ||
27 | | |
28 | | |
29 | | |
30 | | |
31 | ||
end |
rool/rails/typo/trunk/app/models/config_manager.rb:
prev. | current | |
1 | ||
2 | ||
3 | | |
4 | | |
1 | module ConfigManager | |
2 | def self.append_features(base) | |
3 | super | |
4 | base.extend(ClassMethods) | |
end | ||
7 | | |
8 | | |
9 | | |
7 | module ClassMethods | |
8 | def fields | |
9 | @fields ||= Hash.new { Item.new } | |
10 | end | |
11 | | |
12 | | |
13 | | |
14 | | |
12 | def setting(name, type=:object, default=nil) | |
13 | item = Item.new | |
14 | item.name, item.ruby_type, item.default = name.to_s, type, default | |
15 | fields[name.to_s] = item | |
16 | add_setting_accessor(item) | |
end | ||
16 | | |
17 | | |
18 | | |
19 | | |
20 | | |
21 | | |
23 | | |
24 | | |
25 | | |
19 | def default_for(key) | |
20 | fields[key.to_s].default | |
21 | end | |
27 | | |
23 | private | |
29 | | |
30 | | |
31 | | |
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | | |
38 | | |
39 | | |
25 | def add_setting_accessor(item) | |
26 | add_setting_reader(item) | |
27 | add_setting_writer(item) | |
end | ||
29 | ||
30 | def add_setting_reader(item) | |
31 | self.send(:define_method, item.name) do | |
32 | raw_value = settings[item.name] | |
33 | raw_value.nil? ? item.default : raw_value | |
34 | end | |
35 | if item.ruby_type == :boolean | |
36 | self.send(:define_method, item.name + "?") do | |
37 | raw_value = settings[item.name] | |
38 | raw_value.nil? ? item.default : raw_value | |
39 | end | |
40 | end | |
41 | end | |
42 | ||
43 | def add_setting_writer(item) | |
44 | self.send(:define_method, "#{item.name}=") do |newvalue| | |
45 | retval = settings[item.name] = canonicalize(item.name, newvalue) | |
46 | self.save! unless new_record? | |
47 | retval | |
48 | end | |
49 | end | |
50 | ||
end | ||
42 | | |
43 | | |
44 | | |
45 | | |
46 | | |
52 | ||
53 | def canonicalize(key, value) | |
54 | self.class.fields[key.to_s].canonicalize(value) | |
end | ||
49 | | |
50 | | |
57 | class Item | |
58 | attr_accessor :name, :ruby_type, :default | |
59 | ||
60 | def canonicalize(value) | |
61 | case ruby_type | |
62 | when :boolean | |
63 | case value | |
64 | when "0", 0, '', false, "false", "f", nil | |
65 | false | |
66 | else | |
67 | true | |
68 | end | |
69 | when :integer | |
70 | value.to_i | |
71 | when :string | |
72 | value.to_s | |
73 | when :yaml | |
74 | value.to_yaml | |
75 | else | |
76 | value | |
77 | end | |
78 | end | |
end | ||
52 | | |
end |
rool/rails/typo/trunk/app/models/page.rb:
prev. | current | |
1 | ||
1 | class Page < Content | |
belongs_to :user | ||
3 | | |
validates_presence_of :name, :title, :body | ||
validates_uniqueness_of :name | ||
6 | content_fields :body | |
7 | ||
8 | def self.default_order | |
9 | 'name ASC' | |
10 | end | |
11 | ||
12 | def location(anchor=nil, only_path=true) | |
13 | blog.url_for(:only_path => only_path, :action => 'view_page', | |
14 | :name => name, :anchor => anchor) | |
15 | end | |
16 | ||
protected | ||
8 | | |
9 | | |
10 | | |
11 | | |
18 | ||
19 | def default_text_filter_config_key; 'text_filter'; end | |
end |
rool/rails/typo/trunk/app/models/page_cache.rb:
prev. | current | |
class PageCache < ActiveRecord::Base | ||
2 | | |
cattr_accessor :public_path | ||
4 | | |
3 | @@public_path = ActionController::Base.page_cache_directory | |
def self.sweep(pattern) | ||
destroy_all("name like '#{pattern}'") | ||
... | ... | |
private | ||
after_destroy :expire_cache | ||
17 | | |
16 | ||
def expire_cache | ||
# It'd be better to call expire_page here, except it's a | ||
# controller method and we can't get to it. | ||
... | ... | |
logger.info "Sweeping #{self.name}" | ||
delete_file(path) | ||
end | ||
26 | | |
25 | ||
def delete_file(path) | ||
28 | | |
27 | File.delete(path) if File.file?(path) | |
end | ||
end |
rool/rails/typo/trunk/app/models/ping.rb:
prev. | current | |
1 | require 'rexml/document' | |
2 | ||
class Ping < ActiveRecord::Base | ||
belongs_to :article | ||
3 | | |
4 | | |
5 | | |
5 | ||
6 | class Pinger | |
7 | def send_pingback_or_trackback | |
8 | begin | |
9 | @response = Net::HTTP.get_response(URI.parse(ping.url)) | |
10 | send_pingback or send_trackback | |
11 | rescue Timeout::Error => err | |
12 | return | |
13 | rescue => err | |
14 | raise err | |
15 | # Ignore | |
16 | end | |
17 | end | |
18 | ||
19 | def pingback_url | |
20 | if @response["X-Pingback"] | |
21 | @response["X-Pingback"] | |
22 | elsif | |
23 | response.body =~ /<link rel="pingback" href="([^"]+)" ?\/?>/ | |
24 | $1 | |
25 | else | |
26 | nil | |
27 | end | |
28 | end | |
29 | ||
30 | def origin_url | |
31 | @origin_url | |
32 | end | |
33 | ||
34 | def response | |
35 | @response | |
36 | end | |
37 | ||
38 | def ping | |
39 | @ping | |
40 | end | |
41 | ||
42 | def article | |
43 | ping.article | |
44 | end | |
45 | ||
46 | def config | |
47 | ping.config | |
48 | end | |
49 | ||
50 | def send_xml_rpc(*args) | |
51 | ping.send(:send_xml_rpc, *args) | |
52 | end | |
53 | ||
54 | def trackback_url | |
55 | rdfs = response.body.scan(/<rdf:RDF.*?<\/rdf:RDF>/m) | |
56 | rdfs.each do |rdf| | |
57 | xml = REXML::Document.new(rdf) | |
58 | xml.elements.each("//rdf:Description") do |desc| | |
59 | if rdfs.size == 1 || desc.attributes["dc:identifier"] == ping.url | |
60 | return desc.attributes["trackback:ping"] | |
61 | end | |
62 | end | |
63 | end | |
64 | # Didn't find a trackback url, so fall back to the url itself. | |
65 | @ping.url | |
66 | end | |
67 | ||
68 | def send_pingback | |
69 | if pingback_url | |
70 | send_xml_rpc(pingback_url, "pingback.ping", origin_url, ping.url) | |
71 | return true | |
72 | else | |
73 | return false | |
74 | end | |
75 | end | |
76 | ||
77 | def send_trackback | |
78 | ping.send_trackback(trackback_url, origin_url) | |
79 | end | |
80 | ||
81 | private | |
82 | ||
83 | def initialize(origin_url, ping) | |
84 | @origin_url = origin_url | |
85 | @ping = ping | |
86 | end | |
87 | end | |
88 | ||
89 | def send_pingback_or_trackback(origin_url) | |
90 | Pinger.new(origin_url, self).send_pingback_or_trackback | |
91 | end | |
92 | ||
93 | def send_trackback(trackback_url, origin_url) | |
94 | trackback_uri = URI.parse(trackback_url) | |
95 | ||
post = "title=#{URI.escape(article.title)}" | ||
7 | | |
97 | post << "&excerpt=#{URI.escape(article.body_html.strip_html[0..254])}" | |
post << "&url=#{origin_url}" | ||
9 | | |
99 | post << "&blog_name=#{URI.escape(article.blog.blog_name)}" | |
11 | | |
12 | | |
13 | | |
101 | Net::HTTP.start(trackback_uri.host, trackback_uri.port) do |http| | |
102 | path = trackback_uri.path | |
103 | path += "?#{trackback_uri.query}" if trackback_uri.query | |
104 | http.post(path, post, 'Content-type' => 'application/x-www-form-urlencoded; charset=utf-8') | |
105 | end | |
end | ||
15 | ||
108 | ||
109 | ||
110 | ||
111 | def send_weblogupdatesping(server_url, origin_url) | |
112 | send_xml_rpc(self.url, "weblogUpdates.ping", article.blog.blog_name, server_url, origin_url) | |
113 | end | |
114 | ||
115 | protected | |
116 | ||
117 | def send_xml_rpc(xml_rpc_url, name, *args) | |
118 | begin | |
119 | server = XMLRPC::Client.new2(URI.parse(xml_rpc_url).to_s) | |
120 | ||
121 | begin | |
122 | result = server.call(name, *args) | |
123 | rescue XMLRPC::FaultException => e | |
124 | logger.error(e) | |
125 | end | |
126 | rescue Exception => e | |
127 | logger.error(e) | |
128 | end | |
129 | end | |
130 | end |
rool/rails/typo/trunk/app/models/resource.rb:
prev. | current | |
class Resource < ActiveRecord::Base | ||
2 | validates_uniqueness_of :filename | |
3 | after_destroy :delete_filename_on_disk | |
4 | before_validation_on_create :uniq_filename_on_disk | |
5 | belongs_to :article | |
6 | ||
7 | #Reads YAML file from config dir (iTunes.yml) for easy updating | |
8 | def get_itunes_categories | |
9 | itunes_categories_raw = YAML::load( File.open( "#{RAILS_ROOT}/config/iTunes.yml" ) ) | |
10 | itunes_categories = [] | |
11 | itunes_categories_raw.keys.sort.each do |cat| | |
12 | itunes_categories.push cat => itunes_categories_raw[cat] | |
13 | end | |
14 | return itunes_categories | |
15 | end | |
16 | ||
17 | def validate_on_update | |
18 | if itunes_explicit? | |
19 | errors.add_to_base("You must check the box to activate metadata.") unless itunes_metadata? | |
20 | errors.add_to_base("You must specify an author.") if itunes_author.blank? | |
21 | errors.add_to_base("You must specify an subtitle.") if itunes_subtitle.blank? | |
22 | errors.add_to_base("You must specify a summary.") if itunes_summary.blank? | |
23 | errors.add_to_base("You must specify keywords.") if itunes_keywords.blank? | |
24 | if !itunes_duration.blank? | |
25 | errors.add_to_base("You must specify duration in a HH:MM:SS format.") unless itunes_duration =~ /^(\d{0,2}:)?\d{1,2}:?\d{2}$/ | |
26 | end | |
27 | if !itunes_category.nil? | |
28 | errors.add_to_base("You can only specify one parent category, but you can choose multiple sub categories.") if itunes_category.length > 1 | |
29 | end | |
30 | end | |
31 | end | |
32 | def fullpath(file = nil) | |
33 | "#{RAILS_ROOT}/public/files/#{file.nil? ? filename : file}" | |
34 | end | |
35 | ||
36 | def write_to_disk(up) | |
37 | begin | |
38 | # create the public/files dir if it doesn't exist | |
39 | FileUtils.mkdir(fullpath('')) unless File.directory?(fullpath('')) | |
40 | if up.kind_of?(Tempfile) and !up.local_path.nil? and File.exist?(up.local_path) | |
41 | File.chmod(0600, up.local_path) | |
42 | FileUtils.copy(up.local_path, fullpath) | |
43 | else | |
44 | bytes = up | |
45 | if up.kind_of?(StringIO) | |
46 | up.rewind | |
47 | bytes = up.read | |
48 | end | |
49 | File.open(fullpath, "wb") { |f| f.write(bytes) } | |
50 | end | |
51 | File.chmod(0644, fullpath) | |
52 | self.size = File.stat(fullpath).size rescue 0 | |
53 | update | |
54 | self | |
55 | rescue | |
56 | raise | |
57 | end | |
58 | end | |
59 | ||
60 | ||
61 | protected | |
62 | def uniq_filename_on_disk | |
63 | i = 0 | |
64 | raise if filename.empty? | |
65 | tmpfile = File.basename(filename.gsub(/\\/, '/')).gsub(/[^\w\.\-]/,'_') | |
66 | filename = tmpfile | |
67 | while File.exists?(fullpath(tmpfile)) | |
68 | i += 1 | |
69 | tmpfile = filename.sub(/^(.*?)(\.[^\.]+)?$/, '\1'+"#{i}"+'\2') | |
70 | end | |
71 | self.filename = tmpfile | |
72 | end | |
73 | def delete_filename_on_disk | |
74 | File.unlink(fullpath(filename)) if File.exist?(fullpath(filename)) | |
75 | end | |
end |
rool/rails/typo/trunk/app/models/sidebar.rb:
prev. | current | |
1 | ||
2 | ||
class Sidebar < ActiveRecord::Base | ||
# acts_as_list | ||
5 | | |
6 | | |
3 | serialize :config | |
def self.find_all_visible | ||
find :all, :conditions => 'active_position is not null', :order => 'active_position' | ||
... | ... | |
end | ||
def publish | ||
21 | | |
self.active_position=self.staged_position | ||
end | ||
def sidebar_controller | ||
26 | | |
22 | @sidebar_controller ||= SidebarController.available_sidebars.find { |s| s.short_name == self.controller } | |
end | ||
29 | | |
30 | | |
25 | def config | |
26 | self[:config]||{} | |
end | ||
def html_id |
rool/rails/typo/trunk/app/models/simple_cache.rb:
prev. | current | |
class SimpleCache < Hash | ||
2 | | |
2 | ||
class Item | ||
attr_reader :expiry, :value | ||
def initialize(expiry, value) | ||
@expiry, @value = expiry, value | ||
end | ||
end | ||
9 | | |
9 | ||
def initialize(ttl) | ||
@ttl = ttl | ||
logger.info(" SimpleCache: will store items for #{ttl}s") | ||
end | ||
14 | | |
14 | ||
def [](key) | ||
item = super(key) | ||
if item.nil? or item.expiry <= Time.now | ||
... | ... | |
super(key, Item.new(@ttl.from_now, value)) | ||
value | ||
end | ||
31 | | |
32 | | |
31 | ||
32 | ||
def logger | ||
@logger ||= RAILS_DEFAULT_LOGGER || Logger.new(STDOUT) | ||
end | ||
36 | | |
37 | ||
37 | ||
38 | end |
rool/rails/typo/trunk/app/models/theme.rb:
prev. | current | |
cattr_accessor :cache_theme_lookup | ||
@@cache_theme_lookup = false | ||
5 | | |
5 | attr_accessor :name, :path, :description_html | |
def initialize(name, path) | ||
@name, @path = name, path | ||
end | ||
10 | | |
10 | ||
def layout | ||
"../../themes/#{name}/layouts/default" | ||
end | ||
def description | ||
16 | | |
17 | | |
16 | File.read("#{path}/about.markdown") rescue "### #{name}" | |
end | ||
19 | | |
18 | ||
def self.themes_root | ||
RAILS_ROOT + "/themes" | ||
end | ||
24 | | |
25 | | |
26 | | |
27 | ||
28 | | |
29 | | |
30 | | |
31 | | |
def self.theme_from_path(path) | ||
name = path.scan(/[-\w]+$/i).flatten.first | ||
self.new(name, path) | ||
... | ... | |
def self.installed_themes | ||
cache_theme_lookup ? @theme_cache ||= search_theme_directory : search_theme_directory | ||
45 | | |
36 | end | |
def self.search_theme_directory | ||
48 | | |
49 | | |
39 | glob = "#{themes_root}/[a-zA-Z0-9]*" | |
40 | Dir.glob(glob).select do |file| | |
41 | File.readable?("#{file}/about.markdown") | |
end.compact | ||
51 | | |
43 | end | |
end |
rool/rails/typo/trunk/app/models/trackback.rb:
prev. | current | |
1 | ||
1 | require_dependency 'spam_protection' | |
3 | ||
4 | | |
3 | class Trackback < Content | |
4 | include TypoGuid | |
5 | belongs_to :article, :counter_cache => true | |
7 | content_fields :excerpt | |
8 | ||
validates_age_of :article_id | ||
validates_against_spamdb :title, :excerpt, :ip, :url | ||
8 | | |
11 | validates_presence_of :title, :excerpt, :url | |
12 | validate_on_create :article_is_pingable | |
14 | def self.default_order | |
15 | 'created_at ASC' | |
16 | end | |
17 | ||
18 | def initialize(*args, &block) | |
19 | super(*args, &block) | |
20 | self.title ||= self.url | |
21 | self.blog_name ||= "" | |
22 | end | |
23 | ||
24 | def location(anchor=:ignored, only_path=true) | |
25 | blog.url_for(article, "trackback-#{id}", only_path) | |
26 | end | |
27 | ||
protected | ||
11 | | |
29 | before_create :make_nofollow, :process_trackback, :create_guid | |
13 | | |
14 | | |
15 | | |
16 | | |
31 | def make_nofollow | |
32 | self.blog_name = blog_name.strip_html | |
33 | self.title = title.strip_html | |
34 | self.excerpt = excerpt.strip_html | |
35 | end | |
36 | ||
37 | def process_trackback | |
38 | if excerpt.length >= 251 | |
39 | # this limits excerpt to 250 chars, including the trailing "..." | |
40 | self.excerpt = excerpt[0..246] << "..." | |
end | ||
42 | end | |
19 | | |
20 | | |
21 | | |
22 | | |
44 | def article_is_pingable | |
45 | return if article.nil? | |
46 | unless article.allow_pings? | |
47 | errors.add(:article, "Article is not pingable") | |
end | ||
49 | end | |
end | ||
rool/rails/typo/trunk/app/models/user.rb:
prev. | current | |
require 'digest/sha1' | ||
3 | ||
3 | # this model expects a certain database layout and its based on the name/login pattern. | |
class User < ActiveRecord::Base | ||
5 | has_and_belongs_to_many :notify_contents, :class_name => 'Content', | |
6 | :join_table => 'notifications', :foreign_key => 'notify_user_id', | |
7 | :association_foreign_key => 'notify_content_id', :uniq => true | |
9 | has_many :articles, :order => 'created_at DESC' do | |
10 | def published | |
11 | find_published(:all, :order => 'created_at DESC') | |
12 | end | |
13 | end | |
14 | ||
# echo "typo" | sha1sum - | ||
@@salt = '20ac4d290c2293702c64b3b287ae5ea79b26a5c1' | ||
cattr_accessor :salt | ||
10 | | |
19 | # Authenticate a user. | |
# | ||
# Example: | ||
# @user = User.authenticate('bob', 'bobpass') | ||
... | ... | |
def self.authenticate(login, pass) | ||
find_first(["login = ? AND password = ?", login, sha1(pass)]) | ||
end | ||
18 | | |
27 | ||
def self.authenticate?(login, pass) | ||
user = self.authenticate(login, pass) | ||
return false if user.nil? | ||
return true if user.login == login | ||
23 | | |
32 | ||
false | ||
end | ||
26 | | |
35 | ||
36 | def self.find_by_permalink(permalink) | |
37 | self.find_by_login(permalink) | |
38 | end | |
39 | ||
40 | # Let's be lazy, no need to fetch the counters, rails will handle it. | |
41 | def self.find_all_with_article_counters(ignored_arg) | |
42 | find(:all) | |
43 | end | |
44 | ||
45 | def self.to_prefix | |
46 | 'author' | |
47 | end | |
48 | ||
49 | def password=(newpass) | |
50 | @password = newpass | |
51 | end | |
52 | ||
53 | def password(cleartext = nil) | |
54 | if cleartext | |
55 | @password.to_s | |
56 | else | |
57 | @password || read_attribute("password") | |
58 | end | |
59 | end | |
60 | ||
61 | def article_counter | |
62 | articles.size | |
63 | end | |
64 | ||
65 | def display_name | |
66 | name | |
67 | end | |
68 | ||
69 | def permalink | |
70 | login | |
71 | end | |
72 | ||
protected | ||
29 | | |
30 | | |
31 | | |
75 | # Apply SHA1 encryption to the supplied password. | |
76 | # We will additionally surround the password with a salt | |
77 | # for additional security. | |
def self.sha1(pass) | ||
Digest::SHA1.hexdigest("#{salt}--#{pass}--") | ||
end | ||
35 | | |
81 | ||
before_create :crypt_password | ||
37 | | |
38 | | |
39 | | |
83 | ||
84 | # Before saving the record to database we will crypt the password | |
85 | # using SHA1. | |
# We never store the actual password in the DB. | ||
def crypt_password | ||
42 | | |
88 | write_attribute "password", self.class.sha1(password(true)) | |
89 | @password = nil | |
end | ||
44 | | |
91 | ||
before_update :crypt_unless_empty | ||
46 | | |
93 | ||
# If the record is updated we will check if the password is empty. | ||
# If its empty we assume that the user didn't want to change his | ||
# password and just reset it to the old value. | ||
def crypt_unless_empty | ||
51 | | |
98 | if password(true).empty? | |
user = self.class.find(self.id) | ||
self.password = user.password | ||
else | ||
55 | | |
56 | | |
57 | | |
58 | | |
102 | write_attribute "password", self.class.sha1(password(true)) | |
103 | @password = nil | |
104 | end | |
105 | end | |
106 | ||
validates_uniqueness_of :login, :on => :create | ||
validates_length_of :password, :within => 5..40, :on => :create | ||
validates_presence_of :login |
rool/rails/typo/trunk/app/views/accounts/login.rhtml:
prev. | current | |
<h3>Please login</h3> | ||
<div class="form"> | ||
9 | | |
10 | | |
9 | <% if @flash[:notice] %> | |
10 | <h4><%= @flash[:notice] %></h4> | |
<% end %> | ||
<label for="user_login">Login:</label><br/> | ||
<input type="text" name="user_login" id="user_login" size="20" value=""/><br/> |
rool/rails/typo/trunk/app/views/accounts/logout.rhtml:
prev. | current | |
<h3>Logoff</h3> | ||
<div class="memo"> | ||
4 | | |
4 | <p> | |
5 | You are now logged out of the system. | |
6 | <%= link_to "Do you want to go to your blog?", :controller => "/" %> | |
7 | </p> | |
6 | | |
9 | <%= link_to "« login", :action => "login" %><br /> | |
</div> | ||
rool/rails/typo/trunk/app/views/accounts/signup.rhtml:
prev. | current | |
<%= password_field "user", "password_confirmation", :size => 30 %><br/> | ||
<input type="submit" value="Signup »" class="primary" /> | ||
</div> | ||
23 | </div> | |
<%= end_form_tag %> | ||
rool/rails/typo/trunk/app/views/admin/blacklist/_blacklist_patterns.rhtml:
prev. | current | |
</tr> | ||
<% for blacklist_pattern in @blacklist_patterns -%> | ||
<tr <%= alternate_class -%>> | ||
10 | | |
10 | <td class="field"><%= link_to h(blacklist_pattern.pattern), :action => "edit", :id => blacklist_pattern.id %></td> | |
<td class="field"><%= blacklist_pattern.class %></td> | ||
<td class="operation"><%= link_to_edit blacklist_pattern %></td> | ||
<td class="operation"><%= link_to_destroy blacklist_pattern %></td> |
rool/rails/typo/trunk/app/views/admin/blacklist/_quick_post.rhtml:
prev. | current | |
</select> | ||
<div id="operations"> | ||
14 | | |
14 | <%= save("Add pattern") %> or <a href="#" onclick="new Effect.BlindUp('quick-post', {duration: 0.4}); return false;" >Cancel</a> | |
</div> | ||
<%= end_form_tag %> |
rool/rails/typo/trunk/app/views/admin/categories/_categories.rhtml:
prev. | current | |
1 | ||
2 | ||
3 | | |
4 | | |
5 | | |
6 | ||
7 | ||
8 | ||
9 | | |
10 | | |
11 | | |
12 | ||
13 | ||
1 | <table> | |
2 | <tr> | |
3 | <th>Category title</th> | |
4 | <th>Articles</th> | |
5 | <th>Delete</th> | |
6 | </tr> | |
7 | <% for category in @categories -%> | |
8 | <tr <%= alternate_class -%> id="category_<%= category.id -%>"> | |
9 | <td><%= image_tag 'checked.gif' %> <%= link_to category.name, :action => 'show', :id => category.id %></td> | |
10 | <td><%= link_to pluralize(category.articles.size, 'article'), :action => 'show', :id => category.id %></td> | |
11 | <td class="operation"><%= link_to_destroy category %></td> | |
12 | </tr> | |
13 | <% end -%> | |
</table> | ||
rool/rails/typo/trunk/app/views/admin/categories/_quick_post.rhtml:
prev. | current | |
</p> | ||
<div id="operations"> | ||
9 | | |
9 | <%= save("Add category") %> or <a href="#" onclick="new Effect.BlindUp('quick-post', {duration: 0.4}); return false;" >Cancel</a> | |
</div> | ||
<%= end_form_tag %> |
rool/rails/typo/trunk/app/views/admin/categories/destroy.rhtml:
prev. | current | |
<%= task_show 'Show this category', @category.id %> | ||
<% end %> | ||
7 | | |
7 | <p>Are you sure you want to delete the category '<%= @category.name %>'?</p> | |
<%= start_form_tag :action => "destroy", :id => @category.id %> | ||
<%= confirm_delete("Delete this category") %> | ||
<%= end_form_tag %> | ||
rool/rails/typo/trunk/app/views/admin/categories/list.rhtml:
prev. | current | |
<% @page_heading = 'Categories' %> | ||
3 | | |
4 | | |
5 | | |
3 | <% content_for('tasks') do -%> | |
4 | <%= task_quickpost('Create new category') -%> | |
5 | <li><%= link_to_remote('Reorder', :update => 'category_container', :url => { :action => 'reorder' }) %></li> | |
6 | <li><%= link_to_remote('Sort alphabetically', :update => 'category_container', :url => { :action => 'asort' }) -%></li> | |
7 | <% end -%> | |
<div id="quick-post" style="display:none;position:absolute;"> | ||
<%= render :partial => "quick_post" %> | ||
</div> | ||
11 | | |
13 | <div id="category_container" class="list"> | |
<%= render :partial => 'categories' %> | ||
</div> |
rool/rails/typo/trunk/app/views/admin/categories/show.rhtml:
prev. | current | |
<% content_for('tasks') do %> | ||
<%= task_edit 'Edit this category', @category.id %> | ||
5 | | |
5 | <% end %> | |
7 | | |
8 | | |
7 | <%= start_form_tag :action=>"new" %> | |
8 | <div class="list"> | |
<table cellspacing="1" cellpadding="0"> | ||
<% for article in @category.articles -%> | ||
11 | | |
12 | | |
13 | | |
14 | | |
15 | | |
11 | <tr <%= alternate_class -%>> | |
12 | <td><%= image_tag 'checked.gif' %> <%= link_to h(article.title), :controller => "content", :action => "show", :id => article.id %></td> | |
13 | <td><%= distance_of_time_in_words_to_now article.published_at %> ago</td> | |
14 | <td><%= link_to pluralize(article.comments.size, 'comment'), :controller => 'comments', :article_id => article, :action => 'list' %></td> | |
15 | </tr> | |
<% end -%> | ||
</table> | ||
18 | | |
19 | </div> |
rool/rails/typo/trunk/app/views/admin/comments/destroy.rhtml:
prev. | current | |
1 | | |
1 | <% @page_heading = "Comments for #{ link_to h(@article.title), :controller => 'content', :action => 'show', :id => @article }" %> | |
<% content_for('tasks') do %> | ||
<%= task_show 'Show this comment', @comment.id %> | ||
... | ... | |
<%= start_form_tag %> | ||
<%= hidden_field "comment", "id" %> | ||
<%= confirm_delete %> | ||
11 | | |
12 | <%= end_form_tag %> |
rool/rails/typo/trunk/app/views/admin/comments/edit.rhtml:
prev. | current | |
1 | | |
1 | <% @page_heading = "Comments for #{ link_to h(@article.title), :controller => 'content', :action => 'show', :id => @article }" %> | |
<% content_for('tasks') do %> | ||
<li><%= comment_url_link 'View comment on your blog', @comment %></li> | ||
... | ... | |
<%= save %> or <%= cancel %> | ||
</div> | ||
18 | | |
19 | <%= end_form_tag %> |
rool/rails/typo/trunk/app/views/admin/comments/list.rhtml:
prev. | current | |
1 | | |
1 | <% @page_heading = "Comments for #{ link_to h(@article.title), :controller => 'content', :action => 'show', :id => @article }" %> | |
<% content_for('tasks') do %> | ||
<li><%= link_to 'Back to articles', :controller => 'content', :action => 'list' %></li> | ||
... | ... | |
<table> | ||
<tr> | ||
<th>Author</th> | ||
12 | <th>Email</th> | |
<th>Body</th> | ||
<th>IP</th> | ||
<th>Posted date</th> | ||
... | ... | |
</tr> | ||
<% for comment in @comments -%> | ||
<tr> | ||
20 | | |
21 | <td class="field"><%= image_tag 'checked.gif' %> <%=link_to_unless comment.url.blank?, h(comment.author), comment.url %></td> | |
22 | <td class="field"><%=h comment.email %></td> | |
<td class="field"><%=link_to truncate(strip_html(comment.body)), :action => 'show', :id => comment.id %> <%= comment_url_link image_tag('go'), comment %></td> | ||
<td class="field"><%=h comment.ip %></td> | ||
<td class="field"><%=h distance_of_time_in_words_to_now(comment.created_at) %></td> | ||
... | ... | |
</tr> | ||
<% end -%> | ||
</table> | ||
29 | | |
32 | </div> |
rool/rails/typo/trunk/app/views/admin/content/_articles.rhtml:
prev. | current | |
</tr> | ||
<% for article in @articles %> | ||
<tr <%= alternate_class %>> | ||
12 | | |
13 | | |
14 | | |
15 | | |
12 | <td><%= (article.published?) ? image_tag('checked.gif') : image_tag('x-ed.gif') %> <%= link_to h(article.title), {:action => "show", :id => article.id} %> <%= article_link(image_tag('go'), article) %> </td> | |
13 | <td><%= distance_of_time_in_words_to_now article.published_at %> ago</td> | |
14 | <td><%= link_to pluralize(article.comments.size, 'comment'), :controller => 'comments', :article_id => article, :action => 'list' %></td> | |
15 | <td><%= link_to pluralize(article.trackbacks.size, 'trackback'), :controller => 'trackbacks', :article_id => article, :action => 'list' %></td> | |
<td class="operation"><%= link_to_edit article %></td> | ||
17 | | |
18 | ||
17 | <td class="operation"><%= link_to_destroy article %></td> | |
18 | </tr> | |
<% end %> | ||
20 | ||
21 | </table> |
rool/rails/typo/trunk/app/views/admin/content/_form.rhtml:
prev. | current | |
<%= text_field 'article', 'permalink' %> | ||
</p> | ||
<p> | ||
13 | <label for="article_body">Body:</label><br /> | |
14 | <%= text_area 'article', 'body', :rows => 25, :style => 'width: 48%;' %> | |
15 | </p> | |
16 | <p> | |
<label for="categories">Categories:</label><br /> | ||
<select id="categories" name="categories[]" multiple="multiple" size="10" style="width:250px;"> | ||
<%= options_from_collection_for_select(@categories, "id", "name", @selected) %> | ||
</select> | ||
</p> | ||
<p> | ||
19 | | |
20 | | |
23 | <label for="article_keywords">Keywords:</label><br/> | |
24 | <%= text_field 'article', 'keywords' %> | |
</p> | ||
<p> | ||
<a href="#" onclick="Element.toggle('extended'); return false">Add Extended Content</a><br /> | ||
<div id="extended" style="display:none;"> | ||
<label for="article_extended">Extended:</label><br /> | ||
26 | | |
30 | <%= text_area 'article', 'extended', :rows => 30, :style => 'width: 48%;' %> | |
</div> | ||
</p> | ||
... | ... | |
<label for="article_allow_pings">Allow pings: </label><%= check_box 'article', 'allow_pings' %><br /> | ||
<label for="article_published">Published:</label><%= check_box 'article', 'published' %><br /> | ||
<label for="article_text_filter">Textfilter: </label><%= select 'article', 'text_filter', text_filter_options %><br /> | ||
36 | ||
40 | <label for="article_published_at">Publish at:</label><%= datetime_select 'article', 'published_at', :include_blank => true %><br /> | |
</div> | ||
<br clear="all"/> | ||
44 | <p> | |
45 | <a href="#" onclick="Element.toggle('attachments'); return false;">Attachments (+/-)</a> | |
46 | <div id="attachments" style="display:none;"> | |
47 | <%= render :partial => 'admin/content/attachment', :locals => { :attachment_num => 1 } -%> | |
48 | </div> | |
49 | </p> | |
50 | ||
<!--[eoform:articles]--> |
rool/rails/typo/trunk/app/views/admin/content/_quick_post.rhtml:
prev. | current | |
<%= text_area 'article', 'body', :rows => 10 %> | ||
</p> | ||
<div id="operations"> | ||
18 | | |
18 | <%= save("Save Post") %> or <a href="#" onclick="new Effect.BlindUp('quick-post', {duration: 0.4}); return false;" >Cancel</a> | |
</div> | ||
<%= end_form_tag %> |
rool/rails/typo/trunk/app/views/admin/content/destroy.rhtml:
prev. | current | |
<%= task_show "Show this article", @article.id %> | ||
<% end %> | ||
7 | | |
7 | <p>Are you sure you want to delete this article ( <%=h @article.title -%> )?</p> | |
<%= start_form_tag :controller => 'content', :action => 'destroy' %> | ||
<%= hidden_field "article", "id" %> | ||
<%= confirm_delete("Delete this article") %> |
rool/rails/typo/trunk/app/views/admin/content/edit.rhtml:
prev. | current | |
<li><%= link_to 'View article on your blog', article_url(@article) %></li> | ||
<% end %> | ||
8 | | |
8 | <%= start_form_tag({ :action => "edit", :id => @article }, :id => "article_form", :enctype => "multipart/form-data") %> | |
<h3>Editing article</h3> | ||
<div class="form"> |
rool/rails/typo/trunk/app/views/admin/content/new.rhtml:
prev. | current | |
<h3>Creating article</h3> | ||
5 | | |
5 | <%= start_form_tag({ :action => "new" }, :id => "article_form", :enctype => "multipart/form-data") %> | |
<div class="form"> | ||
... | ... | |
:complete => "Element.show('preview')", | ||
:url => { :action => "preview" } %> | ||
27 | | |
28 |
rool/rails/typo/trunk/app/views/admin/content/preview.rhtml:
prev. | current | |
<h4><%= @article[:title] %></h4> | ||
3 | ||
4 | ||
5 | ||
4 | <%= @article.full_html %> |
rool/rails/typo/trunk/app/views/admin/content/show.rhtml:
prev. | current | |
<% @page_heading = 'Articles' %> | ||
2 | | |
2 | ||
<% content_for('tasks') do %> | ||
<%= task_edit 'Edit this article', @article.id %> | ||
<li><%= link_to 'View article on your blog', article_url(@article) %></li> | ||
6 | | |
6 | <% end %> | |
<h3><%=h @article.title %></h3> | ||
10 | | |
11 | | |
12 | | |
13 | | |
14 | | |
15 | | |
10 | <div class="form"> | |
11 | <div><%= @article.full_html %></div> | |
12 | <p class="meta"><label>Posted:</label> <%=h @article.published_at.to_formatted_s(:long_weekday) %> by <%=h @article.author %></p> | |
13 | <p class="meta"><label>Last updated:</label> <%=h @article.updated_at.to_formatted_s(:long_weekday) %></p> | |
14 | <p class="meta"><label>Published:</label> <%=h (@article.published? ? "Yes" : "No") %></p> | |
</div> | ||
17 | | |
16 | ||
<h3>Categories</h3> | ||
19 | | |
20 | | |
21 | | |
22 | | |
23 | | |
18 | <div id="categories" class="form"> | |
19 | <%= render :partial => 'show_categories' -%> | |
20 | </div> | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | ||
22 | <h3>Attachments</h3> | |
23 | <div id="resources" class="form"> | |
24 | <%= render :partial => 'show_resources' -%> | |
25 | </div> |
rool/rails/typo/trunk/app/views/admin/general/index.rhtml:
prev. | current | |
<% @page_heading = 'Blog settings' %> | ||
<%= start_form_tag :action => 'update'%> | ||
4 | | |
4 | ||
<div class="tasks"> | ||
<h3>Which settings group would you like to edit?</h3> | ||
<ul> | ||
<li><a href="#gensettings" onclick="new Effect.ScrollTo('gensettings'); return false">General Settings</a></li> | ||
<li><a href="#textfilter" onclick="new Effect.ScrollTo('textfilter'); return false">Text Filter</a></li> | ||
<li><a href="#spam" onclick="new Effect.ScrollTo('spam'); return false">Spam Protection</a></li> | ||
11 | <li><a href="#resources" onclick="new Effect.ScrollTo('resources'); return false">Resource Defaults</a></li> | |
<li><a href="#misc" onclick="new Effect.ScrollTo('misc'); return false">Cache</a></li> | ||
</ul> | ||
<div style="clear:both;"></div> | ||
</div> | ||
15 | | |
16 | ||
<div id="settings"> | ||
<div id="gensettings" class="set" style="margin-top:10px;"> | ||
<h3>General Settings</h3> | ||
<p> | ||
20 | | |
21 | | |
21 | <label for="blog_name">Blog name:</label> | |
22 | <input name="setting[blog_name]" id="blog_name" type="text" value="<%=h this_blog.blog_name %>" /> | |
</p> | ||
<p> | ||
24 | | |
25 | | |
25 | <label for="blog_subtitle">Blog subtitle:</label> | |
26 | <input name="setting[blog_subtitle]" id="blog_subtitle" type="text" value="<%=h this_blog.blog_subtitle %>" /> | |
</p> | ||
28 | <p> | |
29 | <label for="canonical_server_url">Canonical Server Url:</label> | |
30 | <input name="setting[canonical_server_url]" id="canonical_server_url" type="text" value="<%= this_blog.canonical_server_url %>" /> | |
31 | </p> | |
<p> | ||
28 | | |
33 | <input name="setting[default_allow_comments]" id="default_allow_comments" type="checkbox" value="1" <%= 'checked="checked"' if this_blog.default_allow_comments%> /> | |
<input name="setting[default_allow_comments]" type="hidden" value="0"/> | ||
<label for="default_allow_comments">Enable comments by default</label> | ||
</p> | ||
<p> | ||
33 | | |
38 | <input name="setting[default_allow_pings]" id="default_allow_pings" type="checkbox" value="1" <%= 'checked="checked"' if this_blog.default_allow_pings%> /> | |
<input name="setting[default_allow_pings]" type="hidden" value="0"/> | ||
<label for="default_allow_pings">Enable Trackbacks by default</label> | ||
</p> | ||
<p> | ||
<label for="limit_article_display">Display </label> | ||
39 | | |
44 | <input name="setting[limit_article_display]" size="4" id="limit_article_display" type="text" value="<%= this_blog.limit_article_display %>" /> articles on my homepage by default. | |
</p> | ||
<p> | ||
<label for="limit_rss_display">Display </label> | ||
43 | | |
48 | <input name="setting[limit_rss_display]" size="4" id="limit_rss_display" type="text" value="<%= this_blog.limit_rss_display %>" /> articles in my rss feed by default. | |
</p> | ||
45 | | |
50 | <p> | |
51 | <input name="setting[show_extended_on_rss]" id="show_extended_on_rss" type="checkbox" value="1" <%= 'checked="checked"' if this_blog.show_extended_on_rss%> /> | |
52 | <input name="setting[show_extended_on_rss]" type="hidden" value="0"/> | |
53 | <label for="show_extended_on_rss">Show full article on rss feed</label> | |
54 | </p> | |
55 | ||
56 | <hr /> | |
57 | ||
<p>Should the blog show mailto: links to your email address?</p> | ||
47 | | |
48 | | |
59 | <p><input name="setting[link_to_author]" id="link_to_author" type="checkbox" value="1" <%= 'checked="checked"' if this_blog.link_to_author%> /><input name="setting[link_to_author]" type="hidden" value="0"/> <label for="link_to_author">Enable E-Mail public display</label></p> | |
60 | ||
61 | <hr /> | |
62 | ||
63 | <p>Should the blog use of the <a href="http://www.gravatar.com/">Globally Recognized Avatar (Gravatar)</a> service in comments?</p> | |
64 | <p> | |
65 | <input name="setting[use_gravatar]" id="use_gravatar" type="checkbox" value="1" <%= 'checked="checked"' if this_blog.use_gravatar %> /> | |
66 | <input name="setting[use_gravatar]" type="hidden" value="0"/> | |
67 | <label for="use_gravatar">Enable Gravatar integration</label> | |
68 | </p> | |
69 | ||
70 | <hr /> | |
71 | ||
<p>Would you like to include your latitude and longitude in your blog's HTML pages? See <a href="http://geourl.org">GeoURL</a> for details. <br/>Example: <tt>47.774,-122.201</tt></p> | ||
<p> | ||
<label for="geourl_location">Latitude, Longitude:</label> | ||
53 | | |
54 | | |
55 | | |
76 | <input name="setting[geourl_location]" size="20" id="geourl_location" type="text" value="<%= this_blog.geourl_location %>" /> | |
77 | </p> | |
78 | ||
79 | <hr/> | |
80 | ||
81 | <p>Should Typo send trackbacks to websites that you link to? This should be disabled | |
82 | for private blogs, as it will leak non-public information to sites that you're discussing. | |
83 | For public blogs, there's no real point in disabling this.</p> | |
84 | <p> | |
85 | <input name="setting[send_outbound_pings]" id="send_outbound_pings" type="checkbox" value="1" <%= 'checked="checked"' if this_blog.send_outbound_pings%> /> | |
86 | <input name="setting[send_outbound_pings]" type="hidden" value="0"/> | |
87 | <label for="send_outbound_pings">Send trackbacks to external sites</label> | |
88 | ||
89 | </p> | |
90 | ||
91 | <p> | |
92 | <label for="ping_urls">URLs to ping automatically:</label><br/> | |
93 | <textarea name="setting[ping_urls]" id="ping_urls" rows="5" cols="50"><%=h this_blog.ping_urls %></textarea> | |
94 | </p> | |
95 | ||
<p class="r"><%= save("Save My Settings") %></p> | ||
</div> | ||
58 | | |
59 | | |
98 | ||
99 | ||
<div id="textfilter" class="set"> | ||
<h3>Text Filter</h3> | ||
62 | | |
102 | <p class="note">Typo supports a number of text filtering options. To add new filters, see the "filters" tab on the toolbar above.</p> | |
<p> | ||
<select name="setting[text_filter]" id="text_filter"> | ||
65 | | |
105 | <%= options_for_select text_filter_options, TextFilter.find_by_name(this_blog.text_filter) %> | |
</select> | ||
67 | | |
107 | <label for="text_filter">Article filter</label> | |
</p> | ||
<p> | ||
<select name="setting[comment_text_filter]" id="comment_text_filter"> | ||
71 | | |
111 | <%= options_for_select text_filter_options, TextFilter.find_by_name(this_blog.comment_text_filter) %> | |
</select> | ||
73 | | |
113 | <label for="comment_text_filter">Comments filter</label> | |
</p> | ||
<p class="r"><%= save("Save My Settings") %></p> | ||
</div> | ||
77 | | |
78 | | |
117 | ||
118 | <div id="notification" class="set"> | |
119 | <h3>Notification</h3> | |
120 | <p>Typo can notify you when new articles or comments are posted</p> | |
121 | <p> | |
122 | <label for="email_from">Email address to use in From: field when Typo sends mail:</label> | |
123 | <input name="setting[email_from]" size="20" id="email_from" type="text" value="<%= this_blog.email_from %>" /> | |
124 | </p> | |
125 | <p> | |
126 | <label for="jabber_address">Jabber account to use when sending Jabber notifications:</label> | |
127 | <input name="setting[jabber_address]" size="20" id="jabber_address" type="text" value="<%= this_blog.jabber_address %>" /> | |
128 | </p> | |
129 | <p> | |
130 | <label for="jabber_password">Password for Jabber account:</label> | |
131 | <input name="setting[jabber_password]" size="20" id="jabber_password" type="password" value="<%= this_blog.jabber_password %>" /> | |
132 | </p> | |
133 | <p class="r"><%= save("Save My Settings") %></p> | |
134 | </div> | |
135 | ||
136 | ||
<div id="spam" class="set"> | ||
<h3>Spam Protection</h3> | ||
81 | | |
139 | <p>Enabling spam protection will make typo compare the IP address of posters as well as the contents of their posts against local and remote blacklists. Good defense against spam bots.</p> | |
<p> | ||
83 | | |
141 | <input name="setting[sp_global]" id="sp_global" type="checkbox" value="1" <%= 'checked="checked"' if this_blog.sp_global%> /><input name="setting[sp_global]" type="hidden" value="0"/> | |
<label for="sp_global">Enable spam protection</label> | ||
</p> | ||
<p> | ||
145 | <input name="setting[sp_allow_non_ajax_comments]" id="sp_allow_non_ajax_comments" type="checkbox" value="1" <%= 'checked="checked"' if this_blog.sp_allow_non_ajax_comments%> /> | |
146 | <input name="setting[sp_allow_non_ajax_comments]" type="hidden" value="0" /> | |
147 | <label for="sp_allow_non_ajax_comments">Allow non-ajax comments</label> | |
148 | <br /><small>(Spam bots usually don't know anything about ajax comments)</small> | |
149 | </p> | |
150 | <p> | |
<label for="sp_article_auto_close">Disable comments after</label> | ||
88 | | |
152 | <input name="setting[sp_article_auto_close]" size="4" id="sp_article_auto_close" type="text" value="<%= this_blog.sp_article_auto_close %>" /> days | |
<br /><small>(Set to 0 to never disable comments)</small> | ||
</p> | ||
<p>Typo will automatically reject comments and trackbacks which contain over a certain amount of links in them.</p> | ||
<p> | ||
93 | | |
94 | | |
157 | <label for="sp_url_limit">Max URLs:</label> | |
158 | <input name="setting[sp_url_limit]" size="4" id="sp_url_limit" type="text" value="<%= this_blog.sp_url_limit %>" /> links | |
<br /><small>(Set to 0 to never reject comments)</small> | ||
</p> | ||
<p class="r"><%= save("Save My Settings") %></p> | ||
</div> | ||
163 | <div id="resources" class="set"> | |
164 | <h3>Resource Defaults</h3> | |
165 | <p> | |
166 | The below settings act as defaults when you choose to publish an enclosure with iTunes metadata. | |
167 | </p> | |
168 | <p> | |
169 | <label for="itunes_author">Author:</label> | |
170 | <input name="setting[itunes_author]" size="25" id="itunes_author" type="text" value="<%= this_blog.itunes_author %>" /> | |
171 | </p> | |
172 | <p> | |
173 | <label for="itunes_subtitle">Subtitle:</label> | |
174 | <input name="setting[itunes_subtitle]" size="25" id="itunes_subtitle" type="text" value="<%= this_blog.itunes_subtitle %>" /><small>(setting for channel)</small> | |
175 | </p> | |
176 | <p> | |
177 | <label for="itunes_summary">Summary:<small>(setting for channel)</small> | |
178 | </label> <br /> | |
179 | <textarea name="setting[itunes_summary]" cols="40" rows="3"><%= this_blog.itunes_summary %></textarea> | |
180 | </p> | |
181 | <p> | |
182 | <label for="itunes_email">Email:</label> | |
183 | <input name="setting[itunes_email]" size="25" id="itunes_email" type="text" value="<%= this_blog.itunes_email %>" /> <small> Not Published by Apple</small> | |
184 | </p> | |
185 | <p> | |
186 | <label for="itunes_name">Optional Name:</label> | |
187 | <input name="setting[itunes_name]" size="25" id="itunes_name" type="text" value="<%= this_blog.itunes_name %>" /> <small> Not Published by Apple</small> | |
188 | ||
189 | </p> | |
190 | <p> | |
191 | <label for="itunes_copyright">Copyright Information:</label> | |
192 | <input name="setting[itunes_copyright]" size="25" id="itunes_copyright" type="text" value="<%= this_blog.itunes_copyright %>" /> | |
193 | </p> | |
194 | <p> | |
195 | <label for="itunes_explicit">Explicit:</label> | |
196 | <input name="setting[itunes_explicit]" id="itunes_explicit" type="checkbox" value="1" <%= 'checked="checked"' if this_blog.itunes_explicit%> /><input name="setting[itunes_explicit]" type="hidden" value="0" /> | |
197 | </p> | |
198 | <p class="r"><%= save("Save My Settings") %></p> | |
199 | </div> | |
</div> | ||
100 | | |
201 | ||
<div id="misc" class="set"> | ||
<h3>Cache</h3> | ||
103 | | |
104 | | |
105 | | |
204 | <%= link_to 'Empty Fragment Cache', :controller => 'cache', :action => 'sweep' %><br /> | |
205 | <%= link_to 'Rebuild cached HTML', :controller => 'cache', :action => 'sweep_html' %><br /> | |
206 | <div id="users"> | |
207 | <p>There are <%= @page_cache_size %> entries in the cache</p> | |
</div> | ||
</div> | ||
<div id="operations" class="tasks"> | ||
111 | | |
213 | <%= save("Save My Settings") %> | |
</div> | ||
<%= end_form_tag %> |
rool/rails/typo/trunk/app/views/admin/pages/_form.rhtml:
prev. | current | |
</p> | ||
<p> | ||
<label for="page_body">Content:</label><br /> | ||
13 | | |
13 | <%= text_area 'page', 'body', :rows => 25, :style => 'width: 48%;' %> | |
</p> | ||
<label for="page_text_filter">Textfilter: </label><%= select 'page', 'text_filter', text_filter_options %><br/> |
rool/rails/typo/trunk/app/views/admin/pages/_quick_post.rhtml:
prev. | current | |
</p> | ||
<div id="operations"> | ||
19 | | |
19 | <%= save("Save Post") %> or <a href="#" onclick="new Effect.BlindUp('quick-post', {duration: 0.4}); return false;" >Cancel</a> | |
</div> | ||
<%= end_form_tag %> |
rool/rails/typo/trunk/app/views/admin/pages/preview.rhtml:
prev. | current | |
1 | ||
2 | ||
3 | ||
1 | <div><%= @page.full_html %></div> |
rool/rails/typo/trunk/app/views/admin/pages/show.rhtml:
prev. | current | |
<h3><%=h @page.name %></h3> | ||
<div class="form"> | ||
11 | | |
11 | <div><%= @page.full_html %></div> | |
<p class="meta">Posted: <%=h @page.created_at %> by <%=h @page.user.name %></p> | ||
<p>Lasted updated <%=h @page.updated_at %></p> | ||
</div> |
rool/rails/typo/trunk/app/views/admin/sidebar/_active.rhtml:
prev. | current | |
<h4 class="handle"><%= active.sidebar_controller.display_name %></h4> | ||
<p><%= active.sidebar_controller.description %></p> | ||
<div class="space"> | ||
5 | | |
6 | | |
5 | <div><%= render_component :layout=>false, | |
6 | :controller=>active.sidebar_controller, | |
7 | :action=>'configure_wrapper', :params => {:sidebar => active } %></div> | |
8 | <%= link_to_remote('remove', | |
9 | :url => {:action => 'remove', :id => active.id, | |
10 | :element => "active_#{active.html_id}"}, | |
11 | :before => "new Effect.Fade('active_#{active.html_id}')", | |
12 | :loading => "new Element.show('update_spinner')") %> | |
</div> | ||
</div> |
rool/rails/typo/trunk/app/views/admin/sidebar/_actives.rhtml:
prev. | current | |
1 | ||
<% if actives.blank? %> | ||
3 | | |
2 | <%= render :partial => 'target' %> | |
<% else %> | ||
<%= render :partial => 'active', :collection => actives %> | ||
<% end %> | ||
7 | | |
8 | ||
9 | | |
10 | | |
11 | | |
6 | <%= sortable_element "active", :url => {:action => 'set_active'}, | |
7 | :tag => 'div', | |
8 | :handle => 'handle', :containment => ['active','available_box'], | |
9 | :loading => "new Element.show('update_spinner')" %> |
rool/rails/typo/trunk/app/views/admin/sidebar/index.rhtml:
prev. | current | |
<% @page_heading = 'Sidebar' %> | ||
<p>Drag and drop to change the sidebar items displayed on this blog. To remove items from the sidebar just click remove Changes are saved immediately, but not activated until you click the 'Publish' button.</p> | ||
4 | | |
4 | <%= form_remote_tag(:url=>{:action=>'publish'}, | |
5 | :loading => "new Element.show('update_spinner')") %> | |
<input value="Publish changes" class="space" type="submit"/> | ||
6 | | |
7 | | |
8 | | |
7 | ||
8 | <div id="messages"> </div> | |
9 | ||
<div id="sidebar-config"> | ||
<div id="available" class="dropbox"> | ||
<h3>Available Items</h3> | ||
... | ... | |
</div> | ||
<div id="cnt-active"> | ||
18 | | |
19 | <h3 id="hdr-active"> | |
20 | Active Sidebar items | |
21 | <%= image_tag "spinner-blue.gif", :id => 'update_spinner', | |
22 | :style => 'display:none;' -%> | |
23 | </h3> | |
<div id="active" class="dropbox"> | ||
<%= render :partial => 'actives', :object => @active %> | ||
</div> | ||
</div> | ||
<br clear="all" /> | ||
24 | | |
29 | ||
<input value="Publish changes" class="space" type="submit"/> | ||
26 | | |
31 | ||
</div> | ||
28 | | |
34 | <%= end_form_tag %> | |
35 |
rool/rails/typo/trunk/app/views/admin/themes/index.rhtml:
prev. | current | |
<% for theme in @themes %> | ||
<div class="set theme" style="margin-top:10px;"> | ||
<div class="preview"><img src="<%= url_for :action => 'preview', :theme => theme.name %>" alt="<%= theme.name %>" /></div> | ||
4 | | |
4 | <%= theme.description_html %> | |
<% if theme.path == @active.path -%> | ||
<em>(Active theme)</em> | ||
<% else -%> |
rool/rails/typo/trunk/app/views/admin/users/_form.rhtml:
prev. | current | |
<%= text_field 'user', 'email' %> | ||
</p> | ||
<p> | ||
16 | <label for="user_jabber">Jabber:</label> <small>(this can be blank)</small><br/> | |
17 | <%= text_field 'user', 'jabber' %> | |
18 | </p> | |
19 | <p> | |
<label for="user_password">Password:</label><br /> | ||
17 | | |
21 | <%= password_field_tag 'user[password]', '', :id => 'user_password', :size => 30 %> | |
</p> | ||
<p> | ||
<label for="user_password">Confirmation:</label><br /> | ||
<%= password_field 'user', 'password_confirmation' %> | ||
</p> | ||
27 | ||
28 | <p> | |
29 | <label for="user_notify_via_email">Send notification messages via email?</label><br /> | |
30 | <%= check_box 'user', 'notify_via_email' %> | |
31 | </p> | |
32 | ||
33 | <p> | |
34 | <label for="user_notify_via_jabber">Send notification messages via jabber?</label><br /> | |
35 | <%= check_box 'user', 'notify_via_jabber' %> | |
36 | </p> | |
37 | ||
38 | <p> | |
39 | <label for="user_notify_on_new_articles">Send notification messages when new articles are posted?</label><br /> | |
40 | <%= check_box 'user', 'notify_on_new_articles' %> | |
41 | </p> | |
42 | ||
43 | <p> | |
44 | <label for="user_notify_on_comments">Send notification messages when comments are posted?</label><br /> | |
45 | <%= check_box 'user', 'notify_on_comments' %> | |
46 | </p> | |
47 | ||
<!--[eoform:user]--> |
rool/rails/typo/trunk/app/views/admin/users/_user.rhtml:
prev. | current | |
<div class="user"> | ||
<h4><%= link_to h(user.login), {:action => "show", :id => user.id} %></h4> | ||
<p>Number of Articles: <%= Article.count "user_id = #{user.id}" %></p> | ||
4 | <p>Number of Comments: <%= Comment.count "user_id = #{user.id}" %></p> | |
5 | <p>Notified<% if user.notify_via_email? %> via email<% end %>: | |
6 | <%= "new articles" if user.notify_on_new_articles? %> | |
7 | <%= "comments" if user.notify_on_comments? %></p> | |
<p><%= link_to 'Edit', :action => 'edit', :id => user %><strong> |</strong> <%= link_to 'Delete', :action => 'destroy', :id => user %></p> | ||
</div> |
rool/rails/typo/trunk/app/views/admin/users/show.rhtml:
prev. | current | |
<label>Name:</label> <span class="static"><%=h @user.name %></span><br/> | ||
<label>Login:</label> <span class="static"><%=h @user.login %></span><br/> | ||
<label>Email:</label> <span class="static"><%=h @user.email %></span><br/> | ||
12 | <label>Jabber:</label> <span class="static"><%=h @user.jabber %></span><br/> | |
13 | <label>Notify via email:</label> <span class="static"><%= @user.notify_via_email? ? "yes" : "no" %></span><br/> | |
14 | <label>Notify via jabber:</label> <span class="static"><%= @user.notify_via_jabber? ? "yes" : "no" %></span><br/> | |
15 | <label>Notify on new articles:</label> <span class="static"><%= @user.notify_on_new_articles? ? "yes" : "no" %></span><br/> | |
16 | <label>Notify on new comments:</label> <span class="static"><%= @user.notify_on_comments? ? "yes" : "no" %></span><br/> | |
17 | ||
</div> |
rool/rails/typo/trunk/app/views/articles/_article.rhtml:
prev. | current | |
<h2><%= article_link article.title, article %></h2> | ||
<p class="auth">Posted by <%= author_link(article) %> | ||
3 | ||
3 | <%= js_distance_of_time_in_words_to_now article.published_at %></p> | |
<%= article.body_html %> |
rool/rails/typo/trunk/app/views/articles/_comment.rhtml:
prev. | current | |
1 | ||
1 | <li id="comment-<%= comment.id %>" <%= 'class="author_comment"' if comment.user %> <%= 'style="display:none"' if controller.request.xhr? %><%= onhover_show_admin_tools(:comment, comment.id) %>> | |
<%= admin_tools_for comment %> | ||
<a name="comment-<%= comment.id %>"></a> | ||
4 | | |
5 | | |
6 | ||
5 | <%= gravatar_tag(comment.email) if this_blog.use_gravatar and comment.email %> | |
6 | <cite><strong><%= link_to_unless(comment.url.blank?, h(comment.author), comment.url) %></strong> </cite> said <%= distance_of_time_in_words comment.article.published_at, comment.created_at %> later:<br /> | |
7 | <%= comment.full_html %> | |
8 | </li> |
rool/rails/typo/trunk/app/views/articles/_comment_box.rhtml:
prev. | current | |
<div class="comment-box"> | ||
<div id="errors"></div> | ||
12 | <div id="preview" style="display: none"></div> | |
<a name="respond"></a> | ||
<table cellpadding="4" cellspacing="0" class="frm-tbl"> | ||
... | ... | |
<tr> | ||
<td colspan="2" id="frm-btns"> | ||
<span id="comment_loading" style="display:none;"><%= image_tag "spinner.gif" %></span> | ||
36 | | |
37 | <a href="#" onclick="new Ajax.Updater('preview', '<%= url_for :action => 'comment_preview' %>', {asynchronous:true, evalScripts:true, parameters:Form.serialize('commentform'), onComplete:function(request){Element.show('preview')}}); return false;">Preview comment</a> | |
38 | <input type="submit" name="submit" id="form-submit-button" value="submit" class="button" /> | |
</td> | ||
</tr> | ||
</table> |
rool/rails/typo/trunk/app/views/articles/_trackback.rhtml:
prev. | current | |
1 | ||
1 | <li id="trackback-<%= trackback.id %>"<%= onhover_show_admin_tools(:trackback, trackback.id) %>> | |
<%= admin_tools_for trackback %> | ||
<a name="trackback-<%= trackback.id %>"></a> | ||
From <strong><%= trackback.blog_name %></strong><br /> | ||
5 | | |
5 | <a href="<%= trackback.url %>" rel="nofollow"><%=h trackback.title %></a><br/> | |
<%= trackback.excerpt %> | ||
</li> |
rool/rails/typo/trunk/app/views/articles/archives.rhtml:
prev. | current | |
</div> | ||
<% else | ||
currentmonth = 0 | ||
7 | | |
8 | | |
9 | | |
10 | | |
11 | | |
12 | | |
13 | | |
7 | currentyear = 0 | |
8 | for article in @articles | |
9 | if (article.published_at.month != currentmonth || article.published_at.year != currentyear) | |
10 | currentmonth = article.published_at.month | |
11 | currentyear = article.published_at.year -%> | |
12 | <h3 class="archivemonth"><%= Date::MONTHNAMES[article.published_at.month] %> <%= article.published_at.year %></h3> | |
13 | <% end -%> | |
<div class="archivepost"> | ||
15 | | |
16 | | |
17 | | |
15 | <%= article.published_at.mday %> - | |
16 | <%= article_link h(article.title), article %> | |
17 | <% if !article.categories.empty? %> posted in | |
<%= article.categories.collect {|c| link_to c.name, :controller=>"articles", :action=>"category", :id=>c.name }.join(", ") -%> | ||
<% end -%> | ||
</div> | ||
21 | ||
21 | <% end | |
end -%> |
rool/rails/typo/trunk/app/views/articles/index.rhtml:
prev. | current | |
<% for article in @articles -%> | ||
<div class="post"> | ||
<%= render_partial "article", article %> | ||
4 | | |
5 | | |
4 | <%= article_link "Read more...", article if article.extended? %> | |
5 | <p class="meta"><%= article_links article %></p> | |
</div> | ||
<% end -%> | ||
9 | ||
9 | <% unless @pages.item_count <= this_blog.limit_article_display %> | |
<p id="pagination">Older posts: <%= pagination_links @pages, :params => { :action => @controller.action_name } %></p> | ||
<% end -%> |
rool/rails/typo/trunk/app/views/articles/read.rhtml:
prev. | current | |
xmlns:dc="http://purl.org/dc/elements/1.1/"> | ||
<rdf:Description | ||
rdf:about="" | ||
7 | <% if @article.allow_pings? -%> | |
trackback:ping="<%= server_url_for :controller=>"articles", :action=>"trackback", :id=>@article %>" | ||
9 | <% end -%> | |
dc:title="<%=h @article.title.gsub(/-+/, '-') %>" | ||
9 | | |
10 | | |
11 | dc:identifier="<%= article_url(@article, false) %>" | |
12 | dc:description="<%=h strip_html(@article.full_html[0..255]).gsub(/-+/, '-') %>" | |
dc:creator="<%= h @article.author %>" | ||
dc:date="<%= @article.updated_at.xmlschema %>" /> | ||
</rdf:RDF> | ||
... | ... | |
<div class="post"<%= onhover_show_admin_tools(:article) %>> | ||
<%= link_to("edit", { :controller => "admin/content", :action => "edit", :id => @article }, | ||
:class => "admintools", :style => "display: none", :id => "admin_article") %> | ||
19 | | |
21 | <h2><%=h @article.title %></h2> | |
<p class="auth">Posted by <%= author_link(@article) %> | ||
21 | | |
23 | <%= js_distance_of_time_in_words_to_now @article.published_at.utc %></p> | |
<%= @article.full_html %> | ||
</div> | ||
26 | <p class="meta"> | |
27 | <%= article_links @article %> | |
28 | </p> | |
<% if @article.allow_comments? or @article.comments.size > 0 -%> | ||
26 | | |
27 | ||
28 | | |
29 | | |
30 | | |
31 | <a name="comments"></a><h4 class="blueblk">Comments</h4> | |
32 | <% if @article.allow_comments? -%> | |
33 | <p class="postmetadata alt"> | |
34 | <small><a href="#respond">Leave a response</a></small> | |
35 | </p> | |
36 | <% end -%> | |
37 | <ol class="comment-list" id="commentList"> | |
38 | <% if @article.comments.blank? %> | |
39 | <li id="dummy_comment" style="display: none"></li> | |
40 | <% else %> | |
41 | <%= render(:partial => "comment", :collection => @article.comments.to_a.select {|c| c.published? }) %> | |
42 | <% end %> | |
43 | </ol> | |
<% end -%> | ||
32 | | |
33 | ||
<% if @article.allow_pings? -%> | ||
<a name="trackbacks"></a><h4 class="blueblk">Trackbacks</h4> | ||
<p> | ||
Use the following link to trackback from your own site:<br/> | ||
<span class="light-bg"><%= server_url_for :controller=>"articles", :action=>"trackback", :id=>@article.id %></span> | ||
40 | | |
41 | | |
51 | </p> | |
52 | <%= content_tag(:ol, | |
53 | render(:partial => "trackback", :collection => @article.trackbacks), | |
54 | :id => 'trackbackList', :class => 'trackback-list') unless @article.trackbacks.blank? %> | |
<% end -%> | ||
<p class="postmetadata alt"> | ||
<small> | ||
46 | | |
47 | | |
59 | <a href="<%= xml_url :action=>'feed', :type=>'article', :format => 'rss20', :id => @article %>" title="RSS Feed">RSS feed for this post</a> | |
60 | <% if @article.allow_pings? -%> | |
61 | <a href="<%= server_url_for :controller=>"articles", :action=>"trackback", :id => @article.id %>" >trackback uri</a> | |
62 | <% end -%> | |
</small> | ||
</p> | ||
rool/rails/typo/trunk/app/views/articles/trackback.rxml:
prev. | current | |
xml.instruct! :xml, :version=>"1.0", :encoding=>"iso-8859-1" | ||
xml.response do | ||
3 | | |
4 | | |
5 | | |
6 | | |
7 | | |
8 | | |
9 | ||
4 | xml.error(@error_message.blank? ? 0 : 1) | |
5 | xml.message(@error_message) if @error_message | |
6 | end |
rool/rails/typo/trunk/app/views/articles/view_page.rhtml:
prev. | current | |
<div id="viewpage" > | ||
2 | | |
2 | <%= @page.full_html %> | |
</div> |
rool/rails/typo/trunk/app/views/layouts/administration.rhtml:
prev. | current | |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" | ||
2 | | |
2 | "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | |
<html xmlns="http://www.w3.org/1999/xhtml"> | ||
4 | | |
5 | | |
6 | | |
7 | | |
8 | | |
9 | | |
10 | | |
11 | | |
12 | | |
13 | | |
14 | | |
15 | | |
16 | | |
4 | <head> | |
5 | <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> | |
6 | <title>Typo Administration: <%= controller.controller_name %></title> | |
7 | <meta http-equiv="imagetoolbar" content="no" /> | |
8 | <%= stylesheet_link_tag "administration.css" %> | |
9 | <%= javascript_include_tag "prototype", "effects", "dragdrop", "controls", "typo" %> | |
10 | </head> | |
18 | | |
19 | | |
20 | | |
21 | | |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
30 | | |
31 | | |
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | | |
38 | | |
39 | | |
12 | <body> | |
13 | <div id="container"> | |
41 | | |
42 | | |
43 | | |
44 | | |
45 | | |
46 | | |
47 | | |
15 | <!-- HEADER --> | |
16 | <div id="header"> | |
49 | | |
50 | | |
51 | | |
52 | | |
53 | | |
18 | <div id="info"> | |
19 | <%= link_to "settings", :controller=>"/admin/general", :action => 'index' %> | | |
20 | <%= current_user_notice rescue nil %> | | |
21 | <%= link_to 'your blog »', :controller => "/" %> | |
22 | ||
23 | </div> | |
24 | <h1><%= link_to "Typo admin - #{this_blog.blog_name rescue nil}", :controller => "/admin/" %></h1> | |
25 | </div> | |
26 | <!-- /HEADER --> | |
27 | ||
28 | ||
29 | <div id="tabs-container"> | |
30 | <ul id="tabs"> | |
31 | <%= tab "Articles", :controller=>"/admin/content", :action => 'index' %> | |
32 | <%= tab "Pages", :controller=>"/admin/pages", :action => 'index' %> | |
33 | <%= tab "Categories", :controller=>"/admin/categories", :action => 'index' %> | |
34 | <%= tab "Blacklist", :controller=>"/admin/blacklist", :action => 'index' %> | |
35 | <%= tab "Sidebar", :controller=>"/admin/sidebar", :action => 'index' %> | |
36 | <%= tab "Themes", :controller=>"/admin/themes", :action => 'index' %> | |
37 | <%= tab "Users", :controller=>"/admin/users", :action => 'index' %> | |
38 | <%= tab "Resources", :controller=>"/admin/resources", :action => 'index' %> | |
39 | <%= tab "Filters", :controller=>"/admin/textfilters", :action => 'index' %> | |
40 | </ul> | |
41 | </div> | |
42 | ||
43 | ||
44 | <div id="overall"> | |
45 | <% if flash[:notice] or flash[:error] %> | |
46 | <div id="flash"> | |
47 | <%= render_flash rescue nil %> | |
48 | </div> | |
49 | <% end %> | |
50 | ||
51 | <div id="content"> | |
52 | <div id="main"> | |
53 | <h2><%= @page_heading %></h2> | |
54 | ||
55 | <% if not first_render =~ /general|login|signup|logout|sidebar|themes/ %> | |
<div class="tasks"> | ||
55 | | |
56 | | |
57 | | |
57 | <h3>Things you can do</h3> | |
58 | <ul> | |
59 | <%= @content_for_tasks %> | |
<%= task_overview unless first_render =~ /\/list$/ %> | ||
</ul> | ||
<div style="clear:both;"></div> | ||
61 | | |
63 | </div> | |
<% end %> | ||
<%= @content_for_layout %> | ||
64 | | |
65 | | |
66 | | |
67 | | |
68 | | |
66 | </div> | |
67 | </div> | |
68 | </div> | |
69 | <div id="footer"> | |
70 | Typo <%=h TYPO_VERSION %> | |
71 | </div> | |
72 | </div> | |
73 | </body> | |
</html> | ||
rool/rails/typo/trunk/app/views/live/search.rhtml:
prev. | current | |
<% if !@search.to_s.blank? -%> | ||
2 | | |
2 | <h3>Searched for <em>"<%=h @search %>"</em></h3> | |
<ul> | ||
<% for article in @articles.to_a -%> | ||
5 | | |
5 | <li><%= article_link h(article.title), article %></li> | |
<% end -%> | ||
</ul> | ||
<% else %> | ||
| ||
10 | ||
11 | <% end -%> |
rool/rails/typo/trunk/app/views/settings/done.rhtml:
prev. | current | |
1 | ||
1 | <div class="notice"><%= @flash[:notice] %></div> | |
Installation Complete! |
rool/rails/typo/trunk/app/views/settings/install.rhtml:
prev. | current | |
1 | ||
1 | <div class="notice"><%= @flash[:notice] %></div> | |
<%= start_form_tag %> | ||
<% for field in @fields -%> |
rool/rails/typo/trunk/app/views/xml/rsd.rxml:
prev. | current | |
xml.rsd "version"=>"1.0", "xmlns"=>"http://archipelago.phrasewise.com/rsd" do | ||
xml.service do | ||
xml.engineName "Typo" | ||
5 | | |
5 | xml.engineLink "http://www.typosphere.org" | |
xml.homePageLink server_url_for(:controller => "articles") | ||
xml.apis do | ||
xml.api "name" => "Movable Type", "preferred"=>"true", |
rool/rails/typo/trunk/components/plugins/sidebars/archives/content.rhtml:
prev. | current | |
<ul id="archives"> | ||
<% @archives.each do |month| %> | ||
<li> | ||
6 | | |
7 | | |
6 | <%= link_to month[:name], :controller => "articles", :action => "find_by_date", :year => month[:year], :month => month[:month], :day => nil %> | |
7 | <%= "<em>(#{month[:article_count]})</em>" if show_count %> | |
</li> | ||
<% end %> | ||
</ul> |
rool/rails/typo/trunk/components/plugins/sidebars/archives_controller.rb:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
1 | class Plugins::Sidebars::ArchivesController < Sidebars::ComponentPlugin | |
2 | description 'Displays links to monthly archives' | |
3 | setting :show_count, true, :label => 'Show article counts', :input_type => :checkbox | |
4 | setting :count, 10, :label => 'Number of Months' | |
6 | | |
7 | | |
8 | | |
10 | | |
11 | | |
12 | | |
13 | ||
def content | ||
15 | | |
8 | @archives = this_blog.published_articles.inject([]) do |archives, a| | |
9 | name = a.created_at.strftime('%B %Y') | |
17 | | |
18 | | |
11 | if archives.last and archives.last[:name] == name | |
12 | archives.last[:article_count] += 1 | |
13 | archives | |
14 | else | |
15 | break if archives.size == count.to_i # exit before we go over the limit | |
20 | | |
21 | | |
22 | | |
23 | | |
17 | archives << { :name => name, | |
18 | :year => a.created_at.year, | |
19 | :month => a.created_at.month, | |
20 | :article_count => 1 } | |
end | ||
25 | | |
26 | | |
27 | | |
end | ||
29 | | |
30 | | |
end | ||
32 | ||
33 | | |
34 | | |
end |
rool/rails/typo/trunk/components/plugins/sidebars/category/content.rhtml:
prev. | current | |
<h3>Categories</h3> | ||
<ul id="categories"> | ||
<% for category in @categories -%> | ||
5 | | |
6 | | |
5 | <% unless empty.blank? and category.article_counter == 0 %> | |
6 | <li><%= link_to h(category.name), :controller => "articles", :action => "category", :id => category.permalink %> <% unless count.blank? %><em>(<%= category.article_counter %>)</em><% end %></li> | |
<% end %> | ||
<% end -%> | ||
</ul> |
rool/rails/typo/trunk/components/plugins/sidebars/category_controller.rb:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
1 | class Plugins::Sidebars::CategoryController < Sidebars::ComponentPlugin | |
2 | model :category | |
6 | | |
7 | | |
8 | | |
4 | display_name "Categories" | |
5 | description "List of categories for this blog" | |
10 | | |
11 | | |
12 | | |
7 | setting :count, true, :label => 'Show article count', :input_type => :checkbox | |
8 | setting :empty, false, :label => 'Show empty categories', :input_type => :checkbox | |
def content | ||
@categories = Category.find_all_with_article_counters | ||
end | ||
17 | ||
18 | | |
19 | | |
end |
rool/rails/typo/trunk/components/plugins/sidebars/delicious/content.rhtml:
prev. | current | |
<% if @delicious -%> | ||
<div id="delicious"> | ||
3 | | |
3 | <h3><a href="http://<%= @delicious.title %>"><%= @delicious.title %></a></h3> | |
4 | <% (@sb_config['groupdate'] ? @delicious.days : [{ :container => @delicious.items }]).each do |group| -%> | |
5 | <% if @sb_config['groupdate'] -%> | |
6 | <span class="date"><%= group[:date].to_s.to_date.strftime("%b %d") %></span> | |
7 | <% end -%> | |
<ul> | ||
5 | | |
6 | | |
9 | <% for item in group[:container] %> | |
10 | <li> | |
11 | <a href="<%= item.link %>" title="<%=h item.description%>"><%=h item.title %></a> | |
12 | <% if @sb_config['description'] -%> | |
13 | <br /><span class="desc"><%= @sb_config['desclink'] ? item.description_link : item.description %></span> | |
14 | <% end -%> | |
15 | </li> | |
<% end -%> | ||
</ul> | ||
18 | <% end -%> | |
</div> | ||
10 | ||
21 | <% end -%> |
rool/rails/typo/trunk/components/plugins/sidebars/delicious_controller.rb:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
1 | class Plugins::Sidebars::DeliciousController < Sidebars::ComponentPlugin | |
2 | display_name "Del.icio.us" | |
3 | description 'Bookmarks from <a href="http://del.icio.us">del.icio.us</a>' | |
6 | | |
7 | | |
8 | | |
5 | setting :feed, nil, :label => 'Feed URL' | |
6 | setting :count, 10, :label => 'Items Limit' | |
7 | setting :groupdate, false, :input_type => :checkbox, :label => 'Group links by day' | |
8 | setting :description, false, :input_type => :checkbox, :label => 'Show description' | |
9 | setting :desclink, false, :input_type => :checkbox, :label => 'Allow links in description' | |
10 | | |
11 | | |
12 | | |
13 | ||
def content | ||
15 | | |
16 | | |
12 | response.lifetime = 1.hour | |
13 | @delicious = check_cache(Delicious, @sb_config['feed']) rescue nil | |
18 | | |
15 | return unless @delicious | |
16 | ||
17 | if @sb_config['groupdate'] | |
18 | @delicious.days = {} | |
19 | @delicious.items.each_with_index do |d,i| | |
20 | break if i >= @sb_config['count'].to_i | |
21 | index = d.date.strftime("%Y-%m-%d").to_sym | |
22 | (@delicious.days[index] ||= Array.new) << d | |
23 | end | |
24 | @delicious.days = @delicious.days.sort_by { |d| d.to_s }.reverse.collect { |d| {:container => d.last, :date => d.first} } | |
25 | else | |
26 | @delicious.items = @delicious.items.slice(0, @sb_config['count'].to_i) | |
27 | end | |
end | ||
end |
rool/rails/typo/trunk/components/plugins/sidebars/flickr/content.rhtml:
prev. | current | |
<% for pic in @flickr.choose(@sb_config['count'].to_i) -%> | ||
<div class="flickr<%= @sb_config['format']%>"><%= case @sb_config['format'] | ||
when 'square': | ||
7 | | |
7 | link_to image_tag(pic.square, :alt => pic.title, :title => pic.title),pic.link | |
when 'rectangle': | ||
9 | | |
9 | link_to image_tag(pic.thumb, :alt => pic.title, :title => pic.title),pic.link | |
end | ||
%> | ||
</div> |
rool/rails/typo/trunk/components/plugins/sidebars/flickr_controller.rb:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
1 | class Plugins::Sidebars::FlickrController < Sidebars::ComponentPlugin | |
2 | description 'Pictures from <a href="http://www.flickr.com">flickr.com</a>' | |
3 | setting :feed_url, nil | |
4 | setting :count, 4 | |
5 | setting :format, 'rectangle', :choices => %w{rectangle square} | |
6 | | |
7 | | |
8 | | |
9 | ||
10 | | |
11 | | |
12 | | |
13 | ||
def content | ||
15 | | |
8 | begin | |
9 | response.lifetime = 1.hour | |
10 | @flickr=check_cache(FlickrAggregation, @sb_config['feed_url']) | |
11 | rescue Exception => e | |
12 | logger.info e | |
13 | nil | |
14 | end | |
end | ||
17 | ||
18 | | |
19 | | |
end |
rool/rails/typo/trunk/components/plugins/sidebars/fortythree/content.rhtml:
prev. | current | |
<h3><%= link_to "43 Things", @fortythree.link %></h3> | ||
<ul> | ||
<% for thing in @fortythree.things.to_a.slice(0,@sb_config['count'].to_i) -%> | ||
5 | | |
5 | <li><a href="<%= thing.link %>" title="<%=h thing.title %>"><%=h thing.title %> </a></li> | |
<% end -%> | ||
</ul> | ||
<% end -%> | ||
rool/rails/typo/trunk/components/plugins/sidebars/fortythree_controller.rb:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
1 | class Plugins::Sidebars::FortythreeController < Sidebars::ComponentPlugin | |
2 | display_name "43things" | |
3 | description 'Goals from <a href="http://www.43things.com/">43things.com</a>.' | |
6 | | |
7 | | |
8 | | |
5 | setting :feed, 'http://www.43things.com/rss/uber/author?username=USER', :label => 'Feed URL' | |
6 | setting :count, 43, :label => 'Items limit' | |
10 | | |
11 | | |
12 | | |
13 | ||
def content | ||
9 | response.lifetime = 1.day | |
@fortythree=check_cache(Fortythree, @sb_config['feed']) rescue nil | ||
end | ||
17 | ||
18 | | |
19 | | |
end |
rool/rails/typo/trunk/components/plugins/sidebars/fortythreeplaces/content.rhtml:
prev. | current | |
<h3><%= link_to "43 Places", @fortythreeplaces.link %></h3> | ||
<ul> | ||
<% for thing in @fortythreeplaces.things.to_a.slice(0,@sb_config['count'].to_i) -%> | ||
5 | | |
5 | <li><a href="<%= thing.link %>" title="<%=h thing.title %>"><%=h thing.title %> </a></li> | |
<% end -%> | ||
</ul> | ||
<% end -%> | ||
rool/rails/typo/trunk/components/plugins/sidebars/fortythreeplaces_controller.rb:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
1 | class Plugins::Sidebars::FortythreeplacesController < Sidebars::ComponentPlugin | |
2 | display_name "43places" | |
3 | description 'List of your <a href="http://www.43places.com/">43places.com</a>.' | |
6 | | |
7 | | |
8 | | |
5 | setting :feed, 'http://www.43places.com/rss/uber/author?username=USER', :label => 'Feed URL' | |
6 | setting :count, 43, :label => 'Items limit' | |
10 | | |
11 | | |
12 | | |
13 | ||
def content | ||
9 | response.lifetime = 1.day | |
@fortythreeplaces=check_cache(Fortythree, @sb_config['feed']) rescue nil | ||
end | ||
17 | ||
18 | | |
19 | | |
end |
rool/rails/typo/trunk/components/plugins/sidebars/static_controller.rb:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
1 | class Plugins::Sidebars::StaticController < Sidebars::ComponentPlugin | |
2 | description "Static content, like links to other sites, advertisements, or blog meta-infomation" | |
6 | | |
7 | | |
8 | | |
10 | | |
11 | | |
12 | | |
13 | | |
5 | DEFAULT_TEXT = %q{ | |
6 | <ul> | |
7 | <li><a href="http://www.typosphere.org" title="Typo">Typo</a></li> | |
<li><a href="http://blog.leetsoft.com" title="too-biased">too-biased</a></li> | ||
<li><a href="http://www.poocs.net/" title="poocs.net">poocs.net</a></li> | ||
<li><a href="http://blog.remor.com/" title="seth hall">Seth Hall</a></li> | ||
<li><a href="http://encytemedia.com" title="Encyte Media">EncyteMedia</a></li> | ||
<li><a href="http://scottstuff.net" title="Scottstuff">scottstuff.net</a></li> | ||
13 | <li><a href="http://www.bofh.org.uk" title="Just a Summary">Just A Summary</a></li> | |
<li><a href="http://nubyonrails.com" title="Topfunky">Topfunky</a></li> | ||
<li><a href="http://planettypo.com" title="PlanetTypo">PlanetTypo</a></li> | ||
16 | <li><a href="http://typoforums.org" title="Typo Forums">Typo Forums</a></li> | |
</ul> | ||
22 | ||
23 | | |
24 | | |
25 | | |
26 | | |
18 | } | |
19 | ||
20 | setting :title, 'Links' | |
21 | setting :body, DEFAULT_TEXT, :input_type => :text_area | |
22 | ||
end |
rool/rails/typo/trunk/components/plugins/sidebars/tada/content.rhtml:
prev. | current | |
<ul> | ||
<% for task in @tada.tasks.to_a.slice(0,@sb_config['count'].to_i) -%> | ||
<% if task.status == :completed -%> | ||
6 | | |
6 | <li><del><a href="<%= task.link %>" title="<%=h task.title %>"><%=h task.title %> </a></del></li> | |
<% else -%> | ||
8 | | |
8 | <li><a href="<%= task.link %>" title="<%=h task.title %>"><%=h task.title %> </a></li> | |
<% end -%> | ||
<% end -%> | ||
</ul> |
rool/rails/typo/trunk/components/plugins/sidebars/tada_controller.rb:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
1 | class Plugins::Sidebars::TadaController < Sidebars::ComponentPlugin | |
2 | display_name "Tada List" | |
3 | description 'To-do list from <a href="http://www.tadalist.com">tadalist.com</a>' | |
6 | | |
7 | | |
8 | | |
5 | setting :feed, '', :label => 'Feed URL' | |
6 | setting :count, 10, :label => 'Items limit' | |
10 | | |
11 | | |
12 | | |
13 | ||
def content | ||
9 | response.lifetime = 1.day | |
@tada=check_cache(Tada, @sb_config['feed']) rescue nil | ||
end | ||
17 | ||
18 | | |
19 | | |
end |
rool/rails/typo/trunk/components/plugins/sidebars/technorati/content.rhtml:
prev. | current | |
<% if @cosmos -%> | ||
2 | ||
2 | <h3><%= @sb_config['name'] -%> @Technorati</h3> | |
<ul id="technorati"> | ||
<% for item in @cosmos.choose(@sb_config['count'].to_i) -%> | ||
<li><%= link_to item.title, item.link, {:title => item.title } %> | ||
<% end -%> | ||
</ul> | ||
8 | ||
9 | <% end -%> |
rool/rails/typo/trunk/components/plugins/sidebars/technorati_controller.rb:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
1 | class Plugins::Sidebars::TechnoratiController < Sidebars::ComponentPlugin | |
2 | description 'Display a <a href="http://www.technorati.com">Technorati</a> Watchlist' | |
6 | | |
7 | | |
8 | | |
4 | setting :name, 'Watchlist' | |
5 | setting :feed, 'http://www.technorati.com/watchlists/rss.html?wid=WATCHLISTID', :label => 'Feed URL' | |
6 | setting :count, 4, :label => 'Items limit' | |
10 | | |
11 | | |
12 | | |
13 | ||
def content | ||
9 | response.lifetime = 1.hour | |
@cosmos = check_cache(Technorati, @sb_config['feed']) rescue nil | ||
end | ||
17 | ||
18 | | |
19 | | |
end |
rool/rails/typo/trunk/components/plugins/sidebars/upcoming_controller.rb:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
1 | class Plugins::Sidebars::UpcomingController < Sidebars::ComponentPlugin | |
2 | description 'Events from <a href="http://www.upcoming.org">upcoming.org</a>' | |
6 | | |
7 | | |
8 | | |
4 | setting :feed, '', :label => 'Feed URL' | |
5 | setting :count, 4, :label => 'Items Limit' | |
10 | | |
11 | | |
12 | | |
13 | ||
def content | ||
8 | response.lifetime = 6.hours | |
@upcoming=check_cache(Upcoming, @sb_config['feed']) rescue nil | ||
end | ||
17 | ||
18 | | |
19 | | |
end |
rool/rails/typo/trunk/components/plugins/sidebars/xml/content.rhtml:
prev. | current | |
<h3>Syndicate</h3> | ||
<ul> | ||
<% if @sb_config['articles'] -%> | ||
4 | | |
4 | <li><a href="<%= url_for :controller=>'xml', :action=>'feed', :format => @sb_config['format'], :type => 'feed' %>" title="Articles feed">Articles</a></li> | |
<% end %> | ||
<% if @sb_config['comments'] -%> | ||
7 | | |
7 | <li><a href="<%= url_for :controller=>'xml', :action=>'feed', :format => @sb_config['format'], :type => 'comments' %>" title="Comments feed">Comments</a></li> | |
<% end %> | ||
<% if @sb_config['trackbacks'] -%> | ||
10 | | |
10 | <li><a href="<%= url_for :controller=>'xml', :action=>'feed', :format => @sb_config['format'], :type => 'trackbacks' %>" title="Trackbacks feed">Trackbacks</a></li> | |
<% end %> | ||
</ul> |
rool/rails/typo/trunk/components/plugins/sidebars/xml_controller.rb:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
1 | class Plugins::Sidebars::XmlController < Sidebars::ComponentPlugin | |
2 | display_name "XML Syndication" | |
3 | description "RSS and Atom feeds" | |
6 | | |
7 | | |
8 | | |
9 | | |
10 | | |
11 | | |
12 | | |
13 | | |
14 | | |
15 | | |
5 | setting :articles, true, :input_type => :checkbox | |
6 | setting :comments, true, :input_type => :checkbox | |
7 | setting :trackbacks, false, :input_type => :checkbox | |
8 | ||
9 | setting :format, 'rss20', :input_type => :radio, | |
10 | :choices => [["rss20", "RSS 2.0"], ["atom10", "Atom 1.0"], ["atom03", "Atom 0.3"]] | |
end |
rool/rails/typo/trunk/config/environment.rb:
prev. | current | |
1 | ||
2 | ||
1 | # Be sure to restart your webserver when you modify this file. | |
3 | # Uncomment below to force Rails into production mode | |
4 | # (Use only when you can't set environment variables through your web/app server) | |
5 | # ENV['RAILS_ENV'] = 'production' | |
5 | ||
6 | ||
7 | # Bootstrap the Rails environment, frameworks, and default configuration | |
8 | require File.join(File.dirname(__FILE__), 'boot') | |
8 | ||
9 | ||
10 | ||
10 | Rails::Initializer.run do |config| | |
11 | # Skip frameworks you're not going to use | |
12 | # config.frameworks -= [ :action_web_service, :action_mailer ] | |
12 | ||
13 | ||
14 | | |
15 | | |
16 | | |
17 | | |
18 | | |
19 | | |
20 | | |
21 | | |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
30 | | |
31 | | |
32 | | |
33 | ||
14 | # Add additional load paths for your own custom dirs | |
15 | # config.load_paths += %W( #{RAILS_ROOT}/app/services ) | |
16 | config.load_paths += %W( | |
17 | vendor/rubypants | |
18 | vendor/redcloth/lib | |
19 | vendor/bluecloth/lib | |
20 | vendor/flickr | |
21 | vendor/syntax/lib | |
22 | vendor/sparklines/lib | |
23 | vendor/uuidtools/lib | |
24 | vendor/jabber4r/lib | |
25 | vendor/rails/railties | |
26 | vendor/rails/railties/lib | |
27 | vendor/rails/actionpack/lib | |
28 | vendor/rails/activesupport/lib | |
29 | vendor/rails/activerecord/lib | |
30 | vendor/rails/actionmailer/lib | |
31 | vendor/rails/actionwebservice/lib | |
32 | ).map {|dir| "#{RAILS_ROOT}/#{dir}"}.select { |dir| File.directory?(dir) } | |
35 | ||
36 | ||
34 | # Force all environments to use the same logger level | |
35 | # (by default production uses :info, the others :debug) | |
36 | # config.log_level = :debug | |
38 | ||
39 | ||
40 | ||
41 | ||
38 | # Use the database for sessions instead of the file system | |
39 | # (create the session table with 'rake create_sessions_table') | |
40 | config.action_controller.session_store = :active_record_store | |
43 | ||
44 | ||
42 | # Enable page/fragment caching by setting a file-based store | |
43 | # (remember to create the caching directory and make it readable to the application) | |
44 | config.action_controller.fragment_cache_store = :file_store, "#{RAILS_ROOT}/tmp/cache" | |
46 | ||
47 | ||
48 | ||
49 | ||
50 | ||
46 | # Activate observers that should always be running | |
47 | # config.active_record.observers = :cacher, :garbage_collector | |
48 | config.active_record.observers = :content_observer, :email_notifier, :web_notifier | |
52 | ||
53 | ||
54 | ||
55 | ||
56 | ||
57 | ||
58 | ||
50 | # Make Active Record use UTC-base instead of local time | |
51 | # config.active_record.default_timezone = :utc | |
53 | # Use Active Record's schema dumper instead of SQL when creating the test database | |
54 | # (enables use of different database adapters for development and test environments) | |
55 | # config.active_record.schema_format = :ruby | |
61 | ||
62 | ||
63 | | |
64 | | |
65 | ||
66 | | |
67 | | |
68 | | |
69 | | |
70 | | |
71 | | |
57 | # See Rails::Configuration for more options | |
end | ||
74 | ||
75 | ||
76 | ||
60 | # Add new inflection rules using the following format | |
61 | # (all these examples are active by default): | |
62 | # Inflector.inflections do |inflect| | |
63 | # inflect.plural /^(ox)$/i, '\1en' | |
64 | # inflect.singular /^(ox)en/i, '\1' | |
65 | # inflect.irregular 'person', 'people' | |
66 | # inflect.uncountable %w( fish sheep ) | |
67 | # end | |
78 | ||
79 | | |
80 | | |
81 | ||
69 | # Include your application configuration below | |
83 | ||
71 | # Load included libraries. | |
72 | require 'redcloth' | |
73 | require 'bluecloth' | |
74 | require 'rubypants' | |
75 | require 'flickr' | |
76 | require 'uuidtools' | |
77 | ||
78 | require_dependency 'spam_protection' | |
79 | require_dependency 'migrator' | |
80 | require_dependency 'rails_patch/components' | |
81 | require_dependency 'rails_patch/active_record' | |
82 | require_dependency 'login_system' | |
83 | require_dependency 'typo_version' | |
84 | require_dependency 'metafragment' | |
85 | require_dependency 'actionparamcache' | |
$KCODE = 'u' | ||
require_dependency 'jcode' | ||
88 | require_dependency 'aggregations/audioscrobbler' | |
require_dependency 'aggregations/delicious' | ||
require_dependency 'aggregations/tada' | ||
require_dependency 'aggregations/flickr' | ||
require_dependency 'aggregations/fortythree' | ||
93 | require_dependency 'aggregations/magnolia' | |
require_dependency 'aggregations/upcoming' | ||
91 | ||
92 | ||
require_dependency 'xmlrpc_fix' | ||
94 | ||
96 | require_dependency 'transforms' | |
97 | require_dependency 'builder' | |
96 | ||
99 | unless Builder::XmlMarkup.methods.include? '_attr_value' | |
100 | # Builder 2.0 has many important fixes, but for now we will only backport | |
101 | # this one... | |
102 | class Builder::XmlMarkup | |
103 | # Insert the attributes (given in the hash). | |
104 | def _insert_attributes(attrs, order=[]) | |
105 | return if attrs.nil? | |
106 | order.each do |k| | |
107 | v = attrs[k] | |
108 | @target << %{ #{k}="#{_attr_value(v)}"} if v # " WART | |
109 | end | |
110 | attrs.each do |k, v| | |
111 | @target << %{ #{k}="#{_attr_value(v)}"} unless order.member?(k) # " WART | |
112 | end | |
113 | end | |
115 | def _attr_value(value) | |
116 | case value | |
117 | when Symbol | |
118 | value.to_s | |
119 | else | |
120 | _escape(value.to_s).gsub(%r{"}, '"') # " WART | |
121 | end | |
122 | end | |
123 | end | |
124 | end | |
125 | ||
ActiveSupport::CoreExtensions::Time::Conversions::DATE_FORMATS.merge!( | ||
:long_weekday => '%a %B %e, %Y %H:%M' | ||
) | ||
102 | ||
130 | ActionMailer::Base.default_charset = 'utf-8' | |
131 | ||
132 | if RAILS_ENV != 'test' | |
133 | begin | |
134 | mail_settings = YAML.load(File.read("#{RAILS_ROOT}/config/mail.yml")) | |
135 | ||
136 | ActionMailer::Base.delivery_method = mail_settings['method'] | |
137 | ActionMailer::Base.server_settings = mail_settings['settings'] | |
138 | rescue | |
139 | # Fall back to using sendmail by default | |
140 | ActionMailer::Base.delivery_method = :sendmail | |
141 | end | |
142 | end | |
143 | ||
144 | FLICKR_KEY='84f652422f05b96b29b9a960e0081c50' |
rool/rails/typo/trunk/config/environments/development.rb:
prev. | current | |
1 | ||
1 | # In the development environment your application's code is reloaded on | |
2 | # every request. This slows down response time but is perfect for development | |
3 | # since you don't have to restart the webserver when you make code changes. | |
4 | config.cache_classes = false | |
3 | ||
4 | ||
5 | ||
6 | ||
7 | ||
7 | # Log error messages when you accidentally call methods on nil. | |
8 | config.whiny_nils = true | |
9 | ||
10 | # Enable the breakpoint server that script/breakpointer connects to | |
11 | config.breakpoint_server = true | |
12 | ||
13 | # Show full error reports and disable caching | |
14 | config.action_controller.consider_all_requests_local = true | |
15 | config.action_controller.perform_caching = false | |
16 | ||
17 | # Don't care if the mailer can't send | |
18 | config.action_mailer.raise_delivery_errors = false |
rool/rails/typo/trunk/config/environments/production.rb:
prev. | current | |
1 | ||
2 | ||
3 | ||
4 | ||
2 | # The production environment is meant for finished, "live" apps. | |
3 | # Code is not reloaded between requests | |
4 | config.cache_classes = true | |
5 | ||
6 | # Use a different logger for distributed setups | |
7 | # config.logger = SyslogLogger.new | |
8 | ||
9 | ||
10 | # Full error reports are disabled and caching is turned on | |
11 | config.action_controller.consider_all_requests_local = false | |
12 | config.action_controller.perform_caching = true | |
13 | ||
14 | # Enable serving of images, stylesheets, and javascripts from an asset server | |
15 | # config.action_controller.asset_host = "http://assets.example.com" | |
16 | ||
17 | # Disable delivery errors if you bad email addresses should just be ignored | |
18 | # config.action_mailer.raise_delivery_errors = false | |
19 | ||
20 | Migrator.offer_migration_when_available = true |
rool/rails/typo/trunk/config/environments/test.rb:
prev. | current | |
1 | ||
1 | # The test environment is used exclusively to run your application's | |
2 | # test suite. You never need to work with it otherwise. Remember that | |
3 | # your test database is "scratch space" for the test suite and is wiped | |
4 | # and recreated between test runs. Don't rely on the data there! | |
5 | config.cache_classes = true | |
3 | ||
4 | ||
5 | ||
6 | ||
7 | ||
8 | # Log error messages when you accidentally call methods on nil. | |
9 | config.whiny_nils = true | |
10 | ||
11 | # Show full error reports and disable caching | |
12 | config.action_controller.consider_all_requests_local = true | |
13 | config.action_controller.perform_caching = false | |
14 | ||
15 | # Tell ActionMailer not to deliver emails to the real world. | |
16 | # The :test delivery method accumulates sent emails in the | |
17 | # ActionMailer::Base.deliveries array. | |
18 | config.action_mailer.delivery_method = :test | |
19 | ||
20 | # Overwrite the default settings for fixtures in tests. See Fixtures | |
21 | # for more details about these settings. | |
22 | ||
23 | #config.transactional_fixtures = true | |
24 | #config.instantiated_fixtures = false | |
25 | #onfig.pre_loaded_fixtures = false | |
26 | ||
27 | Migrator.offer_migration_when_available = false |
rool/rails/typo/trunk/config/lighttpd.conf:
prev. | current | |
1 | ||
2 | ||
3 | ||
1 | # Default configuration file for the lighttpd web server | |
2 | # Start using ./script/server lighttpd | |
5 | ||
6 | ||
7 | ||
8 | ||
9 | ||
4 | server.port = 3000 | |
11 | ||
6 | server.modules = ( "mod_rewrite", "mod_accesslog", "mod_fastcgi" ) | |
7 | server.error-handler-404 = "/dispatch.fcgi" | |
8 | server.document-root = CWD + "/public/" | |
13 | ||
14 | ||
15 | | |
16 | | |
17 | | |
18 | | |
19 | | |
20 | | |
21 | | |
22 | | |
23 | | |
10 | server.errorlog = CWD + "/log/lighttpd.error.log" | |
11 | accesslog.filename = CWD + "/log/lighttpd.access.log" | |
12 | ||
13 | url.rewrite = ( "^/$" => "index.html", "^([^.]+)$" => "$1.html" ) | |
14 | ||
15 | # Change *-procs to 2 if you need to use Upload Progress or other tasks that | |
16 | # *need* to execute a second request while the first is still pending. | |
17 | fastcgi.server = ( ".fcgi" => | |
18 | ( "localhost" => | |
19 | ( | |
20 | "min-procs" => 2, | |
21 | "max-procs" => 2, | |
22 | "socket" => CWD + "/tmp/sockets/fcgi.socket", | |
23 | "bin-path" => CWD + "/public/dispatch.fcgi", | |
24 | "bin-environment" => ( "RAILS_ENV" => "development" ) | |
25 | ) | |
26 | ) | |
) | ||
29 | mimetype.assign = ( | |
30 | ".css" => "text/css", | |
31 | ".gif" => "image/gif", | |
32 | ".htm" => "text/html", | |
33 | ".html" => "text/html", | |
34 | ".jpeg" => "image/jpeg", | |
35 | ".jpg" => "image/jpeg", | |
36 | ".js" => "text/javascript", | |
37 | ".png" => "image/png", | |
38 | ".swf" => "application/x-shockwave-flash", | |
39 | ".txt" => "text/plain" | |
40 | ) | |
27 | ||
28 | | |
29 | | |
30 | | |
31 | | |
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | | |
38 | | |
39 | | |
40 | | |
41 | | |
42 | | |
43 | | |
44 | | |
45 | | |
46 | | |
47 | | |
48 | | |
49 | | |
50 | | |
51 | | |
52 | | |
53 | | |
54 | | |
55 | | |
56 | | |
57 | | |
58 | | |
59 | | |
60 | | |
61 | | |
62 | | |
63 | | |
64 | | |
65 | | |
66 | | |
67 | | |
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
73 | | |
74 | | |
75 | | |
76 | | |
77 | | |
78 | | |
43 | # Making sure file uploads above 64k always work when using IE or Safari | |
44 | # For more information, see http://trac.lighttpd.net/trac/ticket/360 | |
45 | $HTTP["useragent"] =~ "^(.*MSIE.*)|(.*AppleWebKit.*)$" { | |
46 | server.max-keep-alive-requests = 0 | |
47 | } |
rool/rails/typo/trunk/config/routes.rb:
prev. | current | |
ActionController::Routing::Routes.draw do |map| | ||
3 | | |
3 | # default | |
map.index '', :controller => 'articles', :action => 'index' | ||
map.admin 'admin', :controller => 'admin/general', :action => 'index' | ||
6 | | |
6 | ||
# admin/comments controller needs parent article id | ||
map.connect 'admin/comments/article/:article_id/:action/:id', | ||
:controller => 'admin/comments', :action => nil, :id => nil | ||
10 | | |
11 | | |
10 | map.connect 'admin/trackbacks/article/:article_id/:action/:id', | |
11 | :controller => 'admin/trackbacks', :action => nil, :id => nil | |
map.connect 'admin/content/:action/:id', :controller => 'admin/content' | ||
# make rss feed urls pretty and let them end in .xml | ||
15 | | |
16 | | |
17 | | |
15 | # this improves caches_page because now apache and webrick will send out the | |
16 | # cached feeds with the correct xml mime type. | |
17 | map.xml 'xml/itunes/feed.xml', :controller => 'xml', :action => 'itunes' | |
map.xml 'xml/articlerss/:id/feed.xml', :controller => 'xml', :action => 'articlerss' | ||
19 | map.xml 'xml/commentrss/feed.xml', :controller => 'xml', :action => 'commentrss' | |
20 | map.xml 'xml/trackbackrss/feed.xml', :controller => 'xml', :action => 'trackbackrss' | |
22 | map.xml 'xml/:format/feed.xml', :controller => 'xml', :action => 'feed', :type => 'feed' | |
23 | map.xml 'xml/:format/:type/feed.xml', :controller => 'xml', :action => 'feed' | |
24 | map.xml 'xml/:format/:type/:id/feed.xml', :controller => 'xml', :action => 'feed' | |
25 | map.xml 'xml/rss', :controller => 'xml', :action => 'feed', :type => 'feed', :format => 'rss' | |
26 | ||
# allow neat perma urls | ||
map.connect 'articles', | ||
:controller => 'articles', :action => 'index' | ||
... | ... | |
:controller => 'articles', :action => 'index', | ||
:page => /\d+/ | ||
34 | map.connect 'articles/:year/:month/:day', | |
35 | :controller => 'articles', :action => 'find_by_date', | |
36 | :year => /\d{4}/, :month => /\d{1,2}/, :day => /\d{1,2}/ | |
37 | map.connect 'articles/:year/:month', | |
38 | :controller => 'articles', :action => 'find_by_date', | |
39 | :year => /\d{4}/, :month => /\d{1,2}/ | |
40 | map.connect 'articles/:year', | |
41 | :controller => 'articles', :action => 'find_by_date', | |
42 | :year => /\d{4}/ | |
43 | ||
map.connect 'articles/:year/:month/:day/page/:page', | ||
:controller => 'articles', :action => 'find_by_date', | ||
:year => /\d{4}/, :month => /\d{1,2}/, :day => /\d{1,2}/, :page => /\d+/ | ||
... | ... | |
:controller => 'articles', :action => 'find_by_date', | ||
:year => /\d{4}/, :page => /\d+/ | ||
37 | | |
38 | | |
39 | | |
40 | | |
41 | | |
42 | | |
43 | | |
44 | | |
45 | | |
46 | ||
map.connect 'articles/:year/:month/:day/:title', | ||
:controller => 'articles', :action => 'permalink', | ||
:year => /\d{4}/, :day => /\d{1,2}/, :month => /\d{1,2}/ | ||
... | ... | |
:controller => 'articles', :action => 'category', | ||
:page => /\d+/ | ||
64 | map.connect 'articles/tag/:id', | |
65 | :controller => 'articles', :action => 'tag' | |
66 | map.connect 'articles/tag/:id/page/:page', | |
67 | :controller => 'articles', :action => 'tag', | |
68 | :page => /\d+/ | |
69 | ||
map.connect 'pages/*name',:controller => 'articles', :action => 'view_page' | ||
map.connect 'stylesheets/theme/:filename', | ||
... | ... | |
map.connect 'images/theme/:filename', | ||
:controller => 'theme', :action => 'images' | ||
79 | map.connect 'plugins/filters/:filter/:public_action', | |
80 | :controller => 'textfilter', :action => 'public_action' | |
81 | ||
# Kill attempts to connect directly to the theme controller. | ||
# Ideally we'd disable these by removing the default route (below), | ||
# but that breaks too many things for Typo 2.5. | ||
map.connect 'theme/*stuff', | ||
:controller => 'theme', :action => 'error' | ||
71 | | |
87 | ||
# Allow legacy urls to still work | ||
map.connect ':controller/:action/:id' | ||
90 | ||
91 | map.connect '*from', :controller => 'redirect', :action => 'redirect' | |
end |
rool/rails/typo/trunk/db/converters/mt3.rb:
prev. | current | |
#!/usr/bin/env ruby | ||
# MovableType 3.x converter for typo by Patrick Lenz <patrick@lenz.sh> | ||
4 | ||
4 | # | |
# MAKE BACKUPS OF EVERYTHING BEFORE RUNNING THIS SCRIPT! | ||
# THIS SCRIPT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND | ||
... | ... | |
class MTMigrate | ||
attr_accessor :options | ||
13 | | |
13 | ||
def initialize | ||
self.options = {} | ||
self.parse_options | ||
... | ... | |
}) | ||
puts "Converting #{mt_categories.size} categories.." | ||
30 | | |
30 | ||
mt_categories.each do |cat| | ||
Category.create(cat) unless Category.find_by_name(cat['name']) | ||
end | ||
end | ||
35 | | |
35 | ||
def convert_entries | ||
default_filter = translate_filter ActiveRecord::Base.connection.select_all(%{ | ||
SELECT | ||
39 | | |
39 | blog_convert_paras | |
FROM `#{self.options[:mt_db]}`.mt_blog | ||
WHERE blog_id = '#{self.options[:blog_id]}' | ||
})[0]["blog_convert_paras"] | ||
... | ... | |
entry_keywords AS keywords, | ||
entry_created_on AS created_at, | ||
entry_modified_on AS updated_at, | ||
57 | | |
57 | author_name AS author | |
FROM `#{self.options[:mt_db]}`.mt_entry, `#{self.options[:mt_db]}`.mt_author | ||
WHERE entry_blog_id = '#{self.options[:blog_id]}' | ||
AND author_id = entry_author_id | ||
}) | ||
62 | | |
62 | ||
puts "Converting #{mt_entries.size} entries.." | ||
64 | | |
64 | ||
mt_entries.each do |entry| | ||
a = Article.new | ||
a.attributes = entry.reject { |k,v| k =~ /entry_id|convert_breaks/ } | ||
... | ... | |
}).each do |c| | ||
a.categories.push_with_attributes(Category.find_by_name(c['category_label']), :is_primary => c['placement_is_primary']) | ||
end | ||
87 | | |
87 | ||
# Fetch comments | ||
ActiveRecord::Base.connection.select_all(%{ | ||
SELECT | ||
... | ... | |
comment_url AS url, | ||
comment_text AS body, | ||
comment_created_on AS created_at, | ||
96 | | |
96 | comment_modified_on AS updated_at | |
FROM `#{self.options[:mt_db]}`.mt_comment | ||
WHERE comment_entry_id = #{entry['entry_id']} | ||
}).each do |c| | ||
a.comments.create(c) | ||
end | ||
102 | | |
102 | ||
# Fetch trackbacks | ||
ActiveRecord::Base.connection.select_all(%{ | ||
SELECT | ||
... | ... | |
def convert_prefs | ||
puts "Converting prefs" | ||
124 | | |
124 | ||
ActiveRecord::Base.connection.select_one(%{ | ||
SELECT | ||
blog_name, | ||
blog_allow_comments_default AS default_allow_comments, | ||
blog_allow_pings_default AS default_allow_pings | ||
130 | | |
130 | FROM `#{self.options[:mt_db]}`.mt_blog | |
WHERE blog_id = '#{self.options[:blog_id]}' | ||
}).each do |pref_name, pref_value| | ||
begin | ||
... | ... | |
Setting.create({'name' => pref_name, 'value' => pref_value}) | ||
end | ||
end | ||
139 | | |
139 | ||
end | ||
def parse_options | ||
... | ... | |
end | ||
end | ||
172 | ||
173 | MTMigrate.new |
rool/rails/typo/trunk/db/converters/s9y.rb:
prev. | current | |
# Migrated users will have the default password "password", since the | ||
# MD5 hashes of S9Y cannot be converted to salted SHA1 hashes which are | ||
# used by Typo. | ||
15 | ||
15 | # | |
require File.dirname(__FILE__) + '/../../config/environment' | ||
require 'optparse' | ||
... | ... | |
puts "See s9y.rb --help for help." | ||
exit | ||
end | ||
174 | | |
174 | ||
unless self.options.include?(:s9y_prefix) | ||
self.options[:s9y_prefix] = "" | ||
end |
rool/rails/typo/trunk/db/converters/textpattern.rb:
prev. | current | |
#!/usr/bin/env ruby | ||
# TextPattern 1.x converter for typo by Patrick Lenz <patrick@lenz.sh> | ||
4 | ||
4 | # | |
# MAKE BACKUPS OF EVERYTHING BEFORE RUNNING THIS SCRIPT! | ||
# THIS SCRIPT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND | ||
... | ... | |
class TXPMigrate | ||
attr_accessor :options | ||
13 | | |
13 | ||
def initialize | ||
self.options = {} | ||
self.parse_options | ||
... | ... | |
def convert_categories | ||
txp_categories = ActiveRecord::Base.connection.select_all(%{ | ||
SELECT name | ||
25 | | |
25 | FROM `#{self.options[:txp_db]}`.`#{self.options[:txp_pfx]}`txp_category | |
WHERE parent = 'root' | ||
AND type = 'article' | ||
}) | ||
puts "Converting #{txp_categories.size} categories.." | ||
31 | | |
31 | ||
txp_categories.each do |cat| | ||
Category.create(cat) unless Category.find_by_name(cat['name']) | ||
end | ||
end | ||
36 | | |
36 | ||
def convert_entries | ||
txp_entries = ActiveRecord::Base.connection.select_all(%{ | ||
SELECT | ||
... | ... | |
1 AS allow_pings, | ||
Title AS title, | ||
(CASE LENGTH(Body) WHEN 0 THEN Excerpt ELSE Body END) AS body, | ||
45 | Body_html AS body_html, | |
Excerpt AS excerpt, | ||
Keywords AS keywords, | ||
Posted AS created_at, | ||
... | ... | |
(CASE textile_body WHEN '1' THEN 'textile' ELSE 'none' END) AS text_filter, | ||
(CASE Status WHEN '1' THEN '0' ELSE '1' END) AS published, | ||
Category1, Category2 | ||
53 | | |
54 | FROM `#{self.options[:txp_db]}`..`#{self.options[:txp_pfx]}`textpattern | |
}) | ||
55 | | |
56 | ||
puts "Converting #{txp_entries.size} entries.." | ||
57 | | |
58 | ||
txp_entries.each do |entry| | ||
a = Article.new | ||
a.attributes = entry.reject { |k,v| k =~ /^(Category|ID)/ } | ||
a.save | ||
62 | | |
63 | ||
# Assign categories | ||
puts "Assign primary category for entry #{entry['ID']}" | ||
a.categories.push_with_attributes(Category.find_by_name(entry['Category1']), :is_primary => 1) rescue nil | ||
puts "Assign secondary category for entry #{entry['ID']}" | ||
a.categories.push_with_attributes(Category.find_by_name(entry['Category2']), :is_primary => 0) rescue nil | ||
68 | | |
69 | ||
# Fetch comments | ||
ActiveRecord::Base.connection.select_all(%{ | ||
SELECT | ||
... | ... | |
email AS email, | ||
web AS url, | ||
message AS body, | ||
77 | message as body_html, | |
posted AS created_at, | ||
ip AS ip | ||
78 | | |
80 | FROM `#{self.options[:txp_db]}`..`#{self.options[:txp_pfx]}`txp_discuss | |
WHERE parentid = #{entry['ID']} | ||
}).each do |c| | ||
a.comments.create(c) | ||
end | ||
83 | | |
85 | ||
end | ||
end | ||
def convert_prefs | ||
puts "Converting prefs" | ||
89 | | |
91 | ||
ActiveRecord::Base.connection.select_all(%{ | ||
SELECT | ||
(CASE name | ||
... | ... | |
WHEN 'use_textile' THEN 'text_filter' | ||
END) AS name, | ||
val AS value | ||
98 | | |
99 | | |
100 | FROM `#{self.options[:txp_db]}`..`#{self.options[:txp_pfx]}`txp_prefs | |
101 | WHERE name IN ('sitename', 'comments_on_default', 'use_textile') | |
}).each do |pref| | ||
101 | | |
103 | if pref['name'] == "text_filter" and pref['value'].to_i > 0 | |
pref['value'] = 'textile' | ||
end | ||
104 | | |
106 | ||
begin | ||
Setting.find_by_name(pref['name']).update_attribute("value", pref['value']) | ||
rescue | ||
... | ... | |
opt.banner = "Usage: textpattern.rb [options]" | ||
opt.on('--db DBNAME', String, 'Text Pattern database name.') { |d| self.options[:txp_db] = d } | ||
120 | opt.on('--pf PREFIX', String, 'Textpattern table prefix.') { |p| self.options[:txp_pfx] = p } | |
opt.on_tail('-h', '--help', 'Show this message.') do | ||
puts opt | ||
... | ... | |
end | ||
end | ||
134 | ||
138 | TXPMigrate.new |
rool/rails/typo/trunk/db/converters/wordpress.rb:
prev. | current | |
#!/usr/bin/env ruby | ||
# WordPress 1.5x converter for typo by Patrick Lenz <patrick@lenz.sh> | ||
4 | ||
4 | # | |
# MAKE BACKUPS OF EVERYTHING BEFORE RUNNING THIS SCRIPT! | ||
# THIS SCRIPT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND | ||
... | ... | |
class WPMigrate | ||
attr_accessor :options | ||
13 | | |
13 | ||
def initialize | ||
self.options = {} | ||
self.parse_options | ||
... | ... | |
}) | ||
puts "Converting #{wp_categories.size} categories.." | ||
29 | | |
29 | ||
wp_categories.each do |cat| | ||
Category.create(cat) unless Category.find_by_name(cat['name']) | ||
end | ||
end | ||
34 | | |
34 | ||
def convert_entries | ||
wp_entries = ActiveRecord::Base.connection.select_all(%{ | ||
SELECT | ||
... | ... | |
FROM `#{self.options[:wp_db]}`.`#{self.options[:wp_prefix]}_posts`, `#{self.options[:wp_db]}`.`#{self.options[:wp_prefix]}_users` | ||
WHERE `#{self.options[:wp_prefix]}_users`.ID = `#{self.options[:wp_prefix]}_posts`.post_author | ||
}) | ||
52 | | |
52 | ||
puts "Converting #{wp_entries.size} entries.." | ||
54 | | |
54 | ||
wp_entries.each do |entry| | ||
a = Article.new | ||
57 | | |
57 | a.attributes = entry.reject { |k,v| k =~ /^(ID|post_category|body)/ } | |
58 | a.text_filter = self.options[:text_filter] | |
59 | body = entry['body'] | |
60 | more_index = body.index('<!--more-->') | |
61 | if more_index | |
62 | a.body = body[0...more_index] | |
63 | a.extended = body[more_index+11...body.length] | |
64 | else | |
65 | a.body = body | |
66 | end | |
a.save | ||
59 | | |
68 | ||
# Assign primary category | ||
unless entry['post_category'].to_i.zero? | ||
puts "Assign primary category for entry #{entry['ID']}" | ||
... | ... | |
}).each do |c| | ||
a.categories.push_with_attributes(Category.find_by_name(c['cat_name']), :is_primary => 0) | ||
end | ||
83 | | |
92 | ||
# Fetch comments | ||
ActiveRecord::Base.connection.select_all(%{ | ||
SELECT | ||
... | ... | |
}).each do |c| | ||
a.comments.create(c) | ||
end | ||
100 | | |
109 | ||
# Fetch trackbacks | ||
ActiveRecord::Base.connection.select_all(%{ | ||
SELECT | ||
... | ... | |
AND comment_type = 'trackback' | ||
AND comment_approved = '1' | ||
}).each do |c| | ||
114 | | |
123 | c['title'] = c['excerpt'].match("<(strong)>(.+?)</\\1>")[2] rescue c['blog_name'] | |
a.trackbacks.create(c) | ||
end | ||
... | ... | |
def convert_prefs | ||
puts "Converting prefs" | ||
123 | | |
132 | ||
ActiveRecord::Base.connection.select_all(%{ | ||
SELECT | ||
(CASE option_name | ||
... | ... | |
END) AS name, | ||
option_value AS value | ||
FROM `#{self.options[:wp_db]}`.`#{self.options[:wp_prefix]}_options` | ||
133 | | |
142 | WHERE option_name IN ('blogname', 'default_comment_status', 'default_ping_status') | |
}).each do |pref| | ||
if pref['name'] =~ /^default_allow/ | ||
pref['value'] = (pref['value'] == "open" ? 1 : 0) | ||
end | ||
138 | | |
147 | ||
begin | ||
Setting.find_by_name(pref['name']).update_attribute("value", pref['value']) | ||
rescue | ||
... | ... | |
opt.on('--db DBNAME', String, 'WordPress database name.') { |d| self.options[:wp_db] = d } | ||
opt.on('--prefix PREFIX', String, 'WordPress table prefix (defaults to \'wp\').') { |d| self.options[:wp_prefix] = d } | ||
162 | opt.on('--filter TEXTFILTER', String, 'Textfilter for imported articles (defaults to markdown).') { |d| self.options[:text_filter] = d } | |
opt.on_tail('-h', '--help', 'Show this message.') do | ||
puts opt | ||
... | ... | |
puts "See wordpress.rb --help for help." | ||
exit | ||
end | ||
166 | | |
176 | ||
unless self.options.include?(:wp_prefix) | ||
self.options[:wp_prefix] = "wp" | ||
end | ||
180 | ||
181 | unless self.options.include?(:text_filter) | |
182 | self.options[:text_filter] = 'markdown' | |
183 | end | |
end | ||
end | ||
173 | ||
188 | WPMigrate.new |
rool/rails/typo/trunk/db/schema.mysql.sql:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
5 | | |
6 | | |
7 | | |
8 | | |
9 | ||
1 | -- This file is autogenerated by the Rail schema generator, using | |
2 | -- the schema defined in db/migration/*.rb | |
3 | -- | |
4 | -- Do not edit this file. Instead, add a new migration using | |
5 | -- ./script/generate migration <name>, and then run | |
6 | -- ./script/generate schema | |
11 | ||
12 | | |
13 | | |
14 | | |
8 | -- tables | |
9 | ||
10 | CREATE TABLE articles_categories ( | |
11 | `article_id` int(11), | |
12 | `category_id` int(11), | |
13 | `is_primary` int(11) | |
14 | ) ENGINE=InnoDB; | |
15 | ||
16 | CREATE TABLE articles_tags ( | |
17 | `article_id` int(11), | |
18 | `tag_id` int(11) | |
19 | ) ENGINE=InnoDB; | |
20 | ||
21 | CREATE TABLE blacklist_patterns ( | |
22 | `id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, | |
23 | `type` varchar(255), | |
24 | `pattern` varchar(255) | |
25 | ) ENGINE=InnoDB; | |
26 | ||
27 | CREATE TABLE blogs ( | |
28 | `id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, | |
29 | `settings` text | |
30 | ) ENGINE=InnoDB; | |
31 | ||
32 | CREATE TABLE categories ( | |
33 | `id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, | |
34 | `name` varchar(255), | |
35 | `position` int(11), | |
36 | `permalink` varchar(255) | |
37 | ) ENGINE=InnoDB; | |
38 | ||
39 | CREATE TABLE contents ( | |
40 | `id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, | |
41 | `type` varchar(255), | |
42 | `title` varchar(255), | |
43 | `author` varchar(255), | |
`body` text, | ||
`body_html` text, | ||
`extended` text, | ||
47 | `excerpt` text, | |
48 | `keywords` varchar(255), | |
49 | `created_at` datetime, | |
50 | `updated_at` datetime, | |
`extended_html` text, | ||
19 | | |
20 | | |
21 | | |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
30 | | |
31 | | |
32 | ||
52 | `user_id` int(11), | |
53 | `permalink` varchar(255), | |
54 | `guid` varchar(255), | |
55 | `text_filter_id` int(11), | |
56 | `whiteboard` text, | |
57 | `article_id` int(11), | |
58 | `email` varchar(255), | |
59 | `url` varchar(255), | |
60 | `ip` varchar(40), | |
61 | `blog_name` varchar(255), | |
62 | `name` varchar(255), | |
63 | `comments_count` int(11), | |
64 | `trackbacks_count` int(11), | |
65 | `published` tinyint(1) DEFAULT 0, | |
66 | `allow_pings` tinyint(1), | |
67 | `allow_comments` tinyint(1), | |
68 | `blog_id` int(11) NOT NULL, | |
69 | `published_at` datetime | |
70 | ) ENGINE=InnoDB; | |
34 | ||
35 | | |
36 | | |
37 | | |
38 | ||
72 | CREATE TABLE notifications ( | |
73 | `notify_user_id` int(11), | |
74 | `notify_content_id` int(11), | |
75 | `created_at` datetime, | |
76 | `updated_at` datetime | |
77 | ) ENGINE=InnoDB; | |
40 | ||
41 | | |
42 | | |
43 | | |
44 | | |
45 | ||
79 | CREATE TABLE page_caches ( | |
80 | `id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, | |
81 | `name` varchar(255) | |
82 | ) ENGINE=InnoDB; | |
47 | ||
48 | | |
49 | | |
50 | | |
51 | | |
52 | ||
84 | CREATE TABLE pings ( | |
85 | `id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, | |
86 | `article_id` int(11), | |
87 | `url` varchar(255), | |
88 | `created_at` datetime | |
89 | ) ENGINE=InnoDB; | |
54 | ||
55 | | |
56 | | |
57 | | |
58 | | |
59 | | |
60 | | |
61 | | |
62 | | |
63 | | |
64 | | |
65 | ||
91 | CREATE TABLE redirects ( | |
92 | `id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, | |
93 | `from_path` varchar(255), | |
94 | `to_path` varchar(255) | |
95 | ) ENGINE=InnoDB; | |
67 | ||
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
73 | | |
74 | ||
97 | CREATE TABLE resources ( | |
98 | `id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, | |
99 | `size` int(11), | |
100 | `filename` varchar(255), | |
101 | `mime` varchar(255), | |
102 | `created_at` datetime, | |
103 | `updated_at` datetime, | |
104 | `article_id` int(11), | |
105 | `itunes_metadata` tinyint(1), | |
106 | `itunes_author` varchar(255), | |
107 | `itunes_subtitle` varchar(255), | |
108 | `itunes_duration` int(11), | |
109 | `itunes_summary` text, | |
110 | `itunes_keywords` varchar(255), | |
111 | `itunes_category` varchar(255), | |
112 | `itunes_explicit` tinyint(1) | |
113 | ) ENGINE=InnoDB; | |
76 | ||
77 | | |
78 | | |
79 | | |
80 | | |
81 | | |
82 | | |
83 | | |
84 | | |
85 | | |
86 | | |
87 | | |
88 | | |
89 | ||
115 | CREATE TABLE sessions ( | |
116 | `id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, | |
117 | `sessid` varchar(255), | |
118 | `data` text, | |
119 | `created_at` datetime, | |
120 | `updated_at` datetime | |
121 | ) ENGINE=InnoDB; | |
91 | ||
92 | | |
93 | | |
94 | | |
95 | | |
96 | | |
97 | | |
98 | ||
123 | CREATE TABLE sidebars ( | |
124 | `id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, | |
125 | `controller` varchar(255), | |
126 | `active_position` int(11), | |
127 | `config` text, | |
128 | `staged_position` int(11) | |
129 | ) ENGINE=InnoDB; | |
100 | ||
101 | | |
102 | | |
103 | | |
104 | | |
105 | | |
106 | | |
107 | | |
108 | ||
131 | CREATE TABLE tags ( | |
132 | `id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, | |
133 | `name` varchar(255), | |
134 | `created_at` datetime, | |
135 | `updated_at` datetime, | |
136 | `display_name` varchar(255) | |
137 | ) ENGINE=InnoDB; | |
110 | ||
111 | | |
112 | | |
113 | | |
114 | | |
115 | | |
116 | | |
117 | ||
139 | CREATE TABLE text_filters ( | |
140 | `id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, | |
141 | `name` varchar(255), | |
142 | `description` varchar(255), | |
143 | `markup` varchar(255), | |
144 | `filters` text, | |
145 | `params` text | |
146 | ) ENGINE=InnoDB; | |
119 | ||
120 | | |
121 | | |
122 | | |
123 | | |
124 | ||
148 | CREATE TABLE triggers ( | |
149 | `id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, | |
150 | `pending_item_id` int(11), | |
151 | `pending_item_type` varchar(255), | |
152 | `due_at` datetime, | |
153 | `trigger_method` varchar(255) | |
154 | ) ENGINE=InnoDB; | |
126 | ||
127 | | |
128 | | |
129 | | |
130 | | |
131 | | |
132 | | |
133 | | |
134 | | |
135 | ||
156 | CREATE TABLE users ( | |
157 | `id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, | |
158 | `login` varchar(255), | |
159 | `password` varchar(255), | |
160 | `email` text, | |
161 | `name` text, | |
162 | `notify_via_email` tinyint(1), | |
163 | `notify_on_new_articles` tinyint(1), | |
164 | `notify_on_comments` tinyint(1), | |
165 | `notify_watch_my_articles` tinyint(1), | |
166 | `notify_via_jabber` tinyint(1), | |
167 | `jabber` varchar(255) | |
168 | ) ENGINE=InnoDB; | |
137 | ||
138 | | |
139 | ||
140 | | |
141 | ||
142 | | |
144 | ||
145 | | |
146 | | |
147 | | |
148 | | |
149 | | |
150 | | |
151 | | |
152 | | |
153 | | |
154 | | |
155 | | |
156 | | |
157 | ||
171 | -- indexes | |
159 | ||
160 | | |
161 | ||
173 | CREATE INDEX `blacklist_patterns_pattern_index` ON blacklist_patterns (`pattern`); | |
174 | CREATE INDEX `categories_permalink_index` ON categories (`permalink`); | |
175 | CREATE INDEX `contents_blog_id_index` ON contents (`blog_id`); | |
176 | CREATE INDEX `contents_article_id_index` ON contents (`article_id`); | |
177 | CREATE INDEX `page_caches_name_index` ON page_caches (`name`); | |
178 | CREATE INDEX `pings_article_id_index` ON pings (`article_id`); | |
179 | CREATE INDEX `sessions_sessid_index` ON sessions (`sessid`); | |
163 | ||
181 | -- data | |
182 | ||
183 | INSERT INTO sidebars (`config`, `staged_position`, `active_position`, `controller`) VALUES(NULL, NULL, 0, 'category'); | |
184 | INSERT INTO sidebars (`config`, `staged_position`, `active_position`, `controller`) VALUES(NULL, NULL, 1, 'static'); | |
185 | INSERT INTO sidebars (`config`, `staged_position`, `active_position`, `controller`) VALUES(NULL, NULL, 2, 'xml'); | |
186 | INSERT INTO text_filters (`name`, `filters`, `description`, `params`, `markup`) VALUES('none', '--- [] | |
187 | ||
188 | ', 'None', '--- {} | |
189 | ||
190 | ', 'none'); | |
191 | INSERT INTO text_filters (`name`, `filters`, `description`, `params`, `markup`) VALUES('markdown', '--- [] | |
192 | ||
193 | ', 'Markdown', '--- {} | |
194 | ||
195 | ', 'markdown'); | |
196 | INSERT INTO text_filters (`name`, `filters`, `description`, `params`, `markup`) VALUES('smartypants', '--- | |
197 | - :smartypants | |
198 | ', 'SmartyPants', '--- {} | |
199 | ||
200 | ', 'none'); | |
201 | INSERT INTO text_filters (`name`, `filters`, `description`, `params`, `markup`) VALUES('markdown smartypants', '--- | |
202 | - :smartypants | |
203 | ', 'Markdown with SmartyPants', '--- {} | |
204 | ||
205 | ', 'markdown'); | |
206 | INSERT INTO text_filters (`name`, `filters`, `description`, `params`, `markup`) VALUES('textile', '--- [] | |
207 | ||
208 | ', 'Textile', '--- {} | |
209 | ||
210 | ', 'textile'); | |
211 | ||
212 | -- schema version meta-info | |
213 | ||
214 | CREATE TABLE schema_info ( | |
215 | `version` int(11) | |
216 | ) ENGINE=InnoDB; | |
217 | ||
218 | insert into schema_info (version) values (46); |
rool/rails/typo/trunk/db/schema.sqlite.sql:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
5 | | |
6 | | |
1 | -- This file is autogenerated by the Rail schema generator, using | |
2 | -- the schema defined in db/migration/*.rb | |
3 | -- | |
4 | -- Do not edit this file. Instead, add a new migration using | |
5 | -- ./script/generate migration <name>, and then run | |
6 | -- ./script/generate schema | |
7 | ||
8 | -- tables | |
9 | ||
10 | CREATE TABLE articles_categories ( | |
11 | "article_id" integer, | |
12 | "category_id" integer, | |
13 | "is_primary" integer | |
); | ||
9 | ||
10 | | |
11 | | |
12 | | |
13 | | |
14 | | |
15 | | |
16 | | |
17 | | |
18 | | |
19 | | |
20 | | |
21 | | |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
16 | CREATE TABLE articles_tags ( | |
17 | "article_id" integer, | |
18 | "tag_id" integer | |
); | ||
30 | ||
31 | | |
32 | | |
33 | | |
21 | CREATE TABLE blacklist_patterns ( | |
22 | "id" INTEGER PRIMARY KEY NOT NULL, | |
23 | "type" varchar(255), | |
24 | "pattern" varchar(255) | |
); | ||
36 | ||
37 | | |
38 | | |
39 | | |
27 | CREATE TABLE blogs ( | |
28 | "id" INTEGER PRIMARY KEY NOT NULL, | |
29 | "settings" text | |
); | ||
42 | ||
43 | | |
44 | | |
32 | CREATE TABLE categories ( | |
33 | "id" INTEGER PRIMARY KEY NOT NULL, | |
34 | "name" varchar(255), | |
35 | "position" integer, | |
36 | "permalink" varchar(255) | |
); | ||
47 | ||
48 | | |
49 | | |
50 | | |
51 | | |
52 | | |
53 | | |
54 | | |
55 | | |
56 | | |
39 | CREATE TABLE contents ( | |
40 | "id" INTEGER PRIMARY KEY NOT NULL, | |
41 | "type" varchar(255), | |
42 | "title" varchar(255), | |
43 | "author" varchar(255), | |
44 | "body" text, | |
45 | "body_html" text, | |
46 | "extended" text, | |
47 | "excerpt" text, | |
48 | "keywords" varchar(255), | |
49 | "created_at" datetime, | |
50 | "updated_at" datetime, | |
51 | "extended_html" text, | |
52 | "user_id" integer, | |
53 | "permalink" varchar(255), | |
54 | "guid" varchar(255), | |
55 | "text_filter_id" integer, | |
56 | "whiteboard" text, | |
57 | "article_id" integer, | |
58 | "email" varchar(255), | |
59 | "url" varchar(255), | |
60 | "ip" varchar(40), | |
61 | "blog_name" varchar(255), | |
62 | "name" varchar(255), | |
63 | "comments_count" integer, | |
64 | "trackbacks_count" integer, | |
65 | "published" boolean DEFAULT 'f', | |
66 | "allow_pings" boolean, | |
67 | "allow_comments" boolean, | |
68 | "blog_id" integer NOT NULL, | |
69 | "published_at" datetime | |
); | ||
59 | ||
60 | | |
61 | | |
62 | | |
63 | | |
72 | CREATE TABLE notifications ( | |
73 | "notify_user_id" integer, | |
74 | "notify_content_id" integer, | |
75 | "created_at" datetime, | |
76 | "updated_at" datetime | |
); | ||
66 | ||
67 | | |
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
73 | | |
74 | | |
75 | | |
76 | | |
79 | CREATE TABLE page_caches ( | |
80 | "id" INTEGER PRIMARY KEY NOT NULL, | |
81 | "name" varchar(255) | |
); | ||
79 | ||
80 | | |
81 | | |
82 | | |
83 | | |
84 | CREATE TABLE pings ( | |
85 | "id" INTEGER PRIMARY KEY NOT NULL, | |
86 | "article_id" integer, | |
87 | "url" varchar(255), | |
88 | "created_at" datetime | |
); | ||
86 | ||
87 | | |
88 | | |
89 | | |
90 | | |
91 | | |
92 | | |
91 | CREATE TABLE redirects ( | |
92 | "id" INTEGER PRIMARY KEY NOT NULL, | |
93 | "from_path" varchar(255), | |
94 | "to_path" varchar(255) | |
); | ||
95 | ||
96 | | |
97 | | |
98 | | |
99 | | |
97 | CREATE TABLE resources ( | |
98 | "id" INTEGER PRIMARY KEY NOT NULL, | |
99 | "size" integer, | |
100 | "filename" varchar(255), | |
101 | "mime" varchar(255), | |
102 | "created_at" datetime, | |
103 | "updated_at" datetime, | |
104 | "article_id" integer, | |
105 | "itunes_metadata" boolean, | |
106 | "itunes_author" varchar(255), | |
107 | "itunes_subtitle" varchar(255), | |
108 | "itunes_duration" integer, | |
109 | "itunes_summary" text, | |
110 | "itunes_keywords" varchar(255), | |
111 | "itunes_category" varchar(255), | |
112 | "itunes_explicit" boolean | |
); | ||
101 | | |
102 | ||
103 | | |
104 | | |
105 | | |
106 | | |
114 | ||
115 | CREATE TABLE sessions ( | |
116 | "id" INTEGER PRIMARY KEY NOT NULL, | |
117 | "sessid" varchar(255), | |
118 | "data" text, | |
119 | "created_at" datetime, | |
120 | "updated_at" datetime | |
); | ||
109 | ||
110 | | |
111 | | |
112 | | |
113 | | |
114 | | |
115 | | |
116 | | |
117 | | |
118 | ||
119 | ||
120 | | |
121 | ||
122 | | |
123 | ||
124 | | |
123 | CREATE TABLE sidebars ( | |
124 | "id" INTEGER PRIMARY KEY NOT NULL, | |
125 | "controller" varchar(255), | |
126 | "active_position" integer, | |
127 | "config" text, | |
128 | "staged_position" integer | |
129 | ); | |
126 | ||
127 | | |
128 | | |
129 | | |
130 | | |
131 | | |
132 | | |
133 | | |
134 | | |
135 | | |
136 | | |
131 | CREATE TABLE tags ( | |
132 | "id" INTEGER PRIMARY KEY NOT NULL, | |
133 | "name" varchar(255), | |
134 | "created_at" datetime, | |
135 | "updated_at" datetime, | |
136 | "display_name" varchar(255) | |
); | ||
139 | ||
140 | | |
139 | CREATE TABLE text_filters ( | |
140 | "id" INTEGER PRIMARY KEY NOT NULL, | |
141 | "name" varchar(255), | |
142 | "description" varchar(255), | |
143 | "markup" varchar(255), | |
144 | "filters" text, | |
145 | "params" text | |
); | ||
143 | ||
148 | CREATE TABLE triggers ( | |
149 | "id" INTEGER PRIMARY KEY NOT NULL, | |
150 | "pending_item_id" integer, | |
151 | "pending_item_type" varchar(255), | |
152 | "due_at" datetime, | |
153 | "trigger_method" varchar(255) | |
154 | ); | |
155 | ||
156 | CREATE TABLE users ( | |
157 | "id" INTEGER PRIMARY KEY NOT NULL, | |
158 | "login" varchar(255), | |
159 | "password" varchar(255), | |
160 | "email" text, | |
161 | "name" text, | |
162 | "notify_via_email" boolean, | |
163 | "notify_on_new_articles" boolean, | |
164 | "notify_on_comments" boolean, | |
165 | "notify_watch_my_articles" boolean, | |
166 | "notify_via_jabber" boolean, | |
167 | "jabber" varchar(255) | |
168 | ); | |
169 | ||
170 | ||
171 | -- indexes | |
172 | ||
173 | CREATE INDEX "blacklist_patterns_pattern_index" ON blacklist_patterns ("pattern"); | |
174 | CREATE INDEX "categories_permalink_index" ON categories ("permalink"); | |
175 | CREATE INDEX "contents_blog_id_index" ON contents ("blog_id"); | |
176 | CREATE INDEX "contents_article_id_index" ON contents ("article_id"); | |
177 | CREATE INDEX "page_caches_name_index" ON page_caches ("name"); | |
178 | CREATE INDEX "pings_article_id_index" ON pings ("article_id"); | |
179 | CREATE INDEX "sessions_sessid_index" ON sessions ("sessid"); | |
180 | ||
181 | -- data | |
182 | ||
183 | INSERT INTO sidebars ("config", "staged_position", "active_position", "controller") VALUES(NULL, NULL, 0, 'category'); | |
184 | INSERT INTO sidebars ("config", "staged_position", "active_position", "controller") VALUES(NULL, NULL, 1, 'static'); | |
185 | INSERT INTO sidebars ("config", "staged_position", "active_position", "controller") VALUES(NULL, NULL, 2, 'xml'); | |
186 | INSERT INTO text_filters ("name", "filters", "description", "params", "markup") VALUES('none', '--- [] | |
187 | ||
188 | ', 'None', '--- {} | |
189 | ||
190 | ', 'none'); | |
191 | INSERT INTO text_filters ("name", "filters", "description", "params", "markup") VALUES('markdown', '--- [] | |
192 | ||
193 | ', 'Markdown', '--- {} | |
194 | ||
195 | ', 'markdown'); | |
196 | INSERT INTO text_filters ("name", "filters", "description", "params", "markup") VALUES('smartypants', '--- | |
197 | - :smartypants | |
198 | ', 'SmartyPants', '--- {} | |
199 | ||
200 | ', 'none'); | |
201 | INSERT INTO text_filters ("name", "filters", "description", "params", "markup") VALUES('markdown smartypants', '--- | |
202 | - :smartypants | |
203 | ', 'Markdown with SmartyPants', '--- {} | |
204 | ||
205 | ', 'markdown'); | |
206 | INSERT INTO text_filters ("name", "filters", "description", "params", "markup") VALUES('textile', '--- [] | |
207 | ||
208 | ', 'Textile', '--- {} | |
209 | ||
210 | ', 'textile'); | |
211 | ||
212 | -- schema version meta-info | |
213 | ||
214 | CREATE TABLE schema_info ( | |
215 | "version" integer | |
216 | ); | |
217 | ||
218 | insert into schema_info (version) values (46); |
rool/rails/typo/trunk/db/scripts/fix_permalinks.rb:
prev. | current | |
require File.dirname(__FILE__) + '/../../config/environment' | ||
Article.find(:all).each do |a| | ||
(puts "Processing #{a.title} (#{a.stripped_title})" ; a.save) if a.permalink.blank? | ||
5 | ||
6 | end |
rool/rails/typo/trunk/lib/format.rb:
prev. | current | |
module Format | ||
2 | | |
3 | | |
2 | ||
3 | EMAIL = /^[_a-z0-9\+\.\-]+\@[_a-z0-9\-]+\.[_a-z0-9\.\-]+$/i | |
PASSWORD = /^[\_a-zA-Z0-9\.\-]+$/ | ||
5 | | |
6 | | |
7 | | |
5 | ||
6 | ||
7 | # matches everything to the last \ or / in a string. | |
# can chop of path of a filename like this : '/tobi/home/tobi.jpg'.sub(/^.*[\\\/]/,'') => tobi.jpg | ||
9 | | |
10 | | |
9 | FILENAME = /^.*[\\\/]/ | |
10 | ||
# good for replacing all special chars with something else, like an underscore | ||
FILENORMAL = /[^a-zA-Z0-9.]/ | ||
13 | | |
13 | ||
# Laxly matches an IP Address , would also pass numbers > 255 though | ||
IP_ADDRESS = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/ | ||
16 | | |
16 | ||
# Laxly matches an HTTP(S) URI | ||
HTTP_URI = /^https?:\/\/\S+$/ | ||
19 | ||
20 | end |
rool/rails/typo/trunk/lib/login_system.rb:
prev. | current | |
1 | ||
2 | | |
1 | module LoginSystem | |
2 | ||
protected | ||
4 | | |
4 | ||
# overwrite this if you want to restrict access to only a few actions | ||
6 | | |
6 | # or if you want to check if the user has the correct rights | |
# example: | ||
# | ||
# # only allow nonbobs | ||
... | ... | |
def authorize?(user) | ||
true | ||
end | ||
16 | | |
16 | ||
# overwrite this method if you only want to protect certain actions of the controller | ||
# example: | ||
19 | | |
19 | # | |
# # don't protect the login and the about method | ||
# def protect?(action) | ||
# if ['action', 'about'].include?(action) | ||
... | ... | |
def protect?(action) | ||
true | ||
end | ||
31 | | |
32 | | |
31 | ||
32 | # login_required filter. add | |
# | ||
# before_filter :login_required | ||
# | ||
36 | | |
36 | # if the controller should be under any rights management. | |
# for finer access control you can overwrite | ||
38 | | |
38 | # | |
# def authorize?(user) | ||
40 | | |
40 | # | |
def login_required | ||
42 | | |
42 | ||
if not protect?(action_name) | ||
44 | | |
44 | return true | |
end | ||
if session[:user] and authorize?(session[:user]) | ||
return true | ||
end | ||
51 | | |
51 | # store current location so that we can | |
# come back after the user logged in | ||
store_location | ||
54 | | |
54 | ||
# call overwriteable reaction to unauthorized access | ||
access_denied | ||
57 | | |
57 | return false | |
end | ||
# overwrite if you want to have special behavior in case the user is not authorized | ||
61 | | |
61 | # to access the current operation. | |
# the default action is to redirect to the login screen | ||
# example use : | ||
# a popup window might just close itself for instance | ||
def access_denied | ||
redirect_to :controller=>"/accounts", :action =>"login" | ||
67 | | |
68 | | |
67 | end | |
68 | ||
# store current uri in the session. | ||
# we can return to this location by calling return_location | ||
def store_location | ||
... | ... | |
end | ||
end | ||
85 | ||
86 | end |
rool/rails/typo/trunk/lib/migrator.rb:
prev. | current | |
module Migrator | ||
mattr_accessor :offer_migration_when_available | ||
@@offer_migration_when_available = true | ||
4 | | |
4 | ||
def self.migrations_path | ||
"#{RAILS_ROOT}/db/migrate" | ||
end | ||
def self.available_migrations | ||
10 | | |
10 | Dir["#{migrations_path}/[0-9]*_*.rb"].sort_by { |name| name.scan(/\d+/).first.to_i } | |
end | ||
def self.current_schema_version | ||
... | ... | |
def self.max_schema_version | ||
available_migrations.size | ||
end | ||
20 | | |
20 | ||
def self.db_supports_migrations? | ||
ActiveRecord::Base.connection.supports_migrations? | ||
end | ||
24 | | |
24 | ||
def self.migrate(version = nil) | ||
26 | | |
27 | | |
28 | ||
27 | ActiveRecord::Migrator.migrate("#{migrations_path}/", version) | |
28 | end | |
29 | end |
rool/rails/typo/trunk/lib/spam_protection.rb:
prev. | current | |
1 | ||
2 | ||
class SpamProtection | ||
5 | | |
6 | | |
3 | IP_RBLS = [ 'opm.blitzed.us', 'bsb.empty.us' ] | |
4 | HOST_RBLS = [ 'multi.surbl.org', 'bsb.empty.us' ] | |
SECOND_LEVEL = [ 'co', 'com', 'net', 'org', 'gov' ] | ||
7 | attr_accessor :this_blog | |
8 | ||
9 | def initialize(a_blog) | |
10 | self.this_blog = a_blog | |
11 | end | |
12 | ||
def article_closed?(record) | ||
10 | | |
11 | | |
12 | | |
13 | | |
14 | | |
14 | return false if this_blog.sp_article_auto_close.zero? or not record.new_record? | |
15 | ||
16 | if record.article.created_at.to_i < this_blog.sp_article_auto_close.days.ago.to_i | |
17 | logger.info("[SP] Blocked interaction with #{record.article.title}") | |
18 | return true | |
end | ||
end | ||
def is_spam?(string) | ||
19 | | |
23 | return false unless this_blog.sp_global | |
return false if string.blank? | ||
reason = catch(:hit) do | ||
... | ... | |
else self.scan_text(string) | ||
end | ||
end | ||
29 | | |
33 | ||
if reason | ||
logger.info("[SP] Hit: #{reason}") | ||
return true | ||
end | ||
end | ||
35 | | |
39 | ||
protected | ||
37 | | |
41 | ||
def scan_ip(ip_address) | ||
logger.info("[SP] Scanning IP #{ip_address}") | ||
40 | | |
41 | | |
42 | | |
43 | | |
44 | | |
45 | | |
46 | | |
47 | | |
48 | | |
49 | | |
50 | | |
44 | query_rbls(IP_RBLS, ip_address.split('.').reverse.join('.')) | |
end | ||
52 | | |
46 | ||
def scan_text(string) | ||
# Scan contained URLs | ||
uri_list = string.scan(/(http:\/\/[^\s"]+)/m).flatten | ||
57 | | |
58 | | |
59 | | |
51 | # Check for URL count limit | |
52 | if this_blog.sp_url_limit > 0 | |
53 | throw :hit, "Hard URL Limit hit: #{uri_list.size} > #{this_blog.sp_url_limit}" if uri_list.size > this_blog.sp_url_limit | |
end | ||
61 | | |
55 | ||
uri_list.collect { |uri| URI.parse(uri).host rescue nil }.uniq.compact.each do |host| | ||
scan_uri(host) | ||
end | ||
65 | | |
59 | ||
# Pattern scanning | ||
BlacklistPattern.find_all.each do |pattern| | ||
logger.info("[SP] Scanning for #{pattern.class} #{pattern.pattern}") | ||
70 | | |
71 | | |
72 | | |
73 | | |
74 | | |
64 | throw :hit, "#{pattern} matched" if pattern.matches?(string) | |
end | ||
76 | | |
66 | ||
return false | ||
end | ||
... | ... | |
host_parts = host.split('.').reverse | ||
domain = Array.new | ||
85 | | |
# Check for two level TLD | ||
(SECOND_LEVEL.include?(host_parts[1]) ? 3:2).times do | ||
... | ... | |
end | ||
logger.info("[SP] Scanning domain #{domain.join('.')}") | ||
82 | query_rbls(HOST_RBLS, host, domain.join('.')) | |
83 | end | |
94 | | |
95 | | |
96 | | |
97 | | |
98 | | |
99 | | |
100 | | |
85 | def query_rbls(rbls, *subdomains) | |
86 | rbls.each do |rbl| | |
87 | subdomains.uniq.each do |d| | |
88 | begin | |
89 | response = IPSocket.getaddress([d, rbl].join('.')) | |
90 | throw :hit, "#{rbl} positively resolved subdomain #{d} => #{response}" if response =~ /^127\.0\.0\./ | |
91 | rescue SocketError | |
92 | # NXDOMAIN response => negative: d is not in RBL | |
end | ||
102 | | |
end | ||
end | ||
105 | | |
return false | ||
end | ||
... | ... | |
configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash) | ||
validates_each(attr_names, configuration) do |record, attr_name, value| | ||
122 | | |
112 | record.errors.add(attr_name, configuration[:message]) if SpamProtection.new(record.blog).is_spam?(value) | |
end | ||
end | ||
def validates_age_of(*attr_names) | ||
126 | | |
116 | configuration = { :on => :create, :message => "points to an item that is no longer available for interaction"} | |
configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash) | ||
128 | | |
118 | ||
validates_each(attr_names, configuration) do |record, attr_name, value| | ||
next unless value.to_i > 0 | ||
131 | | |
121 | record.errors.add(attr_name, configuration[:message]) if SpamProtection.new(record.blog).article_closed?(record) | |
end | ||
end | ||
end | ||
end | ||
136 | ||
127 | end |
rool/rails/typo/trunk/lib/transforms.rb:
prev. | current | |
1 | ||
2 | | |
3 | ||
4 | ||
5 | ||
6 | | |
7 | | |
8 | | |
9 | | |
10 | | |
11 | | |
12 | | |
13 | ||
14 | ||
class String | ||
16 | | |
17 | | |
2 | # Returns a-string-with-dashes when passed 'a string with dashes'. | |
3 | # All special chars are stripped in the process | |
def to_url | ||
return if self.nil? | ||
20 | | |
21 | | |
23 | | |
24 | | |
7 | self.downcase.tr("\"'", '').gsub(/\W/, ' ').strip.tr_s(' ', '-').tr(' ', '-').sub(/^$/, "-") | |
8 | end | |
26 | | |
27 | | |
10 | # A quick and dirty fix to add 'nofollow' to any urls in a string. | |
11 | # Decidedly unsafe, but will have to do for now. | |
12 | def nofollowify | |
13 | self.gsub(/<\s*a\s*(.+?)>/i, '<a \1 rel="nofollow">') | |
14 | end | |
29 | | |
30 | | |
31 | ||
32 | | |
33 | | |
34 | | |
35 | ||
36 | | |
16 | # Strips any html markup from a string | |
17 | TYPO_TAG_KEY = TYPO_ATTRIBUTE_KEY = /[\w:_-]+/ | |
18 | TYPO_ATTRIBUTE_VALUE = /(?:[A-Za-z0-9]+|(?:'[^']*?'|"[^"]*?"))/ | |
19 | TYPO_ATTRIBUTE = /(?:#{TYPO_ATTRIBUTE_KEY}(?:\s*=\s*#{TYPO_ATTRIBUTE_VALUE})?)/ | |
20 | TYPO_ATTRIBUTES = /(?:#{TYPO_ATTRIBUTE}(?:\s+#{TYPO_ATTRIBUTE})*)/ | |
21 | TAG = %r{<[!/?\[]?(?:#{TYPO_TAG_KEY}|--)(?:\s+#{TYPO_ATTRIBUTES})?\s*(?:[!/?\]]+|--)?>} | |
22 | def strip_html | |
23 | self.gsub(TAG, '').gsub(/\s+/, ' ').strip | |
end | ||
38 | ||
26 | ||
27 | end |
rool/rails/typo/trunk/lib/xmlrpc_fix.rb:
prev. | current | |
end | ||
end | ||
end | ||
13 | ||
14 | end |
rool/rails/typo/trunk/public/.htaccess:
prev. | current | |
AddHandler cgi-script .cgi | ||
Options +FollowSymLinks +ExecCGI | ||
6 | # If you don't want Rails to look in certain directories, | |
7 | # use the following rewrite rules so that Apache won't rewrite certain requests | |
8 | # | |
9 | # Example: | |
10 | # RewriteCond %{REQUEST_URI} ^/notrails.* | |
11 | # RewriteRule .* - [L] | |
12 | ||
# Redirect all requests not available on the filesystem to Rails | ||
RewriteEngine On | ||
9 | ||
10 | ||
16 | # If Typo is accessed via an Alias directive, then you MUST also set | |
17 | # the RewriteBase in this htaccess file. | |
# | ||
12 | ||
19 | # Example: | |
20 | # Alias /blog /path/to/typo/public | |
21 | # RewriteBase /blog | |
14 | ||
15 | ||
RewriteRule ^$ index.html [QSA] | ||
RewriteRule ^([^.]+)$ $1.html [QSA] | ||
RewriteCond %{REQUEST_FILENAME} !-f | ||
RewriteRule ^(.*)$ dispatch.fcgi [QSA,L] | ||
21 | ||
22 | ||
28 | # In case Typo experiences terminal errors | |
29 | # Instead of displaying this message you can supply a file here which will be rendered instead | |
30 | # | |
31 | # Example: | |
32 | # ErrorDocument 500 /500.html | |
33 | ||
34 | ErrorDocument 500 "<h2>Application error</h2>Typo failed to start properly" | |
rool/rails/typo/trunk/public/404.html:
prev. | current | |
1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | |
2 | "http://www.w3.org/TR/html4/loose.dtd"> | |
<html> | ||
<body> | ||
<h1>File not found</h1> |
rool/rails/typo/trunk/public/500.html:
prev. | current | |
1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | |
2 | "http://www.w3.org/TR/html4/loose.dtd"> | |
<html> | ||
<body> | ||
<h1>Application error (Apache)</h1> |
rool/rails/typo/trunk/public/dispatch.rb:
prev. | current | |
1 | ||
1 | #!/usr/bin/ruby | |
require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT) | ||
rool/rails/typo/trunk/public/javascripts/controls.js:
prev. | current | |
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) | ||
// (c) 2005 Ivan Krstic (http://blogs.law.harvard.edu/ivan) | ||
3 | // (c) 2005 Jon Tirsen (http://www.tirsen.com) | |
4 | // Contributors: | |
5 | // Richard Livsey | |
6 | // Rahul Bhargava | |
7 | // Rob Wills | |
// | ||
4 | ||
5 | ||
6 | ||
7 | ||
8 | ||
9 | ||
10 | ||
11 | ||
12 | ||
13 | ||
14 | ||
15 | ||
16 | ||
17 | ||
18 | ||
19 | ||
20 | ||
21 | ||
9 | // See scriptaculous.js for full license. | |
23 | ||
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
30 | | |
31 | | |
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | | |
38 | ||
39 | ||
// Autocompleter.Base handles all the autocompletion functionality | ||
// that's independent of the data source for autocompletion. This | ||
// includes drawing the autocompletion menu, observing keyboard | ||
... | ... | |
// a getUpdatedChoices function that will be invoked every time | ||
// the text inside the monitored textbox changes. This method | ||
// should get the text for which to provide autocompletion by | ||
49 | ||
20 | // invoking this.getToken(), NOT by directly accessing | |
// this.element.value. This is to allow incremental tokenized | ||
// autocompletion. Specific auto-completion logic (AJAX, etc) | ||
// belongs in getUpdatedChoices. | ||
... | ... | |
// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); | ||
// will incrementally autocomplete with a comma as the token. | ||
// Additionally, ',' in the above example can be replaced with | ||
60 | ||
31 | // a token array, e.g. { tokens: [',', '\n'] } which | |
// enables autocompletion on multiple tokens. This is most | ||
// useful when one of the tokens is \n (a newline), as it | ||
// allows smart autocompletion after linebreaks. | ||
... | ... | |
var Autocompleter = {} | ||
Autocompleter.Base = function() {}; | ||
Autocompleter.Base.prototype = { | ||
68 | | |
39 | baseInitialize: function(element, update, options) { | |
this.element = $(element); | ||
this.update = $(update); | ||
71 | | |
42 | this.hasFocus = false; | |
this.changed = false; | ||
this.active = false; | ||
this.index = 0; | ||
75 | | |
46 | this.entryCount = 0; | |
if (this.setOptions) | ||
this.setOptions(options); | ||
else | ||
80 | | |
81 | | |
82 | | |
51 | this.options = options || {}; | |
52 | ||
53 | this.options.paramName = this.options.paramName || this.element.name; | |
54 | this.options.tokens = this.options.tokens || []; | |
this.options.frequency = this.options.frequency || 0.4; | ||
84 | | |
56 | this.options.minChars = this.options.minChars || 1; | |
this.options.onShow = this.options.onShow || | ||
function(element, update){ | ||
if(!update.style.position || update.style.position=='absolute') { | ||
update.style.position = 'absolute'; | ||
89 | | |
90 | | |
91 | | |
92 | | |
61 | Position.clone(element, update, {setHeight: false, offsetTop: element.offsetHeight}); | |
} | ||
94 | | |
63 | Effect.Appear(update,{duration:0.15}); | |
}; | ||
this.options.onHide = this.options.onHide || | ||
function(element, update){ new Effect.Fade(update,{duration:0.15}) }; | ||
98 | | |
99 | | |
100 | | |
if (typeof(this.options.tokens) == 'string') | ||
this.options.tokens = new Array(this.options.tokens); | ||
104 | | |
70 | ||
this.observer = null; | ||
73 | this.element.setAttribute('autocomplete','off'); | |
74 | ||
Element.hide(this.update); | ||
108 | | |
76 | ||
Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this)); | ||
Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this)); | ||
}, | ||
show: function() { | ||
114 | | |
115 | | |
82 | if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); | |
83 | if(!this.iefix && | |
84 | (navigator.appVersion.indexOf('MSIE')>0) && | |
85 | (navigator.userAgent.indexOf('Opera')<0) && | |
86 | (Element.getStyle(this.update, 'position')=='absolute')) { | |
new Insertion.After(this.update, | ||
'<iframe id="' + this.update.id + '_iefix" '+ | ||
118 | | |
89 | 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + | |
'src="javascript:false;" frameborder="0" scrolling="no"></iframe>'); | ||
this.iefix = $(this.update.id+'_iefix'); | ||
} | ||
122 | | |
123 | | |
124 | | |
125 | | |
126 | | |
127 | | |
93 | if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); | |
}, | ||
96 | fixIEOverlapping: function() { | |
97 | Position.clone(this.update, this.iefix); | |
98 | this.iefix.style.zIndex = 1; | |
99 | this.update.style.zIndex = 2; | |
100 | Element.show(this.iefix); | |
101 | }, | |
102 | ||
hide: function() { | ||
131 | | |
104 | this.stopIndicator(); | |
105 | if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); | |
if(this.iefix) Element.hide(this.iefix); | ||
}, | ||
134 | | |
108 | ||
startIndicator: function() { | ||
136 | | |
110 | if(this.options.indicator) Element.show(this.options.indicator); | |
}, | ||
138 | | |
112 | ||
stopIndicator: function() { | ||
140 | | |
114 | if(this.options.indicator) Element.hide(this.options.indicator); | |
}, | ||
onKeyPress: function(event) { | ||
... | ... | |
switch(event.keyCode) { | ||
case Event.KEY_TAB: | ||
case Event.KEY_RETURN: | ||
148 | | |
122 | this.selectEntry(); | |
Event.stop(event); | ||
case Event.KEY_ESC: | ||
this.hide(); | ||
this.active = false; | ||
127 | Event.stop(event); | |
return; | ||
case Event.KEY_LEFT: | ||
case Event.KEY_RIGHT: | ||
return; | ||
case Event.KEY_UP: | ||
158 | | |
133 | this.markPrevious(); | |
this.render(); | ||
if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event); | ||
return; | ||
case Event.KEY_DOWN: | ||
163 | | |
138 | this.markNext(); | |
this.render(); | ||
if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event); | ||
return; | ||
} | ||
else | ||
169 | | |
170 | | |
171 | | |
144 | if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || | |
145 | (navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return; | |
146 | ||
this.changed = true; | ||
173 | | |
174 | | |
148 | this.hasFocus = true; | |
149 | ||
if(this.observer) clearTimeout(this.observer); | ||
this.observer = | ||
setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); | ||
}, | ||
179 | | |
154 | ||
155 | activate: function() { | |
156 | this.changed = false; | |
157 | this.hasFocus = true; | |
158 | this.getUpdatedChoices(); | |
159 | }, | |
160 | ||
onHover: function(event) { | ||
var element = Event.findElement(event, 'LI'); | ||
if(this.index != element.autocompleteIndex) | ||
... | ... | |
onClick: function(event) { | ||
var element = Event.findElement(event, 'LI'); | ||
this.index = element.autocompleteIndex; | ||
193 | | |
194 | | |
174 | this.selectEntry(); | |
175 | this.hide(); | |
}, | ||
onBlur: function(event) { | ||
// needed to make click events working | ||
setTimeout(this.hide.bind(this), 250); | ||
200 | | |
181 | this.hasFocus = false; | |
this.active = false; | ||
}, | ||
render: function() { | ||
205 | | |
206 | | |
186 | if(this.entryCount > 0) { | |
187 | for (var i = 0; i < this.entryCount; i++) | |
this.index==i ? | ||
208 | | |
209 | | |
189 | Element.addClassName(this.getEntry(i),"selected") : | |
190 | Element.removeClassName(this.getEntry(i),"selected"); | |
211 | | |
212 | | |
213 | | |
214 | | |
192 | if(this.hasFocus) { | |
this.show(); | ||
this.active = true; | ||
} | ||
218 | | |
196 | } else { | |
197 | this.active = false; | |
198 | this.hide(); | |
199 | } | |
}, | ||
221 | | |
202 | markPrevious: function() { | |
if(this.index > 0) this.index-- | ||
223 | | |
204 | else this.index = this.entryCount-1; | |
}, | ||
226 | | |
227 | | |
207 | markNext: function() { | |
208 | if(this.index < this.entryCount-1) this.index++ | |
else this.index = 0; | ||
}, | ||
231 | | |
212 | getEntry: function(index) { | |
return this.update.firstChild.childNodes[index]; | ||
}, | ||
235 | | |
236 | | |
216 | getCurrentEntry: function() { | |
217 | return this.getEntry(this.index); | |
}, | ||
239 | | |
220 | selectEntry: function() { | |
this.active = false; | ||
241 | | |
242 | | |
243 | | |
222 | this.updateElement(this.getCurrentEntry()); | |
}, | ||
246 | | |
247 | | |
248 | | |
249 | | |
250 | | |
225 | updateElement: function(selectedElement) { | |
226 | if (this.options.updateElement) { | |
227 | this.options.updateElement(selectedElement); | |
228 | return; | |
229 | } | |
230 | var value = ''; | |
231 | if (this.options.select) { | |
232 | var nodes = document.getElementsByClassName(this.options.select, selectedElement) || []; | |
233 | if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); | |
234 | } else | |
235 | value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); | |
236 | ||
237 | var lastTokenPos = this.findLastToken(); | |
238 | if (lastTokenPos != -1) { | |
239 | var newValue = this.element.value.substr(0, lastTokenPos + 1); | |
240 | var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/); | |
if (whitespace) | ||
252 | | |
253 | | |
242 | newValue += whitespace[0]; | |
243 | this.element.value = newValue + value; | |
} else { | ||
this.element.value = value; | ||
256 | | |
246 | } | |
247 | this.element.focus(); | |
248 | ||
249 | if (this.options.afterUpdateElement) | |
250 | this.options.afterUpdateElement(this.element, selectedElement); | |
}, | ||
258 | | |
252 | ||
updateChoices: function(choices) { | ||
260 | | |
254 | if(!this.changed && this.hasFocus) { | |
this.update.innerHTML = choices; | ||
Element.cleanWhitespace(this.update); | ||
Element.cleanWhitespace(this.update.firstChild); | ||
if(this.update.firstChild && this.update.firstChild.childNodes) { | ||
266 | | |
260 | this.entryCount = | |
this.update.firstChild.childNodes.length; | ||
268 | | |
269 | | |
262 | for (var i = 0; i < this.entryCount; i++) { | |
263 | var entry = this.getEntry(i); | |
entry.autocompleteIndex = i; | ||
this.addObservers(entry); | ||
} | ||
} else { | ||
274 | | |
268 | this.entryCount = 0; | |
} | ||
276 | | |
270 | ||
this.stopIndicator(); | ||
278 | | |
272 | ||
this.index = 0; | ||
this.render(); | ||
} | ||
... | ... | |
onObserverEvent: function() { | ||
this.changed = false; | ||
291 | | |
285 | if(this.getToken().length>=this.options.minChars) { | |
this.startIndicator(); | ||
this.getUpdatedChoices(); | ||
} else { | ||
... | ... | |
} | ||
}, | ||
300 | | |
301 | | |
302 | | |
303 | | |
294 | getToken: function() { | |
295 | var tokenPos = this.findLastToken(); | |
296 | if (tokenPos != -1) | |
297 | var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,''); | |
else | ||
var ret = this.element.value; | ||
306 | | |
300 | ||
return /\n/.test(ret) ? '' : ret; | ||
}, | ||
findLastToken: function() { | ||
311 | | |
305 | var lastTokenPos = -1; | |
for (var i=0; i<this.options.tokens.length; i++) { | ||
314 | | |
315 | | |
316 | | |
308 | var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]); | |
309 | if (thisTokenPos > lastTokenPos) | |
310 | lastTokenPos = thisTokenPos; | |
} | ||
318 | | |
312 | return lastTokenPos; | |
} | ||
} | ||
Ajax.Autocompleter = Class.create(); | ||
323 | ||
324 | ||
317 | Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), { | |
initialize: function(element, update, url, options) { | ||
326 | | |
319 | this.baseInitialize(element, update, options); | |
this.options.asynchronous = true; | ||
328 | | |
329 | | |
321 | this.options.onComplete = this.onComplete.bind(this); | |
this.options.defaultParams = this.options.parameters || null; | ||
this.url = url; | ||
}, | ||
333 | | |
325 | ||
getUpdatedChoices: function() { | ||
335 | | |
336 | | |
337 | | |
327 | entry = encodeURIComponent(this.options.paramName) + '=' + | |
328 | encodeURIComponent(this.getToken()); | |
329 | ||
this.options.parameters = this.options.callback ? | ||
this.options.callback(this.element, entry) : entry; | ||
340 | | |
332 | ||
if(this.options.defaultParams) | ||
this.options.parameters += '&' + this.options.defaultParams; | ||
343 | | |
335 | ||
new Ajax.Request(this.url, this.options); | ||
}, | ||
346 | | |
338 | ||
onComplete: function(request) { | ||
this.updateChoices(request.responseText); | ||
} | ||
351 | ||
343 | }); | |
// The local array autocompleter. Used when you'd prefer to | ||
// inject an array of autocompletion options into the page, rather | ||
... | ... | |
// Extra local autocompletion options: | ||
// - choices - How many autocompletion choices to offer | ||
// | ||
365 | ||
357 | // - partialSearch - If false, the autocompleter will match entered | |
// text only at the beginning of strings in the | ||
// autocomplete array. Defaults to true, which will | ||
// match text at the beginning of any *word* in the | ||
// strings in the autocomplete array. If you want to | ||
// search anywhere in the string, additionally set | ||
371 | ||
363 | // the option fullSearch to true (default: off). | |
// | ||
373 | ||
365 | // - fullSsearch - Search anywhere in autocomplete array strings. | |
// | ||
375 | ||
376 | ||
367 | // - partialChars - How many characters to enter before triggering | |
368 | // a partial match (unlike minChars, which defines | |
// how many characters are required to do any match | ||
// at all). Defaults to 2. | ||
// | ||
380 | ||
372 | // - ignoreCase - Whether to ignore case when autocompleting. | |
// Defaults to true. | ||
// | ||
// It's possible to pass in a custom function as the 'selector' | ||
... | ... | |
Autocompleter.Local = Class.create(); | ||
Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), { | ||
initialize: function(element, update, array, options) { | ||
391 | | |
383 | this.baseInitialize(element, update, options); | |
this.options.array = array; | ||
}, | ||
... | ... | |
setOptions: function(options) { | ||
this.options = Object.extend({ | ||
choices: 10, | ||
402 | | |
403 | | |
404 | | |
405 | | |
394 | partialSearch: true, | |
395 | partialChars: 2, | |
396 | ignoreCase: true, | |
397 | fullSearch: false, | |
selector: function(instance) { | ||
407 | | |
408 | | |
409 | | |
399 | var ret = []; // Beginning matches | |
400 | var partial = []; // Inside matches | |
401 | var entry = instance.getToken(); | |
var count = 0; | ||
411 | | |
403 | ||
for (var i = 0; i < instance.options.array.length && | ||
413 | | |
405 | ret.length < instance.options.choices ; i++) { | |
406 | ||
var elem = instance.options.array[i]; | ||
415 | | |
408 | var foundPos = instance.options.ignoreCase ? | |
elem.toLowerCase().indexOf(entry.toLowerCase()) : | ||
elem.indexOf(entry); | ||
419 | | |
420 | | |
412 | while (foundPos != -1) { | |
413 | if (foundPos == 0 && elem.length != entry.length) { | |
ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + | ||
elem.substr(entry.length) + "</li>"); | ||
break; | ||
424 | | |
425 | | |
426 | | |
427 | | |
428 | | |
429 | | |
417 | } else if (entry.length >= instance.options.partialChars && | |
418 | instance.options.partialSearch && foundPos != -1) { | |
419 | if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { | |
420 | partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" + | |
421 | elem.substr(foundPos, entry.length) + "</strong>" + elem.substr( | |
422 | foundPos + entry.length) + "</li>"); | |
break; | ||
} | ||
} | ||
434 | | |
435 | | |
436 | | |
427 | foundPos = instance.options.ignoreCase ? | |
428 | elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : | |
429 | elem.indexOf(entry, foundPos + 1); | |
} | ||
} | ||
... | ... | |
}, options || {}); | ||
} | ||
}); | ||
440 | ||
441 | // AJAX in-place editor | |
442 | // | |
443 | // see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor | |
444 | ||
445 | // Use this if you notice weird scrolling problems on some browsers, | |
446 | // the DOM might be a bit confused when this gets called so do this | |
447 | // waits 1 ms (with setTimeout) until it does the activation | |
448 | Field.scrollFreeActivate = function(field) { | |
449 | setTimeout(function() { | |
450 | Field.activate(field); | |
451 | }, 1); | |
452 | } | |
453 | ||
454 | Ajax.InPlaceEditor = Class.create(); | |
455 | Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99"; | |
456 | Ajax.InPlaceEditor.prototype = { | |
457 | initialize: function(element, url, options) { | |
458 | this.url = url; | |
459 | this.element = $(element); | |
460 | ||
461 | this.options = Object.extend({ | |
462 | okButton: true, | |
463 | okText: "ok", | |
464 | cancelLink: true, | |
465 | cancelText: "cancel", | |
466 | savingText: "Saving...", | |
467 | clickToEditText: "Click to edit", | |
468 | okText: "ok", | |
469 | rows: 1, | |
470 | onComplete: function(transport, element) { | |
471 | new Effect.Highlight(element, {startcolor: this.options.highlightcolor}); | |
472 | }, | |
473 | onFailure: function(transport) { | |
474 | alert("Error communicating with the server: " + transport.responseText.stripTags()); | |
475 | }, | |
476 | callback: function(form) { | |
477 | return Form.serialize(form); | |
478 | }, | |
479 | handleLineBreaks: true, | |
480 | loadingText: 'Loading...', | |
481 | savingClassName: 'inplaceeditor-saving', | |
482 | loadingClassName: 'inplaceeditor-loading', | |
483 | formClassName: 'inplaceeditor-form', | |
484 | highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor, | |
485 | highlightendcolor: "#FFFFFF", | |
486 | externalControl: null, | |
487 | submitOnBlur: false, | |
488 | ajaxOptions: {}, | |
489 | evalScripts: false | |
490 | }, options || {}); | |
491 | ||
492 | if(!this.options.formId && this.element.id) { | |
493 | this.options.formId = this.element.id + "-inplaceeditor"; | |
494 | if ($(this.options.formId)) { | |
495 | // there's already a form with that name, don't specify an id | |
496 | this.options.formId = null; | |
497 | } | |
498 | } | |
499 | ||
500 | if (this.options.externalControl) { | |
501 | this.options.externalControl = $(this.options.externalControl); | |
502 | } | |
503 | ||
504 | this.originalBackground = Element.getStyle(this.element, 'background-color'); | |
505 | if (!this.originalBackground) { | |
506 | this.originalBackground = "transparent"; | |
507 | } | |
508 | ||
509 | this.element.title = this.options.clickToEditText; | |
510 | ||
511 | this.onclickListener = this.enterEditMode.bindAsEventListener(this); | |
512 | this.mouseoverListener = this.enterHover.bindAsEventListener(this); | |
513 | this.mouseoutListener = this.leaveHover.bindAsEventListener(this); | |
514 | Event.observe(this.element, 'click', this.onclickListener); | |
515 | Event.observe(this.element, 'mouseover', this.mouseoverListener); | |
516 | Event.observe(this.element, 'mouseout', this.mouseoutListener); | |
517 | if (this.options.externalControl) { | |
518 | Event.observe(this.options.externalControl, 'click', this.onclickListener); | |
519 | Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener); | |
520 | Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener); | |
521 | } | |
522 | }, | |
523 | enterEditMode: function(evt) { | |
524 | if (this.saving) return; | |
525 | if (this.editing) return; | |
526 | this.editing = true; | |
527 | this.onEnterEditMode(); | |
528 | if (this.options.externalControl) { | |
529 | Element.hide(this.options.externalControl); | |
530 | } | |
531 | Element.hide(this.element); | |
532 | this.createForm(); | |
533 | this.element.parentNode.insertBefore(this.form, this.element); | |
534 | Field.scrollFreeActivate(this.editField); | |
535 | // stop the event to avoid a page refresh in Safari | |
536 | if (evt) { | |
537 | Event.stop(evt); | |
538 | } | |
539 | return false; | |
540 | }, | |
541 | createForm: function() { | |
542 | this.form = document.createElement("form"); | |
543 | this.form.id = this.options.formId; | |
544 | Element.addClassName(this.form, this.options.formClassName) | |
545 | this.form.onsubmit = this.onSubmit.bind(this); | |
546 | ||
547 | this.createEditField(); | |
548 | ||
549 | if (this.options.textarea) { | |
550 | var br = document.createElement("br"); | |
551 | this.form.appendChild(br); | |
552 | } | |
553 | ||
554 | if (this.options.okButton) { | |
555 | okButton = document.createElement("input"); | |
556 | okButton.type = "submit"; | |
557 | okButton.value = this.options.okText; | |
558 | okButton.className = 'editor_ok_button'; | |
559 | this.form.appendChild(okButton); | |
560 | } | |
561 | ||
562 | if (this.options.cancelLink) { | |
563 | cancelLink = document.createElement("a"); | |
564 | cancelLink.href = "#"; | |
565 | cancelLink.appendChild(document.createTextNode(this.options.cancelText)); | |
566 | cancelLink.onclick = this.onclickCancel.bind(this); | |
567 | cancelLink.className = 'editor_cancel'; | |
568 | this.form.appendChild(cancelLink); | |
569 | } | |
570 | }, | |
571 | hasHTMLLineBreaks: function(string) { | |
572 | if (!this.options.handleLineBreaks) return false; | |
573 | return string.match(/<br/i) || string.match(/<p>/i); | |
574 | }, | |
575 | convertHTMLLineBreaks: function(string) { | |
576 | return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, ""); | |
577 | }, | |
578 | createEditField: function() { | |
579 | var text; | |
580 | if(this.options.loadTextURL) { | |
581 | text = this.options.loadingText; | |
582 | } else { | |
583 | text = this.getText(); | |
584 | } | |
585 | ||
586 | var obj = this; | |
587 | ||
588 | if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) { | |
589 | this.options.textarea = false; | |
590 | var textField = document.createElement("input"); | |
591 | textField.obj = this; | |
592 | textField.type = "text"; | |
593 | textField.name = "value"; | |
594 | textField.value = text; | |
595 | textField.style.backgroundColor = this.options.highlightcolor; | |
596 | textField.className = 'editor_field'; | |
597 | var size = this.options.size || this.options.cols || 0; | |
598 | if (size != 0) textField.size = size; | |
599 | if (this.options.submitOnBlur) | |
600 | textField.onblur = this.onSubmit.bind(this); | |
601 | this.editField = textField; | |
602 | } else { | |
603 | this.options.textarea = true; | |
604 | var textArea = document.createElement("textarea"); | |
605 | textArea.obj = this; | |
606 | textArea.name = "value"; | |
607 | textArea.value = this.convertHTMLLineBreaks(text); | |
608 | textArea.rows = this.options.rows; | |
609 | textArea.cols = this.options.cols || 40; | |
610 | textArea.className = 'editor_field'; | |
611 | if (this.options.submitOnBlur) | |
612 | textArea.onblur = this.onSubmit.bind(this); | |
613 | this.editField = textArea; | |
614 | } | |
615 | ||
616 | if(this.options.loadTextURL) { | |
617 | this.loadExternalText(); | |
618 | } | |
619 | this.form.appendChild(this.editField); | |
620 | }, | |
621 | getText: function() { | |
622 | return this.element.innerHTML; | |
623 | }, | |
624 | loadExternalText: function() { | |
625 | Element.addClassName(this.form, this.options.loadingClassName); | |
626 | this.editField.disabled = true; | |
627 | new Ajax.Request( | |
628 | this.options.loadTextURL, | |
629 | Object.extend({ | |
630 | asynchronous: true, | |
631 | onComplete: this.onLoadedExternalText.bind(this) | |
632 | }, this.options.ajaxOptions) | |
633 | ); | |
634 | }, | |
635 | onLoadedExternalText: function(transport) { | |
636 | Element.removeClassName(this.form, this.options.loadingClassName); | |
637 | this.editField.disabled = false; | |
638 | this.editField.value = transport.responseText.stripTags(); | |
639 | }, | |
640 | onclickCancel: function() { | |
641 | this.onComplete(); | |
642 | this.leaveEditMode(); | |
643 | return false; | |
644 | }, | |
645 | onFailure: function(transport) { | |
646 | this.options.onFailure(transport); | |
647 | if (this.oldInnerHTML) { | |
648 | this.element.innerHTML = this.oldInnerHTML; | |
649 | this.oldInnerHTML = null; | |
650 | } | |
651 | return false; | |
652 | }, | |
653 | onSubmit: function() { | |
654 | // onLoading resets these so we need to save them away for the Ajax call | |
655 | var form = this.form; | |
656 | var value = this.editField.value; | |
657 | ||
658 | // do this first, sometimes the ajax call returns before we get a chance to switch on Saving... | |
659 | // which means this will actually switch on Saving... *after* we've left edit mode causing Saving... | |
660 | // to be displayed indefinitely | |
661 | this.onLoading(); | |
662 | ||
663 | if (this.options.evalScripts) { | |
664 | new Ajax.Request( | |
665 | this.url, Object.extend({ | |
666 | parameters: this.options.callback(form, value), | |
667 | onComplete: this.onComplete.bind(this), | |
668 | onFailure: this.onFailure.bind(this), | |
669 | asynchronous:true, | |
670 | evalScripts:true | |
671 | }, this.options.ajaxOptions)); | |
672 | } else { | |
673 | new Ajax.Updater( | |
674 | { success: this.element, | |
675 | // don't update on failure (this could be an option) | |
676 | failure: null }, | |
677 | this.url, Object.extend({ | |
678 | parameters: this.options.callback(form, value), | |
679 | onComplete: this.onComplete.bind(this), | |
680 | onFailure: this.onFailure.bind(this) | |
681 | }, this.options.ajaxOptions)); | |
682 | } | |
683 | // stop the event to avoid a page refresh in Safari | |
684 | if (arguments.length > 1) { | |
685 | Event.stop(arguments[0]); | |
686 | } | |
687 | return false; | |
688 | }, | |
689 | onLoading: function() { | |
690 | this.saving = true; | |
691 | this.removeForm(); | |
692 | this.leaveHover(); | |
693 | this.showSaving(); | |
694 | }, | |
695 | showSaving: function() { | |
696 | this.oldInnerHTML = this.element.innerHTML; | |
697 | this.element.innerHTML = this.options.savingText; | |
698 | Element.addClassName(this.element, this.options.savingClassName); | |
699 | this.element.style.backgroundColor = this.originalBackground; | |
700 | Element.show(this.element); | |
701 | }, | |
702 | removeForm: function() { | |
703 | if(this.form) { | |
704 | if (this.form.parentNode) Element.remove(this.form); | |
705 | this.form = null; | |
706 | } | |
707 | }, | |
708 | enterHover: function() { | |
709 | if (this.saving) return; | |
710 | this.element.style.backgroundColor = this.options.highlightcolor; | |
711 | if (this.effect) { | |
712 | this.effect.cancel(); | |
713 | } | |
714 | Element.addClassName(this.element, this.options.hoverClassName) | |
715 | }, | |
716 | leaveHover: function() { | |
717 | if (this.options.backgroundColor) { | |
718 | this.element.style.backgroundColor = this.oldBackground; | |
719 | } | |
720 | Element.removeClassName(this.element, this.options.hoverClassName) | |
721 | if (this.saving) return; | |
722 | this.effect = new Effect.Highlight(this.element, { | |
723 | startcolor: this.options.highlightcolor, | |
724 | endcolor: this.options.highlightendcolor, | |
725 | restorecolor: this.originalBackground | |
726 | }); | |
727 | }, | |
728 | leaveEditMode: function() { | |
729 | Element.removeClassName(this.element, this.options.savingClassName); | |
730 | this.removeForm(); | |
731 | this.leaveHover(); | |
732 | this.element.style.backgroundColor = this.originalBackground; | |
733 | Element.show(this.element); | |
734 | if (this.options.externalControl) { | |
735 | Element.show(this.options.externalControl); | |
736 | } | |
737 | this.editing = false; | |
738 | this.saving = false; | |
739 | this.oldInnerHTML = null; | |
740 | this.onLeaveEditMode(); | |
741 | }, | |
742 | onComplete: function(transport) { | |
743 | this.leaveEditMode(); | |
744 | this.options.onComplete.bind(this)(transport, this.element); | |
745 | }, | |
746 | onEnterEditMode: function() {}, | |
747 | onLeaveEditMode: function() {}, | |
748 | dispose: function() { | |
749 | if (this.oldInnerHTML) { | |
750 | this.element.innerHTML = this.oldInnerHTML; | |
751 | } | |
752 | this.leaveEditMode(); | |
753 | Event.stopObserving(this.element, 'click', this.onclickListener); | |
754 | Event.stopObserving(this.element, 'mouseover', this.mouseoverListener); | |
755 | Event.stopObserving(this.element, 'mouseout', this.mouseoutListener); | |
756 | if (this.options.externalControl) { | |
757 | Event.stopObserving(this.options.externalControl, 'click', this.onclickListener); | |
758 | Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener); | |
759 | Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener); | |
760 | } | |
761 | } | |
762 | }; | |
763 | ||
764 | Ajax.InPlaceCollectionEditor = Class.create(); | |
765 | Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype); | |
766 | Object.extend(Ajax.InPlaceCollectionEditor.prototype, { | |
767 | createEditField: function() { | |
768 | if (!this.cached_selectTag) { | |
769 | var selectTag = document.createElement("select"); | |
770 | var collection = this.options.collection || []; | |
771 | var optionTag; | |
772 | collection.each(function(e,i) { | |
773 | optionTag = document.createElement("option"); | |
774 | optionTag.value = (e instanceof Array) ? e[0] : e; | |
775 | if(this.options.value==optionTag.value) optionTag.selected = true; | |
776 | optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e)); | |
777 | selectTag.appendChild(optionTag); | |
778 | }.bind(this)); | |
779 | this.cached_selectTag = selectTag; | |
780 | } | |
781 | ||
782 | this.editField = this.cached_selectTag; | |
783 | if(this.options.loadTextURL) this.loadExternalText(); | |
784 | this.form.appendChild(this.editField); | |
785 | this.options.callback = function(form, value) { | |
786 | return "value=" + encodeURIComponent(value); | |
787 | } | |
788 | } | |
789 | }); | |
790 | ||
791 | // Delayed observer, like Form.Element.Observer, | |
792 | // but waits for delay after last key input | |
793 | // Ideal for live-search fields | |
794 | ||
795 | Form.Element.DelayedObserver = Class.create(); | |
796 | Form.Element.DelayedObserver.prototype = { | |
797 | initialize: function(element, delay, callback) { | |
798 | this.delay = delay || 0.5; | |
799 | this.element = $(element); | |
800 | this.callback = callback; | |
801 | this.timer = null; | |
802 | this.lastValue = $F(this.element); | |
803 | Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); | |
804 | }, | |
805 | delayedListener: function(event) { | |
806 | if(this.lastValue == $F(this.element)) return; | |
807 | if(this.timer) clearTimeout(this.timer); | |
808 | this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); | |
809 | this.lastValue = $F(this.element); | |
810 | }, | |
811 | onTimerEvent: function() { | |
812 | this.timer = null; | |
813 | this.callback(this.element, $F(this.element)); | |
814 | } | |
815 | }; |
rool/rails/typo/trunk/public/javascripts/cookies.js:
prev. | current | |
if (end == -1) { | ||
end = dc.length; | ||
} | ||
43 | | |
43 | return unescape(decodeURI(dc.substring(begin + prefix.length, end))).split("+").join(" "); | |
} | ||
/** | ||
... | ... | |
"; expires=Thu, 01-Jan-70 00:00:01 GMT"; | ||
} | ||
} | ||
61 | ||
62 | | |
63 | | |
64 | | |
65 | | |
66 | | |
67 | | |
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
73 | ||
74 | | |
75 | | |
76 | | |
77 | | |
78 | | |
79 | ||
80 | ||
81 | ||
82 | | |
83 | | |
84 | | |
85 | | |
86 | | |
87 | | |
88 | | |
89 | ||
90 | | |
91 | | |
92 | | |
93 | | |
94 | | |
95 | | |
96 | | |
97 | | |
98 | | |
99 | | |
100 | | |
101 | | |
102 | | |
103 | | |
104 | ||
105 | ||
106 | ||
107 | | |
108 | | |
109 | | |
110 | | |
111 | | |
112 | | |
113 | ||
114 | | |
115 | | |
116 | | |
117 | | |
118 | | |
119 | | |
120 |
rool/rails/typo/trunk/public/javascripts/dragdrop.js:
prev. | current | |
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) | ||
// | ||
3 | ||
4 | ||
5 | ||
6 | ||
7 | ||
8 | ||
9 | ||
10 | ||
11 | ||
12 | ||
13 | ||
14 | ||
15 | ||
16 | ||
17 | ||
18 | ||
19 | ||
20 | ||
21 | ||
22 | ||
3 | // See scriptaculous.js for full license. | |
24 | ||
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
30 | | |
31 | | |
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | ||
38 | | |
39 | | |
40 | | |
41 | | |
42 | | |
43 | ||
44 | | |
45 | | |
46 | | |
47 | | |
48 | | |
49 | | |
50 | | |
51 | | |
52 | | |
53 | ||
54 | | |
55 | | |
56 | | |
57 | | |
58 | | |
59 | | |
60 | | |
61 | ||
62 | | |
63 | | |
64 | | |
65 | | |
66 | | |
67 | | |
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
73 | | |
74 | | |
75 | | |
76 | | |
77 | | |
78 | | |
79 | | |
80 | | |
81 | | |
82 | | |
83 | | |
84 | | |
85 | | |
86 | | |
87 | | |
88 | | |
89 | | |
90 | | |
91 | | |
92 | | |
93 | | |
94 | | |
95 | | |
96 | | |
97 | | |
98 | | |
99 | | |
100 | | |
101 | | |
102 | | |
103 | | |
104 | | |
105 | | |
106 | | |
107 | | |
108 | ||
109 | ||
/*--------------------------------------------------------------------------*/ | ||
var Droppables = { | ||
113 | | |
114 | | |
8 | drops: [], | |
9 | ||
remove: function(element) { | ||
116 | | |
117 | | |
118 | | |
11 | this.drops = this.drops.reject(function(d) { return d.element==$(element) }); | |
}, | ||
120 | | |
13 | ||
add: function(element) { | ||
122 | | |
15 | element = $(element); | |
var options = Object.extend({ | ||
greedy: true, | ||
hoverclass: null | ||
}, arguments[1] || {}); | ||
127 | | |
20 | ||
// cache containers | ||
if(options.containment) { | ||
130 | | |
23 | options._containers = []; | |
var containment = options.containment; | ||
if((typeof containment == 'object') && | ||
(containment.constructor == Array)) { | ||
134 | | |
135 | | |
27 | containment.each( function(c) { options._containers.push($(c)) }); | |
} else { | ||
options._containers.push($(containment)); | ||
} | ||
139 | | |
140 | | |
} | ||
33 | if(options.accept) options.accept = [options.accept].flatten(); | |
34 | ||
Element.makePositioned(element); // fix IE | ||
144 | | |
options.element = element; | ||
146 | | |
147 | | |
148 | | |
37 | ||
this.drops.push(options); | ||
}, | ||
151 | | |
152 | | |
153 | | |
40 | ||
41 | isContained: function(element, drop) { | |
var parentNode = element.parentNode; | ||
155 | | |
156 | | |
157 | | |
43 | return drop._containers.detect(function(c) { return parentNode == c }); | |
}, | ||
159 | | |
160 | | |
45 | ||
46 | isAffected: function(point, element, drop) { | |
return ( | ||
(drop.element!=element) && | ||
((!drop._containers) || | ||
164 | | |
50 | this.isContained(element, drop)) && | |
((!drop.accept) || | ||
166 | | |
167 | | |
52 | (Element.classNames(element).detect( | |
53 | function(v) { return drop.accept.include(v) } ) )) && | |
54 | Position.within(drop.element, point[0], point[1]) ); | |
}, | ||
169 | | |
56 | ||
deactivate: function(drop) { | ||
171 | | |
58 | if(drop.hoverclass) | |
59 | Element.removeClassName(drop.element, drop.hoverclass); | |
this.last_active = null; | ||
}, | ||
174 | | |
62 | ||
activate: function(drop) { | ||
176 | | |
177 | | |
178 | | |
179 | | |
180 | | |
64 | if(drop.hoverclass) | |
65 | Element.addClassName(drop.element, drop.hoverclass); | |
66 | this.last_active = drop; | |
}, | ||
182 | | |
183 | | |
184 | | |
185 | | |
186 | | |
187 | | |
68 | ||
69 | show: function(point, element) { | |
70 | if(!this.drops.length) return; | |
189 | | |
190 | | |
191 | | |
72 | if(this.last_active) this.deactivate(this.last_active); | |
73 | this.drops.each( function(drop) { | |
74 | if(Droppables.isAffected(point, element, drop)) { | |
if(drop.onHover) | ||
drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); | ||
if(drop.greedy) { | ||
195 | | |
196 | | |
78 | Droppables.activate(drop); | |
79 | throw $break; | |
} | ||
} | ||
199 | | |
82 | }); | |
}, | ||
201 | | |
84 | ||
fire: function(event, element) { | ||
if(!this.last_active) return; | ||
Position.prepare(); | ||
205 | | |
206 | | |
88 | ||
89 | if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) | |
if (this.last_active.onDrop) | ||
208 | | |
209 | | |
91 | this.last_active.onDrop(element, this.last_active.element, event); | |
}, | ||
211 | | |
93 | ||
reset: function() { | ||
if(this.last_active) | ||
this.deactivate(this.last_active); | ||
} | ||
} | ||
218 | ||
219 | | |
100 | var Draggables = { | |
101 | drags: [], | |
102 | observers: [], | |
103 | ||
104 | register: function(draggable) { | |
105 | if(this.drags.length == 0) { | |
106 | this.eventMouseUp = this.endDrag.bindAsEventListener(this); | |
107 | this.eventMouseMove = this.updateDrag.bindAsEventListener(this); | |
108 | this.eventKeypress = this.keyPress.bindAsEventListener(this); | |
109 | ||
110 | Event.observe(document, "mouseup", this.eventMouseUp); | |
111 | Event.observe(document, "mousemove", this.eventMouseMove); | |
112 | Event.observe(document, "keypress", this.eventKeypress); | |
113 | } | |
114 | this.drags.push(draggable); | |
115 | }, | |
116 | ||
117 | unregister: function(draggable) { | |
118 | this.drags = this.drags.reject(function(d) { return d==draggable }); | |
119 | if(this.drags.length == 0) { | |
120 | Event.stopObserving(document, "mouseup", this.eventMouseUp); | |
121 | Event.stopObserving(document, "mousemove", this.eventMouseMove); | |
122 | Event.stopObserving(document, "keypress", this.eventKeypress); | |
123 | } | |
124 | }, | |
125 | ||
126 | activate: function(draggable) { | |
127 | window.focus(); // allows keypress events if window isn't currently focused, fails for Safari | |
128 | this.activeDraggable = draggable; | |
129 | }, | |
130 | ||
131 | deactivate: function() { | |
132 | this.activeDraggable = null; | |
133 | }, | |
134 | ||
135 | updateDrag: function(event) { | |
136 | if(!this.activeDraggable) return; | |
137 | var pointer = [Event.pointerX(event), Event.pointerY(event)]; | |
138 | // Mozilla-based browsers fire successive mousemove events with | |
139 | // the same coordinates, prevent needless redrawing (moz bug?) | |
140 | if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; | |
141 | this._lastPointer = pointer; | |
142 | this.activeDraggable.updateDrag(event, pointer); | |
143 | }, | |
144 | ||
145 | endDrag: function(event) { | |
146 | if(!this.activeDraggable) return; | |
147 | this._lastPointer = null; | |
148 | this.activeDraggable.endDrag(event); | |
149 | this.activeDraggable = null; | |
150 | }, | |
151 | ||
152 | keyPress: function(event) { | |
153 | if(this.activeDraggable) | |
154 | this.activeDraggable.keyPress(event); | |
155 | }, | |
156 | ||
addObserver: function(observer) { | ||
221 | | |
158 | this.observers.push(observer); | |
159 | this._cacheObserverCallbacks(); | |
}, | ||
223 | | |
224 | | |
225 | | |
226 | | |
161 | ||
162 | removeObserver: function(element) { // element instead of observer fixes mem leaks | |
163 | this.observers = this.observers.reject( function(o) { return o.element==element }); | |
164 | this._cacheObserverCallbacks(); | |
}, | ||
228 | | |
229 | | |
230 | | |
166 | ||
167 | notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' | |
168 | if(this[eventName+'Count'] > 0) | |
169 | this.observers.each( function(o) { | |
170 | if(o[eventName]) o[eventName](eventName, draggable, event); | |
171 | }); | |
172 | }, | |
173 | ||
174 | _cacheObserverCallbacks: function() { | |
175 | ['onStart','onEnd','onDrag'].each( function(eventName) { | |
176 | Draggables[eventName+'Count'] = Draggables.observers.select( | |
177 | function(o) { return o[eventName]; } | |
178 | ).length; | |
179 | }); | |
} | ||
} | ||
/*--------------------------------------------------------------------------*/ | ||
236 | ||
185 | var Draggable = Class.create(); | |
Draggable.prototype = { | ||
initialize: function(element) { | ||
var options = Object.extend({ | ||
... | ... | |
new Effect.Opacity(element, {duration:0.2, from:1.0, to:0.7}); | ||
}, | ||
reverteffect: function(element, top_offset, left_offset) { | ||
245 | | |
194 | var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; | |
195 | element._revert = new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur}); | |
}, | ||
endeffect: function(element) { | ||
248 | | |
198 | new Effect.Opacity(element, {duration:0.2, from:0.7, to:1.0}); | |
}, | ||
zindex: 1000, | ||
251 | | |
201 | revert: false, | |
202 | scroll: false, | |
203 | scrollSensitivity: 20, | |
204 | scrollSpeed: 15, | |
205 | snap: false // false, or xy or [x,y] or function(x,y){ return [x,y] } | |
}, arguments[1] || {}); | ||
207 | ||
208 | this.element = $(element); | |
254 | | |
255 | | |
210 | if(options.handle && (typeof options.handle == 'string')) | |
211 | this.handle = Element.childrenWithClassName(this.element, options.handle, true)[0]; | |
212 | if(!this.handle) this.handle = $(options.handle); | |
213 | if(!this.handle) this.handle = this.element; | |
257 | | |
215 | if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) | |
216 | options.scroll = $(options.scroll); | |
217 | ||
218 | Element.makePositioned(this.element); // fix IE | |
219 | ||
220 | this.delta = this.currentDelta(); | |
221 | this.options = options; | |
222 | this.dragging = false; | |
223 | ||
224 | this.eventMouseDown = this.initDrag.bindAsEventListener(this); | |
225 | Event.observe(this.handle, "mousedown", this.eventMouseDown); | |
259 | | |
260 | | |
261 | | |
262 | | |
263 | | |
264 | | |
265 | | |
266 | | |
267 | | |
268 | | |
269 | | |
270 | | |
271 | | |
272 | | |
273 | | |
274 | | |
275 | | |
276 | | |
277 | | |
278 | | |
279 | | |
280 | | |
227 | Draggables.register(this); | |
}, | ||
229 | ||
destroy: function() { | ||
Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); | ||
284 | | |
285 | | |
286 | | |
232 | Draggables.unregister(this); | |
}, | ||
288 | | |
289 | | |
234 | ||
235 | currentDelta: function() { | |
236 | return([ | |
237 | parseInt(Element.getStyle(this.element,'left') || '0'), | |
238 | parseInt(Element.getStyle(this.element,'top') || '0')]); | |
}, | ||
291 | | |
292 | | |
293 | | |
294 | | |
295 | | |
296 | | |
240 | ||
241 | initDrag: function(event) { | |
242 | if(Event.isLeftClick(event)) { | |
243 | // abort on form elements, fixes a Firefox issue | |
244 | var src = Event.element(event); | |
245 | if(src.tagName && ( | |
246 | src.tagName=='INPUT' || | |
247 | src.tagName=='SELECT' || | |
248 | src.tagName=='OPTION' || | |
249 | src.tagName=='BUTTON' || | |
250 | src.tagName=='TEXTAREA')) return; | |
251 | ||
252 | if(this.element._revert) { | |
253 | this.element._revert.cancel(); | |
254 | this.element._revert = null; | |
255 | } | |
298 | | |
299 | | |
300 | | |
301 | | |
302 | | |
257 | var pointer = [Event.pointerX(event), Event.pointerY(event)]; | |
258 | var pos = Position.cumulativeOffset(this.element); | |
259 | this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); | |
261 | Draggables.activate(this); | |
Event.stop(event); | ||
} | ||
}, | ||
265 | ||
266 | startDrag: function(event) { | |
267 | this.dragging = true; | |
268 | ||
269 | if(this.options.zindex) { | |
270 | this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); | |
271 | this.element.style.zIndex = this.options.zindex; | |
272 | } | |
273 | ||
274 | if(this.options.ghosting) { | |
275 | this._clone = this.element.cloneNode(true); | |
276 | Position.absolutize(this.element); | |
277 | this.element.parentNode.insertBefore(this._clone, this.element); | |
278 | } | |
279 | ||
280 | if(this.options.scroll) { | |
281 | if (this.options.scroll == window) { | |
282 | var where = this._getWindowScroll(this.options.scroll); | |
283 | this.originalScrollLeft = where.left; | |
284 | this.originalScrollTop = where.top; | |
285 | } else { | |
286 | this.originalScrollLeft = this.options.scroll.scrollLeft; | |
287 | this.originalScrollTop = this.options.scroll.scrollTop; | |
288 | } | |
289 | } | |
290 | ||
291 | Draggables.notify('onStart', this, event); | |
292 | if(this.options.starteffect) this.options.starteffect(this.element); | |
293 | }, | |
294 | ||
295 | updateDrag: function(event, pointer) { | |
296 | if(!this.dragging) this.startDrag(event); | |
297 | Position.prepare(); | |
298 | Droppables.show(pointer, this.element); | |
299 | Draggables.notify('onDrag', this, event); | |
300 | this.draw(pointer); | |
301 | if(this.options.change) this.options.change(this); | |
302 | ||
303 | if(this.options.scroll) { | |
304 | this.stopScrolling(); | |
305 | ||
306 | var p; | |
307 | if (this.options.scroll == window) { | |
308 | with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } | |
309 | } else { | |
310 | p = Position.page(this.options.scroll); | |
311 | p[0] += this.options.scroll.scrollLeft; | |
312 | p[1] += this.options.scroll.scrollTop; | |
313 | p.push(p[0]+this.options.scroll.offsetWidth); | |
314 | p.push(p[1]+this.options.scroll.offsetHeight); | |
315 | } | |
316 | var speed = [0,0]; | |
317 | if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); | |
318 | if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); | |
319 | if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); | |
320 | if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); | |
321 | this.startScrolling(speed); | |
322 | } | |
323 | ||
324 | // fix AppleWebKit rendering | |
325 | if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); | |
326 | ||
327 | Event.stop(event); | |
328 | }, | |
329 | ||
finishDrag: function(event, success) { | ||
308 | | |
this.dragging = false; | ||
310 | | |
332 | ||
333 | if(this.options.ghosting) { | |
334 | Position.relativize(this.element); | |
335 | Element.remove(this._clone); | |
336 | this._clone = null; | |
337 | } | |
338 | ||
if(success) Droppables.fire(event, this.element); | ||
312 | | |
313 | | |
340 | Draggables.notify('onEnd', this, event); | |
341 | ||
var revert = this.options.revert; | ||
if(revert && typeof revert == 'function') revert = revert(this.element); | ||
316 | | |
344 | ||
345 | var d = this.currentDelta(); | |
if(revert && this.options.reverteffect) { | ||
this.options.reverteffect(this.element, | ||
319 | | |
320 | | |
348 | d[1]-this.delta[1], d[0]-this.delta[0]); | |
} else { | ||
322 | | |
323 | | |
350 | this.delta = d; | |
} | ||
325 | | |
326 | | |
327 | | |
352 | ||
353 | if(this.options.zindex) | |
354 | this.element.style.zIndex = this.originalZ; | |
355 | ||
if(this.options.endeffect) | ||
this.options.endeffect(this.element); | ||
330 | | |
358 | ||
359 | Draggables.deactivate(this); | |
Droppables.reset(); | ||
}, | ||
362 | ||
keyPress: function(event) { | ||
334 | | |
335 | | |
336 | | |
337 | | |
338 | | |
339 | | |
364 | if(event.keyCode!=Event.KEY_ESC) return; | |
365 | this.finishDrag(event, false); | |
366 | Event.stop(event); | |
}, | ||
368 | ||
endDrag: function(event) { | ||
342 | | |
343 | | |
344 | | |
370 | if(!this.dragging) return; | |
371 | this.stopScrolling(); | |
372 | this.finishDrag(event, true); | |
373 | Event.stop(event); | |
374 | }, | |
375 | ||
376 | draw: function(point) { | |
377 | var pos = Position.cumulativeOffset(this.element); | |
378 | var d = this.currentDelta(); | |
379 | pos[0] -= d[0]; pos[1] -= d[1]; | |
380 | ||
381 | if(this.options.scroll && (this.options.scroll != window)) { | |
382 | pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; | |
383 | pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; | |
} | ||
346 | | |
347 | | |
348 | | |
349 | | |
385 | ||
386 | var p = [0,1].map(function(i){ | |
387 | return (point[i]-pos[i]-this.offset[i]) | |
388 | }.bind(this)); | |
389 | ||
390 | if(this.options.snap) { | |
391 | if(typeof this.options.snap == 'function') { | |
392 | p = this.options.snap(p[0],p[1]); | |
393 | } else { | |
394 | if(this.options.snap instanceof Array) { | |
395 | p = p.map( function(v, i) { | |
396 | return Math.round(v/this.options.snap[i])*this.options.snap[i] }.bind(this)) | |
397 | } else { | |
398 | p = p.map( function(v) { | |
399 | return Math.round(v/this.options.snap)*this.options.snap }.bind(this)) | |
400 | } | |
401 | }} | |
402 | ||
var style = this.element.style; | ||
351 | | |
352 | | |
if((!this.options.constraint) || (this.options.constraint=='horizontal')) | ||
354 | | |
405 | style.left = p[0] + "px"; | |
if((!this.options.constraint) || (this.options.constraint=='vertical')) | ||
356 | | |
407 | style.top = p[1] + "px"; | |
if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering | ||
}, | ||
359 | | |
360 | | |
361 | | |
362 | | |
363 | | |
364 | | |
365 | | |
366 | | |
367 | | |
410 | ||
411 | stopScrolling: function() { | |
412 | if(this.scrollInterval) { | |
413 | clearInterval(this.scrollInterval); | |
414 | this.scrollInterval = null; | |
415 | } | |
416 | }, | |
417 | ||
418 | startScrolling: function(speed) { | |
419 | this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; | |
420 | this.lastScrolled = new Date(); | |
421 | this.scrollInterval = setInterval(this.scroll.bind(this), 10); | |
422 | }, | |
423 | ||
424 | scroll: function() { | |
425 | var current = new Date(); | |
426 | var delta = current - this.lastScrolled; | |
427 | this.lastScrolled = current; | |
428 | if(this.options.scroll == window) { | |
429 | with (this._getWindowScroll(this.options.scroll)) { | |
430 | if (this.scrollSpeed[0] || this.scrollSpeed[1]) { | |
431 | var d = delta / 1000; | |
432 | this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); | |
433 | } | |
} | ||
369 | | |
370 | | |
371 | | |
372 | | |
373 | | |
374 | | |
375 | | |
376 | | |
377 | | |
378 | | |
435 | } else { | |
436 | this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; | |
437 | this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; | |
438 | } | |
439 | ||
440 | Position.prepare(); | |
441 | Droppables.show(Draggables._lastPointer, this.element); | |
442 | Draggables.notify('onDrag', this); | |
443 | this.draw(Draggables._lastPointer); | |
444 | ||
445 | if(this.options.change) this.options.change(this); | |
446 | }, | |
447 | ||
448 | _getWindowScroll: function(w) { | |
449 | var T, L, W, H; | |
450 | with (w.document) { | |
451 | if (w.document.documentElement && documentElement.scrollTop) { | |
452 | T = documentElement.scrollTop; | |
453 | L = documentElement.scrollLeft; | |
454 | } else if (w.document.body) { | |
455 | T = body.scrollTop; | |
456 | L = body.scrollLeft; | |
457 | } | |
458 | if (w.innerWidth) { | |
459 | W = w.innerWidth; | |
460 | H = w.innerHeight; | |
461 | } else if (w.document.documentElement && documentElement.clientWidth) { | |
462 | W = documentElement.clientWidth; | |
463 | H = documentElement.clientHeight; | |
464 | } else { | |
465 | W = body.offsetWidth; | |
466 | H = body.offsetHeight | |
467 | } | |
468 | } | |
469 | return { top: T, left: L, width: W, height: H }; | |
} | ||
} | ||
/*--------------------------------------------------------------------------*/ | ||
384 | ||
475 | var SortableObserver = Class.create(); | |
SortableObserver.prototype = { | ||
initialize: function(element, observer) { | ||
this.element = $(element); | ||
this.observer = observer; | ||
this.lastValue = Sortable.serialize(this.element); | ||
}, | ||
482 | ||
onStart: function() { | ||
this.lastValue = Sortable.serialize(this.element); | ||
}, | ||
394 | | |
486 | ||
487 | onEnd: function() { | |
488 | Sortable.unmark(); | |
if(this.lastValue != Sortable.serialize(this.element)) | ||
this.observer(this.element) | ||
} | ||
} | ||
400 | ||
494 | var Sortable = { | |
sortables: new Array(), | ||
496 | ||
options: function(element){ | ||
403 | | |
404 | | |
405 | | |
406 | | |
407 | | |
498 | element = $(element); | |
499 | return this.sortables.detect(function(s) { return s.element == element }); | |
}, | ||
501 | ||
destroy: function(element){ | ||
410 | | |
411 | | |
412 | | |
413 | | |
414 | | |
415 | | |
416 | | |
417 | | |
418 | | |
419 | | |
420 | | |
421 | | |
503 | element = $(element); | |
504 | this.sortables.findAll(function(s) { return s.element == element }).each(function(s){ | |
505 | Draggables.removeObserver(s.element); | |
506 | s.droppables.each(function(d){ Droppables.remove(d) }); | |
507 | s.draggables.invoke('destroy'); | |
508 | }); | |
509 | this.sortables = this.sortables.reject(function(s) { return s.element == element }); | |
}, | ||
511 | ||
create: function(element) { | ||
424 | | |
513 | element = $(element); | |
var options = Object.extend({ | ||
element: element, | ||
tag: 'li', // assumes li children, override with tag: 'tagname' | ||
517 | dropOnEmpty: false, | |
518 | tree: false, // fixme: unimplemented | |
overlap: 'vertical', // one of 'vertical', 'horizontal' | ||
constraint: 'vertical', // one of 'vertical', 'horizontal', false | ||
containment: element, // also takes array of elements (or id's); or false | ||
handle: false, // or a CSS class | ||
only: false, | ||
hoverclass: null, | ||
434 | | |
435 | | |
525 | ghosting: false, | |
526 | scroll: false, | |
527 | scrollSensitivity: 20, | |
528 | scrollSpeed: 15, | |
529 | format: /^[^_]*_(.*)$/, | |
530 | onChange: Prototype.emptyFunction, | |
531 | onUpdate: Prototype.emptyFunction | |
}, arguments[1] || {}); | ||
437 | | |
533 | ||
// clear any old sortable with same element | ||
this.destroy(element); | ||
440 | | |
536 | ||
// build options for the draggables | ||
var options_for_draggable = { | ||
revert: true, | ||
540 | scroll: options.scroll, | |
541 | scrollSpeed: options.scrollSpeed, | |
542 | scrollSensitivity: options.scrollSensitivity, | |
543 | ghosting: options.ghosting, | |
constraint: options.constraint, | ||
445 | | |
545 | handle: options.handle }; | |
546 | ||
if(options.starteffect) | ||
options_for_draggable.starteffect = options.starteffect; | ||
549 | ||
if(options.reverteffect) | ||
options_for_draggable.reverteffect = options.reverteffect; | ||
552 | else | |
553 | if(options.ghosting) options_for_draggable.reverteffect = function(element) { | |
554 | element.style.top = 0; | |
555 | element.style.left = 0; | |
556 | }; | |
557 | ||
if(options.endeffect) | ||
options_for_draggable.endeffect = options.endeffect; | ||
560 | ||
if(options.zindex) | ||
options_for_draggable.zindex = options.zindex; | ||
454 | | |
563 | ||
// build options for the droppables | ||
var options_for_droppable = { | ||
overlap: options.overlap, | ||
containment: options.containment, | ||
hoverclass: options.hoverclass, | ||
460 | | |
461 | | |
462 | | |
463 | | |
464 | | |
465 | | |
466 | | |
467 | | |
468 | | |
469 | | |
470 | | |
471 | | |
472 | | |
473 | | |
474 | | |
475 | | |
476 | | |
477 | | |
478 | | |
479 | | |
480 | | |
481 | | |
482 | | |
483 | | |
569 | onHover: Sortable.onHover, | |
570 | greedy: !options.dropOnEmpty | |
} | ||
// fix for gecko engine | ||
Element.cleanWhitespace(element); | ||
488 | | |
575 | ||
options.draggables = []; | ||
options.droppables = []; | ||
491 | | |
492 | | |
493 | | |
494 | | |
495 | | |
496 | | |
497 | | |
498 | | |
499 | | |
500 | | |
501 | | |
502 | | |
503 | | |
504 | | |
505 | | |
506 | | |
507 | | |
508 | | |
578 | ||
579 | // make it so | |
580 | ||
581 | // drop on empty handling | |
582 | if(options.dropOnEmpty) { | |
583 | Droppables.add(element, | |
584 | {containment: options.containment, onHover: Sortable.onEmptyHover, greedy: false}); | |
585 | options.droppables.push(element); | |
586 | } | |
587 | ||
588 | (this.findElements(element, options) || []).each( function(e) { | |
589 | // handles are per-draggable | |
590 | var handle = options.handle ? | |
591 | Element.childrenWithClassName(e, options.handle)[0] : e; | |
592 | options.draggables.push( | |
593 | new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); | |
594 | Droppables.add(e, options_for_droppable); | |
595 | options.droppables.push(e); | |
596 | }); | |
597 | ||
// keep reference | ||
this.sortables.push(options); | ||
511 | | |
600 | ||
// for onupdate | ||
Draggables.addObserver(new SortableObserver(element, options.onUpdate)); | ||
}, | ||
516 | | |
517 | | |
518 | | |
519 | | |
520 | | |
521 | | |
522 | | |
523 | | |
605 | ||
606 | // return all suitable-for-sortable elements in a guaranteed order | |
607 | findElements: function(element, options) { | |
608 | if(!element.hasChildNodes()) return null; | |
609 | var elements = []; | |
610 | var only = options.only ? [options.only].flatten() : null; | |
611 | $A(element.childNodes).each( function(e) { | |
612 | if(e.tagName && e.tagName.toUpperCase()==options.tag.toUpperCase() && | |
613 | (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) | |
614 | elements.push(e); | |
615 | if(options.tree) { | |
616 | var grandchildren = this.findElements(e, options); | |
617 | if(grandchildren) elements.push(grandchildren); | |
618 | } | |
619 | }); | |
620 | ||
621 | return (elements.length>0 ? elements.flatten() : null); | |
622 | }, | |
623 | ||
624 | onHover: function(element, dropon, overlap) { | |
625 | if(overlap>0.5) { | |
626 | Sortable.mark(dropon, 'before'); | |
627 | if(dropon.previousSibling != element) { | |
628 | var oldParentNode = element.parentNode; | |
629 | element.style.visibility = "hidden"; // fix gecko rendering | |
630 | dropon.parentNode.insertBefore(element, dropon); | |
631 | if(dropon.parentNode!=oldParentNode) | |
632 | Sortable.options(oldParentNode).onChange(element); | |
633 | Sortable.options(dropon.parentNode).onChange(element); | |
634 | } | |
635 | } else { | |
636 | Sortable.mark(dropon, 'after'); | |
637 | var nextElement = dropon.nextSibling || null; | |
638 | if(nextElement != element) { | |
639 | var oldParentNode = element.parentNode; | |
640 | element.style.visibility = "hidden"; // fix gecko rendering | |
641 | dropon.parentNode.insertBefore(element, nextElement); | |
642 | if(dropon.parentNode!=oldParentNode) | |
643 | Sortable.options(oldParentNode).onChange(element); | |
644 | Sortable.options(dropon.parentNode).onChange(element); | |
645 | } | |
646 | } | |
647 | }, | |
648 | ||
649 | onEmptyHover: function(element, dropon) { | |
650 | if(element.parentNode!=dropon) { | |
651 | var oldParentNode = element.parentNode; | |
652 | dropon.appendChild(element); | |
653 | Sortable.options(oldParentNode).onChange(element); | |
654 | Sortable.options(dropon).onChange(element); | |
655 | } | |
656 | }, | |
657 | ||
658 | unmark: function() { | |
659 | if(Sortable._marker) Element.hide(Sortable._marker); | |
660 | }, | |
661 | ||
662 | mark: function(dropon, position) { | |
663 | // mark on ghosting only | |
664 | var sortable = Sortable.options(dropon.parentNode); | |
665 | if(sortable && !sortable.ghosting) return; | |
666 | ||
667 | if(!Sortable._marker) { | |
668 | Sortable._marker = $('dropmarker') || document.createElement('DIV'); | |
669 | Element.hide(Sortable._marker); | |
670 | Element.addClassName(Sortable._marker, 'dropmarker'); | |
671 | Sortable._marker.style.position = 'absolute'; | |
672 | document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); | |
673 | } | |
674 | var offsets = Position.cumulativeOffset(dropon); | |
675 | Sortable._marker.style.left = offsets[0] + 'px'; | |
676 | Sortable._marker.style.top = offsets[1] + 'px'; | |
525 | | |
526 | | |
527 | | |
528 | | |
529 | | |
530 | | |
531 | | |
532 | | |
533 | | |
678 | if(position=='after') | |
679 | if(sortable.overlap == 'horizontal') | |
680 | Sortable._marker.style.left = (offsets[0]+dropon.clientWidth) + 'px'; | |
681 | else | |
682 | Sortable._marker.style.top = (offsets[1]+dropon.clientHeight) + 'px'; | |
683 | ||
684 | Element.show(Sortable._marker); | |
685 | }, | |
535 | | |
687 | sequence: function(element) { | |
688 | element = $(element); | |
689 | var options = Object.extend(this.options(element), arguments[1] || {}); | |
690 | ||
691 | return $(this.findElements(element, options) || []).map( function(item) { | |
692 | return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; | |
693 | }); | |
694 | }, | |
695 | ||
696 | setSequence: function(element, new_sequence) { | |
697 | element = $(element); | |
698 | var options = Object.extend(this.options(element), arguments[2] || {}); | |
699 | ||
700 | var nodeMap = {}; | |
701 | this.findElements(element, options).each( function(n) { | |
702 | if (n.id.match(options.format)) | |
703 | nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; | |
704 | n.parentNode.removeChild(n); | |
705 | }); | |
706 | ||
707 | new_sequence.each(function(ident) { | |
708 | var n = nodeMap[ident]; | |
709 | if (n) { | |
710 | n[1].appendChild(n[0]); | |
711 | delete nodeMap[ident]; | |
712 | } | |
713 | }); | |
714 | }, | |
715 | ||
716 | serialize: function(element) { | |
717 | element = $(element); | |
718 | var name = encodeURIComponent( | |
719 | (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); | |
720 | return Sortable.sequence(element, arguments[1]).map( function(item) { | |
721 | return name + "[]=" + encodeURIComponent(item); | |
722 | }).join('&'); | |
} | ||
537 | ||
725 | } |
rool/rails/typo/trunk/public/javascripts/effects.js:
prev. | current | |
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) | ||
2 | ||
3 | ||
4 | ||
2 | // Contributors: | |
3 | // Justin Palmer (http://encytemedia.com/) | |
4 | // Mark Pilgrim (http://diveintomark.org/) | |
5 | // Martin Bialasinki | |
// | ||
6 | ||
7 | ||
8 | ||
9 | ||
10 | ||
11 | ||
12 | ||
13 | ||
14 | ||
15 | ||
16 | ||
17 | ||
18 | ||
19 | ||
20 | ||
21 | ||
22 | ||
23 | ||
7 | // See scriptaculous.js for full license. | |
9 | // converts rgb() and #xxx to #xxxxxx format, | |
10 | // returns self (or first argument) if not convertable | |
11 | String.prototype.parseColor = function() { | |
12 | var color = '#'; | |
13 | if(this.slice(0,4) == 'rgb(') { | |
14 | var cols = this.slice(4,this.length-1).split(','); | |
15 | var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); | |
16 | } else { | |
17 | if(this.slice(0,1) == '#') { | |
18 | if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); | |
19 | if(this.length==7) color = this.toLowerCase(); | |
20 | } | |
21 | } | |
22 | return(color.length==7 ? color : (arguments[0] || this)); | |
23 | } | |
26 | ||
27 | ||
25 | /*--------------------------------------------------------------------------*/ | |
27 | Element.collectTextNodes = function(element) { | |
28 | return $A($(element).childNodes).collect( function(node) { | |
29 | return (node.nodeType==3 ? node.nodeValue : | |
30 | (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); | |
31 | }).flatten().join(''); | |
32 | } | |
33 | ||
34 | Element.collectTextNodesIgnoreClass = function(element, className) { | |
35 | return $A($(element).childNodes).collect( function(node) { | |
36 | return (node.nodeType==3 ? node.nodeValue : | |
37 | ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? | |
38 | Element.collectTextNodesIgnoreClass(node, className) : '')); | |
39 | }).flatten().join(''); | |
40 | } | |
41 | ||
42 | Element.setContentZoom = function(element, percent) { | |
43 | element = $(element); | |
44 | Element.setStyle(element, {fontSize: (percent/100) + 'em'}); | |
45 | if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); | |
46 | } | |
47 | ||
48 | Element.getOpacity = function(element){ | |
49 | var opacity; | |
50 | if (opacity = Element.getStyle(element, 'opacity')) | |
51 | return parseFloat(opacity); | |
52 | if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/)) | |
53 | if(opacity[1]) return parseFloat(opacity[1]) / 100; | |
54 | return 1.0; | |
55 | } | |
56 | ||
57 | Element.setOpacity = function(element, value){ | |
58 | element= $(element); | |
59 | if (value == 1){ | |
60 | Element.setStyle(element, { opacity: | |
61 | (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? | |
62 | 0.999999 : null }); | |
63 | if(/MSIE/.test(navigator.userAgent)) | |
64 | Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')}); | |
65 | } else { | |
66 | if(value < 0.00001) value = 0; | |
67 | Element.setStyle(element, {opacity: value}); | |
68 | if(/MSIE/.test(navigator.userAgent)) | |
69 | Element.setStyle(element, | |
70 | { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') + | |
71 | 'alpha(opacity='+value*100+')' }); | |
72 | } | |
73 | } | |
74 | ||
75 | Element.getInlineOpacity = function(element){ | |
76 | return $(element).style.opacity || ''; | |
77 | } | |
78 | ||
79 | Element.childrenWithClassName = function(element, className, findFirst) { | |
80 | return [$A($(element).getElementsByTagName('*'))[findFirst ? 'detect' : 'select']( function(c) { | |
81 | return c.className ? Element.hasClassName(c, className) : false; | |
82 | })].flatten(); | |
83 | } | |
84 | ||
85 | Element.forceRerendering = function(element) { | |
86 | try { | |
87 | element = $(element); | |
88 | var n = document.createTextNode(' '); | |
89 | element.appendChild(n); | |
90 | element.removeChild(n); | |
91 | } catch(e) { } | |
92 | }; | |
93 | ||
94 | ['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', | |
95 | 'collectTextNodes','collectTextNodesIgnoreClass','childrenWithClassName'].each( | |
96 | function(f) { Element.Methods[f] = Element[f]; } | |
97 | ); | |
98 | ||
99 | /*--------------------------------------------------------------------------*/ | |
100 | ||
101 | Array.prototype.call = function() { | |
102 | var args = arguments; | |
103 | this.each(function(f){ f.apply(this, args) }); | |
104 | } | |
105 | ||
106 | /*--------------------------------------------------------------------------*/ | |
107 | ||
108 | var Effect = { | |
109 | tagifyText: function(element) { | |
110 | var tagifyStyle = 'position:relative'; | |
111 | if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1'; | |
112 | element = $(element); | |
113 | $A(element.childNodes).each( function(child) { | |
114 | if(child.nodeType==3) { | |
115 | child.nodeValue.toArray().each( function(character) { | |
116 | element.insertBefore( | |
117 | Builder.node('span',{style: tagifyStyle}, | |
118 | character == ' ' ? String.fromCharCode(160) : character), | |
119 | child); | |
120 | }); | |
121 | Element.remove(child); | |
122 | } | |
123 | }); | |
124 | }, | |
125 | multiple: function(element, effect) { | |
126 | var elements; | |
127 | if(((typeof element == 'object') || | |
128 | (typeof element == 'function')) && | |
129 | (element.length)) | |
130 | elements = element; | |
131 | else | |
132 | elements = $(element).childNodes; | |
133 | ||
134 | var options = Object.extend({ | |
135 | speed: 0.1, | |
136 | delay: 0.0 | |
137 | }, arguments[2] || {}); | |
138 | var masterDelay = options.delay; | |
139 | ||
140 | $A(elements).each( function(element, index) { | |
141 | new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); | |
142 | }); | |
143 | }, | |
144 | PAIRS: { | |
145 | 'slide': ['SlideDown','SlideUp'], | |
146 | 'blind': ['BlindDown','BlindUp'], | |
147 | 'appear': ['Appear','Fade'] | |
148 | }, | |
149 | toggle: function(element, effect) { | |
150 | element = $(element); | |
151 | effect = (effect || 'appear').toLowerCase(); | |
152 | var options = Object.extend({ | |
153 | queue: { position:'end', scope:(element.id || 'global'), limit: 1 } | |
154 | }, arguments[2] || {}); | |
155 | Effect[element.visible() ? | |
156 | Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); | |
157 | } | |
158 | }; | |
159 | ||
160 | var Effect2 = Effect; // deprecated | |
161 | ||
/* ------------- transitions ------------- */ | ||
Effect.Transitions = {} | ||
... | ... | |
return 1-pos; | ||
} | ||
Effect.Transitions.flicker = function(pos) { | ||
43 | | |
176 | return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; | |
} | ||
Effect.Transitions.wobble = function(pos) { | ||
return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; | ||
... | ... | |
return 1; | ||
} | ||
59 | ||
192 | /* ------------- core effects ------------- */ | |
61 | ||
62 | | |
63 | | |
64 | | |
65 | ||
194 | Effect.ScopedQueue = Class.create(); | |
195 | Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { | |
196 | initialize: function() { | |
197 | this.effects = []; | |
198 | this.interval = null; | |
199 | }, | |
200 | _each: function(iterator) { | |
201 | this.effects._each(iterator); | |
202 | }, | |
203 | add: function(effect) { | |
204 | var timestamp = new Date().getTime(); | |
205 | ||
206 | var position = (typeof effect.options.queue == 'string') ? | |
207 | effect.options.queue : effect.options.queue.position; | |
208 | ||
209 | switch(position) { | |
210 | case 'front': | |
211 | // move unstarted effects after this effect | |
212 | this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { | |
213 | e.startOn += effect.finishOn; | |
214 | e.finishOn += effect.finishOn; | |
215 | }); | |
216 | break; | |
217 | case 'end': | |
218 | // start effect after last queued effect has finished | |
219 | timestamp = this.effects.pluck('finishOn').max() || timestamp; | |
220 | break; | |
221 | } | |
222 | ||
223 | effect.startOn += timestamp; | |
224 | effect.finishOn += timestamp; | |
67 | ||
68 | | |
69 | | |
70 | | |
226 | if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) | |
227 | this.effects.push(effect); | |
228 | ||
229 | if(!this.interval) | |
230 | this.interval = setInterval(this.loop.bind(this), 40); | |
231 | }, | |
232 | remove: function(effect) { | |
233 | this.effects = this.effects.reject(function(e) { return e==effect }); | |
234 | if(this.effects.length == 0) { | |
235 | clearInterval(this.interval); | |
236 | this.interval = null; | |
237 | } | |
238 | }, | |
239 | loop: function() { | |
240 | var timePos = new Date().getTime(); | |
241 | this.effects.invoke('loop', timePos); | |
242 | } | |
243 | }); | |
244 | ||
245 | Effect.Queues = { | |
246 | instances: $H(), | |
247 | get: function(queueName) { | |
248 | if(typeof queueName != 'string') return queueName; | |
249 | ||
250 | if(!this.instances[queueName]) | |
251 | this.instances[queueName] = new Effect.ScopedQueue(); | |
252 | ||
253 | return this.instances[queueName]; | |
254 | } | |
} | ||
256 | Effect.Queue = Effect.Queues.get('global'); | |
73 | ||
74 | | |
75 | | |
258 | Effect.DefaultOptions = { | |
259 | transition: Effect.Transitions.sinoidal, | |
260 | duration: 1.0, // seconds | |
261 | fps: 25.0, // max. 25fps due to Effect.Queue implementation | |
262 | sync: false, // true for combining | |
263 | from: 0.0, | |
264 | to: 1.0, | |
265 | delay: 0.0, | |
266 | queue: 'parallel' | |
} | ||
78 | ||
79 | ||
Effect.Base = function() {}; | ||
Effect.Base.prototype = { | ||
82 | | |
83 | | |
84 | | |
85 | | |
86 | | |
87 | | |
88 | | |
89 | | |
90 | | |
91 | | |
271 | position: null, | |
start: function(options) { | ||
93 | | |
273 | this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {}); | |
this.currentFrame = 0; | ||
95 | | |
275 | this.state = 'idle'; | |
276 | this.startOn = this.options.delay*1000; | |
this.finishOn = this.startOn + (this.options.duration*1000); | ||
97 | | |
98 | | |
278 | this.event('beforeStart'); | |
279 | if(!this.options.sync) | |
280 | Effect.Queues.get(typeof this.options.queue == 'string' ? | |
281 | 'global' : this.options.queue.scope).add(this); | |
}, | ||
100 | | |
101 | | |
102 | | |
103 | | |
104 | | |
105 | | |
106 | | |
283 | loop: function(timePos) { | |
284 | if(timePos >= this.startOn) { | |
285 | if(timePos >= this.finishOn) { | |
286 | this.render(1.0); | |
287 | this.cancel(); | |
288 | this.event('beforeFinish'); | |
289 | if(this.finish) this.finish(); | |
290 | this.event('afterFinish'); | |
291 | return; | |
292 | } | |
293 | var pos = (timePos - this.startOn) / (this.finishOn - this.startOn); | |
294 | var frame = Math.round(pos * this.options.fps * this.options.duration); | |
295 | if(frame > this.currentFrame) { | |
296 | this.render(pos); | |
297 | this.currentFrame = frame; | |
298 | } | |
} | ||
108 | | |
109 | | |
110 | | |
111 | | |
112 | | |
113 | | |
114 | | |
}, | ||
render: function(pos) { | ||
117 | | |
118 | | |
119 | | |
120 | | |
121 | | |
122 | | |
302 | if(this.state == 'idle') { | |
303 | this.state = 'running'; | |
304 | this.event('beforeSetup'); | |
305 | if(this.setup) this.setup(); | |
306 | this.event('afterSetup'); | |
307 | } | |
308 | if(this.state == 'running') { | |
309 | if(this.options.transition) pos = this.options.transition(pos); | |
310 | pos *= (this.options.to-this.options.from); | |
311 | pos += this.options.from; | |
312 | this.position = pos; | |
313 | this.event('beforeUpdate'); | |
314 | if(this.update) this.update(pos); | |
315 | this.event('afterUpdate'); | |
316 | } | |
}, | ||
cancel: function() { | ||
125 | | |
319 | if(!this.options.sync) | |
320 | Effect.Queues.get(typeof this.options.queue == 'string' ? | |
321 | 'global' : this.options.queue.scope).remove(this); | |
322 | this.state = 'finished'; | |
323 | }, | |
324 | event: function(eventName) { | |
325 | if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); | |
326 | if(this.options[eventName]) this.options[eventName](this); | |
327 | }, | |
328 | inspect: function() { | |
329 | return '#<Effect:' + $H(this).inspect() + ',options:' + $H(this.options).inspect() + '>'; | |
} | ||
} | ||
... | ... | |
this.start(arguments[1]); | ||
}, | ||
update: function(position) { | ||
136 | | |
137 | | |
340 | this.effects.invoke('render', position); | |
}, | ||
finish: function(position) { | ||
140 | | |
141 | | |
343 | this.effects.each( function(effect) { | |
344 | effect.render(1.0); | |
345 | effect.cancel(); | |
346 | effect.event('beforeFinish'); | |
347 | if(effect.finish) effect.finish(position); | |
348 | effect.event('afterFinish'); | |
349 | }); | |
} | ||
}); | ||
145 | ||
146 | ||
147 | ||
Effect.Opacity = Class.create(); | ||
Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), { | ||
initialize: function(element) { | ||
this.element = $(element); | ||
152 | | |
153 | | |
357 | // make this work on IE on elements without 'layout' | |
358 | if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout)) | |
359 | this.element.setStyle({zoom: 1}); | |
360 | var options = Object.extend({ | |
361 | from: this.element.getOpacity() || 0.0, | |
to: 1.0 | ||
}, arguments[1] || {}); | ||
this.start(options); | ||
}, | ||
update: function(position) { | ||
159 | | |
160 | | |
161 | | |
162 | | |
163 | | |
164 | | |
367 | this.element.setOpacity(position); | |
} | ||
}); | ||
168 | ||
169 | ||
170 | | |
171 | | |
172 | | |
173 | | |
174 | | |
175 | | |
176 | | |
177 | | |
371 | Effect.Move = Class.create(); | |
372 | Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), { | |
373 | initialize: function(element) { | |
374 | this.element = $(element); | |
375 | var options = Object.extend({ | |
376 | x: 0, | |
377 | y: 0, | |
378 | mode: 'relative' | |
379 | }, arguments[1] || {}); | |
380 | this.start(options); | |
}, | ||
382 | setup: function() { | |
383 | // Bug in Opera: Opera returns the "real" position of a static element or | |
384 | // relative element that does not have top/left explicitly set. | |
385 | // ==> Always set top and left for position relative elements in your stylesheets | |
386 | // (to 0 if you do not need them) | |
387 | this.element.makePositioned(); | |
388 | this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); | |
389 | this.originalTop = parseFloat(this.element.getStyle('top') || '0'); | |
390 | if(this.options.mode == 'absolute') { | |
391 | // absolute movement, so we need to calc deltaX and deltaY | |
392 | this.options.x = this.options.x - this.originalLeft; | |
393 | this.options.y = this.options.y - this.originalTop; | |
394 | } | |
395 | }, | |
update: function(position) { | ||
180 | | |
181 | | |
182 | | |
183 | | |
184 | | |
185 | | |
186 | | |
397 | this.element.setStyle({ | |
398 | left: this.options.x * position + this.originalLeft + 'px', | |
399 | top: this.options.y * position + this.originalTop + 'px' | |
400 | }); | |
} | ||
}); | ||
404 | // for backwards compatibility | |
405 | Effect.MoveBy = function(element, toTop, toLeft) { | |
406 | return new Effect.Move(element, | |
407 | Object.extend({ x: toLeft, y: toTop }, arguments[3] || {})); | |
408 | }; | |
409 | ||
Effect.Scale = Class.create(); | ||
Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), { | ||
initialize: function(element, percent) { | ||
this.element = $(element) | ||
194 | | |
414 | var options = Object.extend({ | |
scaleX: true, | ||
scaleY: true, | ||
scaleContent: true, | ||
scaleFromCenter: false, | ||
scaleMode: 'box', // 'box' or 'contents' or {} with provided values | ||
200 | | |
420 | scaleFrom: 100.0, | |
421 | scaleTo: percent | |
}, arguments[2] || {}); | ||
202 | | |
203 | | |
204 | | |
205 | | |
206 | | |
207 | | |
208 | | |
209 | | |
210 | | |
211 | | |
212 | | |
213 | | |
214 | | |
215 | | |
216 | | |
217 | | |
218 | | |
this.start(options); | ||
}, | ||
221 | ||
425 | setup: function() { | |
426 | this.restoreAfterFinish = this.options.restoreAfterFinish || false; | |
427 | this.elementPositioning = this.element.getStyle('position'); | |
428 | ||
429 | this.originalStyle = {}; | |
430 | ['top','left','width','height','fontSize'].each( function(k) { | |
431 | this.originalStyle[k] = this.element.style[k]; | |
432 | }.bind(this)); | |
433 | ||
434 | this.originalTop = this.element.offsetTop; | |
435 | this.originalLeft = this.element.offsetLeft; | |
436 | ||
437 | var fontSize = this.element.getStyle('font-size') || '100%'; | |
438 | ['em','px','%'].each( function(fontSizeType) { | |
439 | if(fontSize.indexOf(fontSizeType)>0) { | |
440 | this.fontSize = parseFloat(fontSize); | |
441 | this.fontSizeType = fontSizeType; | |
442 | } | |
443 | }.bind(this)); | |
444 | ||
445 | this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; | |
446 | ||
447 | this.dims = null; | |
448 | if(this.options.scaleMode=='box') | |
449 | this.dims = [this.element.offsetHeight, this.element.offsetWidth]; | |
450 | if(/^content/.test(this.options.scaleMode)) | |
451 | this.dims = [this.element.scrollHeight, this.element.scrollWidth]; | |
452 | if(!this.dims) | |
453 | this.dims = [this.options.scaleMode.originalHeight, | |
454 | this.options.scaleMode.originalWidth]; | |
455 | }, | |
update: function(position) { | ||
223 | | |
224 | | |
225 | | |
226 | | |
227 | | |
228 | | |
457 | var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); | |
458 | if(this.options.scaleContent && this.fontSize) | |
459 | this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); | |
460 | this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); | |
}, | ||
230 | ||
231 | | |
232 | | |
233 | | |
462 | finish: function(position) { | |
463 | if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); | |
464 | }, | |
465 | setDimensions: function(height, width) { | |
466 | var d = {}; | |
467 | if(this.options.scaleX) d.width = width + 'px'; | |
468 | if(this.options.scaleY) d.height = height + 'px'; | |
if(this.options.scaleFromCenter) { | ||
235 | | |
236 | | |
237 | | |
238 | | |
239 | | |
470 | var topd = (height - this.dims[0])/2; | |
471 | var leftd = (width - this.dims[1])/2; | |
472 | if(this.elementPositioning == 'absolute') { | |
473 | if(this.options.scaleY) d.top = this.originalTop-topd + 'px'; | |
474 | if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; | |
} else { | ||
241 | | |
242 | | |
476 | if(this.options.scaleY) d.top = -topd + 'px'; | |
477 | if(this.options.scaleX) d.left = -leftd + 'px'; | |
} | ||
} | ||
480 | this.element.setStyle(d); | |
} | ||
}); | ||
... | ... | |
Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), { | ||
initialize: function(element) { | ||
this.element = $(element); | ||
252 | | |
253 | | |
254 | | |
255 | | |
256 | | |
257 | | |
258 | | |
259 | | |
260 | | |
261 | | |
262 | | |
263 | | |
264 | | |
265 | | |
266 | | |
267 | | |
268 | | |
269 | | |
270 | | |
271 | | |
272 | | |
273 | | |
274 | | |
275 | | |
276 | | |
277 | ||
488 | var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {}); | |
this.start(options); | ||
}, | ||
491 | setup: function() { | |
492 | // Prevent executing on elements not in the layout flow | |
493 | if(this.element.getStyle('display')=='none') { this.cancel(); return; } | |
494 | // Disable background image during the effect | |
495 | this.oldStyle = { | |
496 | backgroundImage: this.element.getStyle('background-image') }; | |
497 | this.element.setStyle({backgroundImage: 'none'}); | |
498 | if(!this.options.endcolor) | |
499 | this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); | |
500 | if(!this.options.restorecolor) | |
501 | this.options.restorecolor = this.element.getStyle('background-color'); | |
502 | // init color calculations | |
503 | this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); | |
504 | this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); | |
505 | }, | |
update: function(position) { | ||
281 | | |
282 | | |
283 | | |
284 | | |
285 | | |
286 | | |
507 | this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ | |
508 | return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) }); | |
}, | ||
finish: function() { | ||
289 | | |
511 | this.element.setStyle(Object.extend(this.oldStyle, { | |
512 | backgroundColor: this.options.restorecolor | |
513 | })); | |
} | ||
}); | ||
... | ... | |
Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), { | ||
initialize: function(element) { | ||
this.element = $(element); | ||
521 | this.start(arguments[1] || {}); | |
522 | }, | |
523 | setup: function() { | |
Position.prepare(); | ||
var offsets = Position.cumulativeOffset(this.element); | ||
526 | if(this.options.offset) offsets[1] += this.options.offset; | |
var max = window.innerHeight ? | ||
window.height - window.innerHeight : | ||
document.body.scrollHeight - | ||
(document.documentElement.clientHeight ? | ||
document.documentElement.clientHeight : document.body.clientHeight); | ||
this.scrollStart = Position.deltaY; | ||
305 | | |
306 | | |
533 | this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart; | |
}, | ||
update: function(position) { | ||
Position.prepare(); | ||
... | ... | |
} | ||
}); | ||
315 | ||
542 | /* ------------- combination effects ------------- */ | |
Effect.Fade = function(element) { | ||
318 | | |
319 | | |
545 | element = $(element); | |
546 | var oldOpacity = element.getInlineOpacity(); | |
547 | var options = Object.extend({ | |
548 | from: element.getOpacity() || 1.0, | |
to: 0.0, | ||
321 | | |
322 | | |
323 | | |
324 | | |
325 | | |
550 | afterFinishInternal: function(effect) { | |
551 | if(effect.options.to!=0) return; | |
552 | effect.element.hide(); | |
553 | effect.element.setStyle({opacity: oldOpacity}); | |
554 | }}, arguments[1] || {}); | |
555 | return new Effect.Opacity(element,options); | |
} | ||
Effect.Appear = function(element) { | ||
329 | | |
330 | | |
559 | element = $(element); | |
560 | var options = Object.extend({ | |
561 | from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), | |
to: 1.0, | ||
332 | | |
333 | | |
334 | | |
335 | | |
336 | | |
337 | | |
338 | | |
563 | // force Safari to render floated elements properly | |
564 | afterFinishInternal: function(effect) { | |
565 | effect.element.forceRerendering(); | |
566 | }, | |
567 | beforeSetup: function(effect) { | |
568 | effect.element.setOpacity(effect.options.from); | |
569 | effect.element.show(); | |
570 | }}, arguments[1] || {}); | |
571 | return new Effect.Opacity(element,options); | |
} | ||
Effect.Puff = function(element) { | ||
342 | | |
343 | | |
344 | | |
345 | | |
346 | | |
347 | | |
348 | | |
349 | | |
350 | | |
575 | element = $(element); | |
576 | var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position') }; | |
577 | return new Effect.Parallel( | |
578 | [ new Effect.Scale(element, 200, | |
579 | { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), | |
580 | new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], | |
581 | Object.extend({ duration: 1.0, | |
582 | beforeSetupInternal: function(effect) { | |
583 | effect.effects[0].element.setStyle({position: 'absolute'}); }, | |
584 | afterFinishInternal: function(effect) { | |
585 | effect.effects[0].element.hide(); | |
586 | effect.effects[0].element.setStyle(oldStyle); } | |
587 | }, arguments[1] || {}) | |
); | ||
} | ||
Effect.BlindUp = function(element) { | ||
355 | | |
356 | | |
592 | element = $(element); | |
593 | element.makeClipping(); | |
594 | return new Effect.Scale(element, 0, | |
Object.extend({ scaleContent: false, | ||
scaleX: false, | ||
359 | | |
360 | | |
361 | | |
362 | | |
363 | | |
597 | restoreAfterFinish: true, | |
598 | afterFinishInternal: function(effect) { | |
599 | effect.element.hide(); | |
600 | effect.element.undoClipping(); | |
601 | } | |
}, arguments[1] || {}) | ||
); | ||
} | ||
Effect.BlindDown = function(element) { | ||
369 | | |
370 | | |
371 | | |
372 | | |
607 | element = $(element); | |
608 | var elementDimensions = element.getDimensions(); | |
609 | return new Effect.Scale(element, 100, | |
Object.extend({ scaleContent: false, | ||
374 | | |
375 | | |
611 | scaleX: false, | |
scaleFrom: 0, | ||
377 | | |
378 | | |
613 | scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, | |
614 | restoreAfterFinish: true, | |
615 | afterSetup: function(effect) { | |
616 | effect.element.makeClipping(); | |
617 | effect.element.setStyle({height: '0px'}); | |
618 | effect.element.show(); | |
619 | }, | |
620 | afterFinishInternal: function(effect) { | |
621 | effect.element.undoClipping(); | |
} | ||
}, arguments[1] || {}) | ||
); | ||
} | ||
Effect.SwitchOff = function(element) { | ||
385 | | |
386 | | |
387 | | |
388 | | |
389 | | |
390 | | |
391 | | |
392 | | |
393 | | |
394 | | |
395 | | |
396 | | |
397 | | |
398 | | |
399 | | |
628 | element = $(element); | |
629 | var oldOpacity = element.getInlineOpacity(); | |
630 | return new Effect.Appear(element, { | |
631 | duration: 0.4, | |
632 | from: 0, | |
633 | transition: Effect.Transitions.flicker, | |
634 | afterFinishInternal: function(effect) { | |
635 | new Effect.Scale(effect.element, 1, { | |
636 | duration: 0.3, scaleFromCenter: true, | |
637 | scaleX: false, scaleContent: false, restoreAfterFinish: true, | |
638 | beforeSetup: function(effect) { | |
639 | effect.element.makePositioned(); | |
640 | effect.element.makeClipping(); | |
641 | }, | |
642 | afterFinishInternal: function(effect) { | |
643 | effect.element.hide(); | |
644 | effect.element.undoClipping(); | |
645 | effect.element.undoPositioned(); | |
646 | effect.element.setStyle({opacity: oldOpacity}); | |
647 | } | |
648 | }) | |
649 | } | |
650 | }); | |
} | ||
Effect.DropOut = function(element) { | ||
403 | | |
404 | | |
405 | | |
406 | | |
407 | | |
408 | | |
409 | | |
654 | element = $(element); | |
655 | var oldStyle = { | |
656 | top: element.getStyle('top'), | |
657 | left: element.getStyle('left'), | |
658 | opacity: element.getInlineOpacity() }; | |
659 | return new Effect.Parallel( | |
660 | [ new Effect.Move(element, {x: 0, y: 100, sync: true }), | |
661 | new Effect.Opacity(element, { sync: true, to: 0.0 }) ], | |
662 | Object.extend( | |
663 | { duration: 0.5, | |
664 | beforeSetup: function(effect) { | |
665 | effect.effects[0].element.makePositioned(); | |
666 | }, | |
667 | afterFinishInternal: function(effect) { | |
668 | effect.effects[0].element.hide(); | |
669 | effect.effects[0].element.undoPositioned(); | |
670 | effect.effects[0].element.setStyle(oldStyle); | |
671 | } | |
672 | }, arguments[1] || {})); | |
} | ||
Effect.Shake = function(element) { | ||
413 | | |
414 | | |
415 | | |
416 | | |
417 | | |
418 | | |
419 | | |
420 | | |
421 | | |
422 | | |
423 | | |
424 | | |
676 | element = $(element); | |
677 | var oldStyle = { | |
678 | top: element.getStyle('top'), | |
679 | left: element.getStyle('left') }; | |
680 | return new Effect.Move(element, | |
681 | { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { | |
682 | new Effect.Move(effect.element, | |
683 | { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { | |
684 | new Effect.Move(effect.element, | |
685 | { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { | |
686 | new Effect.Move(effect.element, | |
687 | { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { | |
688 | new Effect.Move(effect.element, | |
689 | { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { | |
690 | new Effect.Move(effect.element, | |
691 | { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { | |
692 | effect.element.undoPositioned(); | |
693 | effect.element.setStyle(oldStyle); | |
}}) }}) }}) }}) }}) }}); | ||
} | ||
Effect.SlideDown = function(element) { | ||
element = $(element); | ||
430 | | |
431 | | |
432 | | |
433 | | |
434 | | |
435 | | |
436 | | |
699 | element.cleanWhitespace(); | |
700 | // SlideDown need to have the content of the element wrapped in a container element with fixed height! | |
701 | var oldInnerBottom = $(element.firstChild).getStyle('bottom'); | |
702 | var elementDimensions = element.getDimensions(); | |
703 | return new Effect.Scale(element, 100, Object.extend({ | |
704 | scaleContent: false, | |
scaleX: false, | ||
438 | | |
scaleFrom: 0, | ||
440 | | |
441 | | |
442 | | |
443 | | |
444 | | |
707 | scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, | |
708 | restoreAfterFinish: true, | |
709 | afterSetup: function(effect) { | |
710 | effect.element.makePositioned(); | |
711 | effect.element.firstChild.makePositioned(); | |
712 | if(window.opera) effect.element.setStyle({top: ''}); | |
713 | effect.element.makeClipping(); | |
714 | effect.element.setStyle({height: '0px'}); | |
715 | effect.element.show(); }, | |
716 | afterUpdateInternal: function(effect) { | |
717 | effect.element.firstChild.setStyle({bottom: | |
718 | (effect.dims[0] - effect.element.clientHeight) + 'px' }); | |
719 | }, | |
720 | afterFinishInternal: function(effect) { | |
721 | effect.element.undoClipping(); | |
722 | // IE will crash if child is undoPositioned first | |
723 | if(/MSIE/.test(navigator.userAgent)){ | |
724 | effect.element.undoPositioned(); | |
725 | effect.element.firstChild.undoPositioned(); | |
726 | }else{ | |
727 | effect.element.firstChild.undoPositioned(); | |
728 | effect.element.undoPositioned(); | |
729 | } | |
730 | effect.element.firstChild.setStyle({bottom: oldInnerBottom}); } | |
}, arguments[1] || {}) | ||
); | ||
} | ||
Effect.SlideUp = function(element) { | ||
element = $(element); | ||
451 | | |
452 | | |
453 | | |
454 | | |
455 | | |
737 | element.cleanWhitespace(); | |
738 | var oldInnerBottom = $(element.firstChild).getStyle('bottom'); | |
739 | return new Effect.Scale(element, 0, | |
Object.extend({ scaleContent: false, | ||
scaleX: false, | ||
458 | | |
459 | | |
460 | | |
461 | | |
462 | | |
463 | | |
464 | | |
465 | | |
742 | scaleMode: 'box', | |
743 | scaleFrom: 100, | |
744 | restoreAfterFinish: true, | |
745 | beforeStartInternal: function(effect) { | |
746 | effect.element.makePositioned(); | |
747 | effect.element.firstChild.makePositioned(); | |
748 | if(window.opera) effect.element.setStyle({top: ''}); | |
749 | effect.element.makeClipping(); | |
750 | effect.element.show(); }, | |
751 | afterUpdateInternal: function(effect) { | |
752 | effect.element.firstChild.setStyle({bottom: | |
753 | (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, | |
754 | afterFinishInternal: function(effect) { | |
755 | effect.element.hide(); | |
756 | effect.element.undoClipping(); | |
757 | effect.element.firstChild.undoPositioned(); | |
758 | effect.element.undoPositioned(); | |
759 | effect.element.setStyle({bottom: oldInnerBottom}); } | |
}, arguments[1] || {}) | ||
); | ||
} | ||
764 | // Bug in opera makes the TD containing this element expand for a instance after finish | |
Effect.Squish = function(element) { | ||
471 | | |
472 | | |
766 | return new Effect.Scale(element, window.opera ? 1 : 0, | |
767 | { restoreAfterFinish: true, | |
768 | beforeSetup: function(effect) { | |
769 | effect.element.makeClipping(effect.element); }, | |
770 | afterFinishInternal: function(effect) { | |
771 | effect.element.hide(effect.element); | |
772 | effect.element.undoClipping(effect.element); } | |
773 | }); | |
} | ||
Effect.Grow = function(element) { | ||
element = $(element); | ||
477 | | |
478 | | |
479 | | |
480 | | |
481 | | |
482 | | |
483 | | |
484 | | |
485 | | |
486 | | |
487 | | |
488 | | |
778 | var options = Object.extend({ | |
779 | direction: 'center', | |
780 | moveTransition: Effect.Transitions.sinoidal, | |
781 | scaleTransition: Effect.Transitions.sinoidal, | |
782 | opacityTransition: Effect.Transitions.full | |
783 | }, arguments[1] || {}); | |
784 | var oldStyle = { | |
785 | top: element.style.top, | |
786 | left: element.style.left, | |
787 | height: element.style.height, | |
788 | width: element.style.width, | |
789 | opacity: element.getInlineOpacity() }; | |
790 | ||
791 | var dims = element.getDimensions(); | |
var initialMoveX, initialMoveY; | ||
var moveX, moveY; | ||
492 | | |
795 | switch (options.direction) { | |
case 'top-left': | ||
initialMoveX = initialMoveY = moveX = moveY = 0; | ||
break; | ||
case 'top-right': | ||
497 | | |
800 | initialMoveX = dims.width; | |
initialMoveY = moveY = 0; | ||
499 | | |
802 | moveX = -dims.width; | |
break; | ||
case 'bottom-left': | ||
initialMoveX = moveX = 0; | ||
503 | | |
504 | | |
806 | initialMoveY = dims.height; | |
807 | moveY = -dims.height; | |
break; | ||
case 'bottom-right': | ||
507 | | |
508 | | |
509 | | |
510 | | |
810 | initialMoveX = dims.width; | |
811 | initialMoveY = dims.height; | |
812 | moveX = -dims.width; | |
813 | moveY = -dims.height; | |
break; | ||
case 'center': | ||
513 | | |
514 | | |
515 | | |
516 | | |
816 | initialMoveX = dims.width / 2; | |
817 | initialMoveY = dims.height / 2; | |
818 | moveX = -dims.width / 2; | |
819 | moveY = -dims.height / 2; | |
break; | ||
} | ||
520 | | |
823 | return new Effect.Move(element, { | |
824 | x: initialMoveX, | |
825 | y: initialMoveY, | |
duration: 0.01, | ||
522 | | |
523 | | |
827 | beforeSetup: function(effect) { | |
828 | effect.element.hide(); | |
829 | effect.element.makeClipping(); | |
830 | effect.element.makePositioned(); | |
831 | }, | |
832 | afterFinishInternal: function(effect) { | |
new Effect.Parallel( | ||
525 | | |
526 | | |
527 | | |
528 | | |
529 | | |
530 | | |
531 | | |
834 | [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), | |
835 | new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), | |
836 | new Effect.Scale(effect.element, 100, { | |
837 | scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, | |
838 | sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) | |
839 | ], Object.extend({ | |
840 | beforeSetup: function(effect) { | |
841 | effect.effects[0].element.setStyle({height: '0px'}); | |
842 | effect.effects[0].element.show(); | |
843 | }, | |
844 | afterFinishInternal: function(effect) { | |
845 | effect.effects[0].element.undoClipping(); | |
846 | effect.effects[0].element.undoPositioned(); | |
847 | effect.effects[0].element.setStyle(oldStyle); | |
848 | } | |
849 | }, options) | |
850 | ) | |
851 | } | |
852 | }); | |
} | ||
Effect.Shrink = function(element) { | ||
element = $(element); | ||
536 | | |
537 | | |
538 | | |
539 | | |
540 | | |
541 | | |
857 | var options = Object.extend({ | |
858 | direction: 'center', | |
859 | moveTransition: Effect.Transitions.sinoidal, | |
860 | scaleTransition: Effect.Transitions.sinoidal, | |
861 | opacityTransition: Effect.Transitions.none | |
862 | }, arguments[1] || {}); | |
863 | var oldStyle = { | |
864 | top: element.style.top, | |
865 | left: element.style.left, | |
866 | height: element.style.height, | |
867 | width: element.style.width, | |
868 | opacity: element.getInlineOpacity() }; | |
543 | | |
544 | | |
545 | | |
546 | | |
547 | | |
870 | var dims = element.getDimensions(); | |
var moveX, moveY; | ||
550 | | |
873 | switch (options.direction) { | |
case 'top-left': | ||
moveX = moveY = 0; | ||
break; | ||
case 'top-right': | ||
555 | | |
878 | moveX = dims.width; | |
moveY = 0; | ||
break; | ||
case 'bottom-left': | ||
moveX = 0; | ||
560 | | |
883 | moveY = dims.height; | |
break; | ||
case 'bottom-right': | ||
563 | | |
564 | | |
886 | moveX = dims.width; | |
887 | moveY = dims.height; | |
break; | ||
case 'center': | ||
567 | | |
568 | | |
890 | moveX = dims.width / 2; | |
891 | moveY = dims.height / 2; | |
break; | ||
} | ||
572 | | |
573 | | |
574 | | |
575 | | |
576 | | |
895 | return new Effect.Parallel( | |
896 | [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), | |
897 | new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), | |
898 | new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) | |
899 | ], Object.extend({ | |
900 | beforeStartInternal: function(effect) { | |
901 | effect.effects[0].element.makePositioned(); | |
902 | effect.effects[0].element.makeClipping(); }, | |
903 | afterFinishInternal: function(effect) { | |
904 | effect.effects[0].element.hide(); | |
905 | effect.effects[0].element.undoClipping(); | |
906 | effect.effects[0].element.undoPositioned(); | |
907 | effect.effects[0].element.setStyle(oldStyle); } | |
908 | }, options) | |
909 | ); | |
} | ||
Effect.Pulsate = function(element) { | ||
913 | element = $(element); | |
var options = arguments[1] || {}; | ||
915 | var oldOpacity = element.getInlineOpacity(); | |
var transition = options.transition || Effect.Transitions.sinoidal; | ||
var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) }; | ||
reverser.bind(transition); | ||
584 | | |
585 | | |
586 | | |
919 | return new Effect.Opacity(element, | |
920 | Object.extend(Object.extend({ duration: 3.0, from: 0, | |
921 | afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } | |
}, options), {transition: reverser})); | ||
} | ||
Effect.Fold = function(element) { | ||
591 | | |
592 | | |
593 | | |
594 | | |
595 | | |
596 | | |
597 | | |
598 | | |
599 | | |
600 | | |
601 | | |
602 | | |
926 | element = $(element); | |
927 | var oldStyle = { | |
928 | top: element.style.top, | |
929 | left: element.style.left, | |
930 | width: element.style.width, | |
931 | height: element.style.height }; | |
932 | Element.makeClipping(element); | |
933 | return new Effect.Scale(element, 5, Object.extend({ | |
934 | scaleContent: false, | |
935 | scaleX: false, | |
936 | afterFinishInternal: function(effect) { | |
937 | new Effect.Scale(element, 1, { | |
938 | scaleContent: false, | |
939 | scaleY: false, | |
940 | afterFinishInternal: function(effect) { | |
941 | effect.element.hide(); | |
942 | effect.element.undoClipping(); | |
943 | effect.element.setStyle(oldStyle); | |
944 | } }); | |
945 | }}, arguments[1] || {})); | |
} | ||
605 | ||
606 | ||
607 | ||
608 | ||
609 | | |
610 | | |
611 | | |
612 | ||
948 | Element.Methods.visualEffect = function(element, effect, options) { | |
949 | s = effect.gsub(/_/, '-').camelize(); | |
950 | effect_class = s.charAt(0).toUpperCase() + s.substring(1); | |
951 | new Effect[effect_class](element, options); | |
952 | return $(element); | |
953 | }; | |
rool/rails/typo/trunk/public/javascripts/prototype.js:
prev. | current | |
1 | ||
1 | /* Prototype JavaScript framework, version 1.5.0_pre1 | |
* (c) 2005 Sam Stephenson <sam@conio.net> | ||
* | ||
4 | | |
5 | | |
6 | | |
* Prototype is freely distributable under the terms of an MIT-style license. | ||
8 | | |
* For details, see the Prototype web site: http://prototype.conio.net/ | ||
* | ||
/*--------------------------------------------------------------------------*/ | ||
var Prototype = { | ||
14 | | |
15 | | |
10 | Version: '1.5.0_pre1', | |
11 | ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', | |
12 | ||
13 | emptyFunction: function() {}, | |
14 | K: function(x) {return x} | |
} | ||
var Class = { | ||
create: function() { | ||
20 | | |
19 | return function() { | |
this.initialize.apply(this, arguments); | ||
} | ||
} | ||
... | ... | |
return destination; | ||
} | ||
35 | ||
36 | | |
34 | Object.inspect = function(object) { | |
35 | try { | |
36 | if (object == undefined) return 'undefined'; | |
37 | if (object == null) return 'null'; | |
38 | return object.inspect ? object.inspect() : object.toString(); | |
39 | } catch (e) { | |
40 | if (e instanceof RangeError) return '...'; | |
41 | throw e; | |
42 | } | |
} | ||
39 | ||
40 | | |
45 | Function.prototype.bind = function() { | |
46 | var __method = this, args = $A(arguments), object = args.shift(); | |
return function() { | ||
42 | | |
48 | return __method.apply(object, args.concat($A(arguments))); | |
} | ||
} | ||
Function.prototype.bindAsEventListener = function(object) { | ||
var __method = this; | ||
return function(event) { | ||
49 | | |
55 | return __method.call(object, event || window.event); | |
} | ||
} | ||
53 | ||
54 | | |
55 | | |
56 | | |
57 | ||
59 | Object.extend(Number.prototype, { | |
60 | toColorPart: function() { | |
61 | var digits = this.toString(16); | |
62 | if (this < 16) return '0' + digits; | |
63 | return digits; | |
64 | }, | |
66 | succ: function() { | |
67 | return this + 1; | |
68 | }, | |
69 | ||
70 | times: function(iterator) { | |
71 | $R(0, this, true).each(iterator); | |
72 | return this; | |
73 | } | |
74 | }); | |
75 | ||
var Try = { | ||
these: function() { | ||
var returnValue; | ||
... | ... | |
onTimerEvent: function() { | ||
if (!this.currentlyExecuting) { | ||
93 | | |
110 | try { | |
this.currentlyExecuting = true; | ||
95 | | |
96 | | |
112 | this.callback(); | |
113 | } finally { | |
this.currentlyExecuting = false; | ||
} | ||
} | ||
} | ||
} | ||
119 | Object.extend(String.prototype, { | |
120 | gsub: function(pattern, replacement) { | |
121 | var result = '', source = this, match; | |
122 | replacement = arguments.callee.prepareReplacement(replacement); | |
103 | ||
124 | while (source.length > 0) { | |
125 | if (match = source.match(pattern)) { | |
126 | result += source.slice(0, match.index); | |
127 | result += (replacement(match) || '').toString(); | |
128 | source = source.slice(match.index + match[0].length); | |
129 | } else { | |
130 | result += source, source = ''; | |
131 | } | |
132 | } | |
133 | return result; | |
134 | }, | |
105 | ||
106 | | |
136 | sub: function(pattern, replacement, count) { | |
137 | replacement = this.gsub.prepareReplacement(replacement); | |
138 | count = count === undefined ? 1 : count; | |
108 | | |
109 | | |
110 | | |
111 | | |
140 | return this.gsub(pattern, function(match) { | |
141 | if (--count < 0) return match[0]; | |
142 | return replacement(match); | |
143 | }); | |
144 | }, | |
113 | | |
114 | | |
146 | scan: function(pattern, iterator) { | |
147 | this.gsub(pattern, iterator); | |
148 | return this; | |
149 | }, | |
116 | | |
117 | | |
151 | truncate: function(length, truncation) { | |
152 | length = length || 30; | |
153 | truncation = truncation === undefined ? '...' : truncation; | |
154 | return this.length > length ? | |
155 | this.slice(0, length - truncation.length) + truncation : this; | |
156 | }, | |
119 | | |
120 | ||
158 | strip: function() { | |
159 | return this.replace(/^\s+/, '').replace(/\s+$/, ''); | |
160 | }, | |
122 | ||
123 | | |
124 | | |
125 | | |
126 | | |
127 | | |
128 | | |
129 | ||
130 | ||
131 | ||
132 | | |
133 | | |
134 | | |
135 | | |
136 | | |
137 | | |
138 | | |
139 | | |
140 | | |
141 | | |
142 | | |
143 | | |
144 | | |
145 | | |
146 | | |
147 | | |
148 | ||
149 | ||
150 | ||
stripTags: function() { | ||
return this.replace(/<\/?[^>]+>/gi, ''); | ||
}, | ||
166 | stripScripts: function() { | |
167 | return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); | |
168 | }, | |
169 | ||
170 | extractScripts: function() { | |
171 | var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); | |
172 | var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); | |
173 | return (this.match(matchAll) || []).map(function(scriptTag) { | |
174 | return (scriptTag.match(matchOne) || ['', ''])[1]; | |
175 | }); | |
176 | }, | |
177 | ||
178 | evalScripts: function() { | |
179 | return this.extractScripts().map(eval); | |
180 | }, | |
181 | ||
escapeHTML: function() { | ||
var div = document.createElement('div'); | ||
var text = document.createTextNode(this); | ||
... | ... | |
unescapeHTML: function() { | ||
var div = document.createElement('div'); | ||
div.innerHTML = this.stripTags(); | ||
165 | | |
192 | return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; | |
193 | }, | |
194 | ||
195 | toQueryParams: function() { | |
196 | var pairs = this.match(/^\??(.*)$/)[1].split('&'); | |
197 | return pairs.inject({}, function(params, pairString) { | |
198 | var pair = pairString.split('='); | |
199 | params[pair[0]] = pair[1]; | |
200 | return params; | |
201 | }); | |
202 | }, | |
203 | ||
204 | toArray: function() { | |
205 | return this.split(''); | |
206 | }, | |
207 | ||
208 | camelize: function() { | |
209 | var oStringList = this.split('-'); | |
210 | if (oStringList.length == 1) return oStringList[0]; | |
211 | ||
212 | var camelizedString = this.indexOf('-') == 0 | |
213 | ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) | |
214 | : oStringList[0]; | |
215 | ||
216 | for (var i = 1, len = oStringList.length; i < len; i++) { | |
217 | var s = oStringList[i]; | |
218 | camelizedString += s.charAt(0).toUpperCase() + s.substring(1); | |
219 | } | |
220 | ||
221 | return camelizedString; | |
222 | }, | |
223 | ||
224 | inspect: function() { | |
225 | return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'"; | |
} | ||
}); | ||
229 | String.prototype.gsub.prepareReplacement = function(replacement) { | |
230 | if (typeof replacement == 'function') return replacement; | |
231 | var template = new Template(replacement); | |
232 | return function(match) { return template.evaluate(match) }; | |
233 | } | |
234 | ||
235 | String.prototype.parseQuery = String.prototype.toQueryParams; | |
236 | ||
237 | var Template = Class.create(); | |
238 | Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; | |
239 | Template.prototype = { | |
240 | initialize: function(template, pattern) { | |
241 | this.template = template.toString(); | |
242 | this.pattern = pattern || Template.Pattern; | |
243 | }, | |
244 | ||
245 | evaluate: function(object) { | |
246 | return this.template.gsub(this.pattern, function(match) { | |
247 | var before = match[1]; | |
248 | if (before == '\\') return match[2]; | |
249 | return before + (object[match[3]] || '').toString(); | |
250 | }); | |
251 | } | |
252 | } | |
253 | ||
254 | var $break = new Object(); | |
255 | var $continue = new Object(); | |
256 | ||
257 | var Enumerable = { | |
258 | each: function(iterator) { | |
259 | var index = 0; | |
260 | try { | |
261 | this._each(function(value) { | |
262 | try { | |
263 | iterator(value, index++); | |
264 | } catch (e) { | |
265 | if (e != $continue) throw e; | |
266 | } | |
267 | }); | |
268 | } catch (e) { | |
269 | if (e != $break) throw e; | |
270 | } | |
271 | }, | |
272 | ||
273 | all: function(iterator) { | |
274 | var result = true; | |
275 | this.each(function(value, index) { | |
276 | result = result && !!(iterator || Prototype.K)(value, index); | |
277 | if (!result) throw $break; | |
278 | }); | |
279 | return result; | |
280 | }, | |
281 | ||
282 | any: function(iterator) { | |
283 | var result = true; | |
284 | this.each(function(value, index) { | |
285 | if (result = !!(iterator || Prototype.K)(value, index)) | |
286 | throw $break; | |
287 | }); | |
288 | return result; | |
289 | }, | |
290 | ||
291 | collect: function(iterator) { | |
292 | var results = []; | |
293 | this.each(function(value, index) { | |
294 | results.push(iterator(value, index)); | |
295 | }); | |
296 | return results; | |
297 | }, | |
298 | ||
299 | detect: function (iterator) { | |
300 | var result; | |
301 | this.each(function(value, index) { | |
302 | if (iterator(value, index)) { | |
303 | result = value; | |
304 | throw $break; | |
305 | } | |
306 | }); | |
307 | return result; | |
308 | }, | |
309 | ||
310 | findAll: function(iterator) { | |
311 | var results = []; | |
312 | this.each(function(value, index) { | |
313 | if (iterator(value, index)) | |
314 | results.push(value); | |
315 | }); | |
316 | return results; | |
317 | }, | |
318 | ||
319 | grep: function(pattern, iterator) { | |
320 | var results = []; | |
321 | this.each(function(value, index) { | |
322 | var stringValue = value.toString(); | |
323 | if (stringValue.match(pattern)) | |
324 | results.push((iterator || Prototype.K)(value, index)); | |
325 | }) | |
326 | return results; | |
327 | }, | |
328 | ||
329 | include: function(object) { | |
330 | var found = false; | |
331 | this.each(function(value) { | |
332 | if (value == object) { | |
333 | found = true; | |
334 | throw $break; | |
335 | } | |
336 | }); | |
337 | return found; | |
338 | }, | |
339 | ||
340 | inject: function(memo, iterator) { | |
341 | this.each(function(value, index) { | |
342 | memo = iterator(memo, value, index); | |
343 | }); | |
344 | return memo; | |
345 | }, | |
346 | ||
347 | invoke: function(method) { | |
348 | var args = $A(arguments).slice(1); | |
349 | return this.collect(function(value) { | |
350 | return value[method].apply(value, args); | |
351 | }); | |
352 | }, | |
353 | ||
354 | max: function(iterator) { | |
355 | var result; | |
356 | this.each(function(value, index) { | |
357 | value = (iterator || Prototype.K)(value, index); | |
358 | if (value >= (result || value)) | |
359 | result = value; | |
360 | }); | |
361 | return result; | |
362 | }, | |
363 | ||
364 | min: function(iterator) { | |
365 | var result; | |
366 | this.each(function(value, index) { | |
367 | value = (iterator || Prototype.K)(value, index); | |
368 | if (value <= (result || value)) | |
369 | result = value; | |
370 | }); | |
371 | return result; | |
372 | }, | |
373 | ||
374 | partition: function(iterator) { | |
375 | var trues = [], falses = []; | |
376 | this.each(function(value, index) { | |
377 | ((iterator || Prototype.K)(value, index) ? | |
378 | trues : falses).push(value); | |
379 | }); | |
380 | return [trues, falses]; | |
381 | }, | |
382 | ||
383 | pluck: function(property) { | |
384 | var results = []; | |
385 | this.each(function(value, index) { | |
386 | results.push(value[property]); | |
387 | }); | |
388 | return results; | |
389 | }, | |
390 | ||
391 | reject: function(iterator) { | |
392 | var results = []; | |
393 | this.each(function(value, index) { | |
394 | if (!iterator(value, index)) | |
395 | results.push(value); | |
396 | }); | |
397 | return results; | |
398 | }, | |
399 | ||
400 | sortBy: function(iterator) { | |
401 | return this.collect(function(value, index) { | |
402 | return {value: value, criteria: iterator(value, index)}; | |
403 | }).sort(function(left, right) { | |
404 | var a = left.criteria, b = right.criteria; | |
405 | return a < b ? -1 : a > b ? 1 : 0; | |
406 | }).pluck('value'); | |
407 | }, | |
408 | ||
409 | toArray: function() { | |
410 | return this.collect(Prototype.K); | |
411 | }, | |
412 | ||
413 | zip: function() { | |
414 | var iterator = Prototype.K, args = $A(arguments); | |
415 | if (typeof args.last() == 'function') | |
416 | iterator = args.pop(); | |
417 | ||
418 | var collections = [this].concat(args).map($A); | |
419 | return this.map(function(value, index) { | |
420 | return iterator(collections.pluck(index)); | |
421 | }); | |
422 | }, | |
423 | ||
424 | inspect: function() { | |
425 | return '#<Enumerable:' + this.toArray().inspect() + '>'; | |
426 | } | |
427 | } | |
428 | ||
429 | Object.extend(Enumerable, { | |
430 | map: Enumerable.collect, | |
431 | find: Enumerable.detect, | |
432 | select: Enumerable.findAll, | |
433 | member: Enumerable.include, | |
434 | entries: Enumerable.toArray | |
435 | }); | |
436 | var $A = Array.from = function(iterable) { | |
437 | if (!iterable) return []; | |
438 | if (iterable.toArray) { | |
439 | return iterable.toArray(); | |
440 | } else { | |
441 | var results = []; | |
442 | for (var i = 0; i < iterable.length; i++) | |
443 | results.push(iterable[i]); | |
444 | return results; | |
445 | } | |
446 | } | |
447 | ||
448 | Object.extend(Array.prototype, Enumerable); | |
449 | ||
450 | Array.prototype._reverse = Array.prototype.reverse; | |
451 | ||
452 | Object.extend(Array.prototype, { | |
453 | _each: function(iterator) { | |
454 | for (var i = 0; i < this.length; i++) | |
455 | iterator(this[i]); | |
456 | }, | |
457 | ||
458 | clear: function() { | |
459 | this.length = 0; | |
460 | return this; | |
461 | }, | |
462 | ||
463 | first: function() { | |
464 | return this[0]; | |
465 | }, | |
466 | ||
467 | last: function() { | |
468 | return this[this.length - 1]; | |
469 | }, | |
470 | ||
471 | compact: function() { | |
472 | return this.select(function(value) { | |
473 | return value != undefined || value != null; | |
474 | }); | |
475 | }, | |
476 | ||
477 | flatten: function() { | |
478 | return this.inject([], function(array, value) { | |
479 | return array.concat(value.constructor == Array ? | |
480 | value.flatten() : [value]); | |
481 | }); | |
482 | }, | |
483 | ||
484 | without: function() { | |
485 | var values = $A(arguments); | |
486 | return this.select(function(value) { | |
487 | return !values.include(value); | |
488 | }); | |
489 | }, | |
490 | ||
491 | indexOf: function(object) { | |
492 | for (var i = 0; i < this.length; i++) | |
493 | if (this[i] == object) return i; | |
494 | return -1; | |
495 | }, | |
496 | ||
497 | reverse: function(inline) { | |
498 | return (inline !== false ? this : this.toArray())._reverse(); | |
499 | }, | |
500 | ||
501 | shift: function() { | |
502 | var result = this[0]; | |
503 | for (var i = 0; i < this.length - 1; i++) | |
504 | this[i] = this[i + 1]; | |
505 | this.length--; | |
506 | return result; | |
507 | }, | |
508 | ||
509 | inspect: function() { | |
510 | return '[' + this.map(Object.inspect).join(', ') + ']'; | |
511 | } | |
512 | }); | |
513 | var Hash = { | |
514 | _each: function(iterator) { | |
515 | for (key in this) { | |
516 | var value = this[key]; | |
517 | if (typeof value == 'function') continue; | |
518 | ||
519 | var pair = [key, value]; | |
520 | pair.key = key; | |
521 | pair.value = value; | |
522 | iterator(pair); | |
523 | } | |
524 | }, | |
525 | ||
526 | keys: function() { | |
527 | return this.pluck('key'); | |
528 | }, | |
529 | ||
530 | values: function() { | |
531 | return this.pluck('value'); | |
532 | }, | |
533 | ||
534 | merge: function(hash) { | |
535 | return $H(hash).inject($H(this), function(mergedHash, pair) { | |
536 | mergedHash[pair.key] = pair.value; | |
537 | return mergedHash; | |
538 | }); | |
539 | }, | |
540 | ||
541 | toQueryString: function() { | |
542 | return this.map(function(pair) { | |
543 | return pair.map(encodeURIComponent).join('='); | |
544 | }).join('&'); | |
545 | }, | |
546 | ||
547 | inspect: function() { | |
548 | return '#<Hash:{' + this.map(function(pair) { | |
549 | return pair.map(Object.inspect).join(': '); | |
550 | }).join(', ') + '}>'; | |
551 | } | |
552 | } | |
553 | ||
554 | function $H(object) { | |
555 | var hash = Object.extend({}, object || {}); | |
556 | Object.extend(hash, Enumerable); | |
557 | Object.extend(hash, Hash); | |
558 | return hash; | |
559 | } | |
560 | ObjectRange = Class.create(); | |
561 | Object.extend(ObjectRange.prototype, Enumerable); | |
562 | Object.extend(ObjectRange.prototype, { | |
563 | initialize: function(start, end, exclusive) { | |
564 | this.start = start; | |
565 | this.end = end; | |
566 | this.exclusive = exclusive; | |
567 | }, | |
568 | ||
569 | _each: function(iterator) { | |
570 | var value = this.start; | |
571 | do { | |
572 | iterator(value); | |
573 | value = value.succ(); | |
574 | } while (this.include(value)); | |
575 | }, | |
576 | ||
577 | include: function(value) { | |
578 | if (value < this.start) | |
579 | return false; | |
580 | if (this.exclusive) | |
581 | return value < this.end; | |
582 | return value <= this.end; | |
583 | } | |
584 | }); | |
585 | ||
586 | var $R = function(start, end, exclusive) { | |
587 | return new ObjectRange(start, end, exclusive); | |
588 | } | |
589 | ||
var Ajax = { | ||
getTransport: function() { | ||
return Try.these( | ||
... | ... | |
function() {return new ActiveXObject('Microsoft.XMLHTTP')}, | ||
function() {return new XMLHttpRequest()} | ||
) || false; | ||
176 | | |
597 | }, | |
598 | ||
599 | activeRequestCount: 0 | |
} | ||
602 | Ajax.Responders = { | |
603 | responders: [], | |
604 | ||
605 | _each: function(iterator) { | |
606 | this.responders._each(iterator); | |
607 | }, | |
608 | ||
609 | register: function(responderToAdd) { | |
610 | if (!this.include(responderToAdd)) | |
611 | this.responders.push(responderToAdd); | |
612 | }, | |
613 | ||
614 | unregister: function(responderToRemove) { | |
615 | this.responders = this.responders.without(responderToRemove); | |
616 | }, | |
617 | ||
618 | dispatch: function(callback, request, transport, json) { | |
619 | this.each(function(responder) { | |
620 | if (responder[callback] && typeof responder[callback] == 'function') { | |
621 | try { | |
622 | responder[callback].apply(responder, [request, transport, json]); | |
623 | } catch (e) {} | |
624 | } | |
625 | }); | |
626 | } | |
627 | }; | |
628 | ||
629 | Object.extend(Ajax.Responders, Enumerable); | |
630 | ||
631 | Ajax.Responders.register({ | |
632 | onCreate: function() { | |
633 | Ajax.activeRequestCount++; | |
634 | }, | |
635 | ||
636 | onComplete: function() { | |
637 | Ajax.activeRequestCount--; | |
638 | } | |
639 | }); | |
640 | ||
Ajax.Base = function() {}; | ||
Ajax.Base.prototype = { | ||
setOptions: function(options) { | ||
... | ... | |
method: 'post', | ||
asynchronous: true, | ||
parameters: '' | ||
186 | | |
648 | } | |
649 | Object.extend(this.options, options || {}); | |
}, | ||
responseIsSuccess: function() { | ||
return this.transport.status == undefined | ||
191 | | |
654 | || this.transport.status == 0 | |
|| (this.transport.status >= 200 && this.transport.status < 300); | ||
}, | ||
... | ... | |
} | ||
Ajax.Request = Class.create(); | ||
201 | ||
664 | Ajax.Request.Events = | |
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; | ||
204 | ||
667 | Ajax.Request.prototype = Object.extend(new Ajax.Base(), { | |
initialize: function(url, options) { | ||
this.transport = Ajax.getTransport(); | ||
this.setOptions(options); | ||
... | ... | |
if (parameters.length > 0) parameters += '&_='; | ||
try { | ||
216 | | |
217 | | |
679 | this.url = url; | |
680 | if (this.options.method == 'get' && parameters.length > 0) | |
681 | this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; | |
219 | | |
683 | Ajax.Responders.dispatch('onCreate', this, this.transport); | |
684 | ||
685 | this.transport.open(this.options.method, this.url, | |
this.options.asynchronous); | ||
if (this.options.asynchronous) { | ||
... | ... | |
this.transport.send(this.options.method == 'post' ? body : null); | ||
} catch (e) { | ||
699 | this.dispatchException(e); | |
} | ||
}, | ||
setRequestHeaders: function() { | ||
237 | | |
704 | var requestHeaders = | |
['X-Requested-With', 'XMLHttpRequest', | ||
239 | | |
706 | 'X-Prototype-Version', Prototype.Version, | |
707 | 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*']; | |
if (this.options.method == 'post') { | ||
242 | | |
710 | requestHeaders.push('Content-type', | |
'application/x-www-form-urlencoded'); | ||
/* Force "Connection: close" for Mozilla browsers to work around | ||
* a bug where XMLHttpReqeuest sends an incorrect Content-length | ||
247 | | |
715 | * header. See Mozilla Bugzilla #246651. | |
*/ | ||
if (this.transport.overrideMimeType) | ||
requestHeaders.push('Connection', 'close'); | ||
... | ... | |
this.respondToReadyState(this.transport.readyState); | ||
}, | ||
734 | header: function(name) { | |
735 | try { | |
736 | return this.transport.getResponseHeader(name); | |
737 | } catch (e) {} | |
738 | }, | |
739 | ||
740 | evalJSON: function() { | |
741 | try { | |
742 | return eval(this.header('X-JSON')); | |
743 | } catch (e) {} | |
744 | }, | |
745 | ||
746 | evalResponse: function() { | |
747 | try { | |
748 | return eval(this.transport.responseText); | |
749 | } catch (e) { | |
750 | this.dispatchException(e); | |
751 | } | |
752 | }, | |
753 | ||
respondToReadyState: function(readyState) { | ||
var event = Ajax.Request.Events[readyState]; | ||
756 | var transport = this.transport, json = this.evalJSON(); | |
269 | | |
270 | | |
271 | | |
272 | | |
758 | if (event == 'Complete') { | |
759 | try { | |
760 | (this.options['on' + this.transport.status] | |
761 | || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] | |
762 | || Prototype.emptyFunction)(transport, json); | |
763 | } catch (e) { | |
764 | this.dispatchException(e); | |
765 | } | |
274 | | |
767 | if ((this.header('Content-type') || '').match(/^text\/javascript/i)) | |
768 | this.evalResponse(); | |
769 | } | |
771 | try { | |
772 | (this.options['on' + event] || Prototype.emptyFunction)(transport, json); | |
773 | Ajax.Responders.dispatch('on' + event, this, transport, json); | |
774 | } catch (e) { | |
775 | this.dispatchException(e); | |
776 | } | |
777 | ||
/* Avoid memory leak in MSIE: clean up the oncomplete event handler */ | ||
if (event == 'Complete') | ||
this.transport.onreadystatechange = Prototype.emptyFunction; | ||
781 | }, | |
782 | ||
783 | dispatchException: function(exception) { | |
784 | (this.options.onException || Prototype.emptyFunction)(this, exception); | |
785 | Ajax.Responders.dispatch('onException', this, exception); | |
} | ||
}); | ||
Ajax.Updater = Class.create(); | ||
283 | ||
285 | ||
791 | Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { | |
initialize: function(container, url, options) { | ||
this.containers = { | ||
success: container.success ? $(container.success) : $(container), | ||
... | ... | |
this.setOptions(options); | ||
var onComplete = this.options.onComplete || Prototype.emptyFunction; | ||
297 | | |
803 | this.options.onComplete = (function(transport, object) { | |
this.updateContent(); | ||
299 | | |
805 | onComplete(transport, object); | |
}).bind(this); | ||
this.request(url); | ||
... | ... | |
updateContent: function() { | ||
var receiver = this.responseIsSuccess() ? | ||
this.containers.success : this.containers.failure; | ||
814 | var response = this.transport.responseText; | |
309 | | |
310 | | |
311 | | |
816 | if (!this.options.evalScripts) | |
817 | response = response.stripScripts(); | |
if (receiver) { | ||
if (this.options.insertion) { | ||
new this.options.insertion(receiver, response); | ||
} else { | ||
317 | | |
823 | Element.update(receiver, response); | |
} | ||
} | ||
if (this.responseIsSuccess()) { | ||
if (this.onComplete) | ||
323 | | |
324 | | |
829 | setTimeout(this.onComplete.bind(this), 10); | |
} | ||
326 | ||
327 | | |
328 | | |
329 | | |
330 | | |
331 | | |
332 | | |
333 | | |
} | ||
}); | ||
Ajax.PeriodicalUpdater = Class.create(); | ||
338 | ||
835 | Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { | |
initialize: function(container, url, options) { | ||
this.setOptions(options); | ||
this.onComplete = this.options.onComplete; | ||
this.frequency = (this.options.frequency || 2); | ||
344 | | |
841 | this.decay = (this.options.decay || 1); | |
this.updater = {}; | ||
this.container = container; | ||
... | ... | |
stop: function() { | ||
this.updater.onComplete = undefined; | ||
clearTimeout(this.timer); | ||
361 | | |
858 | (this.onComplete || Prototype.emptyFunction).apply(this, arguments); | |
}, | ||
updateComplete: function(request) { | ||
if (this.options.decay) { | ||
366 | | |
863 | this.decay = (request.responseText == this.lastText ? | |
this.decay * this.options.decay : 1); | ||
this.lastText = request.responseText; | ||
} | ||
371 | | |
868 | this.timer = setTimeout(this.onTimerEvent.bind(this), | |
this.decay * this.frequency * 1000); | ||
}, | ||
... | ... | |
this.updater = new Ajax.Updater(this.container, this.url, this.options); | ||
} | ||
}); | ||
379 | ||
380 | ||
381 | | |
382 | | |
383 | | |
384 | | |
385 | | |
386 | | |
387 | | |
388 | | |
389 | | |
390 | | |
391 | | |
392 | | |
876 | function $() { | |
877 | var results = [], element; | |
878 | for (var i = 0; i < arguments.length; i++) { | |
879 | element = arguments[i]; | |
880 | if (typeof element == 'string') | |
881 | element = document.getElementById(element); | |
882 | results.push(Element.extend(element)); | |
} | ||
394 | | |
395 | | |
884 | return results.length < 2 ? results[0] : results; | |
} | ||
887 | document.getElementsByClassName = function(className, parentElement) { | |
888 | var children = ($(parentElement) || document.body).getElementsByTagName('*'); | |
889 | return $A(children).inject([], function(elements, child) { | |
890 | if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) | |
891 | elements.push(Element.extend(child)); | |
892 | return elements; | |
893 | }); | |
894 | } | |
895 | ||
/*--------------------------------------------------------------------------*/ | ||
400 | ||
898 | if (!window.Element) | |
var Element = new Object(); | ||
900 | ||
901 | Element.extend = function(element) { | |
902 | if (!element) return; | |
903 | ||
904 | if (!element._extended && element.tagName && element != window) { | |
905 | var methods = Element.Methods; | |
906 | for (property in methods) { | |
907 | var value = methods[property]; | |
908 | if (typeof value == 'function') | |
909 | element[property] = value.bind(null, element); | |
910 | } | |
911 | } | |
912 | ||
913 | element._extended = true; | |
914 | return element; | |
} | ||
404 | ||
917 | Element.Methods = { | |
918 | visible: function(element) { | |
919 | return $(element).style.display != 'none'; | |
920 | }, | |
921 | ||
toggle: function() { | ||
for (var i = 0; i < arguments.length; i++) { | ||
var element = $(arguments[i]); | ||
408 | | |
409 | | |
925 | Element[Element.visible(element) ? 'hide' : 'show'](element); | |
} | ||
}, | ||
... | ... | |
element = $(element); | ||
element.parentNode.removeChild(element); | ||
}, | ||
431 | | |
947 | ||
948 | update: function(element, html) { | |
949 | $(element).innerHTML = html.stripScripts(); | |
950 | setTimeout(function() {html.evalScripts()}, 10); | |
951 | }, | |
952 | ||
953 | replace: function(element, html) { | |
954 | element = $(element); | |
955 | if (element.outerHTML) { | |
956 | element.outerHTML = html.stripScripts(); | |
957 | } else { | |
958 | var range = element.ownerDocument.createRange(); | |
959 | range.selectNodeContents(element); | |
960 | element.parentNode.replaceChild( | |
961 | range.createContextualFragment(html.stripScripts()), element); | |
962 | } | |
963 | setTimeout(function() {html.evalScripts()}, 10); | |
964 | }, | |
965 | ||
getHeight: function(element) { | ||
element = $(element); | ||
434 | | |
968 | return element.offsetHeight; | |
}, | ||
971 | classNames: function(element) { | |
972 | return new Element.ClassNames(element); | |
973 | }, | |
974 | ||
hasClassName: function(element, className) { | ||
438 | | |
439 | | |
440 | | |
441 | | |
442 | | |
443 | | |
444 | | |
445 | | |
446 | | |
976 | if (!(element = $(element))) return; | |
977 | return Element.classNames(element).include(className); | |
}, | ||
addClassName: function(element, className) { | ||
450 | | |
451 | | |
452 | | |
981 | if (!(element = $(element))) return; | |
982 | return Element.classNames(element).add(className); | |
}, | ||
removeClassName: function(element, className) { | ||
456 | | |
457 | | |
458 | | |
459 | | |
460 | | |
461 | | |
462 | | |
463 | | |
464 | | |
465 | | |
466 | | |
467 | | |
468 | | |
986 | if (!(element = $(element))) return; | |
987 | return Element.classNames(element).remove(className); | |
}, | ||
470 | | |
989 | ||
// removes whitespace-only text node children | ||
cleanWhitespace: function(element) { | ||
473 | | |
992 | element = $(element); | |
for (var i = 0; i < element.childNodes.length; i++) { | ||
var node = element.childNodes[i]; | ||
476 | | |
995 | if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) | |
Element.remove(node); | ||
} | ||
998 | }, | |
999 | ||
1000 | empty: function(element) { | |
1001 | return $(element).innerHTML.match(/^\s*$/); | |
1002 | }, | |
1003 | ||
1004 | childOf: function(element, ancestor) { | |
1005 | element = $(element), ancestor = $(ancestor); | |
1006 | while (element = element.parentNode) | |
1007 | if (element == ancestor) return true; | |
1008 | return false; | |
1009 | }, | |
1010 | ||
1011 | scrollTo: function(element) { | |
1012 | element = $(element); | |
1013 | var x = element.x ? element.x : element.offsetLeft, | |
1014 | y = element.y ? element.y : element.offsetTop; | |
1015 | window.scrollTo(x, y); | |
1016 | }, | |
1017 | ||
1018 | getStyle: function(element, style) { | |
1019 | element = $(element); | |
1020 | var value = element.style[style.camelize()]; | |
1021 | if (!value) { | |
1022 | if (document.defaultView && document.defaultView.getComputedStyle) { | |
1023 | var css = document.defaultView.getComputedStyle(element, null); | |
1024 | value = css ? css.getPropertyValue(style) : null; | |
1025 | } else if (element.currentStyle) { | |
1026 | value = element.currentStyle[style.camelize()]; | |
1027 | } | |
1028 | } | |
1029 | ||
1030 | if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) | |
1031 | if (Element.getStyle(element, 'position') == 'static') value = 'auto'; | |
1032 | ||
1033 | return value == 'auto' ? null : value; | |
1034 | }, | |
1035 | ||
1036 | setStyle: function(element, style) { | |
1037 | element = $(element); | |
1038 | for (name in style) | |
1039 | element.style[name.camelize()] = style[name]; | |
1040 | }, | |
1041 | ||
1042 | getDimensions: function(element) { | |
1043 | element = $(element); | |
1044 | if (Element.getStyle(element, 'display') != 'none') | |
1045 | return {width: element.offsetWidth, height: element.offsetHeight}; | |
1046 | ||
1047 | // All *Width and *Height properties give 0 on elements with display none, | |
1048 | // so enable the element temporarily | |
1049 | var els = element.style; | |
1050 | var originalVisibility = els.visibility; | |
1051 | var originalPosition = els.position; | |
1052 | els.visibility = 'hidden'; | |
1053 | els.position = 'absolute'; | |
1054 | els.display = ''; | |
1055 | var originalWidth = element.clientWidth; | |
1056 | var originalHeight = element.clientHeight; | |
1057 | els.display = 'none'; | |
1058 | els.position = originalPosition; | |
1059 | els.visibility = originalVisibility; | |
1060 | return {width: originalWidth, height: originalHeight}; | |
1061 | }, | |
1062 | ||
1063 | makePositioned: function(element) { | |
1064 | element = $(element); | |
1065 | var pos = Element.getStyle(element, 'position'); | |
1066 | if (pos == 'static' || !pos) { | |
1067 | element._madePositioned = true; | |
1068 | element.style.position = 'relative'; | |
1069 | // Opera returns the offset relative to the positioning context, when an | |
1070 | // element is position relative but top and left have not been defined | |
1071 | if (window.opera) { | |
1072 | element.style.top = 0; | |
1073 | element.style.left = 0; | |
1074 | } | |
1075 | } | |
1076 | }, | |
1077 | ||
1078 | undoPositioned: function(element) { | |
1079 | element = $(element); | |
1080 | if (element._madePositioned) { | |
1081 | element._madePositioned = undefined; | |
1082 | element.style.position = | |
1083 | element.style.top = | |
1084 | element.style.left = | |
1085 | element.style.bottom = | |
1086 | element.style.right = ''; | |
1087 | } | |
1088 | }, | |
1089 | ||
1090 | makeClipping: function(element) { | |
1091 | element = $(element); | |
1092 | if (element._overflow) return; | |
1093 | element._overflow = element.style.overflow; | |
1094 | if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') | |
1095 | element.style.overflow = 'hidden'; | |
1096 | }, | |
1097 | ||
1098 | undoClipping: function(element) { | |
1099 | element = $(element); | |
1100 | if (element._overflow) return; | |
1101 | element.style.overflow = element._overflow; | |
1102 | element._overflow = undefined; | |
} | ||
480 | ||
1104 | } | |
1106 | Object.extend(Element, Element.Methods); | |
1107 | ||
var Toggle = new Object(); | ||
Toggle.display = Element.toggle; | ||
... | ... | |
Abstract.Insertion.prototype = { | ||
initialize: function(element, content) { | ||
this.element = $(element); | ||
494 | | |
495 | | |
1120 | this.content = content.stripScripts(); | |
1121 | ||
if (this.adjacency && this.element.insertAdjacentHTML) { | ||
497 | | |
1123 | try { | |
1124 | this.element.insertAdjacentHTML(this.adjacency, this.content); | |
1125 | } catch (e) { | |
1126 | if (this.element.tagName.toLowerCase() == 'tbody') { | |
1127 | this.insertContent(this.contentFromAnonymousTable()); | |
1128 | } else { | |
1129 | throw e; | |
1130 | } | |
1131 | } | |
} else { | ||
this.range = this.element.ownerDocument.createRange(); | ||
if (this.initializeRange) this.initializeRange(); | ||
501 | | |
502 | | |
1135 | this.insertContent([this.range.createContextualFragment(this.content)]); | |
} | ||
1137 | ||
1138 | setTimeout(function() {content.evalScripts()}, 10); | |
1139 | }, | |
1140 | ||
1141 | contentFromAnonymousTable: function() { | |
1142 | var div = document.createElement('div'); | |
1143 | div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; | |
1144 | return $A(div.childNodes[0].childNodes[0].childNodes); | |
} | ||
} | ||
var Insertion = new Object(); | ||
Insertion.Before = Class.create(); | ||
510 | ||
1151 | Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { | |
initializeRange: function() { | ||
this.range.setStartBefore(this.element); | ||
}, | ||
514 | | |
515 | | |
516 | | |
1155 | ||
1156 | insertContent: function(fragments) { | |
1157 | fragments.each((function(fragment) { | |
1158 | this.element.parentNode.insertBefore(fragment, this.element); | |
1159 | }).bind(this)); | |
} | ||
}); | ||
Insertion.Top = Class.create(); | ||
521 | ||
1164 | Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { | |
initializeRange: function() { | ||
this.range.selectNodeContents(this.element); | ||
this.range.collapse(true); | ||
}, | ||
526 | | |
527 | | |
528 | | |
1169 | ||
1170 | insertContent: function(fragments) { | |
1171 | fragments.reverse(false).each((function(fragment) { | |
1172 | this.element.insertBefore(fragment, this.element.firstChild); | |
1173 | }).bind(this)); | |
} | ||
}); | ||
Insertion.Bottom = Class.create(); | ||
533 | ||
1178 | Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { | |
initializeRange: function() { | ||
this.range.selectNodeContents(this.element); | ||
this.range.collapse(this.element); | ||
}, | ||
538 | | |
539 | | |
540 | | |
1183 | ||
1184 | insertContent: function(fragments) { | |
1185 | fragments.each((function(fragment) { | |
1186 | this.element.appendChild(fragment); | |
1187 | }).bind(this)); | |
} | ||
}); | ||
Insertion.After = Class.create(); | ||
545 | ||
1192 | Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { | |
initializeRange: function() { | ||
this.range.setStartAfter(this.element); | ||
}, | ||
549 | | |
550 | | |
551 | | |
552 | | |
1196 | ||
1197 | insertContent: function(fragments) { | |
1198 | fragments.each((function(fragment) { | |
1199 | this.element.parentNode.insertBefore(fragment, | |
1200 | this.element.nextSibling); | |
1201 | }).bind(this)); | |
} | ||
}); | ||
1205 | /*--------------------------------------------------------------------------*/ | |
1206 | ||
1207 | Element.ClassNames = Class.create(); | |
1208 | Element.ClassNames.prototype = { | |
1209 | initialize: function(element) { | |
1210 | this.element = $(element); | |
1211 | }, | |
1212 | ||
1213 | _each: function(iterator) { | |
1214 | this.element.className.split(/\s+/).select(function(name) { | |
1215 | return name.length > 0; | |
1216 | })._each(iterator); | |
1217 | }, | |
1218 | ||
1219 | set: function(className) { | |
1220 | this.element.className = className; | |
1221 | }, | |
1222 | ||
1223 | add: function(classNameToAdd) { | |
1224 | if (this.include(classNameToAdd)) return; | |
1225 | this.set(this.toArray().concat(classNameToAdd).join(' ')); | |
1226 | }, | |
1227 | ||
1228 | remove: function(classNameToRemove) { | |
1229 | if (!this.include(classNameToRemove)) return; | |
1230 | this.set(this.select(function(className) { | |
1231 | return className != classNameToRemove; | |
1232 | }).join(' ')); | |
1233 | }, | |
1234 | ||
1235 | toString: function() { | |
1236 | return this.toArray().join(' '); | |
1237 | } | |
1238 | } | |
1239 | ||
1240 | Object.extend(Element.ClassNames.prototype, Enumerable); | |
1241 | var Selector = Class.create(); | |
1242 | Selector.prototype = { | |
1243 | initialize: function(expression) { | |
1244 | this.params = {classNames: []}; | |
1245 | this.expression = expression.toString().strip(); | |
1246 | this.parseExpression(); | |
1247 | this.compileMatcher(); | |
1248 | }, | |
1249 | ||
1250 | parseExpression: function() { | |
1251 | function abort(message) { throw 'Parse error in selector: ' + message; } | |
1252 | ||
1253 | if (this.expression == '') abort('empty expression'); | |
1254 | ||
1255 | var params = this.params, expr = this.expression, match, modifier, clause, rest; | |
1256 | while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) { | |
1257 | params.attributes = params.attributes || []; | |
1258 | params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''}); | |
1259 | expr = match[1]; | |
1260 | } | |
1261 | ||
1262 | if (expr == '*') return this.params.wildcard = true; | |
1263 | ||
1264 | while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) { | |
1265 | modifier = match[1], clause = match[2], rest = match[3]; | |
1266 | switch (modifier) { | |
1267 | case '#': params.id = clause; break; | |
1268 | case '.': params.classNames.push(clause); break; | |
1269 | case '': | |
1270 | case undefined: params.tagName = clause.toUpperCase(); break; | |
1271 | default: abort(expr.inspect()); | |
1272 | } | |
1273 | expr = rest; | |
1274 | } | |
1275 | ||
1276 | if (expr.length > 0) abort(expr.inspect()); | |
1277 | }, | |
1278 | ||
1279 | buildMatchExpression: function() { | |
1280 | var params = this.params, conditions = [], clause; | |
1281 | ||
1282 | if (params.wildcard) | |
1283 | conditions.push('true'); | |
1284 | if (clause = params.id) | |
1285 | conditions.push('element.id == ' + clause.inspect()); | |
1286 | if (clause = params.tagName) | |
1287 | conditions.push('element.tagName.toUpperCase() == ' + clause.inspect()); | |
1288 | if ((clause = params.classNames).length > 0) | |
1289 | for (var i = 0; i < clause.length; i++) | |
1290 | conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')'); | |
1291 | if (clause = params.attributes) { | |
1292 | clause.each(function(attribute) { | |
1293 | var value = 'element.getAttribute(' + attribute.name.inspect() + ')'; | |
1294 | var splitValueBy = function(delimiter) { | |
1295 | return value + ' && ' + value + '.split(' + delimiter.inspect() + ')'; | |
1296 | } | |
1297 | ||
1298 | switch (attribute.operator) { | |
1299 | case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break; | |
1300 | case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break; | |
1301 | case '|=': conditions.push( | |
1302 | splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect() | |
1303 | ); break; | |
1304 | case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break; | |
1305 | case '': | |
1306 | case undefined: conditions.push(value + ' != null'); break; | |
1307 | default: throw 'Unknown operator ' + attribute.operator + ' in selector'; | |
1308 | } | |
1309 | }); | |
1310 | } | |
1311 | ||
1312 | return conditions.join(' && '); | |
1313 | }, | |
1314 | ||
1315 | compileMatcher: function() { | |
1316 | this.match = new Function('element', 'if (!element.tagName) return false; \ | |
1317 | return ' + this.buildMatchExpression()); | |
1318 | }, | |
1319 | ||
1320 | findElements: function(scope) { | |
1321 | var element; | |
1322 | ||
1323 | if (element = $(this.params.id)) | |
1324 | if (this.match(element)) | |
1325 | if (!scope || Element.childOf(element, scope)) | |
1326 | return [element]; | |
1327 | ||
1328 | scope = (scope || document).getElementsByTagName(this.params.tagName || '*'); | |
1329 | ||
1330 | var results = []; | |
1331 | for (var i = 0; i < scope.length; i++) | |
1332 | if (this.match(element = scope[i])) | |
1333 | results.push(Element.extend(element)); | |
1334 | ||
1335 | return results; | |
1336 | }, | |
1337 | ||
1338 | toString: function() { | |
1339 | return this.expression; | |
1340 | } | |
1341 | } | |
1342 | ||
1343 | function $$() { | |
1344 | return $A(arguments).map(function(expression) { | |
1345 | return expression.strip().split(/\s+/).inject([null], function(results, expr) { | |
1346 | var selector = new Selector(expr); | |
1347 | return results.map(selector.findElements.bind(selector)).flatten(); | |
1348 | }); | |
1349 | }).flatten(); | |
1350 | } | |
var Field = { | ||
clear: function() { | ||
for (var i = 0; i < arguments.length; i++) | ||
... | ... | |
focus: function(element) { | ||
$(element).focus(); | ||
}, | ||
565 | | |
1360 | ||
present: function() { | ||
for (var i = 0; i < arguments.length; i++) | ||
if ($(arguments[i]).value == '') return false; | ||
return true; | ||
}, | ||
571 | | |
1366 | ||
select: function(element) { | ||
$(element).select(); | ||
}, | ||
575 | | |
1370 | ||
activate: function(element) { | ||
577 | | |
578 | | |
1372 | element = $(element); | |
1373 | element.focus(); | |
1374 | if (element.select) | |
1375 | element.select(); | |
} | ||
} | ||
... | ... | |
serialize: function(form) { | ||
var elements = Form.getElements($(form)); | ||
var queryComponents = new Array(); | ||
588 | | |
1385 | ||
for (var i = 0; i < elements.length; i++) { | ||
var queryComponent = Form.Element.serialize(elements[i]); | ||
if (queryComponent) | ||
queryComponents.push(queryComponent); | ||
} | ||
594 | | |
1391 | ||
return queryComponents.join('&'); | ||
}, | ||
597 | | |
1394 | ||
getElements: function(form) { | ||
599 | | |
1396 | form = $(form); | |
var elements = new Array(); | ||
for (tagName in Form.Element.Serializers) { | ||
... | ... | |
} | ||
return elements; | ||
}, | ||
609 | | |
1406 | ||
getInputs: function(form, typeName, name) { | ||
611 | | |
1408 | form = $(form); | |
var inputs = form.getElementsByTagName('input'); | ||
613 | | |
1410 | ||
if (!typeName && !name) | ||
return inputs; | ||
616 | | |
1413 | ||
var matchingInputs = new Array(); | ||
for (var i = 0; i < inputs.length; i++) { | ||
var input = inputs[i]; | ||
if ((typeName && input.type != typeName) || | ||
621 | | |
1418 | (name && input.name != name)) | |
continue; | ||
matchingInputs.push(input); | ||
} | ||
... | ... | |
} | ||
}, | ||
1443 | findFirstElement: function(form) { | |
1444 | return Form.getElements(form).find(function(element) { | |
1445 | return element.type != 'hidden' && !element.disabled && | |
1446 | ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); | |
1447 | }); | |
1448 | }, | |
1449 | ||
focusFirstElement: function(form) { | ||
647 | | |
648 | | |
649 | | |
650 | | |
651 | | |
652 | | |
653 | | |
654 | | |
655 | | |
1451 | Field.activate(Form.findFirstElement(form)); | |
}, | ||
reset: function(form) { | ||
... | ... | |
Form.Element = { | ||
serialize: function(element) { | ||
665 | | |
1461 | element = $(element); | |
var method = element.tagName.toLowerCase(); | ||
var parameter = Form.Element.Serializers[method](element); | ||
668 | | |
669 | | |
670 | | |
671 | | |
1464 | ||
1465 | if (parameter) { | |
1466 | var key = encodeURIComponent(parameter[0]); | |
1467 | if (key.length == 0) return; | |
1468 | ||
1469 | if (parameter[1].constructor != Array) | |
1470 | parameter[1] = [parameter[1]]; | |
1471 | ||
1472 | return parameter[1].map(function(value) { | |
1473 | return key + '=' + encodeURIComponent(value); | |
1474 | }).join('&'); | |
1475 | } | |
}, | ||
673 | | |
1477 | ||
getValue: function(element) { | ||
675 | | |
1479 | element = $(element); | |
var method = element.tagName.toLowerCase(); | ||
var parameter = Form.Element.Serializers[method](element); | ||
678 | | |
679 | | |
1482 | ||
1483 | if (parameter) | |
return parameter[1]; | ||
} | ||
} | ||
... | ... | |
case 'password': | ||
case 'text': | ||
return Form.Element.Serializers.textarea(element); | ||
692 | | |
1496 | case 'checkbox': | |
case 'radio': | ||
return Form.Element.Serializers.inputSelector(element); | ||
} | ||
... | ... | |
}, | ||
select: function(element) { | ||
709 | | |
710 | | |
711 | | |
712 | | |
713 | | |
714 | | |
715 | | |
716 | | |
717 | | |
718 | | |
719 | | |
1513 | return Form.Element.Serializers[element.type == 'select-one' ? | |
1514 | 'selectOne' : 'selectMany'](element); | |
1515 | }, | |
1516 | ||
1517 | selectOne: function(element) { | |
1518 | var value = '', opt, index = element.selectedIndex; | |
1519 | if (index >= 0) { | |
1520 | opt = element.options[index]; | |
1521 | value = opt.value; | |
1522 | if (!value && !('value' in opt)) | |
1523 | value = opt.text; | |
1524 | } | |
1525 | return [element.name, value]; | |
1526 | }, | |
1527 | ||
1528 | selectMany: function(element) { | |
1529 | var value = new Array(); | |
1530 | for (var i = 0; i < element.length; i++) { | |
1531 | var opt = element.options[i]; | |
1532 | if (opt.selected) { | |
1533 | var optValue = opt.value; | |
1534 | if (!optValue && !('value' in opt)) | |
1535 | optValue = opt.text; | |
1536 | value.push(optValue); | |
} | ||
} | ||
return [element.name, value]; | ||
... | ... | |
this.frequency = frequency; | ||
this.element = $(element); | ||
this.callback = callback; | ||
738 | | |
1555 | ||
this.lastValue = this.getValue(); | ||
this.registerCallback(); | ||
}, | ||
742 | | |
1559 | ||
registerCallback: function() { | ||
setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); | ||
}, | ||
746 | | |
1563 | ||
onTimerEvent: function() { | ||
var value = this.getValue(); | ||
if (this.lastValue != value) { | ||
... | ... | |
} | ||
Form.Element.Observer = Class.create(); | ||
757 | ||
1574 | Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { | |
getValue: function() { | ||
return Form.Element.getValue(this.element); | ||
} | ||
}); | ||
Form.Observer = Class.create(); | ||
764 | ||
1581 | Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { | |
getValue: function() { | ||
return Form.serialize(this.element); | ||
} | ||
... | ... | |
initialize: function(element, callback) { | ||
this.element = $(element); | ||
this.callback = callback; | ||
777 | | |
1594 | ||
this.lastValue = this.getValue(); | ||
if (this.element.tagName.toLowerCase() == 'form') | ||
this.registerFormCallbacks(); | ||
else | ||
this.registerCallback(this.element); | ||
}, | ||
784 | | |
1601 | ||
onElementEvent: function() { | ||
var value = this.getValue(); | ||
if (this.lastValue != value) { | ||
... | ... | |
this.lastValue = value; | ||
} | ||
}, | ||
792 | | |
1609 | ||
registerFormCallbacks: function() { | ||
var elements = Form.getElements(this.element); | ||
for (var i = 0; i < elements.length; i++) | ||
this.registerCallback(elements[i]); | ||
}, | ||
798 | | |
1615 | ||
registerCallback: function(element) { | ||
if (element.type) { | ||
switch (element.type.toLowerCase()) { | ||
802 | | |
1619 | case 'checkbox': | |
case 'radio': | ||
804 | | |
805 | | |
806 | | |
807 | | |
808 | | |
809 | | |
1621 | Event.observe(element, 'click', this.onElementEvent.bind(this)); | |
break; | ||
case 'password': | ||
case 'text': | ||
case 'textarea': | ||
case 'select-one': | ||
case 'select-multiple': | ||
816 | | |
817 | | |
818 | | |
819 | | |
820 | | |
821 | | |
1628 | Event.observe(element, 'change', this.onElementEvent.bind(this)); | |
break; | ||
} | ||
824 | | |
1631 | } | |
} | ||
} | ||
Form.Element.EventObserver = Class.create(); | ||
829 | ||
1636 | Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { | |
getValue: function() { | ||
return Form.Element.getValue(this.element); | ||
} | ||
}); | ||
Form.EventObserver = Class.create(); | ||
836 | ||
1643 | Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { | |
getValue: function() { | ||
return Form.serialize(this.element); | ||
} | ||
}); | ||
841 | ||
842 | ||
if (!window.Event) { | ||
var Event = new Object(); | ||
} | ||
... | ... | |
}, | ||
pointerX: function(event) { | ||
868 | | |
1673 | return event.pageX || (event.clientX + | |
(document.documentElement.scrollLeft || document.body.scrollLeft)); | ||
}, | ||
pointerY: function(event) { | ||
873 | | |
1678 | return event.pageY || (event.clientY + | |
(document.documentElement.scrollTop || document.body.scrollTop)); | ||
}, | ||
stop: function(event) { | ||
878 | | |
879 | | |
880 | | |
1683 | if (event.preventDefault) { | |
1684 | event.preventDefault(); | |
1685 | event.stopPropagation(); | |
} else { | ||
event.returnValue = false; | ||
1688 | event.cancelBubble = true; | |
} | ||
}, | ||
... | ... | |
}, | ||
observers: false, | ||
897 | | |
1703 | ||
_observeAndCache: function(element, name, observer, useCapture) { | ||
if (!this.observers) this.observers = []; | ||
if (element.addEventListener) { | ||
... | ... | |
element.attachEvent('on' + name, observer); | ||
} | ||
}, | ||
908 | | |
1714 | ||
unloadCache: function() { | ||
if (!Event.observers) return; | ||
for (var i = 0; i < Event.observers.length; i++) { | ||
... | ... | |
observe: function(element, name, observer, useCapture) { | ||
var element = $(element); | ||
useCapture = useCapture || false; | ||
921 | | |
1727 | ||
if (name == 'keypress' && | ||
923 | | |
1729 | (navigator.appVersion.match(/Konqueror|Safari|KHTML/) | |
|| element.attachEvent)) | ||
name = 'keydown'; | ||
926 | | |
1732 | ||
this._observeAndCache(element, name, observer, useCapture); | ||
}, | ||
stopObserving: function(element, name, observer, useCapture) { | ||
var element = $(element); | ||
useCapture = useCapture || false; | ||
933 | | |
1739 | ||
if (name == 'keypress' && | ||
935 | | |
1741 | (navigator.appVersion.match(/Konqueror|Safari|KHTML/) | |
|| element.detachEvent)) | ||
name = 'keydown'; | ||
938 | | |
1744 | ||
if (element.removeEventListener) { | ||
element.removeEventListener(name, observer, useCapture); | ||
} else if (element.detachEvent) { | ||
... | ... | |
/* prevent memory leaks in IE */ | ||
Event.observe(window, 'unload', Event.unloadCache, false); | ||
949 | ||
var Position = { | ||
951 | ||
// set to true if needed, warning: firefox performance problems | ||
// NOT neeeded for page scrolling, only if draggable contained in | ||
// scrollable elements | ||
955 | | |
1759 | includeScrollOffsets: false, | |
// must be called before calling withinIncludingScrolloffset, every time the | ||
// page is scrolled | ||
prepare: function() { | ||
960 | | |
961 | | |
962 | | |
1764 | this.deltaX = window.pageXOffset | |
1765 | || document.documentElement.scrollLeft | |
1766 | || document.body.scrollLeft | |
|| 0; | ||
964 | | |
965 | | |
966 | | |
1768 | this.deltaY = window.pageYOffset | |
1769 | || document.documentElement.scrollTop | |
1770 | || document.body.scrollTop | |
|| 0; | ||
}, | ||
... | ... | |
var valueT = 0, valueL = 0; | ||
do { | ||
valueT += element.scrollTop || 0; | ||
974 | | |
1778 | valueL += element.scrollLeft || 0; | |
element = element.parentNode; | ||
} while (element); | ||
return [valueL, valueT]; | ||
... | ... | |
return [valueL, valueT]; | ||
}, | ||
1794 | positionedOffset: function(element) { | |
1795 | var valueT = 0, valueL = 0; | |
1796 | do { | |
1797 | valueT += element.offsetTop || 0; | |
1798 | valueL += element.offsetLeft || 0; | |
1799 | element = element.offsetParent; | |
1800 | if (element) { | |
1801 | p = Element.getStyle(element, 'position'); | |
1802 | if (p == 'relative' || p == 'absolute') break; | |
1803 | } | |
1804 | } while (element); | |
1805 | return [valueL, valueT]; | |
1806 | }, | |
1807 | ||
1808 | offsetParent: function(element) { | |
1809 | if (element.offsetParent) return element.offsetParent; | |
1810 | if (element == document.body) return element; | |
1811 | ||
1812 | while ((element = element.parentNode) && element != document.body) | |
1813 | if (Element.getStyle(element, 'position') != 'static') | |
1814 | return element; | |
1815 | ||
1816 | return document.body; | |
1817 | }, | |
1818 | ||
// caches x/y coordinate pair to use with overlap | ||
within: function(element, x, y) { | ||
if (this.includeScrollOffsets) | ||
... | ... | |
return (y >= this.offset[1] && | ||
y < this.offset[1] + element.offsetHeight && | ||
1000 | | |
1829 | x >= this.offset[0] && | |
x < this.offset[0] + element.offsetWidth); | ||
}, | ||
... | ... | |
return (this.ycomp >= this.offset[1] && | ||
this.ycomp < this.offset[1] + element.offsetHeight && | ||
1013 | | |
1842 | this.xcomp >= this.offset[0] && | |
this.xcomp < this.offset[0] + element.offsetWidth); | ||
}, | ||
// within must be called directly before | ||
1018 | | |
1019 | | |
1020 | | |
1021 | | |
1847 | overlap: function(mode, element) { | |
1848 | if (!mode) return 0; | |
1849 | if (mode == 'vertical') | |
1850 | return ((this.offset[1] + element.offsetHeight) - this.ycomp) / | |
element.offsetHeight; | ||
if (mode == 'horizontal') | ||
1024 | | |
1853 | return ((this.offset[0] + element.offsetWidth) - this.xcomp) / | |
element.offsetWidth; | ||
}, | ||
... | ... | |
target.style.left = offsets[0] + 'px'; | ||
target.style.width = source.offsetWidth + 'px'; | ||
target.style.height = source.offsetHeight + 'px'; | ||
1866 | }, | |
1867 | ||
1868 | page: function(forElement) { | |
1869 | var valueT = 0, valueL = 0; | |
1870 | ||
1871 | var element = forElement; | |
1872 | do { | |
1873 | valueT += element.offsetTop || 0; | |
1874 | valueL += element.offsetLeft || 0; | |
1875 | ||
1876 | // Safari fix | |
1877 | if (element.offsetParent==document.body) | |
1878 | if (Element.getStyle(element,'position')=='absolute') break; | |
1879 | ||
1880 | } while (element = element.offsetParent); | |
1881 | ||
1882 | element = forElement; | |
1883 | do { | |
1884 | valueT -= element.scrollTop || 0; | |
1885 | valueL -= element.scrollLeft || 0; | |
1886 | } while (element = element.parentNode); | |
1887 | ||
1888 | return [valueL, valueT]; | |
1889 | }, | |
1890 | ||
1891 | clone: function(source, target) { | |
1892 | var options = Object.extend({ | |
1893 | setLeft: true, | |
1894 | setTop: true, | |
1895 | setWidth: true, | |
1896 | setHeight: true, | |
1897 | offsetTop: 0, | |
1898 | offsetLeft: 0 | |
1899 | }, arguments[2] || {}) | |
1900 | ||
1901 | // find page position of source | |
1902 | source = $(source); | |
1903 | var p = Position.page(source); | |
1904 | ||
1905 | // find coordinate system to use | |
1906 | target = $(target); | |
1907 | var delta = [0, 0]; | |
1908 | var parent = null; | |
1909 | // delta [0,0] will do fine with position: fixed elements, | |
1910 | // position:absolute needs offsetParent deltas | |
1911 | if (Element.getStyle(target,'position') == 'absolute') { | |
1912 | parent = Position.offsetParent(target); | |
1913 | delta = Position.page(parent); | |
1914 | } | |
1915 | ||
1916 | // correct by body offsets (fixes Safari) | |
1917 | if (parent == document.body) { | |
1918 | delta[0] -= document.body.offsetLeft; | |
1919 | delta[1] -= document.body.offsetTop; | |
1920 | } | |
1921 | ||
1922 | // set position | |
1923 | if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; | |
1924 | if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; | |
1925 | if(options.setWidth) target.style.width = source.offsetWidth + 'px'; | |
1926 | if(options.setHeight) target.style.height = source.offsetHeight + 'px'; | |
1927 | }, | |
1928 | ||
1929 | absolutize: function(element) { | |
1930 | element = $(element); | |
1931 | if (element.style.position == 'absolute') return; | |
1932 | Position.prepare(); | |
1933 | ||
1934 | var offsets = Position.positionedOffset(element); | |
1935 | var top = offsets[1]; | |
1936 | var left = offsets[0]; | |
1937 | var width = element.clientWidth; | |
1938 | var height = element.clientHeight; | |
1939 | ||
1940 | element._originalLeft = left - parseFloat(element.style.left || 0); | |
1941 | element._originalTop = top - parseFloat(element.style.top || 0); | |
1942 | element._originalWidth = element.style.width; | |
1943 | element._originalHeight = element.style.height; | |
1944 | ||
1945 | element.style.position = 'absolute'; | |
1946 | element.style.top = top + 'px';; | |
1947 | element.style.left = left + 'px';; | |
1948 | element.style.width = width + 'px';; | |
1949 | element.style.height = height + 'px';; | |
1950 | }, | |
1951 | ||
1952 | relativize: function(element) { | |
1953 | element = $(element); | |
1954 | if (element.style.position == 'relative') return; | |
1955 | Position.prepare(); | |
1956 | ||
1957 | element.style.position = 'relative'; | |
1958 | var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); | |
1959 | var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); | |
1960 | ||
1961 | element.style.top = top + 'px'; | |
1962 | element.style.left = left + 'px'; | |
1963 | element.style.height = element._originalHeight; | |
1964 | element.style.width = element._originalWidth; | |
} | ||
} | ||
1967 | ||
1968 | // Safari returns margins on body which is incorrect if the child is absolutely | |
1969 | // positioned. For performance reasons, redefine Position.cumulativeOffset for | |
1970 | // KHTML/WebKit only. | |
1971 | if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { | |
1972 | Position.cumulativeOffset = function(element) { | |
1973 | var valueT = 0, valueL = 0; | |
1974 | do { | |
1975 | valueT += element.offsetTop || 0; | |
1976 | valueL += element.offsetLeft || 0; | |
1977 | if (element.offsetParent == document.body) | |
1978 | if (Element.getStyle(element, 'position') == 'absolute') break; | |
1979 | ||
1980 | element = element.offsetParent; | |
1981 | } while (element); | |
1982 | ||
1983 | return [valueL, valueT]; | |
1984 | } | |
1985 | } | |
rool/rails/typo/trunk/public/javascripts/typo.js:
prev. | current | |
function register_onload(func) { | ||
2 | | |
3 | | |
4 | | |
2 | Event.observe(window, 'load', func, false); | |
} | ||
function show_dates_as_local_time() { | ||
... | ... | |
} | ||
function commentAdded(request) { | ||
45 | Element.cleanWhitespace('commentList'); | |
new Effect.BlindDown($('commentList').lastChild); | ||
47 | if ($('dummy_comment')) { Element.remove('dummy_comment'); } | |
$('commentform').elements[3].value = ''; | ||
$('commentform').elements[3].focus(); | ||
} | ||
... | ... | |
function loading() { | ||
$('form-submit-button').disabled = true; | ||
Element.show('comment_loading'); | ||
60 | new Element.hide('preview'); | |
} | ||
function complete(request) { | ||
... | ... | |
register_onload(function() { | ||
if ($('commentform')) { | ||
72 | | |
73 | | |
73 | var _author = getCookie('author'); | |
74 | var _url = getCookie('url'); | |
75 | ||
76 | if(_author != null) { $('commentform').elements['comment[author]'].value = _author } | |
77 | if(_url != null) { $('commentform').elements['comment[url]'].value = _url } | |
if ($('commentform').elements['comment[url]'].value != '' | ||
|| $('commentform').elements['comment[email]'].value != '') { |
rool/rails/typo/trunk/public/stylesheets/administration.css:
prev. | current | |
color: #333; | ||
} | ||
74 | hr { | |
75 | border: none; | |
76 | border-bottom: 1px solid #7D8692; | |
77 | } | |
/* | ||
* =PRIMARY NAVIGATION | ||
*/ | ||
... | ... | |
padding: 0; | ||
margin: 0 0 0 30px; | ||
font-family: sans-serif, Arial, Helvetica; | ||
91 | | |
95 | font-size: 0.8em; | |
line-height: normal; | ||
} | ||
... | ... | |
border: 4px double #ccc; | ||
padding: 5px; | ||
z-index: 9999; | ||
286 | | |
290 | width: 48%; | |
float: right; | ||
clear: right; | ||
margin-bottom: 10px; | ||
... | ... | |
margin-left: 10px; | ||
border-top: none; | ||
} | ||
504 | ||
#quick-navigate { | ||
background: #c8d9ed; | ||
padding: 2px 5px 0px 5px; | ||
... | ... | |
margin-left: 10px; | ||
border-top: none; | ||
} | ||
512 | #edit-resource-metadata { | |
513 | background: #c8d9ed; | |
514 | padding: 1px; | |
515 | border: 1px solid #9cabba; | |
516 | margin-left: 0px; | |
517 | border-top: none; | |
518 | } | |
520 | #add-resource-metadata { | |
521 | background: #c8d9ed; | |
522 | padding: 1px; | |
523 | border: 1px solid #9cabba; | |
524 | margin-left: 0px; | |
525 | } | |
#advanced { line-height: 1.3em; } | ||
#advanced label { | ||
... | ... | |
border: 1px solid red; | ||
} | ||
549 | #flash span { | |
550 | padding: 5px; | |
551 | margin-top: 10px; | |
552 | color: #0C2504; | |
553 | display: block; | |
554 | } | |
532 | ||
556 | #flash .notice { | |
background: #CBE4C3; | ||
534 | | |
535 | | |
border-top: 1px solid #2E9410; | ||
border-bottom: 1px solid #2E9410; | ||
538 | | |
} | ||
561 | ||
562 | #flash .error { | |
563 | background: #e99; | |
564 | border-top: 1px solid #822; | |
565 | border-bottom: 1px solid #822; | |
566 | } | |
567 | ||
568 | #category_list { | |
569 | list-style: none; | |
570 | margin: 0; | |
571 | padding: 0; | |
572 | margin-top: 10px; | |
573 | width: 300px; | |
574 | } | |
575 | ||
576 | #category_list li { | |
577 | cursor: move; | |
578 | border-bottom: 1px dotted #ccc; | |
579 | } | |
580 | ||
581 | #footer { | |
582 | font-size: 0.8em; | |
583 | color: #888; | |
584 | font-style: italic; | |
585 | } |
rool/rails/typo/trunk/script/breakpointer:
prev. | current | |
#!/usr/bin/env ruby | ||
2 | ||
3 | ||
4 | ||
2 | require File.dirname(__FILE__) + '/../config/boot' | |
3 | require 'commands/breakpointer' |
rool/rails/typo/trunk/script/console:
prev. | current | |
#!/usr/bin/env ruby | ||
2 | ||
3 | ||
4 | ||
5 | ||
6 | ||
7 | | |
8 | | |
9 | | |
10 | ||
11 | ||
12 | ||
13 | ||
14 | ||
15 | ||
16 | ||
17 | ||
18 | | |
19 | | |
20 | ||
21 | | |
22 | ||
23 | ||
2 | require File.dirname(__FILE__) + '/../config/boot' | |
3 | require 'commands/console' |
rool/rails/typo/trunk/script/destroy:
prev. | current | |
#!/usr/bin/env ruby | ||
2 | ||
3 | ||
4 | ||
5 | ||
6 | ||
7 | ||
2 | require File.dirname(__FILE__) + '/../config/boot' | |
3 | require 'commands/destroy' |
rool/rails/typo/trunk/script/generate:
prev. | current | |
#!/usr/bin/env ruby | ||
2 | ||
3 | ||
4 | ||
5 | ||
6 | ||
7 | ||
2 | require File.dirname(__FILE__) + '/../config/boot' | |
3 | require 'commands/generate' |
rool/rails/typo/trunk/script/process/reaper:
prev. | current | |
1 | ||
2 | ||
3 | ||
4 | ||
5 | ||
6 | ||
7 | ||
8 | | |
9 | | |
10 | | |
11 | ||
12 | ||
13 | ||
14 | ||
15 | ||
16 | | |
17 | | |
18 | | |
19 | ||
20 | | |
21 | | |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | ||
30 | | |
31 | | |
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | ||
38 | | |
39 | | |
40 | | |
41 | | |
42 | | |
43 | ||
44 | | |
45 | | |
46 | | |
47 | ||
48 | | |
49 | | |
50 | ||
51 | | |
52 | | |
53 | | |
54 | ||
55 | | |
56 | | |
57 | | |
58 | ||
59 | | |
60 | | |
61 | | |
62 | ||
63 | | |
64 | | |
65 | | |
66 | ||
67 | | |
68 | | |
69 | | |
70 | ||
71 | ||
72 | ||
73 | | |
74 | | |
75 | | |
76 | | |
77 | | |
78 | | |
79 | ||
80 | ||
81 | ||
82 | | |
83 | ||
84 | | |
85 | ||
86 | | |
87 | | |
88 | | |
89 | | |
90 | | |
91 | ||
92 | | |
93 | ||
94 | | |
95 | | |
96 | | |
97 | ||
98 | | |
99 | | |
100 | | |
101 | ||
102 | | |
103 | | |
104 | | |
105 | | |
106 | ||
107 | | |
108 | | |
109 | | |
110 | | |
111 | ||
112 | | |
113 | ||
114 | | |
115 | | |
116 | | |
117 | | |
118 | | |
119 | | |
120 | ||
121 | | |
122 | ||
123 | | |
124 | ||
125 | | |
126 | ||
127 | ||
128 | ||
129 | ||
130 | ||
131 | ||
2 | #!/usr/bin/env ruby | |
3 | require File.dirname(__FILE__) + '/../../config/boot' | |
4 | require 'commands/process/reaper' |
rool/rails/typo/trunk/script/process/spawner:
prev. | current | |
1 | ||
2 | ||
3 | ||
4 | ||
5 | ||
6 | | |
7 | | |
8 | ||
9 | ||
10 | ||
11 | | |
12 | | |
13 | | |
14 | | |
15 | | |
16 | ||
17 | ||
18 | ||
19 | | |
20 | ||
21 | | |
22 | ||
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | ||
30 | | |
31 | | |
32 | ||
33 | | |
34 | | |
35 | | |
36 | | |
37 | ||
38 | | |
39 | ||
40 | | |
41 | | |
42 | | |
43 | | |
44 | | |
45 | ||
46 | | |
47 | ||
48 | | |
49 | ||
50 | | |
51 | ||
52 | ||
53 | ||
54 | ||
2 | #!/usr/bin/env ruby | |
3 | require File.dirname(__FILE__) + '/../../config/boot' | |
4 | require 'commands/process/spawner' |
rool/rails/typo/trunk/script/process/spinner:
prev. | current | |
1 | ||
2 | ||
3 | ||
4 | ||
5 | ||
6 | | |
7 | | |
8 | | |
9 | | |
10 | | |
11 | | |
12 | | |
13 | | |
14 | ||
15 | ||
16 | ||
17 | | |
18 | | |
19 | | |
20 | | |
21 | ||
22 | ||
23 | ||
24 | | |
25 | ||
26 | | |
27 | ||
28 | | |
29 | | |
30 | | |
31 | | |
32 | | |
33 | ||
34 | | |
35 | | |
36 | | |
37 | | |
38 | | |
39 | ||
40 | | |
41 | ||
42 | | |
43 | | |
44 | | |
45 | | |
46 | ||
47 | | |
48 | ||
49 | | |
50 | ||
51 | | |
52 | ||
53 | ||
54 | ||
55 | ||
56 | ||
57 | ||
58 | | |
59 | | |
60 | ||
61 | ||
62 | ||
63 | ||
64 | ||
65 | | |
66 | | |
67 | ||
2 | #!/usr/bin/env ruby | |
3 | require File.dirname(__FILE__) + '/../../config/boot' | |
4 | require 'commands/process/spinner' |
rool/rails/typo/trunk/script/runner:
prev. | current | |
#!/usr/bin/env ruby | ||
2 | ||
3 | ||
4 | ||
5 | ||
6 | ||
7 | | |
8 | | |
9 | ||
10 | | |
11 | ||
12 | | |
13 | | |
14 | | |
15 | ||
16 | | |
17 | ||
18 | | |
19 | | |
20 | ||
21 | | |
22 | ||
23 | ||
24 | ||
25 | ||
26 | ||
27 | ||
28 | ||
29 | ||
3 | require File.dirname(__FILE__) + '/../config/boot' | |
4 | require 'commands/runner' | |
rool/rails/typo/trunk/script/server:
prev. | current | |
#!/usr/bin/env ruby | ||
2 | ||
3 | ||
4 | ||
5 | ||
6 | ||
7 | | |
8 | | |
9 | | |
10 | | |
11 | | |
12 | ||
13 | ||
14 | ||
15 | | |
16 | | |
17 | ||
18 | | |
19 | ||
20 | | |
21 | | |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
30 | | |
31 | | |
32 | ||
33 | | |
34 | ||
35 | | |
36 | | |
37 | ||
38 | | |
39 | ||
40 | ||
41 | ||
42 | ||
43 | ||
44 | ||
45 | ||
46 | ||
47 | ||
48 | ||
49 | ||
2 | require File.dirname(__FILE__) + '/../config/boot' | |
3 | require 'commands/server' | |
rool/rails/typo/trunk/test/fixtures/articles_categories.yml:
prev. | current | |
1 | articles_categories1: | |
2 | article_id: 1 | |
3 | category_id: 1 | |
4 | ||
5 | articles_categories2: | |
6 | article_id: 1 | |
7 | category_id: 2 | |
8 | ||
9 | articles_categories3: | |
10 | article_id: 1 | |
11 | category_id: 3 | |
12 | ||
13 | articles_categories4: | |
14 | article_id: 2 | |
15 | category_id: 3 | |
16 | ||
17 | articles_categories5: | |
18 | article_id: 3 | |
19 | category_id: 3 | |
20 | ||
21 | articles_categories6: | |
22 | article_id: 4 | |
23 | category_id: 3 | |
24 | ||
25 | articles_categories7: | |
26 | article_id: 1 | |
27 | category_id: 5 | |
28 | ||
29 | articles_categories8: | |
30 | article_id: 18 | |
31 | category_id: 6 |
rool/rails/typo/trunk/test/fixtures/categories.yml:
prev. | current | |
id: 1 | ||
name: Software | ||
permalink: software | ||
5 | position: 1 | |
hardware: | ||
id: 2 | ||
name: Hardware | ||
permalink: hardware | ||
11 | position: 2 | |
personal: | ||
id: 3 | ||
name: Personal | ||
14 | | |
17 | permalink: personal | |
18 | position: 3 | |
19 | ||
20 | lifeonmars: | |
21 | id: 4 | |
22 | name: Life On Mars | |
23 | permalink: life-on-mars | |
24 | position: 4 | |
25 | ||
26 | strangelynamed: | |
27 | id: 5 | |
28 | name: "The Permalink doesn't match" | |
29 | permalink: weird-permalink | |
30 | position: 5 | |
31 | ||
32 | xmltest: | |
33 | id: 6 | |
34 | name: "this & that" | |
35 | permalink: this-and-that | |
36 | position: 6 |
rool/rails/typo/trunk/test/fixtures/resources.yml:
prev. | current | |
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html | ||
2 | resource1: | |
3 | id: 1 | |
4 | article_id: 1 | |
5 | filename: me.jpg | |
6 | mime: 'image/jpeg' | |
7 | created_at: <%= 1.week.ago.strftime("%Y-%m-%d %H:%M:%S") %> | |
8 | size: 100 | |
9 | ||
10 | resource2: | |
11 | id: 2 | |
12 | article_id: 1 | |
13 | filename: moi | |
14 | mime: 'image/jpeg' | |
15 | created_at: <%= 1.day.ago.strftime("%Y-%m-%d %H:%M:%S") %> | |
16 | size: 110 | |
17 | ||
18 | resource3: | |
19 | id: 3 | |
20 | article_id: 2 | |
21 | filename: my_latest_typo_patch.diff | |
22 | mime: 'text/plain' | |
23 | created_at: <%= 1.day.ago.strftime("%Y-%m-%d %H:%M:%S") %> | |
24 | size: 0 |
rool/rails/typo/trunk/test/fixtures/users.yml:
prev. | current | |
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html | ||
tobi: | ||
4 | | |
4 | id: 1 | |
login: tobi | ||
password: ea0f5fd4398054c1c7aa0fbc7aaea30914a14441 # whatever | ||
7 | name: Tobi | |
8 | email: tobi@example.com | |
9 | notify_via_email: true | |
10 | notify_via_jabber: false | |
11 | notify_on_new_articles: false | |
12 | notify_on_comments: true | |
bob: | ||
9 | | |
15 | id: 2 | |
login: bob | ||
password: 9a91e1d8d95b6315991a88121bb0aa9f03ba0dfc # test | ||
12 | | |
18 | name: Bob | |
19 | email: bob@example.com | |
20 | notify_via_email: false | |
21 | notify_via_jabber: false | |
22 | notify_on_new_articles: true | |
23 | notify_on_comments: false | |
24 | ||
existingbob: | ||
14 | | |
26 | id: 3 | |
login: existingbob | ||
password: 9a91e1d8d95b6315991a88121bb0aa9f03ba0dfc # test | ||
29 | name: Also Bob | |
30 | email: alsobob@example.com | |
31 | notify_via_email: true | |
32 | notify_via_jabber: false | |
33 | notify_on_new_articles: false | |
34 | notify_on_comments: false | |
longbob: | ||
19 | | |
37 | id: 4 | |
login: longbob | ||
21 | | |
40 | password: 8e9b1a9a38e66ca572a5e8fdac8e256848842dfa # longtest | |
41 | name: More Bob | |
42 | email: longbob@example.com | |
43 | notify_via_email: false | |
44 | notify_via_jabber: false | |
45 | notify_on_new_articles: false | |
46 | notify_on_comments: false | |
47 | ||
48 | randomuser: | |
49 | id: 5 | |
50 | login: randomuser | |
51 | password: 8e9b1a9a38e66ca572a5e8fdac8e256848842dfa # longtest | |
52 | name: Random User | |
53 | email: randomuser@example.com | |
54 | notify_via_email: true | |
55 | notify_via_jabber: false | |
56 | notify_on_new_articles: true | |
57 | notify_on_comments: true |
rool/rails/typo/trunk/test/functional/accounts_controller_test.rb:
prev. | current | |
require File.dirname(__FILE__) + '/../test_helper' | ||
require 'accounts_controller' | ||
4 | ||
4 | # Set salt to 'change-me' because thats what the fixtures assume. | |
User.salt = 'change-me' | ||
# Raise errors beyond the default web-based presentation | ||
class AccountsController; def rescue_action(e) raise e end; end | ||
class AccountsControllerTest < Test::Unit::TestCase | ||
11 | | |
12 | | |
13 | | |
11 | ||
12 | fixtures :users, :blogs | |
13 | ||
def setup | ||
@controller = AccountsController.new | ||
@request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new | ||
@request.host = "localhost" | ||
end | ||
19 | | |
19 | ||
def test_auth_bob | ||
@request.session[:return_to] = "/bogus/location" | ||
post :login, :user_login => "bob", :user_password => "test" | ||
assert_session_has :user | ||
26 | | |
27 | | |
26 | assert_equal users(:bob), @response.session[:user] | |
27 | ||
assert_redirect_url "http://localhost/bogus/location" | ||
end | ||
30 | | |
30 | ||
def test_signup | ||
User.destroy_all # Need to trick AccountController#signup into thinking this is a brand new blog | ||
post :signup, :user => { :login => "newbob", :password => "newpassword", :password_confirmation => "newpassword" } | ||
assert_session_has :user | ||
35 | | |
35 | ||
assert_redirect | ||
assert_redirected_to :controller => "admin/general", :action => "index" | ||
end | ||
... | ... | |
def test_bad_signup | ||
@request.session[:return_to] = "/bogus/location" | ||
48 | | |
48 | ||
User.delete_all | ||
post :signup, :user => { :login => "newbob", :password => "newpassword", :password_confirmation => "wrong" } | ||
assert_invalid_column_on_record "user", :password | ||
assert_success | ||
54 | | |
54 | ||
post :signup, :user => { :login => "yo", :password => "newpassword", :password_confirmation => "newpassword" } | ||
assert_invalid_column_on_record "user", :login | ||
assert_success | ||
... | ... | |
def test_invalid_login | ||
post :login, :user_login => "bob", :user_password => "not_correct" | ||
66 | | |
66 | ||
assert_session_has_no :user | ||
68 | | |
68 | ||
assert_template_has "login" | ||
end | ||
71 | | |
71 | ||
def test_login_logoff | ||
post :login, :user_login => "bob", :user_password => "test" | ||
... | ... | |
assert_session_has_no :user | ||
end | ||
81 | | |
81 | ||
end |
rool/rails/typo/trunk/test/functional/admin/blacklist_controller_test.rb:
prev. | current | |
@request = ActionController::TestRequest.new | ||
@response = ActionController::TestResponse.new | ||
15 | | |
15 | @request.session = { :user => users(:tobi) } | |
end | ||
def test_index | ||
... | ... | |
get :destroy, 'id' => 1 | ||
assert_success | ||
55 | | |
55 | ||
post :destroy, 'id' => 1 | ||
assert_redirected_to :action => 'list' | ||
rool/rails/typo/trunk/test/functional/admin/categories_controller_test.rb:
prev. | current | |
@request = ActionController::TestRequest.new | ||
@response = ActionController::TestResponse.new | ||
15 | | |
15 | @request.session = { :user => users(:tobi) } | |
end | ||
def test_index | ||
get :index | ||
assert_rendered_file 'list' | ||
21 | assert_template_has 'categories' | |
end | ||
def test_list | ||
get :list | ||
assert_rendered_file 'list' | ||
assert_template_has 'categories' | ||
28 | assert_tag :tag => "div", | |
29 | :attributes => { :id => "category_container" } | |
end | ||
28 | | |
31 | ||
def test_show | ||
get :show, 'id' => 1 | ||
assert_rendered_file 'show' | ||
... | ... | |
end | ||
def test_edit | ||
46 | | |
49 | get :edit, :id => 1 | |
assert_rendered_file 'edit' | ||
assert_template_has 'category' | ||
assert_valid_record 'category' | ||
end | ||
def test_update | ||
53 | | |
56 | post :edit, :id => 1 | |
assert_redirected_to :action => 'list' | ||
end | ||
def test_destroy | ||
assert_not_nil Category.find(1) | ||
60 | | |
63 | get :destroy, :id => 1 | |
assert_success | ||
62 | | |
63 | | |
65 | assert_rendered_file 'destroy' | |
66 | ||
67 | post :destroy, :id => 1 | |
assert_redirected_to :action => 'list' | ||
66 | | |
67 | | |
68 | | |
70 | assert_raise(ActiveRecord::RecordNotFound) { Category.find(1) } | |
end | ||
72 | ||
73 | def test_order | |
74 | assert_equal categories(:software), Category.find(:first, :order => :position) | |
75 | get :order, :category_list => [categories(:personal).id, categories(:hardware).id, categories(:software).id] | |
76 | assert_response :success | |
77 | assert_equal categories(:personal), Category.find(:first, :order => :position) | |
78 | end | |
79 | ||
80 | def test_asort | |
81 | assert_equal categories(:software), Category.find(:first, :order => :position) | |
82 | get :asort | |
83 | assert_response :success | |
84 | assert_template "_categories" | |
85 | assert_equal categories(:hardware), Category.find(:first, :order => :position) | |
86 | end | |
87 | ||
88 | def test_category_container | |
89 | get :category_container | |
90 | assert_response :success | |
91 | assert_template "_categories" | |
92 | assert_tag :tag => "table", | |
93 | :children => { :count => Category.count + 1, | |
94 | :only => { :tag => "tr", | |
95 | :children => { :count => 3, | |
96 | :only => { :tag => /t[dh]/ } } } } | |
97 | end | |
98 | ||
99 | def test_reorder | |
100 | get :reorder | |
101 | assert_response :success | |
102 | assert_template "reorder" | |
103 | assert_tag :tag => "ul", | |
104 | :attributes => { :id => "category_list" }, | |
105 | :children => { :count => Category.count, | |
106 | :only => { :tag => "li", | |
107 | :attributes => { :id => /category_\d+/ } } } | |
108 | ||
109 | assert_tag :tag => "a", | |
110 | :content => "(Done)" | |
111 | end | |
end |
rool/rails/typo/trunk/test/functional/admin/comments_controller_test.rb:
prev. | current | |
class Admin::CommentsController; def rescue_action(e) raise e end; end | ||
class Admin::CommentsControllerTest < Test::Unit::TestCase | ||
9 | | |
9 | fixtures :contents, :users | |
def setup | ||
@controller = Admin::CommentsController.new | ||
@request = ActionController::TestRequest.new | ||
@response = ActionController::TestResponse.new | ||
15 | | |
16 | | |
15 | ||
16 | @request.session = { :user => users(:tobi) } | |
end | ||
def test_index | ||
... | ... | |
end | ||
def test_show | ||
31 | | |
31 | get :show, :id => 5, :article_id => 2 | |
assert_rendered_file 'show' | ||
assert_template_has 'comment' | ||
assert_valid_record 'comment' | ||
... | ... | |
def test_create | ||
num_comments = Comment.find_all.size | ||
46 | | |
46 | post(:new, :comment => { 'author' => 'author', 'body' => 'body' }, | |
47 | :article_id => 2) | |
assert_redirected_to :action => 'show' | ||
assert_equal num_comments + 1, Comment.find_all.size | ||
end | ||
def test_edit | ||
53 | | |
54 | get :edit, :id => 5, :article_id => 2 | |
assert_rendered_file 'edit' | ||
assert_template_has 'comment' | ||
assert_valid_record 'comment' | ||
end | ||
def test_update | ||
60 | | |
61 | | |
61 | post :edit, :id => 5, :article_id => 2 | |
62 | assert_redirected_to :action => 'show', :id => 5 | |
end | ||
def test_destroy | ||
65 | | |
66 | assert_not_nil Comment.find(5) | |
67 | | |
68 | get :destroy, :id => 5, :article_id => 2 | |
assert_success | ||
69 | | |
70 | | |
70 | ||
71 | post :destroy, :id => 5, :article_id => 2 | |
assert_redirected_to :action => 'list' | ||
assert_raise(ActiveRecord::RecordNotFound) { | ||
74 | | |
75 | comment = Comment.find(5) | |
} | ||
end | ||
end |
rool/rails/typo/trunk/test/functional/admin/content_controller_test.rb:
prev. | current | |
require File.dirname(__FILE__) + '/../../test_helper' | ||
require 'admin/content_controller' | ||
4 | require 'http_mock' | |
5 | ||
# Re-raise errors caught by the controller. | ||
class Admin::ContentController; def rescue_action(e) raise e end; end | ||
class Admin::ContentControllerTest < Test::Unit::TestCase | ||
8 | | |
10 | fixtures :contents, :users, :categories, :resources, :text_filters, | |
11 | :blogs, :articles_categories | |
def setup | ||
@controller = Admin::ContentController.new | ||
@request = ActionController::TestRequest.new | ||
@response = ActionController::TestResponse.new | ||
14 | | |
17 | @request.session = { :user => users(:tobi) } | |
end | ||
def test_index | ||
... | ... | |
assert_rendered_file 'show' | ||
assert_template_has 'article' | ||
assert_valid_record 'article' | ||
36 | assert_not_nil assigns(:article) | |
37 | assert_not_nil assigns(:categories) | |
38 | assert_not_nil assigns(:resources) | |
end | ||
def test_new | ||
... | ... | |
assert_template_has 'article' | ||
end | ||
47 | def test_create_no_comments | |
48 | post(:new, 'article' => { :title => "posted via tests!", :body => "You can't comment", | |
49 | :keywords => "tagged", | |
50 | :allow_comments => '0', :allow_pings => '1' }, | |
51 | 'categories' => [1]) | |
52 | assert !assigns(:article).allow_comments? | |
53 | assert assigns(:article).allow_pings? | |
54 | assert assigns(:article).published? | |
55 | end | |
56 | ||
57 | def test_create_with_no_pings | |
58 | post(:new, 'article' => { :title => "posted via tests!", :body => "You can't ping!", | |
59 | :keywords => "tagged", | |
60 | :allow_comments => '1', :allow_pings => '0' }, | |
61 | 'categories' => [1]) | |
62 | assert assigns(:article).allow_comments? | |
63 | assert !assigns(:article).allow_pings? | |
64 | assert assigns(:article).published? | |
65 | end | |
66 | ||
def test_create | ||
42 | | |
43 | ||
44 | | |
68 | num_articles = this_blog.published_articles.size | |
69 | emails = ActionMailer::Base.deliveries | |
70 | emails.clear | |
71 | tags = ['foo', 'bar', 'baz bliz', 'gorp gack gar'] | |
72 | post :new, 'article' => { :title => "posted via tests!", :body => "Foo", :keywords => "foo bar 'baz bliz' \"gorp gack gar\""}, 'categories' => [1] | |
assert_redirected_to :action => 'show' | ||
47 | | |
75 | assert_equal num_articles + 1, this_blog.published_articles.size | |
new_article = Article.find(:first, :order => "id DESC") | ||
50 | | |
78 | assert_equal users(:tobi), new_article.user | |
79 | assert_equal 1, new_article.categories.size | |
80 | assert_equal [1], new_article.categories.collect {|c| c.id} | |
81 | assert_equal 4, new_article.tags.size | |
82 | ||
83 | assert_equal(1, emails.size) | |
84 | assert_equal('randomuser@example.com', emails.first.to[0]) | |
end | ||
87 | def test_create_future_article | |
88 | num_articles = this_blog.published_articles.size | |
89 | post(:new, | |
90 | :article => { :title => "News from the future!", | |
91 | :body => "The future's cool!", | |
92 | :published_at => Time.now + 1.hour }) | |
93 | assert_redirected_to :action => 'show' | |
94 | assert ! assigns(:article).published? | |
95 | assert_equal num_articles, this_blog.published_articles.size | |
96 | assert_equal 1, Trigger.count | |
97 | end | |
98 | ||
99 | def test_request_fires_triggers | |
100 | art = this_blog.articles.create!(:title => 'future article', | |
101 | :body => 'content', | |
102 | :published_at => Time.now + 2.seconds, | |
103 | :published => true) | |
104 | assert !art.published? | |
105 | sleep 3 | |
106 | get(:show, :id => art.id) | |
107 | assert assigns(:article).published? | |
108 | end | |
109 | ||
110 | def test_create_filtered | |
111 | body = "body via *textile*" | |
112 | extended="*foo*" | |
113 | post :new, 'article' => { :title => "another test", :body => body, :extended => extended} | |
114 | assert_redirected_to :action => 'show' | |
115 | ||
116 | new_article = Article.find(:first, :order => "created_at DESC") | |
117 | assert_equal body, new_article.body | |
118 | assert_equal extended, new_article.extended | |
119 | assert_equal "textile", new_article.text_filter.name | |
120 | assert_equal "<p>body via <strong>textile</strong></p>", new_article.html(@controller, :body) | |
121 | assert_equal "<p><strong>foo</strong></p>", new_article.html(@controller, :extended) | |
122 | end | |
123 | ||
def test_edit | ||
get :edit, 'id' => 1 | ||
126 | assert_equal assigns(:selected), Article.find(1).categories.collect {|c| c.id} | |
assert_rendered_file 'edit' | ||
assert_template_has 'article' | ||
assert_valid_record 'article' | ||
end | ||
def test_update | ||
61 | | |
133 | emails = ActionMailer::Base.deliveries | |
134 | emails.clear | |
135 | ||
136 | body = "another *textile* test" | |
137 | post :edit, 'id' => 1, 'article' => {:body => body, :text_filter => 'textile'} | |
assert_redirected_to :action => 'show', :id => 1 | ||
139 | ||
140 | article = Article.find(1) | |
141 | assert_equal "textile", article.text_filter.name | |
142 | assert_equal body, article.body | |
143 | # Deliberately *not* using the mediating protocol, we want to ensure that the | |
144 | # body_html got reset to nil. | |
145 | assert_nil article.body_html | |
146 | ||
147 | assert_equal 0, emails.size | |
end | ||
def test_destroy | ||
... | ... | |
get :destroy, 'id' => 1 | ||
assert_success | ||
70 | | |
155 | ||
post :destroy, 'id' => 1 | ||
assert_redirected_to :action => 'list' | ||
... | ... | |
article = Article.find(1) | ||
} | ||
end | ||
163 | ||
164 | def test_category_add | |
165 | get :category_add, :id => 1, :category_id => 1 | |
166 | ||
167 | assert_rendered_file '_show_categories' | |
168 | assert_valid_record 'article' | |
169 | assert_valid_record 'category' | |
170 | assert Article.find(1).categories.include?(Category.find(1)) | |
171 | assert_not_nil assigns(:article) | |
172 | assert_not_nil assigns(:category) | |
173 | assert_not_nil assigns(:categories) | |
174 | end | |
175 | ||
176 | def test_category_remove | |
177 | get :category_remove, :id => 1, :category_id => 1 | |
178 | ||
179 | assert_rendered_file '_show_categories' | |
180 | assert_valid_record 'article' | |
181 | assert_valid_record 'category' | |
182 | assert !Article.find(1).categories.include?(Category.find(1)) | |
183 | assert_not_nil assigns(:article) | |
184 | assert_not_nil assigns(:category) | |
185 | assert_not_nil assigns(:categories) | |
186 | end | |
187 | ||
188 | def test_resource_add | |
189 | get :resource_add, :id => 1, :resource_id => 1 | |
190 | ||
191 | assert_rendered_file '_show_resources' | |
192 | assert_valid_record 'article' | |
193 | assert_valid_record 'resource' | |
194 | assert Article.find(1).resources.include?(Resource.find(1)) | |
195 | assert_not_nil assigns(:article) | |
196 | assert_not_nil assigns(:resource) | |
197 | assert_not_nil assigns(:resources) | |
198 | end | |
199 | ||
200 | def test_resource_remove | |
201 | get :resource_remove, :id => 1, :resource_id => 1 | |
202 | ||
203 | assert_rendered_file '_show_resources' | |
204 | assert_valid_record 'article' | |
205 | assert_valid_record 'resource' | |
206 | assert !Article.find(1).resources.include?(Resource.find(1)) | |
207 | assert_not_nil assigns(:article) | |
208 | assert_not_nil assigns(:resource) | |
209 | assert_not_nil assigns(:resources) | |
210 | end | |
211 | ||
212 | def test_attachment_box_add | |
213 | get :attachment_box_add, :id => 2 | |
214 | assert_rendered_file '_attachment' | |
215 | #assert_tag :tag => 'script' | |
216 | end | |
217 | ||
218 | def test_attachment_box_remove | |
219 | get :attachment_box_remove, :id => 1 | |
220 | assert_tag :tag => 'script', :attributes => {:type => 'text/javascript'} | |
221 | end | |
222 | ||
223 | def test_resource_container | |
224 | get :show, :id => contents(:article1).id # article without attachments | |
225 | Resource.find(:all).each do |resource| | |
226 | assert_tag( :tag => 'a', | |
227 | :attributes =>{ | |
228 | :onclick => | |
229 | /^new Ajax.Updater\('resources/ | |
230 | }, | |
231 | :content => /[-+] #{resource.filename}/) | |
232 | end | |
233 | end | |
end |
rool/rails/typo/trunk/test/functional/admin/general_controller_test.rb:
prev. | current | |
class Admin::GeneralControllerTest < Test::Unit::TestCase | ||
fixtures :users | ||
9 | | |
9 | ||
def setup | ||
@controller = Admin::GeneralController.new | ||
@request = ActionController::TestRequest.new | ||
@response = ActionController::TestResponse.new | ||
14 | | |
14 | @request.session = { :user => users(:tobi) } | |
end | ||
def test_index | ||
get :index | ||
assert_rendered_file 'index' | ||
end | ||
21 | ||
22 | def test_redirect | |
23 | get :redirect | |
24 | assert_redirected_to :controller => 'admin/general', :action => 'index' | |
25 | end | |
end |
rool/rails/typo/trunk/test/functional/admin/themes_controller_test.rb:
prev. | current | |
class Admin::ThemesControllerTest < Test::Unit::TestCase | ||
fixtures :users | ||
9 | | |
9 | ||
def setup | ||
@controller = Admin::ThemesController.new | ||
@request = ActionController::TestRequest.new | ||
@response = ActionController::TestResponse.new | ||
14 | | |
15 | | |
14 | ||
15 | @request.session = { :user => users(:tobi) } | |
end | ||
# Replace this with your real tests. | ||
def test_index | ||
get :index | ||
assert_response :success | ||
22 | | |
22 | assert_not_nil assigns(:themes) | |
end | ||
24 | ||
25 | def test_switchto | |
26 | get :switchto, :theme => 'azure' | |
27 | assert_redirected_to :action => 'index' | |
28 | end | |
29 | ||
30 | def test_preview | |
31 | get :preview, :theme => 'azure' | |
32 | assert_response :success | |
33 | end | |
end |
rool/rails/typo/trunk/test/functional/admin/trackbacks_controller_test.rb:
prev. | current | |
class Admin::TrackbacksController; def rescue_action(e) raise e end; end | ||
class Admin::TrackbacksControllerTest < Test::Unit::TestCase | ||
8 | | |
8 | fixtures :contents, :users | |
def setup | ||
11 | | |
11 | @controller = Admin::TrackbacksController.new | |
@request = ActionController::TestRequest.new | ||
@response = ActionController::TestResponse.new | ||
14 | | |
15 | | |
14 | ||
15 | @request.session = { :user => users(:tobi) } | |
end | ||
def test_index | ||
... | ... | |
end | ||
def test_show | ||
30 | | |
30 | get :show, :id => 7, :article_id => 2 | |
assert_rendered_file 'show' | ||
assert_template_has 'trackback' | ||
assert_valid_record 'trackback' | ||
... | ... | |
end | ||
def test_edit | ||
52 | | |
52 | get :edit, :id => 7, :article_id => 2 | |
assert_rendered_file 'edit' | ||
assert_template_has 'trackback' | ||
assert_valid_record 'trackback' | ||
end | ||
def test_update | ||
59 | | |
60 | | |
59 | post :edit, :id => 7, :article_id => 2 | |
60 | assert_redirected_to :action => 'show', :id => 7 | |
end | ||
def test_destroy | ||
64 | | |
64 | assert_not_nil Trackback.find(7) | |
66 | | |
66 | get :destroy, :id => 7, :article_id => 2 | |
assert_success | ||
68 | | |
69 | | |
68 | ||
69 | post :destroy, :id => 7, :article_id => 2 | |
assert_redirected_to :action => 'list' | ||
assert_raise(ActiveRecord::RecordNotFound) { | ||
73 | | |
73 | trackback = Trackback.find(7) | |
} | ||
end | ||
end |
rool/rails/typo/trunk/test/functional/admin/users_controller_test.rb:
prev. | current | |
class Admin::UsersController; def rescue_action(e) raise e end; end | ||
class Admin::UsersControllerTest < Test::Unit::TestCase | ||
8 | | |
8 | fixtures :users, :blogs | |
def setup | ||
@controller = Admin::UsersController.new | ||
@request = ActionController::TestRequest.new | ||
@response = ActionController::TestResponse.new | ||
14 | | |
15 | | |
14 | ||
15 | @request.session = { :user => users(:tobi) } | |
end | ||
def test_index | ||
get :index | ||
assert_rendered_file 'list' | ||
21 | assert_template_has 'users' | |
end | ||
def test_list | ||
... | ... | |
assert_template_has 'users' | ||
end | ||
30 | def test_new | |
31 | get :new | |
32 | assert_rendered_file 'new' | |
34 | post :new, :user => { :login => 'errand', :email => 'corey@test.com', | |
35 | :password => 'testpass', :password_confirmation => 'testpass' } | |
36 | assert_redirected_to :action => 'list' | |
37 | follow_redirect | |
38 | assert_rendered_file 'list' | |
39 | end | |
40 | ||
41 | def test_show | |
42 | get :show, :id => 1 | |
43 | assert_rendered_file 'show' | |
44 | assert_valid_record 'user' | |
45 | end | |
46 | ||
47 | def test_edit | |
48 | get :edit, :id => 1 | |
49 | assert_rendered_file 'edit' | |
50 | assert_valid_record 'user' | |
51 | ||
52 | post :edit, :id => 1, :user => { :login => 'errand', | |
53 | :email => 'corey@test.com', :password => 'testpass', | |
54 | :password_confirmation => 'testpass' } | |
55 | assert_redirected_to :action => 'show' | |
56 | follow_redirect | |
57 | assert_rendered_file 'show' | |
58 | assert_valid_record 'user' | |
59 | end | |
60 | ||
61 | def test_destroy | |
62 | get :destroy, :id => 1 | |
63 | assert_rendered_file 'destroy' | |
64 | assert_valid_record 'user' | |
65 | ||
66 | post :destroy, :id => 1 | |
67 | assert_redirected_to :action => 'list' | |
68 | follow_redirect | |
69 | assert_rendered_file 'list' | |
70 | end | |
71 | ||
end |
rool/rails/typo/trunk/test/functional/articles_controller_test.rb:
prev. | current | |
require File.dirname(__FILE__) + '/../test_helper' | ||
require 'articles_controller' | ||
3 | require 'dns_mock' | |
4 | require 'http_mock' | |
6 | require 'content' | |
7 | ||
8 | # | |
# Re-raise errors caught by the controller. | ||
class ArticlesController; def rescue_action(e) raise e end; end | ||
12 | class Content | |
13 | def self.find_last_posted | |
14 | self.find(:first, :conditions => ['created_at < ?', Time.now], | |
15 | :order => 'created_at desc') | |
16 | end | |
17 | end | |
18 | ||
class ArticlesControllerTest < Test::Unit::TestCase | ||
8 | | |
20 | fixtures :contents, :categories, :blogs, :users, :articles_categories, :text_filters, :articles_tags, :tags | |
21 | include ArticlesHelper | |
def setup | ||
@controller = ArticlesController.new | ||
@request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new | ||
14 | | |
15 | | |
27 | Article.create!(:title => "News from the future!", | |
28 | :body => "The future is cool!", | |
29 | :keywords => "future", | |
30 | :created_at => Time.now + 12.minutes) | |
31 | ||
end | ||
# Category subpages | ||
... | ... | |
assert_response :success | ||
assert_rendered_file "index" | ||
40 | ||
41 | # Check it works when permalink != name. Ticket #736 | |
42 | get :category, :id => "weird-permalink" | |
43 | ||
44 | assert_response :success | |
45 | assert_rendered_file "index" | |
end | ||
25 | | |
47 | ||
48 | def test_empty_category | |
49 | get :category, :id => "life-on-mars" | |
50 | assert_response :success | |
51 | assert_rendered_file "error" | |
52 | end | |
53 | ||
54 | def test_nonexistent_category | |
55 | get :category, :id => 'nonexistent-category' | |
56 | assert_response :success | |
57 | assert_rendered_file "error" | |
58 | end | |
59 | ||
60 | def test_tag | |
61 | get :tag, :id => "foo" | |
62 | ||
63 | assert_response :success | |
64 | assert_rendered_file "index" | |
65 | ||
66 | assert_tag :tag => 'h2', :content => 'Article 2!' | |
67 | assert_tag :tag => 'h2', :content => 'Article 1!' | |
68 | end | |
69 | ||
70 | def test_nonexistent_tag | |
71 | get :tag, :id => "nonexistent" | |
72 | assert_response :success | |
73 | assert_rendered_file "error" | |
74 | end | |
75 | ||
76 | def test_tag_routes | |
77 | opts = {:controller => "articles", :action => "tag", :id => "foo", :page => "2"} | |
78 | assert_routing("articles/tag/foo/page/2", opts) | |
79 | end | |
80 | ||
81 | def test_simple_tag_pagination | |
82 | this_blog.limit_article_display = 1 | |
83 | get :tag, :id => "foo" | |
84 | assert_equal 1, assigns(:articles).size | |
85 | assert_tag(:tag => 'p', | |
86 | :attributes =>{ | |
87 | :id => 'pagination'}, | |
88 | :content => 'Older posts: 1', | |
89 | :descendant => {:tag => 'a', | |
90 | :attributes =>{ | |
91 | :href => "/articles/tag/foo/page/2"}, | |
92 | :content => "2"}) | |
93 | end | |
94 | ||
# Main index | ||
def test_index | ||
get :index | ||
assert_response :success | ||
assert_rendered_file "index" | ||
end | ||
32 | | |
101 | ||
# Archives page | ||
def test_archives | ||
get :archives | ||
assert_response :success | ||
assert_rendered_file "archives" | ||
end | ||
39 | | |
108 | ||
# Permalinks | ||
def test_permalink | ||
42 | | |
111 | get :permalink, :year => 2004, :month => 06, :day => 01, :title => "article-3" | |
assert_response :success | ||
assert_template "read" | ||
assert_not_nil assigns(:article) | ||
46 | | |
115 | assert_equal contents(:article3), assigns(:article) | |
end | ||
# Posts for given day | ||
def test_find_by_date | ||
51 | | |
120 | get :find_by_date, :year => 2004, :month => 06, :day => 01 | |
assert_response :success | ||
assert_rendered_file "index" | ||
end | ||
55 | | |
56 | | |
124 | ||
125 | def test_comment_posting | |
126 | emails = ActionMailer::Base.deliveries | |
127 | emails.clear | |
128 | ||
129 | assert_equal 0, emails.size | |
130 | ||
131 | Article.find(1).notify_users << users(:tobi) | |
132 | ||
133 | post :comment, { :id => 1, :comment => {'body' => 'This is *textile*', 'author' => 'bob' }} | |
134 | ||
135 | assert_response :success | |
136 | assert_tag :tag => 'strong', :content => 'textile' | |
137 | ||
138 | comment = Article.find(1).comments.last | |
139 | assert comment | |
140 | ||
141 | assert_not_nil cookies["author"] | |
142 | ||
143 | assert_equal "<p>This is <strong>textile</strong></p>", comment.html(@controller).to_s | |
144 | ||
145 | assert_equal User.find(:all, | |
146 | :conditions => ['(notify_via_email = ?) and (notify_on_comments = ?)', true, true], | |
147 | :order => 'email').collect { |each| each.email }, | |
148 | emails.collect { |each| each.to[0] }.sort | |
149 | end | |
150 | ||
151 | def test_comment_spam_markdown_smarty | |
152 | this_blog.comment_text_filter = "markdown smartypants" | |
153 | test_comment_spam1 | |
154 | end | |
155 | ||
156 | def comment_template_test(expected_html, source_text, | |
157 | art_id=1, author='bob', email='foo', args={}) | |
158 | post :comment, { | |
159 | :id => art_id, | |
160 | :comment => { | |
161 | 'body' => source_text, | |
162 | 'author' => author, | |
163 | 'email' => email }.merge(args) } | |
164 | ||
165 | assert_response :success | |
166 | comment = Article.find(art_id).comments.last | |
167 | assert comment | |
168 | ||
169 | assert_match expected_html, comment.html(@controller).to_s | |
170 | $do_breakpoints | |
171 | end | |
172 | ||
173 | def test_comment_spam1 | |
174 | comment_template_test "<p>Link to <a href='http://spammer.example.com' rel=\"nofollow\">spammy goodness</a></p>", 'Link to <a href="http://spammer.example.com">spammy goodness</a>' | |
175 | end | |
176 | ||
177 | def test_comment_spam2 | |
178 | comment_template_test %r{<p>Link to <a href=["']http://spammer.example.com['"] rel=["']nofollow['"]>spammy goodness</a></p>}, 'Link to "spammy goodness":http://spammer.example.com' | |
179 | end | |
180 | ||
181 | def test_comment_xss1 | |
182 | this_blog.comment_text_filter = "none" | |
183 | comment_template_test %{Have you ever <script lang='javascript'>alert("foo");</script> been hacked?}, | |
184 | %{Have you ever <script lang="javascript">alert("foo");</script> been hacked?} | |
185 | end | |
186 | ||
187 | def test_comment_xss2 | |
188 | this_blog.comment_text_filter = "none" | |
189 | comment_template_test "Have you ever <a href='#' rel=\"nofollow\">been hacked?</a>", 'Have you ever <a href="#" onclick="javascript">been hacked?</a>' | |
190 | end | |
191 | ||
192 | def test_comment_autolink | |
193 | comment_template_test "<p>What’s up with <a href='http://slashdot.org' rel=\"nofollow\">http://slashdot.org</a> these days?</p>", "What's up with http://slashdot.org these days?" | |
194 | end #" | |
195 | ||
196 | ### TODO -- there's a bug in Rails with auto_links | |
197 | # def test_comment_autolink2 | |
198 | # comment_template_test "<p>My web page is <a href='http://somewhere.com/~me/index.html' rel=\"nofollow\">http://somewhere.com/~me/index.html</a></p>", "My web page is http://somewhere.com/~me/index.html" | |
199 | # end | |
200 | ||
201 | def test_comment_nuking | |
num_comments = Comment.count | ||
58 | | |
203 | post :nuke_comment, { :id => 5 }, {} | |
assert_response 403 | ||
61 | | |
206 | get :nuke_comment, { :id => 5 }, { :user => users(:bob)} | |
assert_response 403 | ||
63 | | |
64 | | |
208 | ||
209 | post :nuke_comment, { :id => 5 }, { :user => users(:bob)} | |
assert_response :success | ||
66 | | |
211 | assert_equal num_comments -1, Comment.count | |
end | ||
69 | | |
214 | def test_comment_user_blank | |
215 | post :comment, { :id => 2, :comment => {'body' => 'foo', 'author' => 'bob' }} | |
216 | assert_response :success | |
217 | ||
218 | comment = Article.find(2).comments.last | |
219 | assert comment | |
220 | assert comment.published? | |
221 | assert_nil comment.user_id | |
222 | ||
223 | get :read, {:id => 2} | |
224 | assert_response :success | |
225 | assert_no_tag :tag => "li", | |
226 | :attributes => { :class => "author_comment"} | |
227 | ||
228 | end | |
229 | ||
230 | def test_comment_user_set | |
231 | @request.session = { :user => users(:tobi) } | |
232 | post :comment, { :id => 2, :comment => {'body' => 'foo', 'author' => 'bob' }} | |
233 | assert_response :success | |
234 | ||
235 | comment = Article.find(2).comments.last | |
236 | assert comment | |
237 | assert_equal users(:tobi), comment.user | |
238 | ||
239 | get :read, {:id => 2} | |
240 | assert_response :success | |
241 | assert_tag :tag => "li", | |
242 | :attributes => { :class => "author_comment"} | |
243 | end | |
244 | ||
245 | def test_trackback | |
246 | num_trackbacks = Article.find(2).trackbacks.count | |
247 | post :trackback, { :id => 2, :url => "http://www.google.com", :title => "My Trackback", :excerpt => "This is a test" } | |
248 | assert_response :success | |
249 | assert_not_xpath(%{/response/error[text()="1"]}, "Error: " + get_xpath("/response/message/text()").first.to_s) | |
250 | ||
251 | assert_equal num_trackbacks+1, Article.find(2).trackbacks.count | |
252 | end | |
253 | ||
254 | def test_trackback_nuking | |
num_comments = Trackback.count | ||
72 | | |
257 | post :nuke_trackback, { :id => 7 }, {} | |
assert_response 403 | ||
75 | | |
260 | get :nuke_trackback, { :id => 7 }, { :user => users(:bob)} | |
assert_response 403 | ||
78 | | |
263 | post :nuke_trackback, { :id => 7 }, { :user => users(:bob)} | |
assert_response :success | ||
80 | | |
265 | assert_equal num_comments -1, Trackback.count | |
end | ||
82 | | |
267 | ||
def test_no_settings | ||
84 | | |
85 | | |
86 | | |
87 | | |
88 | | |
89 | | |
269 | this_blog.update_attribute(:settings, { }) | |
get :index | ||
92 | | |
272 | ||
assert_redirect | ||
94 | | |
95 | | |
96 | | |
97 | | |
274 | assert_redirected_to :controller => "admin/general", :action => "redirect" | |
275 | ||
end | ||
99 | | |
277 | ||
def test_no_users_exist | ||
101 | | |
102 | | |
279 | this_blog.update_attribute(:settings, { }) | |
104 | | |
105 | | |
106 | | |
107 | ||
User.destroy_all | ||
assert User.count.zero? | ||
110 | | |
283 | ||
get :index | ||
assert_redirect | ||
assert_redirected_to :controller => "accounts", :action => "signup" | ||
115 | | |
116 | | |
end | ||
def test_pages_static | ||
get :view_page, :name => 'page_one' | ||
assert_response :success | ||
assert_rendered_file "view_page" | ||
123 | | |
294 | ||
get :view_page, :name => 'page one' | ||
assert_response 404 | ||
end | ||
298 | ||
299 | def test_read_non_published | |
300 | get :read, :id => 4 | |
301 | assert_response :success | |
302 | assert_template "error" | |
303 | end | |
304 | ||
305 | def test_tags_non_published | |
306 | get :tag, :id => 'bar' | |
307 | assert_response :success | |
308 | assert_equal 1, assigns(:articles).size | |
309 | assert ! assigns(:articles).include?(@article4), "Unpublished article displayed" | |
310 | end | |
311 | ||
312 | def test_gravatar | |
313 | assert ! this_blog.use_gravatar | |
314 | get :read, :id => 1 | |
315 | assert_response :success | |
316 | assert_template "read" | |
317 | assert_no_tag :tag => "img", | |
318 | :attributes => { :class => "gravatar" } | |
319 | ||
320 | # Switch gravatar integration to on | |
321 | this_blog.use_gravatar = true | |
322 | assert this_blog.use_gravatar | |
323 | get :read, :id => 1 | |
324 | assert_response :success | |
325 | assert_template "read" | |
326 | assert_tag :tag => "img", | |
327 | :attributes => { | |
328 | :class => "gravatar", | |
329 | :src => "http://www.gravatar.com/avatar.php?gravatar_id=740618d2fe0450ec244d8b86ac1fe3f8&size=60" | |
330 | } | |
331 | end | |
332 | ||
333 | def test_comment_preview | |
334 | get :comment_preview | |
335 | assert_response :success | |
336 | assert_template nil | |
337 | ||
338 | get :comment_preview, :comment => { :author => "bob", :body => "comment preview" } | |
339 | assert_response :success | |
340 | assert_template "comment_preview" | |
341 | ||
342 | assert_tag :tag => "cite", | |
343 | :children => { :count => 1, | |
344 | :only => { :tag => "strong", | |
345 | :content => "bob" } } | |
346 | ||
347 | assert_tag :tag => "p", | |
348 | :content => "comment preview" | |
349 | end | |
350 | ||
351 | def test_read_article_with_comments_and_trackbacks | |
352 | get :read, :id => contents(:article1).id | |
353 | assert_response :success | |
354 | assert_template "read" | |
355 | ||
356 | assert_tag :tag => "ol", | |
357 | :attributes => { :id => "commentList"}, | |
358 | :children => { :count => contents(:article1).comments.to_a.select{|c| c.published?}.size, | |
359 | :only => { :tag => "li" } } | |
360 | ||
361 | assert_tag :tag => "li", | |
362 | :attributes => { :class => "author_comment"} | |
363 | ||
364 | assert_tag :tag => "ol", | |
365 | :attributes => { :id => "trackbackList" }, | |
366 | :children => { :count => contents(:article1).trackbacks.size, | |
367 | :only => { :tag => "li" } } | |
368 | end | |
369 | ||
370 | def test_read_article_no_comments_no_trackbacks | |
371 | get :read, :id => contents(:article3).id | |
372 | assert_response :success | |
373 | assert_template "read" | |
374 | ||
375 | assert_tag :tag => "ol", | |
376 | :attributes => { :id => "commentList"}, | |
377 | :children => { :count => 1, | |
378 | :only => { :tag => "li", | |
379 | :attributes => { :id => "dummy_comment", :style => "display: none" } } } | |
380 | ||
381 | assert_no_tag :tag => "ol", | |
382 | :attributes => { :id => "trackbackList" } | |
383 | end | |
384 | ||
385 | def test_autodiscovery_default | |
386 | ||
387 | get :index | |
388 | assert_response :success | |
389 | assert_tag :tag => 'link', :attributes => | |
390 | { :rel => 'alternate', :type => 'application/rss+xml', :title => 'RSS', | |
391 | :href => 'http://test.host/xml/rss20/feed.xml'} | |
392 | assert_tag :tag => 'link', :attributes => | |
393 | { :rel => 'alternate', :type => 'application/atom+xml', :title => 'Atom', | |
394 | :href => 'http://test.host/xml/atom/feed.xml'} | |
395 | end | |
396 | ||
397 | ||
398 | def test_autodiscovery_article | |
399 | get :read, :id => 1 | |
400 | assert_response :success | |
401 | assert_tag :tag => 'link', :attributes => | |
402 | { :rel => 'alternate', :type => 'application/rss+xml', :title => 'RSS', | |
403 | :href => 'http://test.host/xml/rss20/article/1/feed.xml'} | |
404 | assert_tag :tag => 'link', :attributes => | |
405 | { :rel => 'alternate', :type => 'application/atom+xml', :title => 'Atom', | |
406 | :href => 'http://test.host/xml/atom/article/1/feed.xml'} | |
407 | end | |
408 | ||
409 | def test_autodiscovery_category | |
410 | get :category, :id => 'hardware' | |
411 | assert_response :success | |
412 | assert_tag :tag => 'link', :attributes => | |
413 | { :rel => 'alternate', :type => 'application/rss+xml', :title => 'RSS', | |
414 | :href => 'http://test.host/xml/rss20/category/hardware/feed.xml'} | |
415 | assert_tag :tag => 'link', :attributes => | |
416 | { :rel => 'alternate', :type => 'application/atom+xml', :title => 'Atom', | |
417 | :href => 'http://test.host/xml/atom/category/hardware/feed.xml'} | |
418 | end | |
419 | ||
420 | def test_autodiscovery_tag | |
421 | get :tag, :id => 'hardware' | |
422 | assert_response :success | |
423 | assert_tag :tag => 'link', :attributes => | |
424 | { :rel => 'alternate', :type => 'application/rss+xml', :title => 'RSS', | |
425 | :href => 'http://test.host/xml/rss20/tag/hardware/feed.xml'} | |
426 | assert_tag :tag => 'link', :attributes => | |
427 | { :rel => 'alternate', :type => 'application/atom+xml', :title => 'Atom', | |
428 | :href => 'http://test.host/xml/atom/tag/hardware/feed.xml'} | |
429 | end | |
430 | ||
431 | def test_disabled_ajax_comments | |
432 | this_blog.sp_allow_non_ajax_comments = false | |
433 | assert_equal false, this_blog.sp_allow_non_ajax_comments | |
434 | ||
435 | post :comment, :id => 1, :comment => {'body' => 'This is posted without ajax', 'author' => 'bob' } | |
436 | assert_response 500 | |
437 | assert_equal "non-ajax commenting is disabled", @response.body | |
438 | ||
439 | @request.env['HTTP_X_REQUESTED_WITH'] = "XMLHttpRequest" | |
440 | post :comment, :id => 1, :comment => {'body' => 'This is posted *with* ajax', 'author' => 'bob' } | |
441 | assert_response :success | |
442 | ajax_comment = Article.find(1).comments.last | |
443 | assert_equal "This is posted *with* ajax", ajax_comment.body | |
444 | end | |
445 | ||
446 | def test_tag_max_article_count_is_first | |
447 | tags = Tag.find_all_with_article_counters | |
448 | assert tags.size > 1 | |
449 | max = tags[0].article_counter | |
450 | tags.each do |tag| | |
451 | assert tag.article_counter <= max | |
452 | end | |
453 | end | |
454 | ||
455 | def test_calc_distributed_class_basic | |
456 | assert_equal "prefix5", calc_distributed_class(0, 0, "prefix", 5, 15) | |
457 | (0..10).each do |article| | |
458 | assert_equal "prefix#{article}", calc_distributed_class(article, 10, "prefix", 0, 10) | |
459 | end | |
460 | (0..20).each do |article| | |
461 | assert_equal "prefix#{(article/2).to_i}", calc_distributed_class(article, 20, "prefix", 0, 10) | |
462 | end | |
463 | (0..5).each do |article| | |
464 | assert_equal "prefix#{(article*2).to_i}", calc_distributed_class(article, 5, "prefix", 0, 10) | |
465 | end | |
466 | end | |
467 | ||
468 | def test_calc_distributed_class_offset | |
469 | (0..10).each do |article| | |
470 | assert_equal "prefix#{article+6}", calc_distributed_class(article, 10, "prefix", 6, 16) | |
471 | end | |
472 | end | |
473 | ||
474 | def test_hide_future_article | |
475 | @article = Article.find_last_posted | |
476 | ||
477 | Article.create!(:title => "News from the future!", | |
478 | :body => "The future is cool!", | |
479 | :keywords => "future", | |
480 | :published => true, | |
481 | :created_at => Time.now + 12.minutes) | |
482 | get :index | |
483 | assert_equal @article, assigns(:articles).first | |
484 | assert @response.lifetime <= 12.minutes | |
485 | end | |
486 | ||
487 | def test_search | |
488 | get :search, :q => "search target" | |
489 | assert_equal 1, assigns(:articles).size | |
490 | end | |
491 | ||
492 | def test_author | |
493 | get :author, :id => 'tobi' | |
494 | ||
495 | assert_success | |
496 | assert_rendered_file 'index' | |
497 | assert assigns(:articles) | |
498 | assert_equal users(:tobi).articles.published, assigns(:articles) | |
499 | # This is until we write a proper author feed | |
500 | assert_equal('http://test.host/xml/rss20/feed.xml', | |
501 | assigns(:auto_discovery_url_rss)) | |
502 | end | |
503 | ||
504 | def test_nonexistent_author | |
505 | get :author, :id => 'nonexistent-chap' | |
506 | ||
507 | assert_success | |
508 | assert_rendered_file 'error' | |
509 | assert assigns(:message) | |
510 | assert_equal "Can't find posts with author 'nonexistent-chap'", assigns(:message) | |
511 | end | |
512 | ||
513 | def test_author_list | |
514 | get :author | |
515 | ||
516 | assert_success | |
517 | assert_rendered_file 'groupings' | |
518 | ||
519 | assert_tag(:tag => 'ul', | |
520 | :descendant => {\ | |
521 | :tag => 'a', | |
522 | :attributes => { :href => '/articles/author/tobi' }, | |
523 | }) | |
524 | end | |
end |
rool/rails/typo/trunk/test/functional/backend_controller_test.rb:
prev. | current | |
class BackendController; def rescue_action(e) raise e end; end | ||
class BackendControllerTest < Test::Unit::TestCase | ||
11 | | |
11 | fixtures :contents, :categories, :blogs, :users, :articles_categories, :text_filters | |
def setup | ||
@controller = BackendController.new | ||
... | ... | |
def test_blogger_get_user_info | ||
args = [ 'foo', 'tobi', 'whatever' ] | ||
36 | | |
36 | ||
result = invoke_layered :blogger, :getUserInfo, *args | ||
assert_equal 'tobi', result['userid'] | ||
end | ||
40 | | |
40 | ||
def test_blogger_new_post | ||
42 | | |
42 | args = [ 'foo', '1', 'tobi', 'whatever', '<title>new post title</title>new post *body*', 1] | |
result = invoke_layered :blogger, :newPost, *args | ||
assert_not_nil result | ||
new_post = Article.find(result) | ||
assert_equal "new post title", new_post.title | ||
48 | | |
49 | | |
50 | | |
48 | assert_equal "new post *body*", new_post.body | |
49 | assert_equal "<p>new post <strong>body</strong></p>", new_post.html(@controller, :body) | |
50 | assert_equal "textile", new_post.text_filter.name | |
51 | assert_equal users(:tobi), new_post.user | |
52 | assert_equal this_blog.id, new_post.blog_id | |
53 | assert new_post.published? | |
54 | assert new_post[:published_at] | |
end | ||
52 | | |
56 | ||
def test_blogger_new_post_no_title | ||
args = [ 'foo', '1', 'tobi', 'whatever', 'new post body for post without title but with a lenghty body', 1] | ||
... | ... | |
new_post = Article.find(result) | ||
assert_equal "new post body for post without", new_post.title | ||
assert_equal "new post body for post without title but with a lenghty body", new_post.body | ||
65 | assert_equal "<p>new post body for post without title but with a lenghty body</p>", new_post.html(@controller, :body) | |
end | ||
def test_blogger_new_post_with_categories | ||
... | ... | |
new_post = Article.find(result) | ||
assert_equal "new post title", new_post.title | ||
assert_equal "new post body", new_post.body | ||
71 | | |
76 | assert_equal [categories(:software), categories(:hardware)], new_post.categories.sort_by { |c| c.id } | |
77 | assert_equal this_blog.id, new_post.blog_id | |
78 | assert new_post.published? | |
end | ||
def test_blogger_new_post_with_non_existing_categories | ||
... | ... | |
result = invoke_layered :blogger, :newPost, *args | ||
assert_not_nil result | ||
new_post = Article.find(result) | ||
80 | | |
87 | assert_equal [categories(:hardware)], new_post.categories | |
88 | assert_equal this_blog.id, new_post.blog_id | |
end | ||
def test_blogger_fail_authentication | ||
... | ... | |
# Meta Weblog Tests | ||
def test_meta_weblog_get_categories | ||
args = [ 1, 'tobi', 'whatever' ] | ||
92 | | |
100 | ||
result = invoke_layered :metaWeblog, :getCategories, *args | ||
assert_equal 'Software', result.first | ||
end | ||
def test_meta_weblog_get_post | ||
args = [ 1, 'tobi', 'whatever' ] | ||
99 | | |
107 | ||
result = invoke_layered :metaWeblog, :getPost, *args | ||
assert_equal result['title'], 'Article 1!' | ||
end | ||
def test_meta_weblog_get_recent_posts | ||
105 | | |
106 | | |
113 | args = [ 1, 'tobi', 'whatever', 2 ] | |
114 | ||
result = invoke_layered :metaWeblog, :getRecentPosts, *args | ||
assert_equal result.size, 2 | ||
109 | | |
117 | assert_equal result.last['title'], 'Article 1!' | |
end | ||
def test_meta_weblog_delete_post | ||
args = [ 1, 2, 'tobi', 'whatever', 1 ] | ||
114 | | |
122 | ||
result = invoke_layered :metaWeblog, :deletePost, *args | ||
assert_raise(ActiveRecord::RecordNotFound) { Article.find(2) } | ||
end | ||
... | ... | |
def test_meta_weblog_edit_post | ||
article = Article.find(1) | ||
article.title = "Modified!" | ||
130 | article.body = "this is a *test*" | |
131 | article.text_filter = TextFilter.find_by_name("textile") | |
132 | article.published_at = Time.now.midnight | |
args = [ 1, 'tobi', 'whatever', MetaWeblogService.new(@controller).article_dto_from(article), 1 ] | ||
result = invoke_layered :metaWeblog, :editPost, *args | ||
assert result | ||
127 | | |
138 | ||
139 | new_article = Article.find(1) | |
140 | ||
141 | assert_equal article.title, new_article.title | |
142 | assert_equal article.body, new_article.body | |
143 | assert_equal "<p>this is a <strong>test</strong></p>", new_article.html(@controller, :body) | |
144 | assert_equal Time.now.midnight.to_s, new_article.published_at.to_s | |
145 | assert_equal this_blog.id, new_article.blog_id | |
end | ||
def test_meta_weblog_new_post | ||
article = Article.new | ||
article.title = "Posted via Test" | ||
article.body = "body" | ||
134 | | |
152 | article.extended = "extend me" | |
153 | article.text_filter = TextFilter.find_by_name("textile") | |
154 | article.published_at = Time.now.midnight | |
155 | ||
args = [ 1, 'tobi', 'whatever', MetaWeblogService.new(@controller).article_dto_from(article), 1 ] | ||
result = invoke_layered :metaWeblog, :newPost, *args | ||
assert result | ||
new_post = Article.find(result) | ||
161 | ||
assert_equal "Posted via Test", new_post.title | ||
141 | | |
163 | assert_equal "textile", new_post.text_filter.name | |
164 | assert_equal article.body, new_post.body | |
165 | assert_equal "<p>body</p>", new_post.html(@controller, :body) | |
166 | assert_equal article.extended, new_post.extended | |
167 | assert_equal "<p>extend me</p>", new_post.html(@controller, :extended) | |
168 | assert_equal Time.now.midnight.to_s, new_post.published_at.to_s | |
169 | assert_equal this_blog.id, new_post.blog_id | |
end | ||
def test_meta_weblog_new_media_object | ||
... | ... | |
"type" => "image/jpeg", | ||
"bits" => Base64.encode64(File.open(File.expand_path(RAILS_ROOT) + "/public/images/header.jpg", "rb") { |f| f.read }) | ||
) | ||
150 | | |
178 | ||
args = [ 1, 'tobi', 'whatever', media_object ] | ||
152 | | |
180 | ||
result = invoke_layered :metaWeblog, :newMediaObject, *args | ||
assert result['url'] =~ /#{media_object['name']}/ | ||
assert File.unlink(File.expand_path(RAILS_ROOT) + "/public/files/#{media_object['name']}") | ||
... | ... | |
# Movable Type Tests | ||
166 | | |
194 | def test_mt_get_category_list | |
args = [ 1, 'tobi', 'whatever' ] | ||
168 | | |
196 | ||
result = invoke_layered :mt, :getCategoryList, *args | ||
assert result.map { |c| c['categoryName'] }.include?('Software') | ||
end | ||
def test_mt_get_post_categories | ||
article = Article.find(1) | ||
175 | | |
203 | article.categories << categories(:software) | |
args = [ 1, 'tobi', 'whatever' ] | ||
178 | | |
206 | ||
result = invoke_layered :mt, :getPostCategories, *args | ||
assert_equal result.first['categoryName'], article.categories.first['name'] | ||
end | ||
def test_mt_get_recent_post_titles | ||
184 | | |
185 | | |
212 | args = [ 1, 'tobi', 'whatever', 2 ] | |
213 | ||
result = invoke_layered :mt, :getRecentPostTitles, *args | ||
187 | | |
215 | assert_equal result.first['title'], Article.find(2).title | |
end | ||
def test_mt_set_post_categories | ||
args = [ 2, 'tobi', 'whatever', | ||
[MovableTypeStructs::CategoryPerPost.new('categoryName' => 'personal', 'categoryId' => 3, 'isPrimary' => 1)] ] | ||
193 | | |
221 | ||
result = invoke_layered :mt, :setPostCategories, *args | ||
195 | | |
223 | assert_equal [categories(:personal)], Article.find(2).categories | |
args = [ 2, 'tobi', 'whatever', | ||
[MovableTypeStructs::CategoryPerPost.new('categoryName' => 'Software', 'categoryId' => 1, 'isPrimary' => 1), | ||
... | ... | |
result = invoke_layered :mt, :setPostCategories, *args | ||
203 | | |
231 | assert Article.find(2).categories.include?(categories(:hardware)) | |
end | ||
def test_mt_supported_text_filters | ||
result = invoke_layered :mt, :supportedTextFilters | ||
209 | | |
210 | | |
237 | assert result.map {|f| f['label']}.include?('Markdown') | |
238 | assert result.map {|f| f['label']}.include?('Textile') | |
end | ||
241 | def test_mt_supported_methods | |
242 | result = invoke_layered :mt, :supportedMethods | |
243 | assert_equal 8, result.size | |
244 | assert result.include?("publishPost") | |
245 | end | |
246 | ||
def test_mt_get_trackback_pings | ||
args = [ 1 ] | ||
215 | | |
249 | ||
result = invoke_layered :mt, :getTrackbackPings, *args | ||
217 | | |
251 | ||
assert_equal result.first['pingTitle'], 'Trackback Entry' | ||
end | ||
def test_mt_publish_post | ||
args = [ 4, 'tobi', 'whatever' ] | ||
224 | | |
225 | | |
258 | assert (not Article.find(4).published?) | |
259 | ||
result = invoke_layered :mt, :publishPost, *args | ||
227 | | |
261 | ||
assert result | ||
229 | | |
263 | assert Article.find(4).published? | |
264 | assert Article.find(4)[:published_at] | |
end | ||
def test_mt_fail_authentication |
rool/rails/typo/trunk/test/functional/theme_controller_test.rb:
prev. | current | |
@controller = ThemeController.new | ||
@request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new | ||
end | ||
12 | | |
12 | ||
def test_stylesheets | ||
get :stylesheets, :filename => "azure.css" | ||
assert_response :success | ||
... | ... | |
get :stylesheets, :filename => "../../../config/database.yml" | ||
assert_response 404 | ||
end | ||
31 | | |
31 | ||
def test_view_theming | ||
get :static_view_test | ||
assert_response :success | ||
assert @response.body =~ /Static View Test from azure/ | ||
end | ||
38 | | |
38 | ||
def disabled_test_javascript | ||
get :stylesheets, :filename => "typo.js" | ||
assert_response :success | ||
assert_equal "text/javascript", @response.headers['Content-Type'] | ||
assert_equal "inline; filename=\"typo.js\"", @response.headers['Content-Disposition'] | ||
end | ||
45 | ||
46 | end |
rool/rails/typo/trunk/test/functional/xml_controller_test.rb:
prev. | current | |
require File.dirname(__FILE__) + '/../test_helper' | ||
require 'xml_controller' | ||
3 | require 'dns_mock' | |
5 | # This test now has optional support for validating the generated RSS feeds. | |
6 | # Since Ruby doesn't have a RSS/Atom validator, I'm using the Python source | |
7 | # for http://feedvalidator.org and calling it via 'system'. | |
8 | # | |
9 | # To install the validator, download the source from | |
10 | # http://sourceforge.net/cvs/?group_id=99943 | |
11 | # Then copy src/feedvalidator and src/rdflib into a Python lib directory. | |
12 | # Finally, copy src/demo.py into your path as 'feedvalidator', make it executable, | |
13 | # and change the first line to something like '#!/usr/bin/python'. | |
14 | ||
15 | if($validator_installed == nil) | |
16 | $validator_installed = false | |
17 | begin | |
18 | IO.popen("feedvalidator 2> /dev/null","r") do |pipe| | |
19 | if (pipe.read =~ %r{Validating http://www.intertwingly.net/blog/index.}) | |
20 | puts "Using locally installed Python feed validator" | |
21 | $validator_installed = true | |
22 | end | |
23 | end | |
24 | rescue | |
25 | nil | |
26 | end | |
27 | end | |
28 | ||
# Re-raise errors caught by the controller. | ||
class XmlController; def rescue_action(e) raise e end; end | ||
class XmlControllerTest < Test::Unit::TestCase | ||
8 | | |
33 | fixtures :contents, :categories, :articles_categories, :tags, | |
34 | :articles_tags, :users, :blogs, :resources | |
35 | ||
def setup | ||
@controller = XmlController.new | ||
@request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new | ||
39 | ||
40 | Article.create!(:title => "News from the future!", | |
41 | :body => "The future is cool!", | |
42 | :keywords => "future", | |
43 | :created_at => Time.now + 12.minutes) | |
end | ||
14 | | |
15 | | |
16 | | |
17 | | |
18 | | |
19 | | |
46 | def assert_feedvalidator(rss, todo=nil) | |
47 | return unless $validator_installed | |
48 | ||
49 | begin | |
50 | file = Tempfile.new('typo-feed-test') | |
51 | filename = file.path | |
52 | file.write(rss) | |
53 | file.close | |
54 | ||
55 | messages = '' | |
56 | ||
57 | IO.popen("feedvalidator file://#{filename}") do |pipe| | |
58 | messages = pipe.read | |
59 | end | |
60 | ||
61 | okay, messages = parse_validator_messages(messages) | |
62 | ||
63 | if todo && ! ENV['RUN_TODO_TESTS'] | |
64 | assert !okay, messages + "\nTest unexpectedly passed!\nFeed text:\n"+rss | |
65 | else | |
66 | assert okay, messages + "\nFeed text:\n"+rss | |
67 | end | |
end | ||
end | ||
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
71 | def parse_validator_messages(message) | |
72 | messages=message.split(/\n/).reject do |m| | |
73 | m =~ /Feeds should not be served with the "text\/plain" media type/ || | |
74 | m =~ /Self reference doesn't match document location/ | |
end | ||
76 | ||
77 | if(messages.size > 1) | |
78 | [false, messages.join("\n")] | |
79 | else | |
80 | [true, ""] | |
81 | end | |
end | ||
30 | | |
83 | ||
84 | def test_feed_rss20 | |
85 | get :feed, :format => 'rss20', :type => 'feed' | |
86 | assert_response :success | |
87 | assert_xml @response.body | |
88 | assert_feedvalidator @response.body, :todo | |
89 | ||
90 | assert_rss20(6) | |
91 | end | |
92 | ||
93 | def test_feed_rss20_comments | |
94 | get :feed, :format => 'rss20', :type => 'comments' | |
95 | assert_response :success | |
96 | assert_xml @response.body | |
97 | assert_feedvalidator @response.body | |
98 | ||
99 | assert_rss20(3) | |
100 | end | |
101 | ||
102 | def test_feed_rss20_trackbacks | |
103 | get :feed, :format => 'rss20', :type => 'trackbacks' | |
104 | assert_response :success | |
105 | assert_xml @response.body | |
106 | assert_feedvalidator @response.body | |
107 | ||
108 | assert_rss20(2) | |
109 | end | |
110 | ||
111 | def test_feed_rss20_article | |
112 | get :feed, :format => 'rss20', :type => 'article', :id => 1 | |
113 | assert_response :success | |
114 | assert_xml @response.body | |
115 | assert_feedvalidator @response.body, :todo | |
116 | ||
117 | assert_rss20(2) | |
118 | end | |
119 | ||
120 | def test_feed_rss20_category | |
121 | get :feed, :format => 'rss20', :type => 'category', :id => 'personal' | |
122 | assert_response :success | |
123 | assert_xml @response.body | |
124 | assert_feedvalidator @response.body, :todo | |
125 | ||
126 | assert_rss20(3) | |
127 | end | |
128 | ||
129 | def test_feed_rss20_tag | |
130 | get :feed, :format => 'rss20', :type => 'tag', :id => 'foo' | |
131 | assert_response :success | |
132 | assert_xml @response.body | |
133 | assert_feedvalidator @response.body, :todo | |
134 | ||
135 | assert_rss20(2) | |
136 | end | |
137 | ||
138 | def test_feed_atom10_feed | |
139 | get :feed, :format => 'atom10', :type => 'feed' | |
140 | ||
141 | assert_response :success | |
142 | assert_xml @response.body | |
143 | assert_feedvalidator @response.body | |
144 | ||
145 | assert_equal(assigns(:items).sort { |a, b| b.created_at <=> a.created_at }, | |
146 | assigns(:items)) | |
147 | ||
148 | assert_atom10(6) | |
149 | end | |
150 | ||
151 | def test_feed_atom10_comments | |
152 | get :feed, :format => 'atom10', :type => 'comments' | |
153 | assert_response :success | |
154 | assert_xml @response.body | |
155 | assert_feedvalidator @response.body | |
156 | ||
157 | assert_equal(assigns(:items).sort { |a, b| b.created_at <=> a.created_at }, | |
158 | assigns(:items)) | |
159 | ||
160 | assert_atom10(3) | |
161 | ||
162 | assert_xpath('//title[@type="html"]') | |
163 | end | |
164 | ||
165 | def test_feed_atom10_trackbacks | |
166 | get :feed, :format => 'atom10', :type => 'trackbacks' | |
167 | assert_response :success | |
168 | assert_xml @response.body | |
169 | assert_feedvalidator @response.body | |
170 | ||
171 | assert_equal(assigns(:items).sort { |a, b| b.created_at <=> a.created_at }, | |
172 | assigns(:items)) | |
173 | ||
174 | assert_atom10(2) | |
175 | ||
176 | assert_xpath('//title[@type="html"]') | |
177 | assert_xpath('//summary', "Trackback entry has no summaries") | |
178 | end | |
179 | ||
180 | def test_feed_atom10_article | |
181 | get :feed, :format => 'atom10', :type => 'article', :id => 1 | |
182 | assert_response :success | |
183 | assert_xml @response.body | |
184 | assert_feedvalidator @response.body | |
185 | ||
186 | assert_equal(assigns(:items).sort { |a, b| b.created_at <=> a.created_at }, | |
187 | assigns(:items)) | |
188 | ||
189 | assert_atom10(2) | |
190 | end | |
191 | ||
192 | def test_feed_atom10_category | |
193 | get :feed, :format => 'atom10', :type => 'category', :id => 'personal' | |
194 | assert_response :success | |
195 | assert_xml @response.body | |
196 | assert_feedvalidator @response.body | |
197 | ||
198 | assert_equal(assigns(:items).sort { |a, b| b.created_at <=> a.created_at }, | |
199 | assigns(:items)) | |
200 | ||
201 | assert_atom10(3) | |
202 | end | |
203 | ||
204 | def test_feed_atom10_tag | |
205 | get :feed, :format => 'atom10', :type => 'tag', :id => 'foo' | |
206 | assert_response :success | |
207 | assert_xml @response.body | |
208 | assert_feedvalidator @response.body | |
209 | ||
210 | assert_equal(assigns(:items).sort { |a, b| b.created_at <=> a.created_at }, | |
211 | assigns(:items)) | |
212 | ||
213 | assert_atom10(2) | |
214 | end | |
215 | ||
216 | def test_articlerss | |
217 | get :articlerss, :id => 1 | |
218 | assert_response :redirect | |
219 | end | |
220 | ||
221 | def test_commentrss | |
222 | get :commentrss, :id => 1 | |
223 | assert_response :redirect | |
224 | end | |
225 | ||
def test_trackbackrss | ||
32 | | |
227 | get :trackbackrss, :id => 1 | |
228 | assert_response :redirect | |
229 | end | |
230 | ||
231 | def test_bad_format | |
232 | get :feed, :format => 'atom04', :type => 'feed' | |
233 | assert_response :missing | |
234 | end | |
235 | ||
236 | def test_bad_type | |
237 | get :feed, :format => 'rss20', :type => 'foobar' | |
238 | assert_response :missing | |
239 | end | |
240 | ||
241 | def test_pubdate_conformance | |
242 | get :feed, :format => 'rss20', :type => 'feed' | |
assert_response :success | ||
34 | | |
35 | | |
36 | | |
37 | | |
244 | xml = REXML::Document.new(@response.body) | |
245 | assert_equal contents(:article2).created_at.rfc822, REXML::XPath.match(xml, '/rss/channel/item[title="Article 2!"]/pubDate').first.text | |
246 | end | |
39 | | |
40 | | |
248 | def test_rsd | |
249 | get :rsd, :id => 1 | |
assert_response :success | ||
assert_nothing_raised do | ||
assert REXML::Document.new(@response.body) | ||
end | ||
end | ||
47 | | |
48 | | |
256 | def test_extended_rss20 | |
257 | set_extended_on_rss true | |
258 | get :feed, :format => 'rss20', :type => 'feed' | |
assert_response :success | ||
50 | | |
51 | | |
52 | | |
260 | assert_match /extended content/, @response.body | |
261 | ||
262 | set_extended_on_rss false | |
263 | get :feed, :format => 'rss20', :type => 'feed' | |
264 | assert_response :success | |
265 | assert_no_match /extended content/, @response.body | |
end | ||
54 | | |
55 | | |
56 | | |
267 | ||
268 | def test_atom03 | |
269 | get :feed, :format => 'atom03', :type => 'feed' | |
270 | assert_response :redirect | |
271 | assert_redirected_to :format => 'atom' | |
272 | end | |
273 | ||
274 | def test_extended_atom10 | |
275 | set_extended_on_rss true | |
276 | get :feed, :format => 'atom10', :type => 'feed' | |
assert_response :success | ||
58 | | |
59 | | |
60 | | |
61 | | |
278 | assert_match /extended content/, @response.body | |
279 | assert_not_equal 0, get_xpath(%{//summary]}).size, "Extended feed has no summaries" | |
280 | assert_not_equal 0, get_xpath(%{//content]}).size, "Extended feed has no content" | |
281 | ||
282 | set_extended_on_rss false | |
283 | get :feed, :format => 'atom10', :type => 'feed' | |
284 | assert_response :success | |
285 | assert_no_match /extended content/, @response.body | |
286 | assert_not_equal 0, get_xpath(%{//summary]}).size, "Non-Extended feed has no summaries" | |
287 | assert_equal 0, get_xpath(%{//content]}).size, "Non-extended feed has content" | |
288 | end | |
289 | ||
290 | def test_xml_atom10 | |
291 | get :feed, :format => 'atom10', :type => 'feed' | |
292 | assert_response :success | |
293 | ||
294 | # titles are escaped html | |
295 | assert_xpath('//entry/title[text()="Associations aren\'t :dependent =&gt; true anymore" and @type="html"]') | |
296 | ||
297 | # categories are well formed | |
298 | assert_match /this & that/, @response.body | |
299 | end | |
300 | ||
301 | def test_enclosure_rss20 | |
302 | get :feed, :format => 'rss20', :type => 'feed' | |
303 | assert_response :success | |
304 | ||
305 | # There's an enclosure in there somewhere | |
306 | assert_xpath('/rss/channel/item/enclosure') | |
307 | ||
308 | # There's an enclosure attached to the node with the title "Article 1!" | |
309 | assert_xpath('/rss/channel/item[title="Article 1!"]/enclosure') | |
310 | assert_xpath('/rss/channel/item[title="Article 2!"]/enclosure') | |
311 | ||
312 | # Article 3 exists, but has no enclosure | |
313 | assert_xpath('/rss/channel/item[title="Article 3!"]') | |
314 | assert_not_xpath('/rss/channel/item[title="Article 3!"]/enclosure') | |
315 | end | |
316 | ||
317 | def test_enclosure_atom10 | |
318 | get :feed, :format => 'atom10', :type => 'feed' | |
319 | assert_response :success | |
320 | ||
321 | # There's an enclosure in there somewhere | |
322 | assert_xpath('/feed/entry/link[@rel="enclosure"]') | |
323 | ||
324 | # There's an enclosure attached to "Article 1!" with a length | |
325 | assert_xpath('/feed/entry[title="Article 1!"]/link[@rel="enclosure" and @length]') | |
326 | ||
327 | # There's an enclosure attached to "Article 2!" with no length | |
328 | assert_xpath('/feed/entry[title="Article 2!"]/link[@rel="enclosure" and not(@length)]') | |
329 | ||
330 | # Article 3 exists, but has no enclosure | |
331 | assert_xpath('/feed/entry[title="Article 3!"]') | |
332 | assert_not_xpath('/feed/entry[title="Article 3!"]/link[@rel="enclosure"]') | |
333 | end | |
334 | ||
335 | def test_itunes | |
336 | get :itunes | |
337 | assert_response :success | |
338 | assert_xml @response.body | |
339 | assert_feedvalidator @response.body, :todo | |
340 | end | |
341 | ||
342 | def assert_rss20(items) | |
343 | assert_equal 1, get_xpath(%{/rss[@version="2.0"]/channel[count(child::item)=#{items}]}).size, "RSS 2.0 feed has wrong number of channel/item nodes" | |
344 | end | |
345 | ||
346 | def assert_atom10(entries) | |
347 | assert_equal 1, get_xpath(%{/feed[@xmlns="http://www.w3.org/2005/Atom" and count(child::entry)=#{entries}]}).size, "Atom 1.0 feed has wrong number of feed/entry nodes" | |
348 | end | |
349 | ||
350 | def set_extended_on_rss(value) | |
351 | this_blog.show_extended_on_rss = value | |
352 | end | |
end |
rool/rails/typo/trunk/test/mocks/test/dns_mock.rb:
prev. | current | |
class IPSocket | ||
def self.getaddress(host) | ||
3 | | |
4 | | |
5 | | |
6 | | |
7 | | |
3 | case host | |
4 | when *%w{ buy-computer.us.bsb.empty.us chinaaircatering.com.bsb.empty.us | |
5 | 206.230.42.212.opm.blitzed.us } | |
"127.0.0.2" | ||
7 | when *%w{ bofh.org.uk.multi.surbl.org www.bofh.org.uk.multi.surbl.org } | |
8 | "10.10.10.10" | |
else | ||
10 | | |
10 | raise SocketError.new("getaddrinfo: Name or service not known") | |
end | ||
end | ||
13 | ||
14 | end |
rool/rails/typo/trunk/test/mocks/test/http_mock.rb:
prev. | current | |
module Net | ||
remove_const "HTTP" | ||
3 | | |
4 | | |
3 | class Request < Struct.new(:host, :port, :query, :post_data, :headers) | |
4 | def post(query, post, headers = {}) | |
self.query = query | ||
6 | | |
7 | | |
6 | self.post_data = post | |
7 | self.headers = headers | |
8 | end | |
end | ||
9 | | |
10 | ||
class Net::HTTP | ||
11 | | |
12 | | |
13 | | |
12 | ||
13 | ||
14 | def self.start(host, port) | |
request = Request.new | ||
request.host = host | ||
16 | | |
17 | | |
17 | request.port = port | |
18 | ||
@pings ||= [] | ||
@pings << request | ||
yield request | ||
22 | | |
23 | ||
end | ||
24 | | |
25 | ||
def self.pings | ||
@pings | ||
end | ||
28 | | |
29 | | |
29 | ||
30 | def self.next_response=(mock_response) | |
31 | @@response = mock_response | |
32 | end | |
33 | ||
34 | def self.get_response(*args) | |
35 | @@response | |
36 | end | |
37 | end | |
end | ||
31 |
rool/rails/typo/trunk/test/mocks/test/theme_mock.rb:
prev. | current | |
class Theme | ||
def self.themes_root | ||
3 | | |
3 | RAILS_ROOT + "/test/mocks/themes" | |
end | ||
5 | ||
6 | end |
rool/rails/typo/trunk/test/test_helper.rb:
prev. | current | |
ENV["RAILS_ENV"] = "test" | ||
2 | ||
3 | ||
4 | ||
require File.expand_path(File.dirname(__FILE__) + "/../config/environment") | ||
6 | ||
3 | require 'test_help' | |
8 | ||
9 | ||
10 | ||
11 | ||
12 | ||
13 | ||
14 | ||
User.salt = 'change-me' | ||
17 | ||
18 | ||
class Test::Unit::TestCase | ||
20 | | |
21 | | |
22 | | |
8 | # Turn off transactional fixtures if you're working with MyISAM tables in MySQL | |
9 | self.use_transactional_fixtures = true | |
24 | | |
25 | | |
11 | # Instantiated fixtures are slow, but give you @david where you otherwise would need people(:david) | |
12 | self.use_instantiated_fixtures = false | |
13 | ||
14 | # Add more helper methods to be used by all tests here... | |
15 | def assert_xml(xml) | |
16 | assert_nothing_raised do | |
17 | assert REXML::Document.new(xml) | |
18 | end | |
end | ||
28 | | |
29 | ||
22 | # Add more helper methods to be used by all tests here... | |
23 | def find_tag_in(source, conditions) | |
24 | HTML::Document.new(source).find(conditions) | |
25 | end | |
26 | ||
27 | def assert_tag_in(source, opts) | |
28 | tag = find_tag_in(source, opts) | |
29 | assert tag, "expected tag, but no tag found matching #{opts.inspect} in:\n#{source.inspect}" | |
30 | end | |
31 | ||
32 | def assert_no_tag_in(source, opts) | |
33 | tag = find_tag_in(source, opts) | |
34 | assert !tag, "expected no tag, but tag found matching #{opts.inspect} in:\n#{source.inspect}" | |
35 | end | |
36 | ||
37 | def get_xpath(xpath) | |
38 | rexml = REXML::Document.new(@response.body) | |
39 | assert rexml | |
40 | ||
41 | REXML::XPath.match(rexml, xpath) | |
42 | end | |
43 | ||
44 | def assert_xpath(xpath, msg=nil) | |
45 | assert !(get_xpath(xpath).empty?), msg | |
46 | end | |
47 | ||
48 | def assert_not_xpath(xpath, msg=nil) | |
49 | assert get_xpath(xpath).empty?, msg | |
50 | end | |
51 | ||
52 | def this_blog | |
53 | Blog.default || Blog.create! | |
54 | end | |
55 | end | |
56 | ||
57 | # Extend HTML::Tag to understand URI matching | |
58 | begin | |
59 | require 'html/document' | |
60 | rescue LoadError | |
61 | require 'action_controller/vendor/html-scanner/html/document' | |
62 | end | |
63 | require 'uri' | |
64 | ||
65 | class HTML::Tag | |
66 | private | |
67 | ||
68 | alias :match_condition_orig :match_condition unless private_method_defined? :match_condition_orig | |
69 | def match_condition(value, condition) | |
70 | case condition | |
71 | when URI | |
72 | compare_uri(URI.parse(value), condition.dup) rescue nil | |
73 | else | |
74 | match_condition_orig(value, condition) | |
75 | end | |
76 | end | |
77 | ||
78 | def compare_uri(value, condition) | |
79 | valQuery = value.query | |
80 | condQuery = condition.query | |
81 | value.query = nil | |
82 | condition.query = nil | |
83 | value == condition && compare_query(valQuery, condQuery) | |
84 | end | |
85 | ||
86 | def compare_query(value, condition) | |
87 | def create_query_hash(str) | |
88 | str.split('&').inject({}) do |h,v| | |
89 | key, value = v.split('=') | |
90 | h[key] = value | |
91 | h | |
92 | end | |
93 | end | |
94 | create_query_hash(value) == create_query_hash(condition) | |
95 | end | |
96 | end |
rool/rails/typo/trunk/test/unit/article_test.rb:
prev. | current | |
require 'http_mock' | ||
class ArticleTest < Test::Unit::TestCase | ||
6 | | |
7 | | |
6 | fixtures :blogs, :contents, :articles_tags, :tags, :resources, :categories, :articles_categories, :users, :notifications | |
7 | ||
def setup | ||
9 | | |
9 | @articles = [] | |
end | ||
11 | ||
12 | def assert_results_are(*expected) | |
13 | assert_equal expected.size, @articles.size | |
14 | expected.each do |i| | |
15 | assert @articles.include?(i.is_a?(Symbol) ? contents(i) : i) | |
16 | end | |
17 | end | |
19 | def test_blog | |
20 | a = Article.new | |
21 | ||
22 | assert_equal(1, a.blog_id) | |
23 | assert_kind_of(Blog, a.blog) | |
24 | end | |
25 | ||
26 | def test_create | |
27 | a = Article.new | |
28 | a.user_id = 1 | |
29 | a.body = "Foo" | |
30 | a.title = "Zzz" | |
31 | assert a.save | |
32 | ||
33 | a.categories << Category.find(1) | |
34 | assert_equal 1, a.categories.size | |
35 | ||
36 | b = Article.find(a.id) | |
37 | assert_equal 1, b.categories.size | |
38 | end | |
39 | ||
def test_permalink | ||
13 | | |
14 | | |
15 | | |
41 | assert_equal( contents(:article3), this_blog.articles.find_by_date(2004,06,01) ) | |
42 | assert_equal( [contents(:article2), contents(:article1)], | |
43 | this_blog.articles.find_all_by_date(2.days.ago.year) ) | |
end | ||
def test_permalink_with_title | ||
19 | | |
20 | | |
47 | assert_equal( contents(:article3), | |
48 | this_blog.articles.find_by_permalink(2004, 06, 01, "article-3") ) | |
49 | assert_nil this_blog.articles.find_by_permalink(2005, 06, 01, "article-5") | |
end | ||
22 | | |
51 | ||
def test_strip_title | ||
assert_equal "article-3", "Article-3".to_url | ||
assert_equal "article-3", "Article 3!?#".to_url | ||
... | ... | |
assert_equal "lorem-ipsum-dolor-sit-amet-consectetaur-adipisicing-elit", "Lorem ipsum dolor sit amet, consectetaur adipisicing elit".to_url | ||
assert_equal "my-cats-best-friend", "My Cat's Best Friend".to_url | ||
end | ||
31 | | |
60 | ||
def test_perma_title | ||
33 | | |
34 | | |
35 | | |
62 | assert_equal "article-1", contents(:article1).stripped_title | |
63 | assert_equal "article-2", contents(:article2).stripped_title | |
64 | assert_equal "article-3", contents(:article3).stripped_title | |
end | ||
37 | | |
66 | ||
67 | def test_html_title | |
68 | a = Article.new | |
69 | a.title = "This <i>is</i> a <b>test</b>" | |
70 | assert a.save | |
71 | ||
72 | assert_equal 'this-is-a-test', a.permalink | |
73 | end | |
74 | ||
75 | def test_urls | |
76 | urls = contents(:article4).html_urls | |
77 | assert_equal ["http://www.example.com/public"], urls | |
78 | end | |
79 | ||
80 | ### XXX: Should we have a test here? | |
def test_send_pings | ||
39 | | |
40 | | |
41 | | |
42 | | |
43 | | |
44 | | |
end | ||
47 | ||
84 | ### XXX: Should we have a test here? | |
def test_send_multiple_pings | ||
49 | | |
50 | | |
51 | | |
52 | | |
53 | | |
54 | | |
86 | end | |
56 | | |
57 | | |
58 | | |
59 | | |
60 | | |
88 | def test_tags | |
89 | a = Article.new(:title => 'Test tag article', | |
90 | :keywords => 'test tag tag stuff'); | |
91 | ||
92 | assert_kind_of Article, a | |
93 | assert_equal 0, a.tags.size | |
94 | ||
95 | a.keywords_to_tags | |
96 | ||
97 | assert_equal 3, a.tags.size | |
98 | assert_equal ["test", "tag", "stuff"].sort , a.tags.collect {|t| t.name}.sort | |
99 | assert a.save | |
100 | ||
101 | a.keywords = 'tag bar stuff foo' | |
102 | a.keywords_to_tags | |
103 | ||
104 | assert_equal 4, a.tags.size | |
105 | assert_equal ["foo", "bar", "tag", "stuff"].sort , a.tags.collect {|t| t.name}.sort | |
106 | ||
107 | a.keywords='tag bar' | |
108 | a.keywords_to_tags | |
109 | ||
110 | assert_equal 2, a.tags.size | |
111 | ||
112 | a.keywords='' | |
113 | a.keywords_to_tags | |
114 | ||
115 | assert_equal 0, a.tags.size | |
116 | ||
117 | b = Article.new(:title => 'Tag Test 2', | |
118 | :keywords => 'tag test article one two three') | |
119 | ||
120 | assert_kind_of Article,b | |
121 | assert_equal 0, b.tags.size | |
end | ||
62 | | |
123 | ||
124 | def test_find_published_by_tag_name | |
125 | @articles = Tag.find_by_name(tags(:foo_tag).name).published_articles | |
126 | ||
127 | assert_results_are(:article1, :article2) | |
128 | end | |
129 | ||
130 | ||
131 | def test_find_published | |
132 | @articles = this_blog.articles.find_published | |
133 | assert_results_are(:search_target, :article1, :article2, | |
134 | :article3, :inactive_article,:xmltest) | |
135 | ||
136 | @articles = this_blog.articles.find_published(:all, | |
137 | :conditions => "title = 'Article 1!'") | |
138 | assert_results_are :article1 | |
139 | end | |
140 | ||
141 | def test_just_published_flag | |
142 | art = this_blog.articles.build(:title => 'title', | |
143 | :body => 'body', | |
144 | :published => true) | |
145 | assert art.just_published? | |
146 | assert art.save | |
147 | assert !art.just_published? | |
148 | ||
149 | art = Article.create!(:title => 'title2', | |
150 | :body => 'body', | |
151 | :published => false) | |
152 | ||
153 | assert ! art.just_published? | |
154 | end | |
155 | ||
156 | def test_future_publishing | |
157 | assert_sets_trigger(Article.create!(:title => 'title', :body => 'body', | |
158 | :published => true, | |
159 | :published_at => Time.now + 2.seconds)) | |
160 | end | |
161 | ||
162 | def test_future_publishing_without_published_flag | |
163 | assert_sets_trigger Article.create!(:title => 'title', :body => 'body', | |
164 | :published_at => Time.now + 2.seconds) | |
165 | end | |
166 | ||
167 | def test_triggers_are_dependent | |
168 | art = Article.create!(:title => 'title', :body => 'body', | |
169 | :published_at => Time.now + 1.hour) | |
170 | assert_equal 1, Trigger.count | |
171 | art.destroy | |
172 | assert_equal 0, Trigger.count | |
173 | end | |
174 | ||
175 | def assert_sets_trigger(art) | |
176 | assert_equal 1, Trigger.count | |
177 | assert Trigger.find(:first, :conditions => ['pending_item_id = ?', art.id]) | |
178 | sleep 2 | |
179 | Trigger.fire | |
180 | art.reload | |
181 | assert art.published | |
182 | end | |
183 | ||
184 | def test_find_published_by_category | |
185 | Article.create!(:title => "News from the future!", | |
186 | :body => "The future is cool!", | |
187 | :keywords => "future", | |
188 | :published_at => Time.now + 12.minutes) | |
189 | ||
190 | @articles = Category.find_by_permalink('personal').published_articles | |
191 | assert_results_are :article1, :article2, :article3 | |
192 | ||
193 | @articles = Category.find_by_permalink('foobar').published_articles | |
194 | assert @articles.empty? | |
195 | ||
196 | @articles = Category.find_by_permalink('software').published_articles | |
197 | assert_results_are :article1 | |
198 | end | |
199 | ||
200 | def test_destroy_file_upload_associations | |
201 | assert_equal 2, contents(:article1).resources.size | |
202 | contents(:article1).resources << resources(:resource1) << resources(:resource2) | |
203 | assert_equal 4, contents(:article1).resources.size | |
204 | contents(:article1).destroy | |
205 | assert_equal 0, Resource.find(:all, :conditions => "article_id = #{contents(:article1).id}").size | |
206 | end | |
207 | ||
208 | def test_notifications | |
209 | a = Article.new(:title => 'New Article', :body => 'Foo', :author => 'Tobi', :user => users(:tobi)) | |
210 | assert a.save | |
211 | ||
212 | assert_equal 2, a.notify_users.size | |
213 | assert_equal ['bob', 'randomuser'], a.notify_users.collect {|u| u.login }.sort | |
214 | end | |
215 | ||
216 | def test_tags_on_update | |
217 | contents(:article3).update_attribute :keywords, "my new tags" | |
218 | assert_equal 3, contents(:article3).reload.tags.size | |
219 | assert contents(:article3).tags.include?(Tag.find_by_name("new")) | |
220 | end | |
221 | ||
222 | # this also tests time_delta, indirectly | |
223 | def test_find_all_by_date | |
224 | feb28 = this_blog.articles.build(:published => true) | |
225 | mar1 = this_blog.articles.build(:published => true) | |
226 | mar2 = this_blog.articles.build(:published => true) | |
227 | ||
228 | feb28.title = "February 28" | |
229 | mar1.title = "March 1" | |
230 | mar2.title = "March 2" | |
231 | ||
232 | feb28.created_at = feb28.published_at = "2004-02-28" | |
233 | mar1.created_at = mar1.published_at = "2004-03-01" | |
234 | mar2.created_at = mar2.published_at = "2004-03-02" | |
235 | ||
236 | [feb28, mar1, mar2].each do |x| | |
237 | x.state = ContentState::Published.instance | |
238 | x.save | |
239 | end | |
240 | ||
241 | assert_equal(1, Article.find_all_by_date(2004,02).size) | |
242 | assert_equal(2, Article.find_all_by_date(2004,03).size) | |
243 | assert_equal(1, Article.find_all_by_date(2004,03,01).size) | |
244 | end | |
end |
rool/rails/typo/trunk/test/unit/category_test.rb:
prev. | current | |
require File.dirname(__FILE__) + '/../test_helper' | ||
class CategoryTest < Test::Unit::TestCase | ||
4 | | |
4 | fixtures :contents, :categories, :articles_categories | |
def setup | ||
@category = Category.find(1) | ||
... | ... | |
def test_truth | ||
assert_kind_of Category, @category | ||
end | ||
13 | | |
13 | ||
def test_find_all_with_article_counters | ||
15 | | |
16 | | |
17 | ||
c = Category.find_all_with_article_counters | ||
20 | | |
21 | | |
22 | | |
17 | assert_equal categories(:software), c[0] | |
18 | assert_equal categories(:hardware), c[1] | |
19 | assert_equal categories(:personal), c[2] | |
20 | ||
21 | assert_equal 1, c[0].article_counter | |
22 | assert_equal 1, c[1].article_counter | |
23 | assert_equal 3, c[2].article_counter | |
end | ||
25 | ||
26 | def test_reorder | |
27 | assert_equal categories(:software), Category.find(:first, :order => :position) | |
28 | Category.reorder([categories(:personal).id, categories(:hardware).id, categories(:software).id]) | |
29 | assert_equal categories(:personal), Category.find(:first, :order => :position) | |
30 | end | |
31 | ||
32 | def test_reorder_alpha | |
33 | assert_equal categories(:software), Category.find(:first, :order => :position) | |
34 | Category.reorder_alpha | |
35 | assert_equal categories(:hardware), Category.find(:first, :order => :position) | |
36 | end | |
end |
rool/rails/typo/trunk/test/unit/comment_test.rb:
prev. | current | |
require 'dns_mock' | ||
class CommentTest < Test::Unit::TestCase | ||
6 | | |
6 | fixtures :contents, :blacklist_patterns, :text_filters, :blogs | |
8 | | |
9 | | |
8 | def test_save_regular | |
9 | assert contents(:comment2).save | |
10 | assert_equal "http://www.google.com", contents(:comment2).url | |
end | ||
12 | | |
13 | | |
14 | | |
15 | | |
16 | | |
def test_save_spam | ||
18 | | |
19 | | |
20 | | |
14 | assert contents(:spam_comment).save | |
15 | assert_equal "http://fakeurl.com", contents(:spam_comment).url | |
end | ||
22 | | |
17 | ||
18 | def test_create_comment | |
19 | c = Comment.new | |
20 | c.author = 'Bob' | |
21 | c.article_id = 1 | |
22 | c.body = 'nice post' | |
23 | c.ip = '1.2.3.4' | |
24 | ||
25 | assert c.save | |
26 | assert c.guid.size > 15 | |
27 | end | |
28 | ||
def test_reject_spam_rbl | ||
c = Comment.new | ||
c.author = "Spammer" | ||
... | ... | |
assert ! c.save | ||
assert c.errors.invalid?('body') | ||
assert c.errors.invalid?('url') | ||
39 | assert c.errors.invalid?('ip') | |
end | ||
42 | def test_not_spam_but_rbl_lookup_succeeds | |
43 | c = Comment.new | |
44 | c.author = "Not a Spammer" | |
45 | c.body = "Useful commentary!" | |
46 | c.url = "http://www.bofh.org.uk" | |
47 | c.ip = "10.10.10.10" | |
48 | ||
49 | assert c.save | |
50 | end | |
51 | ||
def test_reject_spam_pattern | ||
c = Comment.new | ||
c.author = "Another Spammer" | ||
c.body = "Texas hold-em poker crap" | ||
c.url = "http://texas.hold-em.us" | ||
40 | | |
57 | ||
assert ! c.save | ||
assert c.errors.invalid?('body') | ||
end | ||
44 | | |
61 | ||
def test_reject_spam_uri_limit | ||
c = Comment.new | ||
c.author = "Yet Another Spammer" | ||
c.body = %{ <a href="http://www.one.com/">one</a> <a href="http://www.two.com/">two</a> <a href="http://www.three.com/">three</a> <a href="http://www.four.com/">four</a> } | ||
c.url = "http://www.uri-limit.com" | ||
c.ip = "123.123.123.123" | ||
51 | | |
68 | ||
assert ! c.save | ||
assert c.errors.invalid?('body') | ||
end | ||
... | ... | |
c = Comment.new | ||
c.author = "Old Spammer" | ||
c.body = "Old trackback body" | ||
60 | | |
77 | c.article = contents(:inactive_article) | |
assert ! c.save | ||
assert c.errors.invalid?('article_id') | ||
64 | | |
81 | ||
c.article = @article1 | ||
66 | | |
83 | ||
assert c.save | ||
assert c.errors.empty? | ||
end | ||
88 | def test_modify_old_comment | |
89 | c = contents(:inactive_article).comments.first | |
90 | c.body = 'Comment body <em>italic</em> <strong>bold</strong>' | |
91 | assert c.save | |
92 | assert c.errors.empty? | |
93 | end | |
94 | ||
def test_article_relation | ||
72 | | |
73 | | |
96 | assert_equal true, contents(:comment2).has_article? | |
97 | assert_equal 1, contents(:comment2).article.id | |
end | ||
def test_xss_rejection | ||
... | ... | |
# Test each filter to make sure that we don't allow scripts through. | ||
# Yes, this is ugly. | ||
['','textile','markdown','smartypants','markdown smartypants'].each do |filter| | ||
85 | | |
86 | | |
87 | | |
109 | this_blog.comment_text_filter = filter | |
assert c.save | ||
assert c.errors.empty? | ||
... | ... | |
assert c.body_html !~ /<script>/ | ||
end | ||
end | ||
95 | ||
96 | | |
97 | | |
98 | | |
99 | | |
100 | | |
101 | | |
end |
rool/rails/typo/trunk/test/unit/configuration_test.rb:
prev. | current | |
require File.dirname(__FILE__) + '/../test_helper' | ||
class ConfigurationTest < Test::Unit::TestCase | ||
4 | | |
4 | fixtures :blogs | |
6 | | |
7 | | |
8 | | |
6 | def test_booleans | |
7 | assert this_blog.sp_global? | |
8 | assert this_blog.sp_allow_non_ajax_comments? | |
9 | assert this_blog.default_allow_comments? | |
10 | assert !this_blog.default_allow_pings? | |
10 | | |
11 | | |
12 | | |
13 | | |
14 | | |
12 | assert TrueClass === this_blog.sp_global | |
13 | assert String === this_blog.blog_name | |
14 | assert Fixnum === this_blog.limit_rss_display | |
end | ||
16 | | |
17 | | |
18 | | |
19 | | |
20 | | |
21 | | |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
30 | | |
31 | | |
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | | |
38 | | |
39 | | |
40 | | |
41 | | |
42 | | |
43 | | |
16 | ||
def test_is_ok | ||
45 | | |
18 | assert this_blog.is_ok? | |
end | ||
47 | | |
48 | ||
21 | ||
22 | end |
rool/rails/typo/trunk/test/unit/delicious_test.rb:
prev. | current | |
@delicious = Delicious.new("", false) | ||
@delicious.send(:parse, fixture) | ||
end | ||
9 | | |
9 | ||
def test_parser | ||
assert_equal 3, @delicious.items.size | ||
end | ||
def test_fields | ||
15 | | |
16 | | |
15 | assert_equal "del.icio.us/shanev", @delicious.title | |
16 | assert_equal "http://del.icio.us/shanev", @delicious.link | |
end | ||
def test_items | ||
assert_equal "Guide to Using XMLHttpRequest (with Baby Steps)", @delicious.items[0].title | ||
assert_equal "http://www.webpasties.com/xmlHttpRequest/", @delicious.items[0].link | ||
end | ||
23 | | |
23 | ||
private | ||
25 | | |
25 | ||
def fixture | ||
%{<?xml version="1.0" encoding="UTF-8"?> | ||
<rdf:RDF | ||
... | ... | |
xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" | ||
xmlns:admin="http://webns.net/mvcb/" | ||
> | ||
36 | | |
36 | ||
<channel rdf:about="http://del.icio.us/shanev"> | ||
<title>del.icio.us/shanev</title> | ||
<link>http://del.icio.us/shanev</link> | ||
... | ... | |
<rdf:Seq> | ||
<rdf:li rdf:resource="http://www.webpasties.com/xmlHttpRequest/" /> | ||
<rdf:li rdf:resource="http://www.w3schools.com/js/default.asp" /> | ||
45 | | |
45 | ||
<rdf:li rdf:resource="http://www.feedfab.com/xmljs/" /> | ||
</rdf:Seq> | ||
</items> | ||
</channel> | ||
50 | | |
50 | ||
<item rdf:about="http://www.webpasties.com/xmlHttpRequest/"> | ||
<title>Guide to Using XMLHttpRequest (with Baby Steps)</title> | ||
<link>http://www.webpasties.com/xmlHttpRequest/</link> | ||
<dc:creator>shanev</dc:creator> | ||
<dc:date>2005-02-24T07:11Z</dc:date> | ||
<dc:subject>XMLHTTPRequest</dc:subject> | ||
57 | | |
57 | ||
<taxo:topics> | ||
<rdf:Bag> | ||
<rdf:li resource="http://del.icio.us/tag/XMLHTTPRequest" /> | ||
</rdf:Bag> | ||
</taxo:topics> | ||
</item> | ||
64 | | |
64 | ||
<item rdf:about="http://www.w3schools.com/js/default.asp"> | ||
<title>W3 Schools Javascript Tutorial</title> | ||
<link>http://www.w3schools.com/js/default.asp</link> | ||
<dc:creator>shanev</dc:creator> | ||
69 | | |
69 | ||
<dc:date>2005-02-24T04:03Z</dc:date> | ||
<dc:subject>javascript</dc:subject> | ||
<taxo:topics> | ||
... | ... | |
</rdf:Bag> | ||
</taxo:topics> | ||
</item> | ||
78 | | |
78 | ||
<item rdf:about="http://www.feedfab.com/xmljs/"> | ||
<title>XMLHTTPRequest Library</title> | ||
81 | | |
81 | ||
<link>http://www.feedfab.com/xmljs/</link> | ||
<dc:creator>shanev</dc:creator> | ||
<dc:date>2005-02-22T21:36Z</dc:date> | ||
... | ... | |
</rdf:Bag> | ||
</taxo:topics> | ||
</item> | ||
92 | | |
92 | ||
</rdf:RDF> | ||
} | ||
95 | | |
95 | end | |
end |
rool/rails/typo/trunk/test/unit/flickr_test.rb:
prev. | current | |
require File.dirname(__FILE__) + '/../test_helper' | ||
class FlickrTest < Test::Unit::TestCase | ||
4 | | |
4 | ||
def setup | ||
6 | | |
7 | | |
6 | @flickr = FlickrAggregation.new("",false) | |
7 | @flickr.send(:parse, fixture) | |
end | ||
# Replace this with your real tests. | ||
11 | | |
12 | | |
11 | def test_parser | |
12 | assert_equal 6, @flickr.pics.size | |
end | ||
14 | | |
15 | | |
14 | ||
15 | def test_random_chooser | |
assert_equal 4, @flickr.choose(4).size | ||
end | ||
18 | | |
19 | | |
18 | ||
19 | ||
def test_fields | ||
21 | | |
22 | | |
23 | | |
21 | assert_equal "xal's Photos", @flickr.title | |
22 | assert_equal "http://www.flickr.com/photos/40235412@N00/", @flickr.link | |
23 | assert_equal "A feed of xal's Photos", @flickr.description | |
end | ||
25 | | |
25 | ||
def test_image | ||
27 | | |
28 | | |
29 | | |
30 | | |
27 | assert_equal "p1010009", @flickr.pics[0].title | |
28 | assert_equal "http://www.flickr.com/photos/40235412@N00/4903142/", @flickr.pics[0].link | |
29 | assert_not_nil @flickr.pics[0].description | |
30 | assert_equal Time.parse("Wed, 16 Feb 2005 07:15:48 -0800"), @flickr.pics[0].date | |
end | ||
32 | | |
32 | ||
def test_image_desc_parsers | ||
assert_equal "http://photos3.flickr.com/4903142_ada4539ae8_m.jpg", @flickr.pics[0].image | ||
35 | | |
35 | assert_equal "http://photos3.flickr.com/4903142_ada4539ae8_t.jpg", @flickr.pics[0].thumb | |
end | ||
37 | | |
37 | ||
private | ||
39 | | |
39 | ||
def fixture | ||
%{<?xml version="1.0" encoding="utf-8"?> | ||
<rss version="2.0"> | ||
... | ... | |
</rss> | ||
} | ||
end | ||
133 | | |
134 | ||
134 | ||
135 | end |
rool/rails/typo/trunk/test/unit/fortythree_test.rb:
prev. | current | |
@fortythree = Fortythree.new("", false) | ||
@fortythree.send(:parse, fixture) | ||
end | ||
9 | | |
9 | ||
def test_parser | ||
assert_equal 3, @fortythree.things.size | ||
end | ||
def test_fields | ||
15 | | |
16 | | |
15 | assert_equal "43 Things: activity for anoop", @fortythree.title | |
16 | assert_equal "http://www.43things.com/people/view/anoop", @fortythree.link | |
end | ||
def test_items | ||
assert_equal "Tidy my room and keep it that way", @fortythree.things[0].title | ||
assert_equal "http://www.43things.com/things/view/3500", @fortythree.things[0].link | ||
end | ||
23 | | |
23 | ||
private | ||
25 | | |
25 | ||
def fixture | ||
%{ | ||
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"> | ||
... | ... | |
</channel> | ||
</rss> | ||
} | ||
65 | | |
65 | end | |
end |
rool/rails/typo/trunk/test/unit/page_cache_test.rb:
prev. | current | |
require 'page_cache' | ||
class PageCache | ||
5 | | |
5 | ||
cattr_accessor :deleted_pages | ||
7 | | |
7 | ||
def delete_file(path) | ||
PageCache.deleted_pages << path | ||
end | ||
... | ... | |
# Replace this with your real tests. | ||
def test_sweep_all | ||
PageCache.sweep_all | ||
24 | | |
24 | ||
assert_equal ['/index.html', '/articles/2005/05/05/title'].sort, PageCache.deleted_pages.sort | ||
end | ||
27 | | |
27 | ||
def test_sweep_by_pattern | ||
PageCache.sweep('articles%') | ||
assert_equal ['/articles/2005/05/05/title'], PageCache.deleted_pages | ||
end | ||
33 | | |
33 | ||
end |
rool/rails/typo/trunk/test/unit/page_test.rb:
prev. | current | |
require File.dirname(__FILE__) + '/../test_helper' | ||
class PageTest < Test::Unit::TestCase | ||
4 | | |
4 | fixtures :contents | |
def setup | ||
7 | | |
7 | @page = Page.find(9) | |
end | ||
10 | | |
11 | | |
12 | | |
13 | | |
14 | | |
15 | | |
16 | ||
17 | | |
18 | | |
19 | ||
def test_validate | ||
a = Page.new | ||
a.name = 'a-new-name' |
rool/rails/typo/trunk/test/unit/ping_test.rb:
prev. | current | |
require File.dirname(__FILE__) + '/../test_helper' | ||
require 'http_mock' | ||
4 | require 'xmlrpc_mock' | |
class PingTest < Test::Unit::TestCase | ||
6 | | |
7 | | |
7 | fixtures :contents, :blogs | |
8 | ||
def setup | ||
9 | | |
10 | @pingback_header = nil | |
11 | @body = '' | |
end | ||
12 | | |
13 | | |
14 | | |
15 | | |
16 | | |
17 | | |
14 | def teardown | |
15 | Net::HTTP.next_response = nil | |
16 | end | |
17 | ||
18 | def test_send_pingback_found_in_pingback_header | |
19 | ||
20 | # We've linked to http://anotherblog.org/a-post from | |
21 | # http://myblog.net/referring-post and discovered a pingback | |
22 | # listener at http://anotherblog.org/xml-rpc | |
23 | # Set up the mocking | |
24 | ||
25 | ||
26 | @pingback_header = "http://anotherblog.org/xml-rpc" | |
27 | assert_pingback_sent | |
28 | end | |
29 | ||
30 | def test_send_pingback_found_in_body | |
31 | @body = %{<link rel="pingback" href="http://anotherblog.org/xml-rpc" />} | |
32 | ||
33 | assert_pingback_sent | |
34 | end | |
35 | ||
36 | def assert_pingback_sent | |
37 | Net::HTTP.next_response = self | |
38 | ping = contents(:article1).pings.build("url" => | |
39 | "http://anotherblog.org/a-post") | |
40 | ||
41 | ping.send_pingback_or_trackback("http://myblog.net/referring-post") | |
42 | ||
43 | sent_ping = XMLRPC::Client.pings.last | |
44 | assert_equal "http://anotherblog.org/xml-rpc", sent_ping.uri | |
45 | assert_equal "pingback.ping", sent_ping.method_name | |
46 | assert_equal "http://myblog.net/referring-post", sent_ping.args[0] | |
47 | assert_equal "http://anotherblog.org/a-post", sent_ping.args[1] | |
48 | end | |
49 | ||
50 | def test_send_trackback | |
51 | ||
52 | # We've linked to http://anotherblog.org/a-post from | |
53 | # http://myblog.net/referring-post and discovered the trackback | |
54 | # URL http://anotherblog.org/a-post/trackback | |
55 | Net::HTTP.next_response = self | |
56 | ||
57 | @body = <<-eobody | |
58 | <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
59 | xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" | |
60 | xmlns:dc="http://purl.org/dc/elements/1.1/"> | |
61 | <rdf:Description | |
62 | rdf:about="" | |
63 | trackback:ping="http://anotherblog.org/a-post/trackback" | |
64 | dc:title="Track me, track me!" | |
65 | dc:identifier="http://anotherblog.org/a-post" | |
66 | dc:description="Track me 'til I fart!'" | |
67 | dc:creator="pdcawley" | |
68 | dc:date="2006-03-01T04:31:00-05:00" /> | |
69 | </rdf:RDF> | |
70 | eobody | |
71 | ||
72 | ping = contents(:article1).pings.build("url" => | |
73 | "http://anotherblog.org/a-post") | |
74 | ping.send_pingback_or_trackback("http://myblog.net/referring-post") | |
75 | ||
76 | ping = Net::HTTP.pings.last | |
77 | assert_equal "anotherblog.org", ping.host | |
assert_equal 80, ping.port | ||
19 | | |
20 | | |
79 | assert_equal "/a-post/trackback", ping.query | |
80 | assert_equal "title=Article%201!&excerpt=body&url=http://myblog.net/referring-post&blog_name=test%20blog", ping.post_data | |
end | ||
83 | def test_send_weblogupdatesping | |
24 | | |
85 | # Our blog, named this_blog.blog_name at http://myblog.net/ has | |
86 | # changed through us posting http://myblog.net/new-post. This, | |
87 | # we'd like to tell to http://rpc.technorati.com/rpc/ping. | |
88 | ||
89 | ping = contents(:article1).pings.build("url" => | |
90 | "http://rpc.technorati.com/rpc/ping") | |
91 | ping.send_weblogupdatesping("http://myblog.net/", | |
92 | "http://myblog.net/new-post") | |
93 | ||
94 | ping = XMLRPC::Client.pings.last | |
95 | assert_equal "http://rpc.technorati.com/rpc/ping", ping.uri | |
96 | assert_equal "weblogUpdates.ping", ping.method_name | |
97 | assert_equal this_blog.blog_name, ping.args[0] | |
98 | assert_equal "http://myblog.net/", ping.args[1] | |
99 | assert_equal "http://myblog.net/new-post", ping.args[2] | |
100 | end | |
101 | ||
102 | # Mock stuff | |
103 | ||
104 | def [](key) | |
105 | @pingback_header | |
106 | end | |
107 | ||
108 | def body | |
109 | @body | |
110 | end | |
end |
rool/rails/typo/trunk/test/unit/resource_test.rb:
prev. | current | |
class ResourceTest < Test::Unit::TestCase | ||
fixtures :resources | ||
6 | | |
7 | | |
8 | | |
6 | def setup | |
7 | # put the files on disk as if it were uploaded | |
8 | FileUtils.mkpath("#{RAILS_ROOT}/public/files") | |
9 | [ resources(:resource1), resources(:resource2) ].each { |f| FileUtils.touch(f.fullpath) } | |
end | ||
11 | ||
12 | def teardown | |
13 | # remove the files on disk | |
14 | [ resources(:resource1), resources(:resource2) ].each { |f| | |
15 | File.unlink(f.fullpath) if File.exist?(f.fullpath) | |
16 | } | |
17 | end | |
18 | ||
19 | def test_fullpath | |
20 | assert_equal resources(:resource1).fullpath, "#{RAILS_ROOT}/public/files/#{resources(:resource1).filename}" | |
21 | end | |
22 | ||
23 | def test_create | |
24 | assert_not_nil resources(:resource1) | |
25 | assert_not_nil resources(:resource2) | |
26 | ||
27 | f1 = Resource.create(:filename => resources(:resource1).filename, | |
28 | :mime => resources(:resource1).mime, | |
29 | :created_at => Time.now) | |
30 | assert_not_nil f1 | |
31 | f2 = Resource.create(:filename => resources(:resource2).filename, | |
32 | :mime => resources(:resource2).mime, | |
33 | :created_at => Time.now) | |
34 | assert_not_nil f2 | |
35 | ||
36 | assert resources(:resource1).filename != f1.filename | |
37 | assert resources(:resource2).filename != f2.filename | |
38 | f1.destroy | |
39 | f2.destroy | |
40 | end | |
41 | ||
42 | def test_read | |
43 | assert_not_nil resources(:resource1) | |
44 | f = Resource.find_by_filename(resources(:resource1).filename) | |
45 | assert_not_nil f | |
46 | assert_equal f, resources(:resource1) | |
47 | end | |
48 | ||
49 | def test_update | |
50 | assert_not_nil resources(:resource1) | |
51 | assert_not_nil resources(:resource2) | |
52 | ||
53 | f = resources(:resource2) | |
54 | assert resources(:resource2).save | |
55 | assert_equal f.filename, resources(:resource2).filename | |
56 | ||
57 | resources(:resource1).filename = f.filename | |
58 | assert !resources(:resource1).save | |
59 | ||
60 | resources(:resource1).filename = Resource.find(1).filename | |
61 | assert resources(:resource1).save | |
62 | end | |
63 | ||
64 | def test_destroy | |
65 | assert_not_nil resources(:resource1) | |
66 | # blow it away, ensure that the file is removed from the public/files dir | |
67 | assert resources(:resource1).destroy | |
68 | assert !File.exist?(resources(:resource1).fullpath) | |
69 | assert_raise(ActiveRecord::RecordNotFound) { Resource.find(resources(:resource1).id) } | |
70 | end | |
end |
rool/rails/typo/trunk/test/unit/theme_test.rb:
prev. | current | |
require File.dirname(__FILE__) + '/../test_helper' | ||
2 | ||
2 | require 'theme' | |
require 'theme_mock' | ||
class ThemeTest < Test::Unit::TestCase | ||
6 | fixtures :blogs | |
7 | ||
def setup | ||
@theme = Theme.new("test", "test") | ||
end | ||
... | ... | |
end | ||
def test_description | ||
15 | | |
16 | | |
17 | # Filtering now occurs in the controller, not the model | |
18 | assert_equal "### Azure\n\nTypo's default theme by [Justin Palmer][1]\n\n[1]: http://www.encytemedia.com/ \"Encyte Media\"\n", | |
19 | this_blog.current_theme.description | |
end | ||
18 | | |
21 | ||
def test_themes_root | ||
# Overridden in theme_mock | ||
21 | | |
24 | assert_equal RAILS_ROOT + "/test/mocks/themes", Theme.themes_root | |
end | ||
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
30 | | |
31 | ||
def test_theme_from_path | ||
33 | | |
28 | assert_equal "azure", Theme.theme_from_path(this_blog.current_theme_path).name | |
end | ||
def test_search_theme_directory | ||
... | ... | |
end | ||
def test_find_all | ||
46 | | |
41 | assert Theme.find_all.collect { |t| t.name }.include?(this_blog.current_theme.name) | |
assert_equal 4, Theme.find_all.size | ||
end | ||
end |
rool/rails/typo/trunk/test/unit/trackback_test.rb:
prev. | current | |
require 'dns_mock' | ||
class TrackbackTest < Test::Unit::TestCase | ||
6 | | |
6 | fixtures :contents, :blacklist_patterns, :blogs | |
8 | | |
9 | | |
10 | | |
11 | ||
def test_incomplete | ||
tb = Trackback.new | ||
tb.blog_name = "Blog name" | ||
tb.title = "Title" | ||
tb.excerpt = "Excerpt" | ||
17 | | |
13 | ||
assert ! tb.save | ||
assert tb.errors.invalid?('url') | ||
20 | | |
16 | ||
tb.url = "http://foo.com" | ||
assert tb.save | ||
assert tb.errors.empty? | ||
20 | assert tb.guid.size > 15 | |
end | ||
def test_reject_spam_rbl | ||
... | ... | |
assert tb.errors.invalid?('excerpt') | ||
assert tb.errors.invalid?('url') | ||
end | ||
38 | | |
35 | ||
def test_reject_spam_pattern | ||
tb = Trackback.new | ||
tb.blog_name = "Another Spammer" | ||
tb.title = "Spammy trackback" | ||
tb.excerpt = "Texas hold-em poker crap" | ||
44 | | |
41 | ||
assert ! tb.save | ||
assert tb.errors.invalid?('excerpt') | ||
end |
rool/rails/typo/trunk/test/unit/user_test.rb:
prev. | current | |
require File.dirname(__FILE__) + '/../test_helper' | ||
class UserTest < Test::Unit::TestCase | ||
4 | | |
5 | | |
6 | | |
4 | ||
5 | fixtures :users, :contents | |
6 | ||
def test_auth | ||
8 | | |
9 | | |
8 | assert_equal users(:bob), User.authenticate("bob", "test") | |
assert_nil User.authenticate("nonbob", "test") | ||
11 | | |
end | ||
13 | | |
11 | ||
12 | def test_articles_link | |
13 | assert_equal 7, User.find(1).articles.size | |
14 | assert_equal 6, User.find(1).articles.find_published.size | |
15 | assert_equal 6, User.find(1).articles.published.size | |
16 | ||
17 | articles = User.find(1).articles.published | |
18 | assert_equal articles.sort_by { |a| a.created_at }.reverse, articles | |
19 | ||
20 | articles = User.find(1).articles | |
21 | assert_equal articles.sort_by { |a| a.created_at }.reverse, articles | |
22 | end | |
23 | ||
def test_authenticate? | ||
assert User.authenticate?("bob", "test") | ||
assert !User.authenticate?("bob", "wrong password") | ||
assert User.authenticate?("tobi", "whatever") | ||
18 | | |
28 | assert !User.authenticate?("tobi", "not whatever") | |
end | ||
20 | | |
30 | ||
def test_disallowed_passwords | ||
22 | | |
23 | | |
32 | u = User.new | |
u.login = "nonbob" | ||
u.password = u.password_confirmation = "tiny" | ||
27 | | |
36 | assert !u.save | |
assert u.errors.invalid?('password') | ||
u.password = u.password_confirmation = "hugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehuge" | ||
31 | | |
40 | assert !u.save | |
assert u.errors.invalid?('password') | ||
33 | | |
42 | ||
u.password = u.password_confirmation = "" | ||
35 | | |
44 | assert !u.save | |
assert u.errors.invalid?('password') | ||
37 | | |
46 | ||
u.password = u.password_confirmation = "bobs_secure_password" | ||
39 | | |
48 | assert u.save | |
assert u.errors.empty? | ||
41 | | |
50 | ||
end | ||
43 | | |
52 | ||
def test_bad_logins | ||
45 | ||
46 | | |
54 | u = User.new | |
u.password = u.password_confirmation = "bobs_secure_password" | ||
u.login = "x" | ||
50 | | |
58 | assert !u.save | |
assert u.errors.invalid?('login') | ||
52 | | |
60 | ||
u.login = "hugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhug" | ||
54 | | |
62 | assert !u.save | |
assert u.errors.invalid?('login') | ||
u.login = "" | ||
... | ... | |
assert u.errors.invalid?('login') | ||
u.login = "okbob" | ||
62 | | |
70 | assert u.save | |
assert u.errors.empty? | ||
64 | | |
72 | ||
end | ||
def test_change_name | ||
... | ... | |
u = User.new | ||
u.login = "nonexistingbob" | ||
u.password = u.password_confirmation = "bobs_secure_password" | ||
91 | | |
92 | | |
93 | | |
99 | ||
100 | assert u.save | |
end | ||
95 | | |
102 | ||
def test_sha1 | ||
u = User.new | ||
u.login = "nonexistingbob" | ||
u.password = u.password_confirmation = "bobs_secure_password" | ||
assert u.save | ||
101 | | |
102 | | |
108 | ||
109 | assert_equal '98740ff87bade6d895010bceebbd9f718e7856bb', u.password | |
end | ||
end |
rool/rails/typo/trunk/themes/azure/layouts/default.rhtml:
prev. | current | |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | ||
<html xmlns="http://www.w3.org/1999/xhtml"> | ||
<head> | ||
4 | | |
5 | | |
6 | | |
7 | | |
8 | | |
9 | | |
10 | | |
11 | | |
12 | | |
13 | | |
14 | | |
15 | | |
4 | <title><%=h page_title %></title> | |
5 | <%= page_header %> | |
6 | <%= stylesheet_link_tag "/stylesheets/theme/azure", :media => 'all' %> | |
7 | <%= stylesheet_link_tag "/stylesheets/user-styles", :media => 'all' %> | |
8 | <%= stylesheet_link_tag "/stylesheets/theme/print", :media => 'print' %> | |
</head> | ||
10 | <% benchmark "BENCHMARK: layout/body" do %> | |
<body> | ||
<div id="container" class="clearfix"> | ||
<div id="header"> | ||
<div id="logo"> | ||
21 | | |
22 | | |
15 | <h1 id="sitename"><%= link_to this_blog.blog_name, { :controller => '/' } %></h1> | |
16 | <h2 id="subtitle"><%= this_blog.blog_subtitle %></h2> | |
</div> | ||
</div> | ||
<div id="search"> <%= render :partial => "shared/search" %></div> | ||
27 | | |
21 | <% benchmark "BENCHMARK: layout/content" do %> | |
22 | ||
<div id="content" class="clearfix"> | ||
<div id="main"> | ||
<%= @content_for_layout %> | ||
<%= javascript_tag "show_dates_as_local_time()" %> | ||
</div> | ||
28 | <% end %> | |
<div id="sidebar"> | ||
<div id="search-results"></div> | ||
36 | ||
37 | | |
38 | | |
32 | <% benchmark "BENCHMARK: layout/sidebars" do %> | |
33 | <%= render_sidebars %> | |
34 | <% end %> | |
35 | ||
36 | <%= link_to image_tag("powered.gif"), "http://www.typosphere.org/", {:class => "powered" } %> | |
</div> | ||
<br clear="all" /> | ||
... | ... | |
</div> | ||
</body> | ||
</html> | ||
50 | <% end %> |
rool/rails/typo/trunk/themes/azure/stylesheets/azure.css:
prev. | current | |
1 | ||
2 |
| |
3 | ||
4 | | |
5 | | |
6 | | |
7 | | |
8 | | |
9 | | |
10 |
| |
11 | ||
12 | | |
13 | | |
14 | | |
15 | | |
16 | | |
17 | | |
18 | | |
19 |
| |
20 |
| |
21 | ||
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 |
| |
30 | ||
31 | | |
32 | | |
33 |
| |
34 | | |
35 |
| |
36 | ||
37 | | |
38 | | |
39 | | |
40 | | |
41 | | |
42 |
| |
43 | ||
44 | | |
45 | | |
46 | | |
47 | | |
48 | | |
49 |
| |
50 | ||
51 | | |
52 | | |
53 | | |
54 | | |
55 | | |
56 |
| |
57 |
| |
58 | ||
59 | | |
60 | | |
61 | | |
62 | | |
63 | | |
64 |
| |
65 | ||
66 | ||
67 |
| |
68 | ||
69 | | |
70 | | |
71 | | |
72 | | |
73 | | |
74 | | |
75 | | |
76 |
| |
77 | | |
78 | ||
79 | | |
80 | | |
81 |
| |
82 | | |
83 | | |
84 | | |
85 | | |
86 |
| |
87 | | |
88 | | |
89 | | |
90 |
| |
91 |
| |
92 | ||
93 | | |
94 | | |
95 |
| |
96 | ||
97 | | |
98 | | |
99 |
| |
100 | ||
101 | ||
102 |
| |
103 | ||
104 | | |
105 | | |
106 |
| |
107 | | |
108 |
| |
109 | | |
110 | | |
111 | | |
112 | | |
113 |
| |
114 | | |
115 | | |
116 | | |
117 |
| |
118 | | |
119 | | |
120 | | |
121 |
| |
122 |
| |
123 | ||
124 | | |
125 | | |
126 | | |
127 | | |
128 | | |
129 | | |
130 | | |
131 |
| |
132 | | |
133 | | |
134 | | |
135 |
| |
136 | | |
137 | | |
138 | | |
139 | | |
140 | | |
141 |
| |
142 | | |
143 | | |
144 | | |
145 |
| |
146 | | |
147 | | |
148 | | |
149 | | |
150 | | |
151 |
| |
152 | | |
153 | | |
154 | | |
155 | | |
156 | | |
157 | | |
158 | | |
159 | | |
160 |
| |
161 | | |
162 | | |
163 | | |
164 | | |
165 | | |
166 | | |
167 |
| |
168 | | |
169 | | |
170 | | |
171 | | |
172 | | |
173 | | |
174 | | |
175 | | |
176 | | |
177 |
| |
178 | | |
179 | | |
180 | | |
181 |
| |
182 | | |
183 | | |
184 | | |
185 | | |
186 | | |
187 |
| |
188 |
| |
189 | | |
190 | | |
191 | | |
192 | | |
193 |
| |
194 | | |
195 |
| |
196 | | |
197 | | |
198 | | |
199 | | |
200 | | |
201 |
| |
202 | | |
203 | | |
204 | | |
205 | | |
206 |
| |
207 | | |
208 | | |
209 | | |
210 |
| |
211 | | |
212 | | |
213 | | |
214 | | |
215 | | |
216 |
| |
217 | | |
218 | | |
219 | | |
220 | | |
221 | | |
222 | | |
223 | | |
224 |
| |
225 | | |
226 |
| |
227 | | |
228 | | |
229 | | |
230 |
| |
231 | | |
232 | | |
233 | | |
234 | | |
235 | | |
236 |
| |
237 | | |
238 | | |
239 | | |
240 | | |
241 | | |
242 | | |
243 |
| |
244 | | |
245 | | |
246 | | |
247 |
| |
248 | | |
249 | | |
250 | | |
251 | | |
252 |
| |
253 | | |
254 | | |
255 |
| |
256 | | |
257 | | |
258 |
| |
259 | | |
260 | | |
261 | | |
262 |
| |
263 | | |
264 | | |
265 | | |
266 | | |
267 | | |
268 | | |
269 | | |
270 | | |
271 | | |
272 | | |
273 | | |
274 | ||
275 | ||
276 | | |
277 | | |
278 | | |
279 | | |
280 | ||
281 |
| |
282 | | |
283 | | |
284 | | |
285 | | |
286 | | |
287 | | |
288 | | |
289 | | |
290 |
| |
291 | | |
292 | | |
293 | | |
294 |
| |
295 | ||
296 | | |
297 | | |
298 | | |
299 | | |
300 | | |
301 | | |
302 | | |
303 | ||
304 |
| |
305 | ||
306 | | |
307 | | |
308 | ||
309 |
| |
310 | ||
311 |
| |
312 | | |
313 | | |
314 | | |
315 |
| |
316 | ||
317 | ||
318 | | |
319 | | |
320 | ||
1 | /* Azure Screen Styles */ | |
2 | ||
3 | body { | |
4 | margin: 20px 0; | |
5 | text-align: center; | |
6 | background: #8ab3d1 url(../../images/theme/bg-tile.gif) repeat-x; | |
7 | font: 1em/1.2em Arial, Verdana, Helvetica, sans-serif; | |
8 | color: #333; | |
9 | } | |
10 | ||
11 | #container { | |
12 | margin: 0 auto; | |
13 | width: 762px; | |
14 | text-align: left; | |
15 | background: #fff; | |
16 | border: 7px solid #fff; | |
17 | font-size: 80%; | |
18 | } | |
19 | ||
20 | ||
21 | #header { | |
22 | background: #8ab3d1 url(../../images/theme/hdr.gif) no-repeat; | |
23 | width: 520px; | |
24 | height: 139px; | |
25 | margin: 0; | |
26 | text-align: center; | |
27 | float: left; | |
28 | } | |
29 | ||
30 | #content { | |
31 | background: #fff url(../../images/theme/sbar-tile.gif) right repeat-y; | |
32 | margin-top: 7px; | |
33 | ||
34 | } | |
35 | ||
36 | #main { | |
37 | float: left; | |
38 | width: 520px; | |
39 | background: #fff; | |
40 | padding: 1px; | |
41 | } | |
42 | ||
43 | #search { | |
44 | background: #d3e0ea; | |
45 | height: 139px; | |
46 | margin-left: 527px; | |
47 | padding-left: 20px; | |
48 | } | |
49 | ||
50 | #sidebar { | |
51 | background: #f8f2e5; | |
52 | margin-left: 530px; | |
53 | padding-left: 10px; | |
54 | padding-right: 5px; | |
55 | } | |
56 | ||
57 | ||
58 | #footer { | |
59 | background: #d3e0ea; | |
60 | margin-top: 7px; | |
61 | height: 35px; | |
62 | text-align: center; | |
63 | } | |
64 | ||
65 | #footer a { border: none; } | |
66 | #footer img { border: none; margin-top: 10px; } | |
67 | ||
68 | /*+-------------------------------------------+ | |
69 | | LINKS | | |
70 | +-------------------------------------------+*/ | |
71 | a { | |
72 | color: #5189b5; | |
73 | text-decoration: none; | |
74 | border-bottom: 1px dotted #5189b5; | |
75 | } | |
76 | ||
77 | a:hover { color: #85ab02; border-bottom-color: #85ab02; } | |
78 | /*+-------------------------------------------+ | |
79 | | UTILITY | | |
80 | +-------------------------------------------+*/ | |
81 | ||
82 | h1, h2, h3, h4, h5, h6 { | |
83 | margin: 0; | |
84 | padding: 0; | |
85 | } | |
86 | ||
87 | form, div { padding: 0; margin: 0; } | |
88 | p { margin: 0 0 1em 0; padding: 0; } | |
89 | img { border: 0; } | |
90 | ||
91 | ||
92 | /*+-------------------------------------------+ | |
93 | | HEADER | | |
94 | +-------------------------------------------+*/ | |
95 | ||
96 | #logo { | |
97 | padding-top: 50px; | |
98 | } | |
99 | ||
100 | #logo h1 a { color: #fff; text-decoration: none; border: none; } | |
101 | #logo h2 { color: #fff; padding-top: .2em; font-size: 1.2em; text-decoration: underline;} | |
102 | ||
103 | /*+-------------------------------------------+ | |
104 | | SEARCH | | |
105 | +-------------------------------------------+*/ | |
106 | ||
107 | #sform { padding-top: 50px; } | |
108 | ||
109 | #sidebar #searchform #s { | |
110 | width: 130px; | |
111 | margin-top: 20px; | |
112 | } | |
113 | ||
114 | #sidebar #searchsubmit { | |
115 | padding: 1px; | |
116 | } | |
117 | ||
118 | #search-results { | |
119 | padding: 2px; | |
120 | } | |
121 | ||
122 | ||
123 | /*+-------------------------------------------+ | |
124 | | POST | | |
125 | +-------------------------------------------+*/ | |
126 | .post { | |
127 | margin: 0 0 20px 5px; | |
128 | border-bottom: 1px solid #f4f4f4; | |
129 | padding-bottom: 10px; | |
130 | } | |
131 | ||
132 | .post h2 { | |
133 | font: normal 140%/1.3em Arial, Verdana, Helvetica, sans-serif; | |
134 | } | |
135 | ||
136 | .post h2 a { | |
137 | color: #5189b5; | |
138 | text-decoration: none; | |
139 | border: none; | |
140 | } | |
141 | ||
142 | .post h2 a:hover { | |
143 | color: #85ab02; | |
144 | } | |
145 | ||
146 | p.meta { | |
147 | font-size: 75%; | |
148 | text-align: right; | |
149 | margin-right: 5px; | |
150 | } | |
151 | ||
152 | p.auth { | |
153 | padding: 0 0 0 12px; | |
154 | font-size: 85%; | |
155 | margin-left: 10px; | |
156 | font-weight: bold; | |
157 | color: #9a9a9b; | |
158 | background: url(../../images/theme/bracket.gif) no-repeat; | |
159 | } | |
160 | ||
161 | h4.blueblk { | |
162 | background: #8ab3d1; | |
163 | padding: 5px; | |
164 | margin: 10px 0; | |
165 | border: 1px solid #1b619b; | |
166 | } | |
167 | ||
168 | /*+-------------------------------------------+ | |
169 | | COMMENTS | | |
170 | +-------------------------------------------+*/ | |
171 | .comment-list li, #preview { | |
172 | background: #d3e0ea; | |
173 | padding: 5px; | |
174 | margin-bottom: 8px; | |
175 | color: #555; | |
176 | clear: right; | |
177 | min-height: 60px; | |
178 | } | |
179 | ||
180 | .gravatar { | |
181 | float: right; | |
182 | padding: 0 5px; | |
183 | } | |
184 | /*+-------------------------------------------+ | |
185 | | SIDEBAR | | |
186 | +-------------------------------------------+*/ | |
187 | ||
188 | #sidebar h3 { | |
189 | font: 110%/1.5em Arial, Verdana, Helvetica, sans-serif; | |
190 | color: #d75a20; | |
191 | margin-top: 10px; | |
192 | } | |
193 | ||
194 | ||
195 | #sidebar h3 a { | |
196 | color: #d75a20; | |
197 | border-bottom: 1px dotted #d75a20; | |
198 | } | |
199 | ||
200 | #sidebar h3 a:hover { color: #85ab02; border-bottom-color: #85ab02; } | |
201 | ||
202 | #sidebar ul { | |
203 | margin: 0; | |
204 | padding: 0; | |
205 | list-style-type: none; | |
206 | } | |
207 | ||
208 | #sidebar ul li { | |
209 | background: url(../../images/theme/bullet.gif) 0 45% no-repeat; | |
210 | padding-left: 17px; | |
211 | } | |
212 | ||
213 | #flickr div img { | |
214 | border: 4px solid #fff; | |
215 | } | |
216 | ||
217 | #flickr div { | |
218 | width: 108px; | |
219 | border: 2px solid #dbd1c1; | |
220 | margin-bottom: 5px; | |
221 | } | |
222 | ||
223 | #flickr div.flickrsquare { | |
224 | width: 82px; | |
225 | border-right: 3px solid #dbd1c1; | |
226 | float:left; | |
227 | margin-right: 5px; | |
228 | margin-right: 5px; | |
229 | } | |
230 | ||
231 | #flickr div a { border: none; } | |
232 | ||
233 | #magnolia-gallery { | |
234 | text-align: center; | |
235 | } | |
236 | #magnolia-gallery .magnolia-pic { | |
237 | border: 1px solid #dbd1c1; | |
238 | background: #ffffff; | |
239 | margin-left: auto; | |
240 | margin-right: auto; | |
241 | margin-bottom: 5px; | |
242 | margin-top: 5px; | |
243 | width: 112px; | |
244 | } | |
245 | ||
246 | #magnolia-gallery .magnolia-pic:hover { | |
247 | background: #000000; | |
248 | } | |
249 | ||
250 | #magnolia-gallery .magnolia-pic img { | |
251 | padding: 6px; | |
252 | } | |
253 | ||
254 | /*+-------------------------------------------+ | |
255 | | FOOTER | | |
256 | +-------------------------------------------+*/ | |
257 | ||
258 | #footer ul { | |
259 | margin: 0; | |
260 | padding: 10px 0 0 0; | |
261 | list-style: none; | |
262 | } | |
263 | ||
264 | #footer ul li { | |
265 | display: inline; | |
266 | margin: 0; | |
267 | padding: 0 5px 0 0; | |
268 | font-size: 75%; | |
269 | } | |
270 | ||
271 | /*+-------------------------------------------+ | |
272 | | FORMS | | |
273 | +-------------------------------------------+*/ | |
274 | ||
275 | input, textarea, select { | |
276 | border: 1px solid #8ab3d1; | |
277 | background: #f9f9f9; | |
278 | } | |
279 | ||
280 | .frm-tbl td { vertical-align: top; padding: 5px; } | |
281 | td#frm-btns { text-align: right; } | |
282 | ||
283 | #comment_body { height: 220px; } | |
284 | #form-submit-button { background: #d3e0ea; } | |
285 | ||
286 | /*+-------------------------------------------+ | |
287 | | MISC | | |
288 | +-------------------------------------------+*/ | |
289 | ||
290 | .powered { border: none; } | |
291 | .powered img { margin-top: 20px; } | |
292 | .pullquote { | |
293 | width: 30%; | |
294 | float:right; | |
295 | font: 150%/1.5em Times, Helvetica, "Times New Roman", serif; | |
296 | color: #666; | |
297 | margin:10px; | |
298 | background: url(../../images/theme/q-close.gif) no-repeat 70% 100% !important; | |
299 | background /**/:url(); /* removing quote graphic in IE5+ */ | |
300 | padding: 0 25px 5px 0; | |
301 | } | |
302 | .pullquote:first-letter { | |
303 | background: url(../../images/theme/q-open.gif) no-repeat left top !important; | |
304 | padding:5px 2px 10px 35px!important; | |
305 | padding /**/:0px; /* resetting padding in IE5+ */ | |
306 | background /**/: url(); /* removing quote graphic in IE5+ */ | |
307 | } | |
308 | ||
309 | .light-bg { background: #f7f7f7; padding: 2px; } | |
310 | .clearfix:after { | |
311 | content: "."; | |
312 | display: block; | |
313 | height: 0; | |
314 | clear: both; | |
315 | visibility: hidden; | |
316 | } | |
317 | ||
318 | #errors { | |
319 | color: red; | |
320 | } | |
321 | ||
322 | .admintools { | |
323 | float: right; | |
324 | background-color: #fff; | |
325 | font-size: smaller; | |
326 | padding: 0 2px; | |
327 | margin: 0 1px; | |
328 | color: #ccc; | |
329 | border: 1px solid #ccc; | |
330 | } | |
331 | ||
332 | .admintools:hover { | |
333 | color: #c00; | |
334 | border: 1px solid #c00; | |
335 | } | |
336 | ||
337 | a[name] { border: none; } | |
338 | ||
339 | /* Hides from IE-mac \*/ | |
340 | * html .clearfix {height: 1%;} | |
341 | /* End hide from IE-mac */ | |
342 | ||
343 | #categories li em, #archives li em | |
344 | { | |
345 | color: #98B4D1; | |
346 | font-size: smaller; | |
347 | } | |
348 | ||
349 | /* Syntax highlighting */ | |
350 | .typocode_ruby .normal {} | |
351 | .typocode_ruby .comment { color: #005; font-style: italic; } | |
352 | .typocode_ruby .keyword { color: #A00; font-weight: bold; } | |
353 | .typocode_ruby .method { color: #077; } | |
354 | .typocode_ruby .class { color: #074; } | |
355 | .typocode_ruby .module { color: #050; } | |
356 | .typocode_ruby .punct { color: #447; font-weight: bold; } | |
357 | .typocode_ruby .symbol { color: #099; } | |
358 | .typocode_ruby .string { color: #944; background: #FFE; } | |
359 | .typocode_ruby .char { color: #F07; } | |
360 | .typocode_ruby .ident { color: #004; } | |
361 | .typocode_ruby .constant { color: #07F; } | |
362 | .typocode_ruby .regex { color: #B66; background: #FEF; } | |
363 | .typocode_ruby .number { color: #F99; } | |
364 | .typocode_ruby .attribute { color: #7BB; } | |
365 | .typocode_ruby .global { color: #7FB; } | |
366 | .typocode_ruby .expr { color: #227; } | |
367 | .typocode_ruby .escape { color: #277; } | |
368 | .typocode_xml .normal {} | |
369 | .typocode_xml .namespace { color: #B66; font-weight: bold; } | |
370 | .typocode_xml .tag { color: #F88; } | |
371 | .typocode_xml .comment { color: #005; font-style: italic; } | |
372 | .typocode_xml .punct { color: #447; font-weight: bold; } | |
373 | .typocode_xml .string { color: #944; } | |
374 | .typocode_xml .number { color: #F99; } | |
375 | .typocode_xml .attribute { color: #BB7; } | |
376 | .typocode_yaml .normal {} | |
377 | .typocode_yaml .document { font-weight: bold; color: #07F; } | |
378 | .typocode_yaml .type { font-weight: bold; color: #05C; } | |
379 | .typocode_yaml .key { color: #F88; } | |
380 | .typocode_yaml .comment { color: #005; font-style: italic; } | |
381 | .typocode_yaml .punct { color: #447; font-weight: bold; } | |
382 | .typocode_yaml .string { color: #944; } | |
383 | .typocode_yaml .number { color: #F99; } | |
384 | .typocode_yaml .time { color: #F99; } | |
385 | .typocode_yaml .date { color: #F99; } | |
386 | .typocode_yaml .ref { color: #944; } | |
387 | .typocode_yaml .anchor { color: #944; } | |
388 | ||
389 | .typocode { | |
390 | background-color:#eee; | |
391 | padding:2px; | |
392 | margin:5px; | |
393 | margin-left:1em; | |
394 | margin-bottom:1em; | |
395 | } | |
396 | ||
397 | .typocode pre { | |
398 | padding: 0px; | |
399 | margin: 0px; | |
400 | background: transparent; | |
401 | font-family: monospace; | |
402 | overflow:auto; | |
403 | } | |
404 | ||
405 | ||
406 | .typocode .lineno { | |
407 | text-align: right; | |
408 | /* color: #B00;*/ | |
409 | font-family: monospace; | |
410 | padding-right: 1em; | |
411 | } | |
412 | ||
413 | code { | |
414 | font-size:120%; | |
415 | } | |
416 | ||
417 | /*+-------------------------------------------+ | |
418 | | TAGLIST | | |
419 | +-------------------------------------------+*/ | |
420 | ||
421 | ul#taglist li { | |
422 | display: inline; | |
423 | line-height: 2em; | |
424 | } | |
425 | ||
426 | .tags .tags0 { font-size: 1.0em; } | |
427 | .tags .tags1 { font-size: 1.2em; } | |
428 | .tags .tags2 { font-size: 1.4em; } | |
429 | .tags .tags3 { font-size: 1.6em; } | |
430 | .tags .tags4 { font-size: 1.8em; } | |
431 | .tags .tags5 { font-size: 2.0em; } | |
432 | .tags .tags6 { font-size: 2.2em; } | |
433 | .tags .tags7 { font-size: 2.4em; } | |
434 | .tags .tags8 { font-size: 2.6em; } | |
435 | .tags .tags9 { font-size: 2.8em; } | |
436 | .tags .tags10 { font-size: 3.0em; } |
rool/rails/typo/trunk/vendor/rails/actionmailer/CHANGELOG:
prev. | current | |
1 | *1.2.1* (April 6th, 2005) | |
2 | ||
3 | * Be part of Rails 1.1.1 | |
4 | ||
5 | ||
6 | *1.2.0* (March 27th, 2005) | |
7 | ||
8 | * Nil charset caused subject line to be improperly quoted in implicitly multipart messages #2662 [ehalvorsen+rails@runbox.com] | |
9 | ||
10 | * Parse content-type apart before using it so that sub-parts of the header can be set correctly #2918 [Jamis Buck] | |
11 | ||
12 | * Make custom headers work in subparts #4034 [elan@bluemandrill.com] | |
13 | ||
14 | * Template paths with dot chars in them no longer mess up implicit template selection for multipart messages #3332 [Chad Fowler] | |
15 | ||
16 | * Make sure anything with content-disposition of "attachment" is passed to the attachment presenter when parsing an email body [Jamis Buck] | |
17 | ||
18 | * Make sure TMail#attachments includes anything with content-disposition of "attachment", regardless of content-type [Jamis Buck] | |
19 | ||
20 | ||
*1.1.5* (December 13th, 2005) | ||
* Become part of Rails 1.0 | ||
... | ... | |
* Rename Version constant to VERSION. #2802 [Marcel Molina Jr.] | ||
30 | * Stricter matching for implicitly multipart filenames excludes files ending in unsupported extensions (such as foo.rhtml.bak) and without a two-part content type (such as foo.text.rhtml or foo.text.really.plain.rhtml). #2398 [Dave Burt <dave@burt.id.au>, Jeremy Kemper] | |
32 | ||
*1.1.3* (November 7th, 2005) | ||
* Allow Mailers to have custom initialize methods that set default instance variables for all mail actions #2563 [mrj@bigpond.net.au] |
rool/rails/typo/trunk/vendor/rails/actionmailer/Rakefile:
prev. | current | |
t.libs << "test" | ||
t.pattern = 'test/*_test.rb' | ||
t.verbose = true | ||
28 | t.warning = false | |
} | ||
... | ... | |
Rake::RDocTask.new { |rdoc| | ||
rdoc.rdoc_dir = 'doc' | ||
rdoc.title = "Action Mailer -- Easy email delivery and testing" | ||
35 | | |
36 | rdoc.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object' | |
rdoc.template = "#{ENV['template']}.rb" if ENV['template'] | ||
rdoc.rdoc_files.include('README', 'CHANGELOG') | ||
rdoc.rdoc_files.include('lib/action_mailer.rb') | ||
... | ... | |
s.rubyforge_project = "actionmailer" | ||
s.homepage = "http://www.rubyonrails.org" | ||
56 | | |
57 | s.add_dependency('actionpack', '= 1.12.1' + PKG_BUILD) | |
s.has_rdoc = true | ||
s.requirements << 'none' | ||
s.require_path = 'lib' | ||
s.autorequire = 'action_mailer' | ||
63 | | |
64 | s.files = [ "Rakefile", "install.rb", "README", "CHANGELOG", "MIT-LICENSE" ] | |
s.files = s.files + Dir.glob( "lib/**/*" ).delete_if { |item| item.include?( "\.svn" ) } | ||
s.files = s.files + Dir.glob( "test/**/*" ).delete_if { |item| item.include?( "\.svn" ) } | ||
end | ||
... | ... | |
end | ||
desc "Publish the release files to RubyForge." | ||
86 | ||
87 | | |
87 | task :release => [ :package ] do | |
88 | `rubyforge login` | |
89 | | |
90 | | |
91 | | |
92 | ||
93 | | |
94 | | |
95 | | |
96 | | |
97 | ||
98 | | |
99 | | |
100 | | |
101 | | |
102 | | |
103 | | |
104 | | |
105 | ||
106 | | |
107 | | |
108 | | |
109 | | |
110 | | |
111 | | |
112 | | |
113 | | |
114 | ||
115 | | |
116 | | |
117 | | |
118 | ||
119 | | |
120 | | |
121 | | |
122 | | |
123 | ||
124 | | |
125 | | |
126 | ||
127 | | |
128 | | |
129 | | |
130 | | |
131 | ||
132 | | |
133 | ||
134 | | |
135 | | |
136 | | |
137 | | |
138 | | |
139 | | |
140 | | |
141 | | |
142 | | |
143 | | |
144 | ||
145 | | |
146 | | |
147 | | |
148 | | |
149 | | |
150 | | |
151 | | |
152 | | |
153 | | |
154 | | |
155 | | |
156 | | |
157 | | |
158 | | |
159 | | |
160 | | |
161 | | |
162 | | |
163 | | |
164 | | |
165 | | |
166 | | |
167 | | |
168 | | |
169 | ||
170 | | |
171 | | |
172 | | |
173 | ||
174 | | |
175 | | |
176 | | |
177 | | |
178 | | |
179 | | |
180 | | |
181 | ||
182 | | |
183 | | |
184 | | |
185 | ||
186 | | |
187 | | |
188 | | |
189 | ||
190 | | |
191 | | |
192 | | |
193 | | |
194 | ||
195 | | |
196 | | |
90 | for ext in %w( gem tgz zip ) | |
91 | release_command = "rubyforge add_release #{PKG_NAME} #{PKG_NAME} 'REL #{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" | |
92 | puts release_command | |
93 | system(release_command) | |
end | ||
198 | ||
95 | end | |
rool/rails/typo/trunk/vendor/rails/actionmailer/lib/action_mailer/adv_attr_accessor.rb:
prev. | current | |
module ClassMethods #:nodoc: | ||
def adv_attr_accessor(*names) | ||
names.each do |name| | ||
11 | ivar = "@#{name}" | |
12 | ||
define_method("#{name}=") do |value| | ||
12 | | |
14 | instance_variable_set(ivar, value) | |
end | ||
define_method(name) do |*parameters| | ||
raise ArgumentError, "expected 0 or 1 parameters" unless parameters.length <= 1 | ||
if parameters.empty? | ||
18 | | |
20 | if instance_variables.include?(ivar) | |
21 | instance_variable_get(ivar) | |
22 | end | |
else | ||
20 | | |
24 | instance_variable_set(ivar, parameters.first) | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionmailer/lib/action_mailer/base.rb:
prev. | current | |
require 'action_mailer/utils' | ||
require 'tmail/net' | ||
7 | ||
7 | module ActionMailer #:nodoc: | |
# Usage: | ||
# | ||
# class ApplicationMailer < ActionMailer::Base | ||
... | ... | |
class Base | ||
include AdvAttrAccessor, PartContainer | ||
124 | # Action Mailer subclasses should be reloaded by the dispatcher in Rails | |
125 | # when Dependencies.mechanism = :load. | |
126 | include Reloadable::Subclasses | |
127 | ||
private_class_method :new #:nodoc: | ||
cattr_accessor :template_root | ||
... | ... | |
if @parts.empty? | ||
templates = Dir.glob("#{template_path}/#{@template}.*") | ||
templates.each do |path| | ||
281 | | |
282 | | |
283 | | |
285 | # TODO: don't hardcode rhtml|rxml | |
286 | basename = File.basename(path) | |
287 | next unless md = /^([^\.]+)\.([^\.]+\.[^\+]+)\.(rhtml|rxml)$/.match(basename) | |
288 | template_name = basename | |
289 | content_type = md.captures[1].gsub('.', '/') | |
290 | @parts << Part.new(:content_type => content_type, | |
:disposition => "inline", :charset => charset, | ||
285 | | |
292 | :body => render_message(template_name, @body)) | |
end | ||
unless @parts.empty? | ||
@content_type = "multipart/alternative" | ||
289 | | |
@parts = sort_parts(@parts, @implicit_parts_order) | ||
end | ||
end | ||
... | ... | |
# normal template exists (or if there were no implicit parts) we render | ||
# it. | ||
template_exists = @parts.empty? | ||
299 | | |
305 | template_exists ||= Dir.glob("#{template_path}/#{@template}.*").any? { |i| File.basename(i).split(".").length == 2 } | |
@body = render_message(@template, @body) if template_exists | ||
# Finally, if there are other message parts and a textual body exists, | ||
... | ... | |
m.date = sent_on.to_time rescue sent_on if sent_on | ||
headers.each { |k, v| m[k] = v } | ||
415 | real_content_type, ctype_attrs = parse_content_type | |
416 | ||
if @parts.empty? | ||
410 | | |
418 | m.set_content_type(real_content_type, nil, ctype_attrs) | |
m.body = Utils.normalize_new_lines(body) | ||
else | ||
if String === body | ||
part = TMail::Mail.new | ||
part.body = Utils.normalize_new_lines(body) | ||
416 | | |
424 | part.set_content_type(real_content_type, nil, ctype_attrs) | |
part.set_content_disposition "inline" | ||
m.parts << part | ||
end | ||
... | ... | |
m.parts << part | ||
end | ||
426 | | |
434 | if real_content_type =~ /multipart/ | |
435 | ctype_attrs.delete "charset" | |
436 | m.set_content_type(real_content_type, nil, ctype_attrs) | |
437 | end | |
end | ||
@mail = m |
rool/rails/typo/trunk/vendor/rails/actionmailer/lib/action_mailer/part.rb:
prev. | current | |
def to_mail(defaults) | ||
part = TMail::Mail.new | ||
59 | real_content_type, ctype_attrs = parse_content_type(defaults) | |
60 | ||
if @parts.empty? | ||
part.content_transfer_encoding = transfer_encoding || "quoted-printable" | ||
case (transfer_encoding || "").downcase | ||
... | ... | |
# Also don't set filename and name when there is none (like in | ||
# non-attachment parts) | ||
if content_disposition == "attachment" | ||
74 | | |
75 | | |
76 | ctype_attrs.delete "charset" | |
77 | part.set_content_type(real_content_type, nil, | |
78 | squish("name" => filename).merge(ctype_attrs)) | |
part.set_content_disposition(content_disposition, | ||
77 | | |
80 | squish("filename" => filename).merge(ctype_attrs)) | |
else | ||
79 | | |
80 | | |
82 | part.set_content_type(real_content_type, nil, ctype_attrs) | |
part.set_content_disposition(content_disposition) | ||
end | ||
else | ||
if String === body | ||
part = TMail::Mail.new | ||
part.body = body | ||
87 | | |
89 | part.set_content_type(real_content_type, nil, ctype_attrs) | |
part.set_content_disposition "inline" | ||
m.parts << part | ||
end | ||
... | ... | |
part.parts << prt | ||
end | ||
97 | | |
99 | part.set_content_type(real_content_type, nil, ctype_attrs) if real_content_type =~ /multipart/ | |
end | ||
99 | | |
101 | ||
102 | headers.each { |k,v| part[k] = v } | |
103 | ||
part | ||
end | ||
private | ||
108 | ||
def squish(values={}) | ||
values.delete_if { |k,v| v.nil? } | ||
end |
rool/rails/typo/trunk/vendor/rails/actionmailer/lib/action_mailer/part_container.rb:
prev. | current | |
part(params, &block) | ||
end | ||
41 | private | |
42 | ||
43 | def parse_content_type(defaults=nil) | |
44 | return [defaults && defaults.content_type, {}] if content_type.blank? | |
45 | ctype, *attrs = content_type.split(/;\s*/) | |
46 | attrs = attrs.inject({}) { |h,s| k,v = s.split(/=/, 2); h[k] = v; h } | |
47 | [ctype, {"charset" => charset || defaults && defaults.charset}.merge(attrs)] | |
48 | end | |
49 | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/attachments.rb:
prev. | current | |
class Mail | ||
def has_attachments? | ||
10 | | |
10 | multipart? && parts.any? { |part| attachment?(part) } | |
end | ||
13 | def attachment?(part) | |
14 | (part['content-disposition'] && part['content-disposition'].disposition == "attachment") || | |
15 | part.header['content-type'].main_type != "text" | |
16 | end | |
17 | ||
def attachments | ||
if multipart? | ||
parts.collect { |part| | ||
16 | | |
21 | if attachment?(part) | |
content = part.body # unquoted automatically by TMail#body | ||
file_name = (part['content-location'] && | ||
part['content-location'].body) || |
rool/rails/typo/trunk/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail/quoting.rb:
prev. | current | |
part.body(to_charset, &attachment_presenter) | ||
elsif header.nil? | ||
"" | ||
36 | | |
36 | elsif !attachment?(part) | |
part.unquoted_body(to_charset) | ||
else | ||
attachment_presenter.call(header["name"] || "(unnamed)") |
rool/rails/typo/trunk/vendor/rails/actionmailer/lib/action_mailer/version.rb:
prev. | current | |
module ActionMailer | ||
module VERSION #:nodoc: | ||
MAJOR = 1 | ||
4 | | |
5 | | |
4 | MINOR = 2 | |
5 | TINY = 1 | |
STRING = [MAJOR, MINOR, TINY].join('.') | ||
end |
rool/rails/typo/trunk/vendor/rails/actionmailer/test/fixtures/raw_email7:
prev. | current | |
This is the first part. | ||
--Apple-Mail-12-196940926 | ||
25 | Content-Transfer-Encoding: 7bit | |
26 | Content-Type: text/x-ruby-script; | |
27 | x-unix-mode=0666; | |
28 | name="test.rb" | |
29 | Content-Disposition: attachment; | |
30 | filename=test.rb | |
31 | ||
32 | puts "testing, testing" | |
33 | ||
34 | --Apple-Mail-12-196940926 | |
Content-Transfer-Encoding: base64 | ||
Content-Type: application/pdf; | ||
x-unix-mode=0666; |
rool/rails/typo/trunk/vendor/rails/actionmailer/test/mail_service_test.rb:
prev. | current | |
end | ||
end | ||
26 | class FunkyPathMailer < ActionMailer::Base | |
27 | def multipart_with_template_path_with_dots(recipient) | |
28 | recipients recipient | |
29 | subject "Have a lovely picture" | |
30 | from "Chad Fowler <chad@chadfowler.com>" | |
31 | attachment :content_type => "image/jpeg", | |
32 | :body => "not really a jpeg, we're only testing, after all" | |
33 | end | |
34 | ||
35 | def template_path | |
36 | "#{File.dirname(__FILE__)}/fixtures/path.with.dots" | |
37 | end | |
38 | end | |
39 | ||
class TestMailer < ActionMailer::Base | ||
def signed_up(recipient) | ||
... | ... | |
@implicit_parts_order = order if order | ||
end | ||
170 | def implicitly_multipart_with_utf8 | |
171 | recipients "no.one@nowhere.test" | |
172 | subject "Foo áëô îü" | |
173 | from "some.one@somewhere.test" | |
174 | template "implicitly_multipart_example" | |
175 | body ({ "recipient" => "no.one@nowhere.test" }) | |
176 | end | |
177 | ||
def html_mail(recipient) | ||
recipients recipient | ||
subject "html mail" | ||
... | ... | |
end | ||
attachment :content_type => "application/octet-stream",:filename => "test.txt", :body => "test abcdefghijklmnopqstuvwxyz" | ||
end | ||
229 | ||
230 | def attachment_with_custom_header(recipient) | |
231 | recipients recipient | |
232 | subject "custom header in attachment" | |
233 | from "test@example.com" | |
234 | content_type "multipart/related" | |
235 | part :content_type => "text/html", :body => 'yo' | |
236 | attachment :content_type => "image/jpeg",:filename => "test.jpeg", :body => "i am not a real picture", :headers => { 'Content-ID' => '<test@test.com>' } | |
237 | end | |
def unnamed_attachment(recipient) | ||
recipients recipient | ||
... | ... | |
body "testing" | ||
end | ||
257 | def custom_content_type_attributes | |
258 | recipients "no.one@nowhere.test" | |
259 | subject "custom content types" | |
260 | from "some.one@somewhere.test" | |
261 | content_type "text/plain; format=flowed" | |
262 | body "testing" | |
263 | end | |
264 | ||
class <<self | ||
attr_accessor :received_body | ||
end | ||
... | ... | |
assert_equal "application/octet-stream", created.parts[1].content_type | ||
end | ||
312 | def test_attachment_with_custom_header | |
313 | created = nil | |
314 | assert_nothing_raised { created = TestMailer.create_attachment_with_custom_header(@recipient)} | |
315 | assert_equal "<test@test.com>", created.parts[1].header['content-id'].to_s | |
316 | end | |
317 | ||
def test_signed_up | ||
expected = new_mail | ||
expected.to = @recipient | ||
... | ... | |
assert_equal "Photo25.jpg", mail.attachments.first.original_filename | ||
end | ||
621 | def test_attachment_with_text_type | |
622 | fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email13") | |
623 | mail = TMail::Mail.parse(fixture) | |
624 | assert mail.has_attachments? | |
625 | assert_equal 1, mail.attachments.length | |
626 | assert_equal "hello.rb", mail.attachments.first.original_filename | |
627 | end | |
628 | ||
def test_decode_part_without_content_type | ||
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email4") | ||
mail = TMail::Mail.parse(fixture) | ||
... | ... | |
assert_match(/\nSubject: =\?utf-8\?Q\?Foo_.*?\?=/, mail.encoded) | ||
end | ||
657 | def test_implicitly_multipart_with_utf8 | |
658 | mail = TestMailer.create_implicitly_multipart_with_utf8 | |
659 | assert_match(/\nSubject: =\?utf-8\?Q\?Foo_.*?\?=/, mail.encoded) | |
660 | end | |
661 | ||
def test_explicitly_multipart_messages | ||
mail = TestMailer.create_explicitly_multipart_example(@recipient) | ||
assert_equal 3, mail.parts.length | ||
... | ... | |
def test_recursive_multipart_processing | ||
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email7") | ||
mail = TMail::Mail.parse(fixture) | ||
700 | | |
758 | assert_equal "This is the first part.\n\nAttachment: test.rb\nAttachment: test.pdf\n\n\nAttachment: smime.p7s\n", mail.body | |
end | ||
def test_decode_encoded_attachment_filename | ||
... | ... | |
end | ||
def test_deliver_with_mail_object | ||
744 | | |
802 | mail = TestMailer.create_headers_with_nonalpha_chars(@recipient) | |
assert_nothing_raised { TestMailer.deliver(mail) } | ||
assert_equal 1, TestMailer.deliveries.length | ||
end | ||
806 | ||
807 | def test_multipart_with_template_path_with_dots | |
808 | mail = FunkyPathMailer.create_multipart_with_template_path_with_dots(@recipient) | |
809 | assert_equal 2, mail.parts.length | |
810 | end | |
811 | ||
812 | def test_custom_content_type_attributes | |
813 | mail = TestMailer.create_custom_content_type_attributes | |
814 | assert_match %r{format=flowed}, mail['content-type'].to_s | |
815 | assert_match %r{charset=utf-8}, mail['content-type'].to_s | |
816 | end | |
end | ||
rool/rails/typo/trunk/vendor/rails/actionpack/CHANGELOG:
prev. | current | |
1 | *1.12.1* (April 6th, 2005) | |
2 | ||
3 | * Fixed that template extensions would be cached development mode #4624 [Stefan Kaes] | |
4 | ||
5 | * Update to Prototype 1.5.0_rc0 [Sam Stephenson] | |
6 | ||
7 | * Honor skipping filters conditionally for only certain actions even when the parent class sets that filter to conditionally be executed only for the same actions. #4522 [Marcel Molina Jr.] | |
8 | ||
9 | * Delegate xml_http_request in integration tests to the session instance. [Jamis Buck] | |
10 | ||
11 | * Update the diagnostics template skip the useless '<controller not set>' text. [Nicholas Seckar] | |
12 | ||
13 | * CHANGED DEFAULT: Don't parse YAML input by default, but keep it available as an easy option [DHH] | |
14 | ||
15 | * Add additional autocompleter options [aballai, Thomas Fuchs] | |
16 | ||
17 | * Fixed fragment caching of binary data on Windows #4493 [bellis@deepthought.org] | |
18 | ||
19 | * Applied Prototype $() performance patches (#4465, #4477) and updated script.aculo.us [Sam Stephenson, Thomas Fuchs] | |
20 | ||
21 | * Added automated timestamping to AssetTagHelper methods for stylesheets, javascripts, and images when Action Controller is run under Rails [DHH]. Example: | |
22 | ||
23 | image_tag("rails.png") # => '<img alt="Rails" src="/images/rails.png?1143664135" />' | |
24 | ||
25 | ...to avoid frequent stats (not a problem for most people), you can set RAILS_ASSET_ID in the ENV to avoid stats: | |
26 | ||
27 | ENV["RAILS_ASSET_ID"] = "2345" | |
28 | image_tag("rails.png") # => '<img alt="Rails" src="/images/rails.png?2345" />' | |
29 | ||
30 | This can be used by deployment managers to set the asset id by application revision | |
31 | ||
32 | ||
33 | *1.12.0* (March 27th, 2005) | |
34 | ||
35 | * Add documentation for respond_to. [Jamis Buck] | |
36 | ||
37 | * Fixed require of bluecloth and redcloth when gems haven't been loaded #4446 [murphy@cYcnus.de] | |
38 | ||
39 | * Update to Prototype 1.5.0_pre1 [Sam Stephenson] | |
40 | ||
41 | * Change #form_for and #fields_for so that the second argument is not required [Dave Thomas] | |
42 | ||
43 | <% form_for :post, @post, :url => { :action => 'create' } do |f| -%> | |
44 | ||
45 | becomes... | |
46 | ||
47 | <% form_for :post, :url => { :action => 'create' } do |f| -%> | |
48 | ||
49 | * Update to script.aculo.us 1.6 [Thomas Fuchs] | |
50 | ||
51 | * Enable application/x-yaml processing by default [Jamis Buck] | |
52 | ||
53 | * Fix double url escaping of remote_function. Add :escape => false option to ActionView's url_for. [Nicholas Seckar] | |
54 | ||
55 | * Add :script option to in_place_editor to support evalScripts (closes #4194) [codyfauser@gmail.com] | |
56 | ||
57 | * Fix mixed case enumerable methods in the JavaScript Collection Proxy (closes #4314) [codyfauser@gmail.com] | |
58 | ||
59 | * Undo accidental escaping for mail_to; add regression test. [Nicholas Seckar] | |
60 | ||
61 | * Added nicer message for assert_redirected_to (closes #4294) [court3nay] | |
62 | ||
63 | assert_redirected_to :action => 'other_host', :only_path => false | |
64 | ||
65 | when it was expecting... | |
66 | ||
67 | redirected_to :action => 'other_host', :only_path => true, :host => 'other.test.host' | |
68 | ||
69 | gives the error message... | |
70 | ||
71 | response is not a redirection to all of the options supplied (redirection is <{:only_path=>false, :host=>"other.test.host", :action=>"other_host"}>), difference: <{:only_path=>"true", :host=>"other.test.host"}> | |
72 | ||
73 | * Change url_for to escape the resulting URLs when called from a view. [Nicholas Seckar, coffee2code] | |
74 | ||
75 | * Added easy support for testing file uploads with fixture_file_upload #4105 [turnip@turnipspatch.com]. Example: | |
76 | ||
77 | # Looks in Test::Unit::TestCase.fixture_path + '/files/spongebob.png' | |
78 | post :change_avatar, :avatar => fixture_file_upload('/files/spongebob.png', 'image/png') | |
79 | ||
80 | * Fixed UrlHelper#current_page? to behave even when url-escaped entities are present #3929 [jeremy@planetargon.com] | |
81 | ||
82 | * Add ability for relative_url_root to be specified via an environment variable RAILS_RELATIVE_URL_ROOT. [isaac@reuben.com, Nicholas Seckar] | |
83 | ||
84 | * Fixed link_to "somewhere", :post => true to produce valid XHTML by using the parentnode instead of document.body for the instant form #3007 [Bob Silva] | |
85 | ||
86 | * Added :function option to PrototypeHelper#observe_field/observe_form that allows you to call a function instead of submitting an ajax call as the trigger #4268 [jonathan@daikini.com] | |
87 | ||
88 | * Make Mime::Type.parse consider q values (if any) [Jamis Buck] | |
89 | ||
90 | * XML-formatted requests are typecast according to "type" attributes for :xml_simple [Jamis Buck] | |
91 | ||
92 | * Added protection against proxy setups treating requests as local even when they're not #3898 [stephen_purcell@yahoo.com] | |
93 | ||
94 | * Added TestRequest#raw_post that simulate raw_post from CgiRequest #3042 [francois.beausoleil@gmail.com] | |
95 | ||
96 | * Underscore dasherized keys in formatted requests [Jamis Buck] | |
97 | ||
98 | * Add MimeResponds::Responder#any for managing multiple types with identical responses [Jamis Buck] | |
99 | ||
100 | * Make the xml_http_request testing method set the HTTP_ACCEPT header [Jamis Buck] | |
101 | ||
102 | * Add Verification to scaffolds. Prevent destructive actions using GET [Michael Koziarski] | |
103 | ||
104 | * Avoid hitting the filesystem when using layouts by using a File.directory? cache. [Stefan Kaes, Nicholas Seckar] | |
105 | ||
106 | * Simplify ActionController::Base#controller_path [Nicholas Seckar] | |
107 | ||
108 | * Added simple alert() notifications for RJS exceptions when config.action_view.debug_rjs = true. [Sam Stephenson] | |
109 | ||
110 | * Added :content_type option to render, so you can change the content type on the fly [DHH]. Example: render :action => "atom.rxml", :content_type => "application/atom+xml" | |
111 | ||
112 | * CHANGED DEFAULT: The default content type for .rxml is now application/xml instead of type/xml, see http://www.xml.com/pub/a/2004/07/21/dive.html for reason [DHH] | |
113 | ||
114 | * Added option to render action/template/file of a specific extension (and here by template type). This means you can have multiple templates with the same name but a different extension [DHH]. Example: | |
115 | ||
116 | class WeblogController < ActionController::Base | |
117 | def index | |
118 | @posts = Post.find :all | |
119 | ||
120 | respond_to do |type| | |
121 | type.html # using defaults, which will render weblog/index.rhtml | |
122 | type.xml { render :action => "index.rxml" } | |
123 | type.js { render :action => "index.rjs" } | |
124 | end | |
125 | end | |
126 | end | |
127 | ||
128 | * Added better support for using the same actions to output for different sources depending on the Accept header [DHH]. Example: | |
129 | ||
130 | class WeblogController < ActionController::Base | |
131 | def create | |
132 | @post = Post.create(params[:post]) | |
133 | ||
134 | respond_to do |type| | |
135 | type.js { render } # renders create.rjs | |
136 | type.html { redirect_to :action => "index" } | |
137 | type.xml do | |
138 | headers["Location"] = url_for(:action => "show", :id => @post) | |
139 | render(:nothing, :status => "201 Created") | |
140 | end | |
141 | end | |
142 | end | |
143 | end | |
144 | ||
145 | * Added Base#render(:xml => xml) that works just like Base#render(:text => text), but sets the content-type to text/xml and the charset to UTF-8 [DHH] | |
146 | ||
147 | * Integration test's url_for now runs in the context of the last request (if any) so after post /products/show/1 url_for :action => 'new' will yield /product/new [Tobias Luetke] | |
148 | ||
149 | * Re-added mixed-in helper methods for the JavascriptGenerator. Moved JavascriptGenerators methods to a module that is mixed in after the helpers are added. Also fixed that variables set in the enumeration methods like #collect are set correctly. Documentation added for the enumeration methods [Rick Olson]. Examples: | |
150 | ||
151 | page.select('#items li').collect('items') do |element| | |
152 | element.hide | |
153 | end | |
154 | # => var items = $$('#items li').collect(function(value, index) { return value.hide(); }); | |
155 | ||
156 | * Added plugin support for parameter parsers, which allows for better support for REST web services. By default, posts submitted with the application/xml content type is handled by creating a XmlSimple hash with the same name as the root element of the submitted xml. More handlers can easily be registered like this: | |
157 | ||
158 | # Assign a new param parser to a new content type | |
159 | ActionController::Base.param_parsers['application/atom+xml'] = Proc.new do |data| | |
160 | node = REXML::Document.new(post) | |
161 | { node.root.name => node.root } | |
162 | end | |
163 | ||
164 | # Assign the default XmlSimple to a new content type | |
165 | ActionController::Base.param_parsers['application/backpack+xml'] = :xml_simple | |
166 | ||
167 | Default YAML web services were retired, ActionController::Base.param_parsers carries an example which shows how to get this functionality back. As part of this new plugin support, request.[formatted_post?, xml_post?, yaml_post? and post_format] were all deprecated in favor of request.content_type [Tobias Luetke] | |
168 | ||
169 | * Fixed Effect.Appear in effects.js to work with floats in Safari #3524, #3813, #3044 [Thomas Fuchs] | |
170 | ||
171 | * Fixed that default image extension was not appended when using a full URL with AssetTagHelper#image_tag #4032, #3728 [rubyonrails@beautifulpixel.com] | |
172 | ||
173 | * Added that page caching will only happen if the response code is less than 400 #4033 [g.bucher@teti.ch] | |
174 | ||
175 | * Add ActionController::IntegrationTest to allow high-level testing of the way the controllers and routes all work together [Jamis Buck] | |
176 | ||
177 | * Added support to AssetTagHelper#javascript_include_tag for having :defaults appear anywhere in the list, so you can now make one call ala javascript_include_tag(:defaults, "my_scripts") or javascript_include_tag("my_scripts", :defaults) depending on how you want the load order #3506 [Bob Silva] | |
178 | ||
179 | * Added support for visual effects scoped queues to the visual_effect helper #3530 [Abdur-Rahman Advany] | |
180 | ||
181 | * Added .rxml (and any non-rhtml template, really) supportfor CaptureHelper#content_for and CaptureHelper#capture #3287 [Brian Takita] | |
182 | ||
183 | * Added script.aculo.us drag and drop helpers to RJS [Thomas Fuchs]. Examples: | |
184 | ||
185 | page.draggable 'product-1' | |
186 | page.drop_receiving 'wastebasket', :url => { :action => 'delete' } | |
187 | page.sortable 'todolist', :url => { action => 'change_order' } | |
188 | ||
189 | * Fixed that form elements would strip the trailing [] from the first parameter #3545 [ruby@bobsilva.com] | |
190 | ||
191 | * During controller resolution, update the NameError suppression to check for the expected constant. [Nicholas Seckar] | |
192 | ||
193 | * Update script.aculo.us to V1.5.3 [Thomas Fuchs] | |
194 | ||
195 | * Added various InPlaceEditor options, #3746, #3891, #3896, #3906 [Bill Burcham, ruairi, sl33p3r] | |
196 | ||
197 | * Added :count option to pagination that'll make it possible for the ActiveRecord::Base.count call to using something else than * for the count. Especially important for count queries using DISTINCT #3839 [skaes] | |
198 | ||
199 | * Update script.aculo.us to V1.5.2 [Thomas Fuchs] | |
200 | ||
201 | * Added element and collection proxies to RJS [DHH]. Examples: | |
202 | ||
203 | page['blank_slate'] # => $('blank_slate'); | |
204 | page['blank_slate'].show # => $('blank_slate').show(); | |
205 | page['blank_slate'].show('first').up # => $('blank_slate').show('first').up(); | |
206 | ||
207 | page.select('p') # => $$('p'); | |
208 | page.select('p.welcome b').first # => $$('p.welcome b').first(); | |
209 | page.select('p.welcome b').first.hide # => $$('p.welcome b').first().hide(); | |
210 | ||
211 | * Add JavaScriptGenerator#replace for replacing an element's "outer HTML". #3246 [tom@craz8.com, Sam Stephenson] | |
212 | ||
213 | * Remove over-engineered form_for code for a leaner implementation. [Nicholas Seckar] | |
214 | ||
215 | * Document form_for's :html option. [Nicholas Seckar] | |
216 | ||
217 | * Major components cleanup and speedup. #3527 [Stefan Kaes] | |
218 | ||
219 | * Fix problems with pagination and :include. [Kevin Clark] | |
220 | ||
221 | * Add ActiveRecordTestCase for testing AR integration. [Kevin Clark] | |
222 | ||
223 | * Add Unit Tests for pagination [Kevin Clark] | |
224 | ||
225 | * Add :html option for specifying form tag options in form_for. [Sam Stephenson] | |
226 | ||
227 | * Replace dubious controller parent class in filter docs. #3655, #3722 [info@rhalff.com, eigentone@gmail.com] | |
228 | ||
229 | * Don't interpret the :value option on text_area as an html attribute. Set the text_area's value. #3752 [gabriel@gironda.org] | |
230 | ||
231 | * Fix remote_form_for creates a non-ajax form. [Rick Olson] | |
232 | ||
233 | * Don't let arbitrary classes match as controllers -- a potentially dangerous bug. [Nicholas Seckar] | |
234 | ||
235 | * Fix Routing tests. Fix routing where failing to match a controller would prevent the rest of routes from being attempted. [Nicholas Seckar] | |
236 | ||
237 | * Add :builder => option to form_for and friends. [Nicholas Seckar, Rick Olson] | |
238 | ||
239 | * Fix controller resolution to avoid accidentally inheriting a controller from a parent module. [Nicholas Seckar] | |
240 | ||
241 | * Set sweeper's @controller to nil after a request so that the controller may be collected between requests. [Nicholas Seckar] | |
242 | ||
243 | * Subclasses of ActionController::Caching::Sweeper should be Reloadable. [Rick Olson] | |
244 | ||
245 | * Document the :xhr option for verifications. #3666 [leeo] | |
246 | ||
247 | * Added :only and :except controls to skip_before/after_filter just like for when you add filters [DHH] | |
248 | ||
249 | * Ensure that the instance variables are copied to the template when performing render :update. [Nicholas Seckar] | |
250 | ||
251 | * Add the ability to call JavaScriptGenerator methods from helpers called in update blocks. [Sam Stephenson] Example: | |
252 | module ApplicationHelper | |
253 | def update_time | |
254 | page.replace_html 'time', Time.now.to_s(:db) | |
255 | page.visual_effect :highlight, 'time' | |
256 | end | |
257 | end | |
258 | ||
259 | class UserController < ApplicationController | |
260 | def poll | |
261 | render :update { |page| page.update_time } | |
262 | end | |
263 | end | |
264 | ||
265 | * Add render(:update) to ActionView::Base. [Sam Stephenson] | |
266 | ||
267 | * Fix render(:update) to not render layouts. [Sam Stephenson] | |
268 | ||
269 | * Fixed that SSL would not correctly be detected when running lighttpd/fcgi behind lighttpd w/mod_proxy #3548 [stephen_purcell@yahoo.com] | |
270 | ||
271 | * Added the possibility to specify atomatic expiration for the memcachd session container #3571 [Stefan Kaes] | |
272 | ||
273 | * Change layout discovery to take into account the change in semantics with File.join and nil arguments. [Marcel Molina Jr.] | |
274 | ||
275 | * Raise a RedirectBackError if redirect_to :back is called when there's no HTTP_REFERER defined #3049 [kevin.clark@gmail.com] | |
276 | ||
277 | * Treat timestamps like datetimes for scaffolding purposes #3388 [Maik Schmidt] | |
278 | ||
279 | * Fix IE bug with link_to "something", :post => true #3443 [Justin Palmer] | |
280 | ||
281 | * Extract Test::Unit::TestCase test process behavior into an ActionController::TestProcess module. [Sam Stephenson] | |
282 | ||
283 | * Pass along blocks from render_to_string to render. [Sam Stephenson] | |
284 | ||
285 | * Add render :update for inline RJS. [Sam Stephenson] Example: | |
286 | class UserController < ApplicationController | |
287 | def refresh | |
288 | render :update do |page| | |
289 | page.replace_html 'user_list', :partial => 'user', :collection => @users | |
290 | page.visual_effect :highlight, 'user_list' | |
291 | end | |
292 | end | |
293 | end | |
294 | ||
295 | * allow nil objects for error_messages_for [Michael Koziarski] | |
296 | ||
297 | * Refactor human_size to exclude decimal place if it is zero. [Marcel Molina Jr.] | |
298 | ||
299 | * Update to Prototype 1.5.0_pre0 [Sam Stephenson] | |
300 | ||
301 | * Automatically discover layouts when a controller is namespaced. #2199, #3424 [me@jonnii.com rails@jeffcole.net Marcel Molina Jr.] | |
302 | ||
303 | * Add support for multiple proxy servers to CgiRequest#host [gaetanot@comcast.net] | |
304 | ||
305 | * Documentation typo fix. #2367 [Blair Zajac] | |
306 | ||
307 | * Remove Upload Progress. #2871 [Sean Treadway] | |
308 | ||
309 | * Fix typo in function name mapping in auto_complete_field. #2929 #3446 [doppler@gmail.com phil.ross@gmail.com] | |
310 | ||
311 | * Allow auto-discovery of third party template library layouts. [Marcel Molina Jr.] | |
312 | ||
313 | * Have the form builder output radio button, not check box, when calling the radio button helper. #3331 [LouisStAmour@gmail.com] | |
314 | ||
315 | * Added assignment of the Autocompleter object created by JavaScriptMacroHelper#auto_complete_field to a local javascript variables [DHH] | |
316 | ||
317 | * Added :on option for PrototypeHelper#observe_field that allows you to specify a different callback hook to have the observer trigger on [DHH] | |
318 | ||
319 | * Added JavaScriptHelper#button_to_function that works just like JavaScriptHelper#link_to_function but uses a button instead of a href [DHH] | |
320 | ||
321 | * Added that JavaScriptHelper#link_to_function will honor existing :onclick definitions when adding the function call [DHH] | |
322 | ||
323 | * Added :disable_with option to FormTagHelper#submit_tag to allow for easily disabled submit buttons with different text [DHH] | |
324 | ||
325 | * Make auto_link handle nil by returning quickly if blank? [Scott Barron] | |
326 | ||
327 | * Make auto_link match urls with a port number specified. [Marcel Molina Jr.] | |
328 | ||
329 | * Added support for toggling visual effects to ScriptaculousHelper::visual_effect, #3323. [Thomas Fuchs] | |
330 | ||
331 | * Update to script.aculo.us to 1.5.0 rev. 3343 [Thomas Fuchs] | |
332 | ||
333 | * Added :select option for JavaScriptMacroHelper#auto_complete_field that makes it easier to only use part of the auto-complete suggestion as the value for insertion [Thomas Fuchs] | |
334 | ||
335 | * Added delayed execution of Javascript from within RJS #3264 [devslashnull@gmail.com]. Example: | |
336 | ||
337 | page.delay(20) do | |
338 | page.visual_effect :fade, 'notice' | |
339 | end | |
340 | ||
341 | * Add session ID to default logging, but remove the verbose description of every step [DHH] | |
342 | ||
343 | * Add the following RJS methods: [Sam Stephenson] | |
344 | ||
345 | * alert - Displays an alert() dialog | |
346 | * redirect_to - Changes window.location.href to simulate a browser redirect | |
347 | * call - Calls a JavaScript function | |
348 | * assign - Assigns to a JavaScript variable | |
349 | * << - Inserts an arbitrary JavaScript string | |
350 | ||
351 | * Fix incorrect documentation for form_for [Nicholas Seckar] | |
352 | ||
353 | * Don't include a layout when rendering an rjs template using render's :template option. [Marcel Molina Jr.] | |
354 | ||
*1.1.2* (December 13th, 2005) | ||
357 | * Become part of Rails 1.0 | |
358 | ||
* Update to script.aculo.us 1.5.0 final (equals 1.5.0_rc6) [Thomas Fuchs] | ||
* Update to Prototype 1.4.0 final [Sam Stephenson] | ||
7 | ||
363 | * Added form_remote_for (form_for meets form_remote_tag) [DHH] | |
365 | * Update to script.aculo.us 1.5.0_rc6 | |
10 | ||
11 | ||
* More robust relative url root discovery for SCGI compatibility. This solves the 'SCGI routes problem' -- you no longer need to prefix all your routes with the name of the SCGI mountpoint. #3070 [Dave Ringoen] | ||
* Fix docs for text_area_tag. #3083. [Christopher Cotton] | ||
15 | | |
370 | ||
371 | * Change form_for and fields_for method signatures to take object name and object as separate arguments rather than as a Hash. [DHH] | |
372 | ||
373 | * Introduce :selected option to the select helper. Allows you to specify a selection other than the current value of object.method. Specify :selected => nil to leave all options unselected. #2991 [Jonathan Viney <jonathan@bluewire.net.nz>] | |
374 | ||
375 | * Initialize @optional in routing code to avoid warnings about uninitialized access to an instance variable. [Nicholas Seckar] | |
376 | ||
* Make ActionController's render honor the :locals option when rendering a :file. #1665. [Emanuel Borsboom, Marcel Molina Jr.] | ||
379 | * Allow assert_tag(:conditions) to match the empty string when a tag has no children. Closes #2959. [Jamis Buck] | |
380 | ||
381 | * Update html-scanner to handle CDATA sections better. Closes #2970. [Jamis Buck] | |
382 | ||
* Don't put flash in session if sessions are disabled. [Jeremy Kemper] | ||
* Strip out trailing &_= for raw post bodies. Closes #2868. [Sam Stephenson] | ||
387 | * Pass multiple arguments to Element.show and Element.hide in JavaScriptGenerator instead of using iterators. [Sam Stephenson] | |
388 | ||
389 | * Improve expire_fragment documentation. #2966 [court3nay@gmail.com] | |
390 | ||
* Correct docs for automatic layout assignment. #2610. [Charles M. Gerungan] | ||
* Always create new AR sessions rather than trying too hard to avoid database traffic. #2731 [Jeremy Kemper] | ||
* Update to Prototype 1.4.0_rc4. Closes #2943 (old Array.prototype.reverse behavior can be obtained by passing false as an argument). [Sam Stephenson] | ||
397 | * Use Element.update('id', 'html') instead of $('id').innerHTML = 'html' in JavaScriptGenerator#replace_html so that script tags are evaluated. [Sam Stephenson] | |
398 | ||
399 | * Make rjs templates always implicitly skip out on layouts. [Marcel Molina Jr.] | |
400 | ||
401 | * Correct length for the truncate text helper. #2913 [Stefan Kaes] | |
402 | ||
* Update to Prototype 1.4.0_rc3. Closes #1893, #2505, #2550, #2748, #2783. [Sam Stephenson] | ||
30 | ||
405 | * Add support for new rjs templates which wrap an update_page block. [Marcel Molina Jr.] | |
* Rename Version constant to VERSION. #2802 [Marcel Molina Jr.] | ||
409 | * Correct time_zone_options_for_select docs. #2892 [pudeyo@rpi.com] | |
410 | ||
* Remove the unused, slow response_dump and session_dump variables from error pages. #1222 [lmarlow@yahoo.com] | ||
413 | * Performance tweaks: use Set instead of Array to speed up prototype helper include? calls. Avoid logging code if logger is nil. Inline commonly-called template presence checks. #2880, #2881, #2882, #2883 [Stefan Kaes] | |
414 | ||
415 | * MemCache store may be given multiple addresses. #2869 [Ryan Carver <ryan@fivesevensix.com>] | |
416 | ||
417 | * Handle cookie parsing irregularity for certain Nokia phones. #2530 [zaitzow@gmail.com] | |
418 | ||
419 | * Added PrototypeHelper::JavaScriptGenerator and PrototypeHelper#update_page for easily modifying multiple elements in an Ajax response. [Sam Stephenson] Example: | |
420 | ||
421 | update_page do |page| | |
422 | page.insert_html :bottom, 'list', '<li>Last item</li>' | |
423 | page.visual_effect :highlight, 'list' | |
424 | page.hide 'status-indicator', 'cancel-link' | |
425 | end | |
426 | ||
427 | generates the following JavaScript: | |
428 | ||
429 | new Insertion.Bottom("list", "<li>Last item</li>"); | |
430 | new Effect.Highlight("list"); | |
431 | ["status-indicator", "cancel-link"].each(Element.hide); | |
432 | ||
433 | * Refactored JavaScriptHelper into PrototypeHelper and ScriptaculousHelper [Sam Stephenson] | |
434 | ||
* Update to latest script.aculo.us version (as of [3031]) | ||
437 | * Updated docs for in_place_editor, fixes a couple bugs and offers extended support for external controls [Justin Palmer] | |
438 | ||
* Update documentation for render :file. #2858 [Tom Werner] | ||
* Only include builtin filters whose filenames match /^[a-z][a-z_]*_helper.rb$/ to avoid including operating system metadata such as ._foo_helper.rb. #2855 [court3nay@gmail.com] | ||
443 | * Added FormHelper#form_for and FormHelper#fields_for that makes it easier to work with forms for single objects also if they don't reside in instance variables [DHH]. Examples: | |
444 | ||
445 | <% form_for :person, @person, :url => { :action => "update" } do |f| %> | |
446 | First name: <%= f.text_field :first_name %> | |
447 | Last name : <%= f.text_field :last_name %> | |
448 | Biography : <%= f.text_area :biography %> | |
449 | Admin? : <%= f.check_box :admin %> | |
450 | <% end %> | |
451 | ||
452 | <% form_for :person, person, :url => { :action => "update" } do |person_form| %> | |
453 | First name: <%= person_form.text_field :first_name %> | |
454 | Last name : <%= person_form.text_field :last_name %> | |
455 | ||
456 | <% fields_for :permission => person.permission do |permission_fields| %> | |
457 | Admin? : <%= permission_fields.check_box :admin %> | |
458 | <% end %> | |
459 | <% end %> | |
460 | ||
* options_for_select allows any objects which respond_to? :first and :last rather than restricting to Array and Range. #2824 [Jacob Robbins <jrobbins@cmj.com>, Jeremy Kemper] | ||
* The auto_link text helper accepts an optional block to format the link text for each url and email address. Example: auto_link(post.body) { |text| truncate(text, 10) } [Jeremy Kemper] |
rool/rails/typo/trunk/vendor/rails/actionpack/Rakefile:
prev. | current | |
t.verbose = true | ||
} | ||
34 | desc 'ActiveRecord Integration Tests' | |
35 | Rake::TestTask.new(:test_active_record_integration) do |t| | |
36 | t.libs << "test" | |
37 | t.test_files = Dir.glob("test/activerecord/*_test.rb") | |
38 | t.verbose = true | |
39 | end | |
41 | ||
# Genereate the RDoc documentation | ||
Rake::RDocTask.new { |rdoc| | ||
rdoc.rdoc_dir = 'doc' | ||
rdoc.title = "Action Pack -- On rails from request to response" | ||
40 | | |
47 | rdoc.options << '--line-numbers' << '--inline-source' | |
rdoc.template = "#{ENV['template']}.rb" if ENV['template'] | ||
rdoc.rdoc_files.include('README', 'RUNNING_UNIT_TESTS', 'CHANGELOG') | ||
rdoc.rdoc_files.include('lib/**/*.rb') | ||
} | ||
46 | ||
# Create compressed packages | ||
dist_dirs = [ "lib", "test", "examples" ] | ||
... | ... | |
s.has_rdoc = true | ||
s.requirements << 'none' | ||
65 | | |
71 | s.add_dependency('activesupport', '= 1.3.1' + PKG_BUILD) | |
s.require_path = 'lib' | ||
s.autorequire = 'action_controller' | ||
70 | | |
76 | s.files = [ "Rakefile", "install.rb", "README", "RUNNING_UNIT_TESTS", "CHANGELOG", "MIT-LICENSE", "examples/.htaccess" ] | |
dist_dirs.each do |dir| | ||
s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) } | ||
end | ||
... | ... | |
# Publishing ------------------------------------------------------ | ||
task :update_scriptaculous do | ||
111 | | |
117 | for js in %w( controls dragdrop effects ) | |
118 | system("svn export --force http://dev.rubyonrails.org/svn/rails/spinoffs/scriptaculous/src/#{js}.js #{File.dirname(__FILE__)}/lib/action_view/helpers/javascripts/#{js}.js") | |
119 | end | |
end | ||
desc "Updates actionpack to the latest version of the javascript spinoffs" | ||
115 | ||
123 | task :update_js => [ :update_scriptaculous ] | |
# Publishing ------------------------------------------------------ | ||
... | ... | |
end | ||
desc "Publish the release files to RubyForge." | ||
131 | ||
132 | | |
139 | task :release => [ :package ] do | |
140 | `rubyforge login` | |
134 | | |
135 | | |
136 | | |
137 | ||
138 | | |
139 | | |
140 | | |
141 | | |
142 | ||
143 | | |
144 | | |
145 | | |
146 | | |
147 | | |
148 | | |
149 | | |
150 | ||
151 | | |
152 | | |
153 | | |
154 | | |
155 | | |
156 | | |
157 | | |
158 | | |
159 | ||
160 | | |
161 | | |
162 | | |
163 | ||
164 | | |
165 | | |
166 | | |
167 | | |
168 | ||
169 | | |
170 | | |
171 | ||
172 | | |
173 | | |
174 | | |
175 | | |
176 | ||
177 | | |
178 | ||
179 | | |
180 | | |
181 | | |
182 | | |
183 | | |
184 | | |
185 | | |
186 | | |
187 | | |
188 | | |
189 | ||
190 | | |
191 | | |
192 | | |
193 | | |
194 | | |
195 | | |
196 | | |
197 | | |
198 | | |
199 | | |
200 | | |
201 | | |
202 | | |
203 | | |
204 | | |
205 | | |
206 | | |
207 | | |
208 | | |
209 | | |
210 | | |
211 | | |
212 | | |
213 | | |
214 | ||
215 | | |
216 | | |
217 | | |
218 | ||
219 | | |
220 | | |
221 | | |
222 | | |
223 | | |
224 | | |
225 | | |
226 | ||
227 | | |
228 | | |
229 | | |
230 | ||
231 | | |
232 | | |
233 | | |
234 | ||
235 | | |
236 | | |
237 | | |
238 | | |
239 | ||
240 | | |
241 | | |
142 | for ext in %w( gem tgz zip ) | |
143 | release_command = "rubyforge add_release #{PKG_NAME} #{PKG_NAME} 'REL #{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" | |
144 | puts release_command | |
145 | system(release_command) | |
end | ||
243 | ||
147 | end | |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller.rb:
prev. | current | |
require 'action_controller/base' | ||
require 'action_controller/deprecated_redirects' | ||
39 | require 'action_controller/request' | |
40 | require 'action_controller/deprecated_request_methods' | |
require 'action_controller/rescue' | ||
require 'action_controller/benchmarking' | ||
43 | require 'action_controller/flash' | |
require 'action_controller/filters' | ||
require 'action_controller/layout' | ||
43 | ||
require 'action_controller/dependencies' | ||
47 | require 'action_controller/mime_responds' | |
require 'action_controller/pagination' | ||
require 'action_controller/scaffolding' | ||
require 'action_controller/helpers' | ||
require 'action_controller/cookies' | ||
require 'action_controller/cgi_process' | ||
require 'action_controller/caching' | ||
51 | ||
require 'action_controller/verification' | ||
require 'action_controller/streaming' | ||
require 'action_controller/session_management' | ||
57 | require 'action_controller/components' | |
require 'action_controller/macros/auto_complete' | ||
require 'action_controller/macros/in_place_editing' | ||
... | ... | |
ActionController::Base.template_class = ActionView::Base | ||
ActionController::Base.class_eval do | ||
65 | include ActionController::Flash | |
include ActionController::Filters | ||
include ActionController::Layout | ||
64 | | |
include ActionController::Benchmarking | ||
include ActionController::Rescue | ||
include ActionController::Dependencies | ||
71 | include ActionController::MimeResponds | |
include ActionController::Pagination | ||
include ActionController::Scaffolding | ||
include ActionController::Helpers | ||
include ActionController::Cookies | ||
include ActionController::Caching | ||
73 | | |
include ActionController::Verification | ||
include ActionController::Streaming | ||
include ActionController::SessionManagement | ||
80 | include ActionController::Components | |
include ActionController::Macros::AutoComplete | ||
include ActionController::Macros::InPlaceEditing | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/assertions.rb:
prev. | current | |
assert_equal(eurl, url, msg) if eurl && url | ||
assert_equal(epath, path, msg) if epath && path | ||
else | ||
88 | | |
89 | | |
88 | @response_diff = options.diff(@response.redirected_to) if options.is_a?(Hash) && @response.redirected_to.is_a?(Hash) | |
89 | msg = build_message(message, "response is not a redirection to all of the options supplied (redirection is <?>)#{', difference: <?>' if @response_diff}", | |
90 | @response.redirected_to || @response.redirect_url, @response_diff) | |
assert_block(msg) do | ||
if options.is_a?(Symbol) | ||
... | ... | |
end | ||
# ensures that the passed record is valid by active record standards. returns the error messages if not | ||
305 | | |
306 | def assert_valid(record) | |
clean_backtrace do | ||
307 | | |
308 | assert record.valid?, record.errors.full_messages.join("\n") | |
end | ||
end | ||
def clean_backtrace(&block) | ||
312 | | |
313 | | |
314 | | |
315 | | |
316 | | |
317 | | |
313 | yield | |
314 | rescue AssertionFailedError => e | |
315 | path = File.expand_path(__FILE__) | |
316 | raise AssertionFailedError, e.message, e.backtrace.reject { |line| File.expand_path(line) =~ /#{path}/ } | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/base.rb:
prev. | current | |
1 | require 'action_controller/mime_type' | |
require 'action_controller/request' | ||
require 'action_controller/response' | ||
require 'action_controller/routing' | ||
... | ... | |
super(message || DEFAULT_MESSAGE) | ||
end | ||
end | ||
44 | class RedirectBackError < ActionControllerError #:nodoc: | |
45 | DEFAULT_MESSAGE = 'No HTTP_REFERER was set in the request to this action, so redirect_to :back could not be called successfully. If this is a test, make sure to specify @request.env["HTTP_REFERER"].' | |
46 | ||
47 | def initialize(message = nil) | |
48 | super(message || DEFAULT_MESSAGE) | |
49 | end | |
50 | end | |
# Action Controllers are made up of one or more actions that performs its purpose and then either renders a template or | ||
# redirects to another action. An action is defined as a public method on the controller, which will automatically be | ||
... | ... | |
# FCGI.each_cgi{ |cgi| WeblogController.process_cgi(cgi) } | ||
class Base | ||
DEFAULT_RENDER_STATUS_CODE = "200 OK" | ||
220 | | |
228 | ||
229 | include Reloadable::Subclasses | |
230 | ||
# Determines whether the view has access to controller internals @request, @response, @session, and @template. | ||
# By default, it does. | ||
@@view_controller_internals = true | ||
... | ... | |
@@allow_concurrency = false | ||
cattr_accessor :allow_concurrency | ||
264 | # Modern REST web services often need to submit complex data to the web application. | |
265 | # The param_parsers hash lets you register handlers wich will process the http body and add parameters to the | |
266 | # @params hash. These handlers are invoked for post and put requests. | |
267 | # | |
268 | # By default application/xml is enabled. A XmlSimple class with the same param name as the root will be instanciated | |
269 | # in the @params. This allows XML requests to mask themselves as regular form submissions, so you can have one | |
270 | # action serve both regular forms and web service requests. | |
271 | # | |
272 | # Example of doing your own parser for a custom content type: | |
273 | # | |
274 | # ActionController::Base.param_parsers[Mime::Type.lookup('application/atom+xml')] = Proc.new do |data| | |
275 | # node = REXML::Document.new(post) | |
276 | # { node.root.name => node.root } | |
277 | # end | |
278 | # | |
279 | # Note: Up until release 1.1 of Rails, Action Controller would default to using XmlSimple configured to discard the | |
280 | # root node for such requests. The new default is to keep the root, such that "<r><name>David</name></r>" results | |
281 | # in params[:r][:name] for "David" instead of params[:name]. To get the old behavior, you can | |
282 | # re-register XmlSimple as application/xml handler ike this: | |
283 | # | |
284 | # ActionController::Base.param_parsers[Mime::XML] = | |
285 | # Proc.new { |data| XmlSimple.xml_in(data, 'ForceArray' => false) } | |
286 | # | |
287 | # A YAML parser is also available and can be turned on with: | |
288 | # | |
289 | # ActionController::Base.param_parsers[Mime::YAML] = :yaml | |
290 | @@param_parsers = { Mime::XML => :xml_simple } | |
291 | cattr_accessor :param_parsers | |
292 | ||
# Template root determines the base from which template references will be made. So a call to render("test/template") | ||
# will be converted to "#{template_root}/test/template.rhtml". | ||
class_inheritable_accessor :template_root | ||
257 | ||
296 | ||
# The logger is used for generating information on the action run-time (including benchmarking) if available. | ||
# Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers. | ||
cattr_accessor :logger | ||
... | ... | |
# Returns the name of the action this controller is processing. | ||
attr_accessor :action_name | ||
296 | ||
335 | ||
class << self | ||
# Factory for the standard create, process loop where the controller is discarded after processing. | ||
def process(request, response) #:nodoc: | ||
... | ... | |
# Converts the class name from something like "OneModule::TwoModule::NeatController" to "one_module/two_module/neat". | ||
def controller_path | ||
315 | | |
316 | | |
317 | | |
318 | | |
319 | | |
320 | | |
321 | | |
322 | | |
354 | @controller_path ||= name.gsub(/Controller$/, '').underscore | |
end | ||
# Return an array containing the names of public methods that have been marked hidden from the action processor. | ||
# By default, all methods defined in ActionController::Base and included modules are hidden. | ||
327 | | |
359 | # More methods can be hidden using <tt>hide_actions</tt>. | |
def hidden_actions | ||
write_inheritable_attribute(:hidden_actions, ActionController::Base.public_instance_methods) unless read_inheritable_attribute(:hidden_actions) | ||
read_inheritable_attribute(:hidden_actions) | ||
... | ... | |
# Hide each of the given methods from being callable as actions. | ||
def hide_action(*names) | ||
335 | | |
367 | write_inheritable_attribute(:hidden_actions, hidden_actions | names.collect { |n| n.to_s }) | |
end | ||
337 | ||
338 | | |
339 | | |
340 | | |
341 | | |
342 | | |
343 | | |
344 | | |
345 | | |
346 | | |
347 | | |
348 | | |
349 | | |
350 | | |
351 | ||
352 | | |
353 | | |
354 | | |
355 | | |
356 | | |
end | ||
359 | | |
371 | public | |
# Extracts the action_name from the request parameters and performs that action. | ||
def process(request, response, method = :perform_action, *arguments) #:nodoc: | ||
initialize_template_class(response) | ||
assign_shortcuts(request, response) | ||
initialize_current_url | ||
365 | | |
366 | | |
367 | ||
368 | | |
377 | assign_names | |
378 | forget_variables_added_to_assigns | |
379 | ||
380 | log_processing | |
send(method, *arguments) | ||
370 | | |
382 | ||
383 | response | |
ensure | ||
372 | | |
385 | process_cleanup | |
end | ||
# Returns a URL that has been rewritten according to the options hash and the defined Routes. | ||
# (For doing a complete redirect, use redirect_to). | ||
377 | | |
390 | # Â | |
# <tt>url_for</tt> is used to: | ||
379 | | |
392 | # Â | |
# All keys given to url_for are forwarded to the Route module, save for the following: | ||
# * <tt>:anchor</tt> -- specifies the anchor name to be appended to the path. For example, | ||
# <tt>url_for :controller => 'posts', :action => 'show', :id => 10, :anchor => 'comments'</tt> | ||
... | ... | |
# | ||
# The default Routes setup supports a typical Rails path of "controller/action/id" where action and id are optional, with | ||
# action defaulting to 'index' when not given. Here are some typical url_for statements and their corresponding URLs: | ||
395 | | |
408 | # Â | |
# url_for :controller => 'posts', :action => 'recent' # => 'proto://host.com/posts/recent' | ||
# url_for :controller => 'posts', :action => 'index' # => 'proto://host.com/posts' | ||
# url_for :controller => 'posts', :action => 'show', :id => 10 # => 'proto://host.com/posts/show/10' | ||
... | ... | |
# <tt>url_for :action => 'some_action'</tt> will retain the current controller, as expected. This behavior extends to | ||
# other parameters, including <tt>:controller</tt>, <tt>:id</tt>, and any other parameters that are placed into a Route's | ||
# path. | ||
404 | | |
417 | # Â | |
# The URL helpers such as <tt>url_for</tt> have a limited form of memory: when generating a new URL, they can look for | ||
# missing values in the current request's parameters. Routes attempts to guess when a value should and should not be | ||
# taken from the defaults. There are a few simple rules on how this is performed: | ||
... | ... | |
# answer has to do with the order in which the parameters appear in the generated path. In a nutshell, since the | ||
# value that appears in the slot for <tt>:first</tt> is not equal to default value for <tt>:first</tt> we stop using | ||
# defaults. On it's own, this rule can account for much of the typical Rails URL behavior. | ||
427 | | |
440 | # Â | |
# Although a convienence, defaults can occasionaly get in your way. In some cases a default persists longer than desired. | ||
# The default may be cleared by adding <tt>:name => nil</tt> to <tt>url_for</tt>'s options. | ||
# This is often required when writing form helpers, since the defaults in play may vary greatly depending upon where the | ||
... | ... | |
# | ||
# _Deprecation_ _notice_: This used to have the signature <tt>render_template(template, status = 200, type = :rhtml)</tt> | ||
# | ||
593 | # === Rendering inline JavaScriptGenerator page updates | |
594 | # | |
595 | # In addition to rendering JavaScriptGenerator page updates with Ajax in RJS templates (see ActionView::Base for details), | |
596 | # you can also pass the <tt>:update</tt> parameter to +render+, along with a block, to render page updates inline. | |
597 | # | |
598 | # render :update do |page| | |
599 | # page.replace_html 'user_list', :partial => 'user', :collection => @users | |
600 | # page.visual_effect :highlight, 'user_list' | |
601 | # end | |
602 | # | |
# === Rendering nothing | ||
# | ||
# Rendering nothing is often convenient in combination with Ajax calls that perform their effect client-side or | ||
... | ... | |
# | ||
# # Renders an empty response with status code 401 (access denied) | ||
# render :nothing => true, :status => 401 | ||
590 | | |
613 | def render(options = nil, deprecated_status = nil, &block) #:doc: | |
raise DoubleRenderError, "Can only render or redirect once per action" if performed? | ||
# Backwards compatibility | ||
unless options.is_a?(Hash) | ||
595 | | |
618 | if options == :update | |
619 | options = {:update => true} | |
620 | else | |
621 | return render_file(options || default_template_name, deprecated_status, true) | |
622 | end | |
end | ||
625 | if content_type = options[:content_type] | |
626 | headers["Content-Type"] = content_type | |
627 | end | |
628 | ||
if text = options[:text] | ||
render_text(text, options[:status]) | ||
... | ... | |
elsif action_name = options[:action] | ||
render_action(action_name, options[:status], options[:layout]) | ||
613 | | |
644 | ||
645 | elsif xml = options[:xml] | |
646 | render_xml(xml, options[:status]) | |
647 | ||
elsif partial = options[:partial] | ||
partial = default_template_name if partial == true | ||
if collection = options[:collection] | ||
... | ... | |
render_partial(partial, ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals], options[:status]) | ||
end | ||
656 | elsif options[:update] | |
657 | add_variables_to_assigns | |
658 | @template.send :evaluate_assigns | |
659 | ||
660 | generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(@template, &block) | |
661 | render_javascript(generator.to_s) | |
662 | ||
elsif options[:nothing] | ||
# Safari doesn't pass the headers of the return if the response is zero length | ||
render_text(" ", options[:status]) | ||
... | ... | |
# Renders according to the same rules as <tt>render</tt>, but returns the result in a string instead | ||
# of sending it as the response body to the browser. | ||
635 | | |
636 | | |
676 | def render_to_string(options = nil, &block) #:doc: | |
677 | result = render(options, &block) | |
678 | ||
erase_render_results | ||
638 | | |
639 | | |
680 | forget_variables_added_to_assigns | |
681 | reset_variables_added_to_assigns | |
682 | ||
result | ||
end | ||
643 | | |
644 | | |
645 | | |
686 | def render_action(action_name, status = nil, with_layout = true) #:nodoc: | |
687 | template = default_template_name(action_name.to_s) | |
688 | if with_layout && !template_exempt_from_layout?(template) | |
689 | render_with_layout(template, status) | |
else | ||
647 | | |
691 | render_without_layout(template, status) | |
end | ||
end | ||
651 | | |
695 | def render_file(template_path, status = nil, use_full_path = false, locals = {}) #:nodoc: | |
add_variables_to_assigns | ||
653 | | |
697 | assert_existence_of_template_file(template_path) if use_full_path | |
logger.info("Rendering #{template_path}" + (status ? " (#{status})" : '')) if logger | ||
render_text(@template.render_file(template_path, use_full_path, locals), status) | ||
end | ||
658 | | |
702 | def render_template(template, status = nil, type = :rhtml, local_assigns = {}) #:nodoc: | |
add_variables_to_assigns | ||
render_text(@template.render_template(type, template, nil, local_assigns), status) | ||
end | ||
663 | | |
707 | def render_text(text = nil, status = nil) #:nodoc: | |
@performed_render = true | ||
@response.headers['Status'] = (status || DEFAULT_RENDER_STATUS_CODE).to_s | ||
@response.body = text | ||
end | ||
669 | | |
713 | def render_javascript(javascript, status = nil) #:nodoc: | |
714 | @response.headers['Content-Type'] = 'text/javascript; charset=UTF-8' | |
715 | render_text(javascript, status) | |
716 | end | |
717 | ||
718 | def render_xml(xml, status = nil) #:nodoc: | |
719 | @response.headers['Content-Type'] = 'application/xml' | |
720 | render_text(xml, status) | |
721 | end | |
722 | ||
723 | def render_nothing(status = nil) #:nodoc: | |
render_text(' ', status) | ||
end | ||
673 | | |
727 | def render_partial(partial_path = default_template_name, object = nil, local_assigns = nil, status = nil) #:nodoc: | |
add_variables_to_assigns | ||
render_text(@template.render_partial(partial_path, object, local_assigns), status) | ||
end | ||
678 | | |
732 | def render_partial_collection(partial_name, collection, partial_spacer_template = nil, local_assigns = nil, status = nil) #:nodoc: | |
add_variables_to_assigns | ||
render_text(@template.render_partial_collection(partial_name, collection, partial_spacer_template, local_assigns), status) | ||
end | ||
683 | | |
737 | def render_with_layout(template_name = default_template_name, status = nil, layout = nil) #:nodoc: | |
render_with_a_layout(template_name, status, layout) | ||
end | ||
687 | | |
741 | def render_without_layout(template_name = default_template_name, status = nil) #:nodoc: | |
render_with_no_layout(template_name, status) | ||
end | ||
# Clears the rendered results, allowing for another render to be performed. | ||
693 | | |
747 | def erase_render_results #:nodoc: | |
@response.body = nil | ||
@performed_render = false | ||
end | ||
697 | ||
751 | ||
# Clears the redirected results from the headers, resets the status to 200 and returns | ||
# the URL that was used to redirect or nil if there was no redirected URL | ||
# Note that +redirect_to+ will change the body of the response to indicate a redirection. | ||
# The response body is not reset here, see +erase_render_results+ | ||
702 | | |
756 | def erase_redirect_results #:nodoc: | |
@performed_redirect = false | ||
response.redirected_to = nil | ||
response.redirected_to_method_params = nil | ||
... | ... | |
end | ||
# Erase both render and redirect results | ||
711 | | |
765 | def erase_results #:nodoc: | |
erase_render_results | ||
erase_redirect_results | ||
end | ||
716 | | |
770 | def rewrite_options(options) #:nodoc: | |
if defaults = default_url_options(options) | ||
defaults.merge(options) | ||
else | ||
... | ... | |
case options | ||
when %r{^\w+://.*} | ||
raise DoubleRenderError if performed? | ||
756 | | |
810 | logger.info("Redirected to #{options}") if logger | |
response.redirect(options) | ||
response.redirected_to = options | ||
@performed_redirect = true | ||
... | ... | |
redirect_to(request.protocol + request.host_with_port + options) | ||
when :back | ||
765 | | |
819 | request.env["HTTP_REFERER"] ? redirect_to(request.env["HTTP_REFERER"]) : raise(RedirectBackError) | |
else | ||
if parameters_for_method_reference.empty? | ||
... | ... | |
private | ||
def self.view_class | ||
810 | | |
864 | @view_class ||= | |
# create a new class based on the default template class and include helper methods | ||
812 | | |
813 | | |
814 | | |
815 | | |
866 | returning Class.new(ActionView::Base) do |view_class| | |
867 | view_class.send(:include, master_helper_module) | |
868 | end | |
end | ||
def self.view_root | ||
... | ... | |
@session = @response.session | ||
@template = @response.template | ||
838 | | |
891 | @assigns = @response.template.assigns | |
892 | ||
@headers = @response.headers | ||
end | ||
... | ... | |
end | ||
def log_processing | ||
847 | | |
848 | | |
901 | if logger | |
902 | logger.info "\n\nProcessing #{controller_class_name}\##{action_name} (for #{request_origin}) [#{request.method.to_s.upcase}]" | |
903 | logger.info " Session ID: #{@session.session_id}" if @session and @session.respond_to?(:session_id) | |
904 | logger.info " Parameters: #{@params.inspect}" | |
905 | end | |
end | ||
def perform_action | ||
... | ... | |
@performed_render || @performed_redirect | ||
end | ||
923 | def assign_names | |
924 | @action_name = (params['action'] || 'index') | |
925 | end | |
926 | ||
def action_methods | ||
self.class.action_methods | ||
end | ||
... | ... | |
@variables_added = true | ||
end | ||
end | ||
942 | ||
943 | def forget_variables_added_to_assigns | |
944 | @variables_added = nil | |
945 | end | |
946 | ||
947 | def reset_variables_added_to_assigns | |
948 | @template.instance_variable_set("@assigns_added", nil) | |
949 | end | |
def add_instance_variables_to_assigns | ||
@@protected_variables_cache ||= protected_instance_variables.inject({}) { |h, k| h[k] = true; h } | ||
... | ... | |
if view_controller_internals | ||
[ "@assigns", "@performed_redirect", "@performed_render" ] | ||
else | ||
900 | | |
969 | [ "@assigns", "@performed_redirect", "@performed_render", "@request", "@response", "@session", "@cookies", "@template", "@request_origin", "@parent_controller" ] | |
end | ||
end | ||
904 | ||
def request_origin | ||
906 | | |
974 | # this *needs* to be cached! | |
975 | # otherwise you'd get different results if calling it more than once | |
976 | @request_origin ||= "#{@request.remote_ip} at #{Time.now.to_s(:db)}" | |
end | ||
def complete_request_uri | ||
910 | | |
980 | "#{@request.protocol}#{@request.host}#{@request.request_uri}" | |
end | ||
def close_session | ||
@session.close unless @session.nil? || Hash === @session | ||
end | ||
916 | ||
def template_exists?(template_name = default_template_name) | ||
@template.file_exists?(template_name) | ||
... | ... | |
@template.file_public?(template_name) | ||
end | ||
926 | | |
995 | def template_exempt_from_layout?(template_name = default_template_name) | |
996 | template_name =~ /\.rjs$/ || (@template.pick_template_extension(template_name) == :rjs rescue false) | |
997 | end | |
998 | ||
999 | def assert_existence_of_template_file(template_name) | |
unless template_exists?(template_name) || ignore_missing_templates | ||
full_template_path = @template.send(:full_template_path, template_name, 'rhtml') | ||
template_type = (template_name =~ /layouts/i) ? 'layout' : 'template' | ||
... | ... | |
end | ||
end | ||
934 | | |
935 | | |
1007 | def default_template_name(action_name = self.action_name) | |
1008 | if action_name | |
1009 | action_name = action_name.to_s | |
1010 | if action_name.include?('/') && template_path_includes_controller?(action_name) | |
1011 | action_name = strip_out_controller(action_name) | |
1012 | end | |
1013 | end | |
1014 | "#{self.class.controller_path}/#{action_name}" | |
end | ||
1016 | ||
1017 | def strip_out_controller(path) | |
1018 | path.split('/', 2).last | |
1019 | end | |
1020 | ||
1021 | def template_path_includes_controller?(path) | |
1022 | self.class.controller_path.split('/')[-1] == path.split('/')[0] | |
1023 | end | |
1024 | ||
1025 | def process_cleanup | |
1026 | close_session | |
1027 | end | |
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/benchmarking.rb:
prev. | current | |
# The benchmarking module times the performance of actions and reports to the logger. If the Active Record | ||
# package has been included, a separate timing section for database calls will be added as well. | ||
module Benchmarking #:nodoc: | ||
7 | | |
8 | | |
7 | def self.included(base) | |
base.extend(ClassMethods) | ||
9 | ||
base.class_eval do | ||
alias_method :perform_action_without_benchmark, :perform_action | ||
alias_method :perform_action, :perform_action_with_benchmark | ||
... | ... | |
end | ||
end | ||
46 | | |
46 | def render_with_benchmark(options = nil, deprecated_status = nil, &block) | |
unless logger | ||
48 | | |
48 | render_without_benchmark(options, deprecated_status, &block) | |
else | ||
db_runtime = ActiveRecord::Base.connection.reset_runtime if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected? | ||
render_output = nil | ||
53 | | |
53 | @rendering_runtime = Benchmark::measure{ render_output = render_without_benchmark(options, deprecated_status, &block) }.real | |
if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected? | ||
@db_rt_before_render = db_runtime |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/caching.rb:
prev. | current | |
# | ||
# Note: To turn off all caching and sweeping, set Base.perform_caching = false. | ||
module Caching | ||
11 | | |
12 | | |
11 | def self.included(base) #:nodoc: | |
base.send(:include, Pages, Actions, Fragments, Sweeping) | ||
13 | ||
base.class_eval do | ||
@@perform_caching = true | ||
cattr_accessor :perform_caching | ||
end | ||
end | ||
20 | | |
20 | # Page caching is an approach to caching where the entire action output of is stored as a HTML file that the web server | |
# can serve without going through the Action Pack. This can be as much as 100 times faster than going through the process of dynamically | ||
# generating the content. Unfortunately, this incredible speed-up is only available to stateless pages where all visitors | ||
# are treated the same. Content management systems -- including weblogs and wikis -- have many pages that are a great fit | ||
... | ... | |
File.delete(page_cache_path(path)) if File.exists?(page_cache_path(path)) | ||
end | ||
end | ||
81 | | |
81 | ||
# Manually cache the +content+ in the key determined by +path+. Example: | ||
# cache_page "I'm the cached content", "/lists/show" | ||
def cache_page(content, path) | ||
... | ... | |
# matches the triggering url. | ||
def caches_page(*actions) | ||
return unless perform_caching | ||
97 | | |
97 | actions.each do |action| | |
class_eval "after_filter { |c| c.cache_page if c.action_name == '#{action}' }" | ||
end | ||
end | ||
101 | | |
101 | ||
private | ||
def page_cache_file(path) | ||
name = ((path.empty? || path == "/") ? "/index" : URI.unescape(path)) | ||
name << page_cache_extension unless (name.split('/').last || name).include? '.' | ||
return name | ||
end | ||
108 | | |
108 | ||
def page_cache_path(path) | ||
page_cache_directory + page_cache_file(path) | ||
end | ||
... | ... | |
private | ||
def caching_allowed | ||
137 | | |
137 | !@request.post? && @response.headers['Status'] && @response.headers['Status'].to_i < 400 | |
end | ||
end | ||
141 | | |
141 | # Action caching is similar to page caching by the fact that the entire output of the response is cached, but unlike page caching, | |
# every request still goes through the Action Pack. The key benefit of this is that filters are run before the cache is served, which | ||
# allows for authentication and other restrictions on whether someone is allowed to see the cache. Example: | ||
# | ||
... | ... | |
def initialize(*actions) | ||
@actions = actions | ||
end | ||
187 | | |
187 | ||
def before(controller) | ||
return unless @actions.include?(controller.action_name.intern) | ||
if cache = controller.read_fragment(controller.url_for.split("://").last) | ||
... | ... | |
false | ||
end | ||
end | ||
196 | | |
196 | ||
def after(controller) | ||
return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache | ||
controller.write_fragment(controller.url_for.split("://").last, controller.response.body) | ||
... | ... | |
# <%= render_collection_of_partials "topic", Topic.find_all %> | ||
# <% end %> | ||
# | ||
214 | | |
214 | # This cache will bind to the name of action that called it. So you would be able to invalidate it using | |
# <tt>expire_fragment(:controller => "topics", :action => "list")</tt> -- if that was the controller/action used. This is not too helpful | ||
# if you need to cache multiple fragments per action or if the action itself is cached using <tt>caches_action</tt>. So instead we should | ||
# qualify the name of the action used with something like: | ||
... | ... | |
# Called by CacheHelper#cache | ||
def cache_erb_fragment(block, name = {}, options = nil) | ||
unless perform_caching then block.call; return end | ||
275 | | |
275 | ||
buffer = eval("_erbout", block.binding) | ||
if cache = read_fragment(name, options) | ||
... | ... | |
write_fragment(name, buffer[pos..-1], options) | ||
end | ||
end | ||
286 | | |
286 | ||
def write_fragment(name, content, options = nil) | ||
return unless perform_caching | ||
... | ... | |
end | ||
content | ||
end | ||
296 | | |
296 | ||
def read_fragment(name, options = nil) | ||
return unless perform_caching | ||
... | ... | |
fragment_cache_store.read(key, options) | ||
end | ||
end | ||
305 | | |
305 | ||
# Name can take one of three forms: | ||
# * String: This would normally take the form of a path like "pages/45/notes" | ||
# * Hash: Is treated as an implicit call to url_for, like { :controller => "pages", :action => "notes", :id => 45 } | ||
309 | | |
309 | # * Regexp: Will destroy all the matched fragments, example: %r{pages/\d*/notes} Ensure you do not specify start and finish in the regex (^$) because the actual filename matched looks like ./cache/filename/path.cache | |
def expire_fragment(name, options = nil) | ||
return unless perform_caching | ||
... | ... | |
def read(name, options=nil) #:nodoc: | ||
@mutex.synchronize { super } | ||
end | ||
358 | | |
358 | ||
def write(name, value, options=nil) #:nodoc: | ||
@mutex.synchronize { super } | ||
end | ||
362 | | |
362 | ||
def delete(name, options=nil) #:nodoc: | ||
@mutex.synchronize { super } | ||
end | ||
366 | | |
366 | ||
def delete_matched(matcher, options=nil) #:nodoc: | ||
@mutex.synchronize { super } | ||
end | ||
... | ... | |
super() | ||
@address = address | ||
@data = DRbObject.new(nil, address) | ||
389 | | |
389 | end | |
end | ||
class MemCacheStore < MemoryStore #:nodoc: | ||
393 | | |
393 | attr_reader :addresses | |
395 | | |
395 | def initialize(*addresses) | |
super() | ||
397 | | |
398 | | |
399 | | |
397 | addresses = addresses.flatten | |
398 | addresses = ["localhost"] if addresses.empty? | |
399 | @addresses = addresses | |
400 | @data = MemCache.new(*addresses) | |
401 | end | |
end | ||
class UnthreadedFileStore #:nodoc: | ||
attr_reader :cache_path | ||
404 | | |
406 | ||
def initialize(cache_path) | ||
@cache_path = cache_path | ||
end | ||
408 | | |
410 | ||
def write(name, value, options = nil) #:nodoc: | ||
ensure_cache_path(File.dirname(real_file_path(name))) | ||
File.open(real_file_path(name), "wb+") { |f| f.write(value) } | ||
... | ... | |
end | ||
def read(name, options = nil) #:nodoc: | ||
417 | | |
419 | File.open(real_file_path(name), 'rb') { |f| f.read } rescue nil | |
end | ||
def delete(name, options) #:nodoc: | ||
... | ... | |
def delete_matched(matcher, options) #:nodoc: | ||
search_dir(@cache_path) do |f| | ||
if f =~ matcher | ||
429 | | |
431 | begin | |
File.delete(f) | ||
rescue Object => e | ||
# If there's no cache, then there's nothing to complain about | ||
... | ... | |
end | ||
end | ||
end | ||
437 | | |
439 | ||
private | ||
def real_file_path(name) | ||
'%s/%s.cache' % [@cache_path, name.gsub('?', '.').gsub(':', '.')] | ||
end | ||
442 | | |
444 | ||
def ensure_cache_path(path) | ||
FileUtils.makedirs(path) unless File.exists?(path) | ||
end | ||
... | ... | |
# Sweepers are the terminators of the caching world and responsible for expiring caches when model objects change. | ||
# They do this by being half-observers, half-filters and implementing callbacks for both roles. A Sweeper example: | ||
473 | | |
475 | # | |
# class ListSweeper < ActionController::Caching::Sweeper | ||
# observe List, Item | ||
476 | | |
478 | # | |
# def after_save(record) | ||
# list = record.is_a?(List) ? record : record.list | ||
# expire_page(:controller => "lists", :action => %w( show public feed ), :id => list.id) | ||
... | ... | |
if defined?(ActiveRecord) and defined?(ActiveRecord::Observer) | ||
class Sweeper < ActiveRecord::Observer #:nodoc: | ||
attr_accessor :controller | ||
523 | ||
524 | # ActiveRecord::Observer will mark this class as reloadable even though it should not be. | |
525 | # However, subclasses of ActionController::Caching::Sweeper should be Reloadable | |
526 | include Reloadable::Subclasses | |
def before(controller) | ||
self.controller = controller | ||
... | ... | |
def after(controller) | ||
callback(:after) | ||
535 | # Clean up, so that the controller can be collected after this request | |
536 | self.controller = nil | |
end | ||
530 | | |
538 | ||
private | ||
def callback(timing) | ||
controller_callback_method_name = "#{timing}_#{controller.controller_name.underscore}" | ||
action_callback_method_name = "#{controller_callback_method_name}_#{controller.action_name}" | ||
535 | | |
543 | ||
send(controller_callback_method_name) if respond_to?(controller_callback_method_name) | ||
send(action_callback_method_name) if respond_to?(action_callback_method_name) | ||
end | ||
539 | | |
547 | ||
def method_missing(method, *arguments) | ||
return if @controller.nil? | ||
@controller.send(method, *arguments) |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb:
prev. | current | |
require 'cgi' | ||
require 'action_controller/vendor/xml_simple' | ||
3 | require 'action_controller/vendor/xml_node' | |
# Static methods for parsing the query and request parameters that can be used in | ||
# a CGI extension class or testing in isolation. | ||
... | ... | |
parsed_params | ||
end | ||
60 | | |
61 | | |
62 | | |
63 | | |
61 | def self.parse_formatted_request_parameters(mime_type, raw_post_data) | |
62 | params = case strategy = ActionController::Base.param_parsers[mime_type] | |
63 | when Proc | |
64 | strategy.call(raw_post_data) | |
65 | when :xml_simple | |
66 | raw_post_data.blank? ? nil : | |
67 | typecast_xml_value(XmlSimple.xml_in(raw_post_data, | |
68 | 'forcearray' => false, | |
69 | 'forcecontent' => true, | |
70 | 'keeproot' => true, | |
71 | 'contentkey' => '__content__')) | |
when :yaml | ||
65 | | |
73 | YAML.load(raw_post_data) | |
74 | when :xml_node | |
75 | node = XmlNode.from_xml(raw_post_data) | |
76 | { node.node_name => node } | |
end | ||
78 | ||
79 | dasherize_keys(params || {}) | |
rescue Object => e | ||
{ "exception" => "#{e.message} (#{e.class})", "backtrace" => e.backtrace, | ||
69 | | |
82 | "raw_post_data" => raw_post_data, "format" => mime_type } | |
end | ||
85 | def self.typecast_xml_value(value) | |
86 | case value | |
87 | when Hash | |
88 | if value.has_key?("__content__") | |
89 | content = translate_xml_entities(value["__content__"]) | |
90 | case value["type"] | |
91 | when "integer" then content.to_i | |
92 | when "boolean" then content == "true" | |
93 | when "datetime" then Time.parse(content) | |
94 | when "date" then Date.parse(content) | |
95 | else content | |
96 | end | |
97 | else | |
98 | value.empty? ? nil : value.inject({}) do |h,(k,v)| | |
99 | h[k] = typecast_xml_value(v) | |
100 | h | |
101 | end | |
102 | end | |
103 | when Array | |
104 | value.map! { |i| typecast_xml_value(i) } | |
105 | case value.length | |
106 | when 0 then nil | |
107 | when 1 then value.first | |
108 | else value | |
109 | end | |
110 | else | |
111 | raise "can't typecast #{value.inspect}" | |
112 | end | |
113 | end | |
114 | ||
private | ||
117 | def self.translate_xml_entities(value) | |
118 | value.gsub(/</, "<"). | |
119 | gsub(/>/, ">"). | |
120 | gsub(/"/, '"'). | |
121 | gsub(/'/, "'"). | |
122 | gsub(/&/, "&") | |
123 | end | |
124 | ||
125 | def self.dasherize_keys(params) | |
126 | case params.class.to_s | |
127 | when "Hash" | |
128 | params.inject({}) do |h,(k,v)| | |
129 | h[k.to_s.tr("-", "_")] = dasherize_keys(v) | |
130 | h | |
131 | end | |
132 | when "Array" | |
133 | params.map { |v| dasherize_keys(v) } | |
134 | else | |
135 | params | |
136 | end | |
137 | end | |
138 | ||
# Splits the given key into several pieces. Example keys are 'name', 'person[name]', | ||
# 'person[name][first]', and 'people[]'. In each instance, an Array instance is returned. | ||
# 'person[name][first]' produces ['person', 'name', 'first']; 'people[]' produces ['people', ''] |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/cgi_ext/cookie_performance_fix.rb:
prev. | current | |
cookies = Hash.new([]) | ||
if raw_cookie | ||
111 | | |
111 | raw_cookie.split(/; ?/).each do |pairs| | |
name, values = pairs.split('=',2) | ||
next unless name and values | ||
name = CGI::unescape(name) |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/cgi_process.rb:
prev. | current | |
DEFAULT_SESSION_OPTIONS = { | ||
:database_manager => CGI::Session::PStore, | ||
39 | | |
40 | | |
39 | :prefix => "ruby_sess.", | |
40 | :session_path => "/" | |
} unless const_defined?(:DEFAULT_SESSION_OPTIONS) | ||
def initialize(cgi, session_options = {}) | ||
@cgi = cgi | ||
@session_options = session_options | ||
46 | @env = @cgi.send(:env_table) | |
super() | ||
end | ||
def query_string | ||
if (qs = @cgi.query_string) && !qs.empty? | ||
qs | ||
52 | | |
53 | elsif uri = @env['REQUEST_URI'] | |
parts = uri.split('?') | ||
parts.shift | ||
parts.join('?') | ||
else | ||
57 | | |
58 | @env['QUERY_STRING'] || '' | |
end | ||
end | ||
... | ... | |
end | ||
def request_parameters | ||
66 | | |
67 | | |
67 | if ActionController::Base.param_parsers.has_key?(content_type) | |
68 | CGIMethods.parse_formatted_request_parameters(content_type, @env['RAW_POST_DATA']) | |
else | ||
CGIMethods.parse_request_parameters(@cgi.params) | ||
end | ||
end | ||
72 | | |
73 | | |
74 | | |
75 | | |
76 | ||
73 | ||
def cookies | ||
@cgi.cookies.freeze | ||
end | ||
78 | def host_with_port | |
79 | if forwarded = env["HTTP_X_FORWARDED_HOST"] | |
80 | forwarded.split(/,\s?/).last | |
81 | elsif http_host = env['HTTP_HOST'] | |
82 | http_host | |
83 | elsif server_name = env['SERVER_NAME'] | |
84 | server_name | |
85 | else | |
86 | "#{env['SERVER_ADDR']}:#{env['SERVER_PORT']}" | |
87 | end | |
88 | end | |
89 | ||
def host | ||
82 | | |
91 | host_with_port[/^[^:]+/] | |
end | ||
84 | | |
93 | ||
def port | ||
86 | | |
95 | if host_with_port =~ /:(\d+)$/ | |
96 | $1.to_i | |
97 | else | |
98 | standard_port | |
99 | end | |
end | ||
88 | | |
89 | | |
90 | | |
91 | | |
def session | ||
unless @session | ||
... | ... | |
Module.const_missing($1) | ||
rescue LoadError, NameError => const_error | ||
raise ActionController::SessionRestoreError, <<end_msg | ||
139 | ||
148 | Session contains objects whose class definition isn\'t available. | |
Remember to require the classes for all objects kept in the session. | ||
(Original exception: #{const_error.message} [#{const_error.class}]) | ||
end_msg | ||
... | ... | |
private | ||
def convert_content_type!(headers) | ||
186 | | |
187 | | |
188 | | |
189 | | |
190 | | |
195 | if header = headers.delete("Content-Type") | |
196 | headers["type"] = header | |
end | ||
198 | if header = headers.delete("Content-type") | |
199 | headers["type"] = header | |
200 | end | |
201 | if header = headers.delete("content-type") | |
202 | headers["type"] = header | |
203 | end | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/components.rb:
prev. | current | |
module ActionController #:nodoc: | ||
2 | | |
2 | # Components allow you to call other actions for their rendered response while executing another action. You can either delegate | |
# the entire response rendering or you can mix a partial response in with your other content. | ||
# | ||
# class WeblogController < ActionController::Base | ||
# # Performs a method and then lets hello_world output its render | ||
# def delegate_action | ||
# do_other_stuff_before_hello_world | ||
9 | | |
9 | # render_component :controller => "greeter", :action => "hello_world", :params => { :person => "david" } | |
# end | ||
# end | ||
# | ||
# class GreeterController < ActionController::Base | ||
# def hello_world | ||
15 | | |
15 | # render :text => "#{params[:person]} says, Hello World!" | |
# end | ||
# end | ||
# | ||
... | ... | |
# | ||
# Let's see a greeting: | ||
# <%= render_component :controller => "greeter", :action => "hello_world" %> | ||
23 | # | |
24 | # It is also possible to specify the controller as a class constant, bypassing the inflector | |
25 | # code to compute the controller class at runtime: | |
26 | # | |
27 | # <%= render_component :controller => GreeterController, :action => "hello_world" %> | |
28 | # | |
29 | # == When to use components | |
30 | # | |
31 | # Components should be used with care. They're significantly slower than simply splitting reusable parts into partials and | |
32 | # conceptually more complicated. Don't use components as a way of separating concerns inside a single application. Instead, | |
33 | # reserve components to those rare cases where you truly have reusable view and controller elements that can be employed | |
34 | # across many applications at once. | |
35 | # | |
36 | # So to repeat: Components are a special-purpose approach that can often be replaced with better use of partials and filters. | |
module Components | ||
24 | | |
25 | | |
38 | def self.included(base) #:nodoc: | |
39 | base.send :include, InstanceMethods | |
40 | base.extend(ClassMethods) | |
41 | ||
base.helper do | ||
def render_component(options) | ||
@controller.send(:render_component_as_string, options) | ||
end | ||
end | ||
47 | ||
48 | # If this controller was instantiated to process a component request, | |
49 | # +parent_controller+ points to the instantiator of this controller. | |
50 | base.send :attr_accessor, :parent_controller | |
51 | ||
52 | base.class_eval do | |
53 | alias_method :process_cleanup_without_components, :process_cleanup | |
54 | alias_method :process_cleanup, :process_cleanup_with_components | |
55 | ||
56 | alias_method :set_session_options_without_components, :set_session_options | |
57 | alias_method :set_session_options, :set_session_options_with_components | |
58 | ||
59 | alias_method :flash_without_components, :flash | |
60 | alias_method :flash, :flash_with_components | |
61 | ||
62 | alias_method :component_request?, :parent_controller | |
63 | end | |
end | ||
33 | | |
34 | | |
35 | | |
36 | | |
66 | module ClassMethods | |
67 | # Track parent controller to identify component requests | |
68 | def process_with_components(request, response, parent_controller = nil) #:nodoc: | |
69 | controller = new | |
70 | controller.parent_controller = parent_controller | |
71 | controller.process(request, response) | |
end | ||
39 | | |
40 | | |
41 | | |
42 | | |
43 | | |
44 | | |
74 | # Set the template root to be one directory behind the root dir of the controller. Examples: | |
75 | # /code/weblog/components/admin/users_controller.rb with Admin::UsersController | |
76 | # will use /code/weblog/components as template root | |
77 | # and find templates in /code/weblog/components/admin/users/ | |
78 | # | |
79 | # /code/weblog/components/admin/parties/users_controller.rb with Admin::Parties::UsersController | |
80 | # will also use /code/weblog/components as template root | |
81 | # and find templates in /code/weblog/components/admin/parties/users/ | |
82 | def uses_component_template_root | |
83 | path_of_calling_controller = File.dirname(caller[0].split(/:\d+:/).first) | |
84 | path_of_controller_root = path_of_calling_controller.sub(/#{controller_path.split("/")[0..-2]}$/, "") # " (for ruby-mode) | |
85 | ||
86 | self.template_root = path_of_controller_root | |
87 | end | |
88 | end | |
89 | ||
90 | module InstanceMethods | |
91 | # Extracts the action_name from the request parameters and performs that action. | |
92 | def process_with_components(request, response, method = :perform_action, *arguments) #:nodoc: | |
93 | flash.discard if component_request? | |
94 | process_without_components(request, response, method, *arguments) | |
95 | end | |
96 | ||
97 | protected | |
98 | # Renders the component specified as the response for the current method | |
99 | def render_component(options) #:doc: | |
100 | component_logging(options) do | |
101 | render_text(component_response(options, true).body, response.headers["Status"]) | |
102 | end | |
103 | end | |
104 | ||
105 | # Returns the component response as a string | |
106 | def render_component_as_string(options) #:doc: | |
107 | component_logging(options) do | |
108 | response = component_response(options, false) | |
109 | ||
110 | if redirected = response.redirected_to | |
111 | render_component_as_string(redirected) | |
112 | else | |
113 | response.body | |
114 | end | |
115 | end | |
116 | end | |
117 | ||
118 | def flash_with_components(refresh = false) #:nodoc: | |
119 | if @flash.nil? || refresh | |
120 | @flash = | |
121 | if @parent_controller | |
122 | @parent_controller.flash | |
123 | else | |
124 | flash_without_components | |
125 | end | |
126 | end | |
127 | ||
128 | @flash | |
129 | end | |
130 | ||
131 | private | |
132 | def component_response(options, reuse_response) | |
133 | klass = component_class(options) | |
134 | request = request_for_component(klass.controller_name, options) | |
135 | response = reuse_response ? @response : @response.dup | |
136 | ||
137 | klass.process_with_components(request, response, self) | |
138 | end | |
139 | ||
140 | # determine the controller class for the component request | |
141 | def component_class(options) | |
142 | if controller = options[:controller] | |
143 | controller.is_a?(Class) ? controller : "#{controller.camelize}Controller".constantize | |
else | ||
46 | | |
145 | self.class | |
end | ||
48 | | |
49 | | |
50 | | |
51 | | |
52 | | |
53 | | |
54 | | |
55 | | |
56 | | |
57 | | |
end | ||
59 | | |
60 | | |
61 | | |
62 | | |
63 | | |
64 | | |
65 | | |
66 | | |
67 | | |
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
73 | | |
74 | | |
75 | | |
76 | | |
77 | | |
78 | | |
79 | | |
80 | | |
81 | | |
82 | | |
83 | | |
84 | | |
148 | ||
149 | # Create a new request object based on the current request. | |
150 | # The new request inherits the session from the current request, | |
151 | # bypassing any session options set for the component controller's class | |
152 | def request_for_component(controller_name, options) | |
153 | request = @request.dup | |
154 | request.session = @request.session | |
155 | ||
156 | request.instance_variable_set( | |
157 | :@parameters, | |
158 | (options[:params] || {}).with_indifferent_access.update( | |
159 | "controller" => controller_name, "action" => options[:action], "id" => options[:id] | |
160 | ) | |
161 | ) | |
162 | ||
163 | request | |
164 | end | |
165 | ||
166 | def component_logging(options) | |
167 | if logger | |
168 | logger.info "Start rendering component (#{options.inspect}): " | |
169 | result = yield | |
170 | logger.info "\n\nEnd of component rendering" | |
171 | result | |
172 | else | |
173 | yield | |
174 | end | |
175 | end | |
176 | ||
177 | def set_session_options_with_components(request) | |
178 | set_session_options_without_components(request) unless component_request? | |
179 | end | |
180 | ||
181 | def process_cleanup_with_components | |
182 | process_cleanup_without_components unless component_request? | |
183 | end | |
184 | end | |
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/dependencies.rb:
prev. | current | |
# | ||
# Also note, that if the models follow the pattern of just 1 class per file in the form of MyClass => my_class.rb, then these | ||
# classes don't have to be required as Active Support will auto-require them. | ||
31 | | |
31 | module ClassMethods #:nodoc: | |
# Specifies a variable number of models that this controller depends on. Models are normally Active Record classes or a similar | ||
# backend for modelling entity classes. | ||
def model(*models) |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/deprecated_redirects.rb:
prev. | current | |
class Base | ||
protected | ||
# Deprecated in favor of calling redirect_to directly with the path. | ||
5 | | |
5 | def redirect_to_path(path) #:nodoc: | |
redirect_to(path) | ||
end | ||
# Deprecated in favor of calling redirect_to directly with the url. If the resource has moved permanently, it's possible to pass | ||
# true as the second parameter and the browser will get "301 Moved Permanently" instead of "302 Found". This can also be done through | ||
# just setting the headers["Status"] to "301 Moved Permanently" before using the redirect_to. | ||
12 | | |
12 | def redirect_to_url(url, permanently = false) #:nodoc: | |
headers["Status"] = "301 Moved Permanently" if permanently | ||
redirect_to(url) | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/filters.rb:
prev. | current | |
module ActionController #:nodoc: | ||
module Filters #:nodoc: | ||
3 | | |
4 | | |
3 | def self.included(base) | |
base.extend(ClassMethods) | ||
base.send(:include, ActionController::Filters::InstanceMethods) | ||
end | ||
... | ... | |
# # will run the :authenticate filter | ||
# end | ||
# | ||
144 | | |
143 | # class SignupController < ApplicationController | |
# # will not run the :authenticate filter | ||
# skip_before_filter :authenticate | ||
# end | ||
... | ... | |
# Removes the specified filters from the +before+ filter chain. Note that this only works for skipping method-reference | ||
# filters, not procs. This is especially useful for managing the chain in inheritance hierarchies where only one out | ||
# of many sub-controllers need a different hierarchy. | ||
253 | # | |
254 | # You can control the actions to skip the filter for with the <tt>:only</tt> and <tt>:except</tt> options, | |
255 | # just like when you apply the filters. | |
def skip_before_filter(*filters) | ||
255 | | |
256 | | |
257 | if conditions = extract_conditions!(filters) | |
258 | remove_contradicting_conditions!(filters, conditions) | |
259 | conditions[:only], conditions[:except] = conditions[:except], conditions[:only] | |
260 | add_action_conditions(filters, conditions) | |
261 | else | |
262 | for filter in filters.flatten | |
263 | write_inheritable_attribute("before_filters", read_inheritable_attribute("before_filters") - [ filter ]) | |
264 | end | |
end | ||
end | ||
# Removes the specified filters from the +after+ filter chain. Note that this only works for skipping method-reference | ||
# filters, not procs. This is especially useful for managing the chain in inheritance hierarchies where only one out | ||
# of many sub-controllers need a different hierarchy. | ||
271 | # | |
272 | # You can control the actions to skip the filter for with the <tt>:only</tt> and <tt>:except</tt> options, | |
273 | # just like when you apply the filters. | |
def skip_after_filter(*filters) | ||
264 | | |
265 | | |
275 | if conditions = extract_conditions!(filters) | |
276 | remove_contradicting_conditions!(filters, conditions) | |
277 | conditions[:only], conditions[:except] = conditions[:except], conditions[:only] | |
278 | add_action_conditions(filters, conditions) | |
279 | else | |
280 | for filter in filters.flatten | |
281 | write_inheritable_attribute("after_filters", read_inheritable_attribute("after_filters") - [ filter ]) | |
282 | end | |
end | ||
end | ||
# Returns all the before filters for this class and all its ancestors. | ||
def before_filters #:nodoc: | ||
271 | | |
288 | @before_filters ||= read_inheritable_attribute("before_filters") || [] | |
end | ||
# Returns all the after filters for this class and all its ancestors. | ||
def after_filters #:nodoc: | ||
276 | | |
293 | @after_filters ||= read_inheritable_attribute("after_filters") || [] | |
end | ||
# Returns a mapping between filters and the actions that may run them. | ||
def included_actions #:nodoc: | ||
281 | | |
298 | @included_actions ||= read_inheritable_attribute("included_actions") || {} | |
end | ||
# Returns a mapping between filters and actions that may not run them. | ||
def excluded_actions #:nodoc: | ||
286 | | |
303 | @excluded_actions ||= read_inheritable_attribute("excluded_actions") || {} | |
end | ||
private | ||
... | ... | |
end | ||
def prepend_filter_to_chain(condition, filters) | ||
295 | | |
312 | old_filters = read_inheritable_attribute("#{condition}_filters") || [] | |
313 | write_inheritable_attribute("#{condition}_filters", filters + old_filters) | |
end | ||
def ensure_filter_responds_to_before_and_after(filter) | ||
... | ... | |
def condition_hash(filters, *actions) | ||
filters.inject({}) {|hash, filter| hash.merge(filter => actions.flatten.map {|action| action.to_s})} | ||
end | ||
337 | ||
338 | def remove_contradicting_conditions!(filters, conditions) | |
339 | return unless conditions[:only] | |
340 | filters.each do |filter| | |
341 | next unless included_actions_for_filter = (read_inheritable_attribute('included_actions') || {})[filter] | |
342 | [*conditions[:only]].each do |conditional_action| | |
343 | conditional_action = conditional_action.to_s | |
344 | included_actions_for_filter.delete(conditional_action) if included_actions_for_filter.include?(conditional_action) | |
345 | end | |
346 | end | |
347 | end | |
end | ||
module InstanceMethods # :nodoc: | ||
322 | | |
323 | | |
324 | | |
351 | def self.included(base) | |
352 | base.class_eval do | |
alias_method :perform_action_without_filters, :perform_action | ||
alias_method :perform_action, :perform_action_with_filters | ||
327 | | |
355 | ||
356 | alias_method :process_without_filters, :process | |
357 | alias_method :process, :process_with_filters | |
358 | ||
359 | alias_method :process_cleanup_without_filters, :process_cleanup | |
360 | alias_method :process_cleanup, :process_cleanup_with_filters | |
361 | end | |
end | ||
def perform_action_with_filters | ||
331 | | |
332 | | |
333 | | |
365 | before_action_result = before_action | |
366 | ||
367 | unless before_action_result == false || performed? | |
368 | perform_action_without_filters | |
369 | after_action | |
370 | end | |
371 | ||
372 | @before_filter_chain_aborted = (before_action_result == false) | |
end | ||
375 | def process_with_filters(request, response, method = :perform_action, *arguments) #:nodoc: | |
376 | @before_filter_chain_aborted = false | |
377 | process_without_filters(request, response, method, *arguments) | |
378 | end | |
379 | ||
# Calls all the defined before-filter filters, which are added by using "before_filter :method". | ||
# If any of the filters return false, no more filters will be executed and the action is aborted. | ||
def before_action #:doc: | ||
... | ... | |
def call_filters(filters) | ||
filters.each do |filter| | ||
next if action_exempted?(filter) | ||
396 | ||
filter_result = case | ||
when filter.is_a?(Symbol) | ||
self.send(filter) | ||
... | ... | |
ea.include?(action_name) | ||
end | ||
end | ||
434 | ||
435 | def process_cleanup_with_filters | |
436 | if @before_filter_chain_aborted | |
437 | close_session | |
438 | else | |
439 | process_cleanup_without_filters | |
440 | end | |
441 | end | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/flash.rb:
prev. | current | |
# | ||
# See docs on the FlashHash class for more details about the flash. | ||
module Flash | ||
27 | | |
28 | | |
29 | | |
30 | | |
27 | def self.included(base) | |
28 | base.send :include, InstanceMethods | |
29 | ||
30 | base.class_eval do | |
31 | alias_method :assign_shortcuts_without_flash, :assign_shortcuts | |
32 | alias_method :assign_shortcuts, :assign_shortcuts_with_flash | |
33 | ||
34 | alias_method :process_cleanup_without_flash, :process_cleanup | |
35 | alias_method :process_cleanup, :process_cleanup_with_flash | |
36 | end | |
end | ||
32 | ||
38 | ||
39 | ||
class FlashNow #:nodoc: | ||
34 | | |
41 | def initialize(flash) | |
@flash = flash | ||
end | ||
... | ... | |
end | ||
class FlashHash < Hash | ||
50 | | |
51 | | |
52 | | |
def initialize #:nodoc: | ||
super | ||
@used = {} | ||
... | ... | |
super | ||
end | ||
63 | | |
64 | | |
67 | def update(h) #:nodoc: | |
68 | h.keys.each{ |k| discard(k) } | |
super | ||
end | ||
68 | | |
72 | alias :merge! :update | |
70 | | |
74 | def replace(h) #:nodoc: | |
@used = {} | ||
super | ||
end | ||
... | ... | |
# | ||
# This method is called automatically by filters, so you generally don't need to care about it. | ||
def sweep #:nodoc: | ||
109 | | |
keys.each do |k| | ||
unless @used[k] | ||
use(k) | ||
... | ... | |
end | ||
end | ||
136 | ||
137 | | |
138 | | |
139 | | |
140 | | |
141 | | |
142 | | |
143 | | |
144 | | |
145 | ||
146 | | |
147 | | |
148 | | |
149 | | |
139 | module InstanceMethods #:nodoc: | |
140 | def assign_shortcuts_with_flash(request, response) #:nodoc: | |
141 | assign_shortcuts_without_flash(request, response) | |
142 | flash(:refresh) | |
end | ||
151 | ||
152 | | |
153 | | |
154 | | |
155 | | |
144 | ||
145 | def process_cleanup_with_flash | |
146 | flash.sweep if @session | |
147 | process_cleanup_without_flash | |
end | ||
149 | ||
150 | protected | |
151 | # Access the contents of the flash. Use <tt>flash["notice"]</tt> to read a notice you put there or | |
152 | # <tt>flash["notice"] = "hello"</tt> to put a new one. | |
153 | # Note that if sessions are disabled only flash.now will work. | |
154 | def flash(refresh = false) #:doc: | |
155 | if @flash.nil? || refresh | |
156 | @flash = | |
157 | if @session.is_a?(Hash) | |
158 | # @session is a Hash, if sessions are disabled | |
159 | # we don't put the flash in the session in this case | |
160 | FlashHash.new | |
161 | else | |
162 | # otherwise, @session is a CGI::Session or a TestSession | |
163 | # so make sure it gets retrieved from/saved to session storage after request processing | |
164 | @session["flash"] ||= FlashHash.new | |
165 | end | |
166 | end | |
167 | ||
168 | @flash | |
169 | end | |
158 | ||
159 | | |
160 | | |
161 | | |
162 | | |
163 | | |
164 | | |
165 | | |
166 | | |
167 | | |
168 | | |
169 | | |
170 | | |
171 | # deprecated. use <tt>flash.keep</tt> instead | |
172 | def keep_flash #:doc: | |
173 | warn 'keep_flash is deprecated; use flash.keep instead.' | |
174 | flash.keep | |
175 | end | |
176 | end | |
end | ||
172 | ||
178 | end | |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/helpers.rb:
prev. | current | |
private | ||
def default_helper_module! | ||
112 | | |
112 | module_name = name.sub(/Controller$|$/, 'Helper') | |
module_path = module_name.split('::').map { |m| m.underscore }.join('/') | ||
require_dependency module_path | ||
helper module_name.constantize | ||
... | ... | |
rescue MissingSourceFile => e | ||
raise unless e.is_missing?("helpers/#{child.controller_path}_helper") | ||
end | ||
131 | | |
131 | end | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/layout.rb:
prev. | current | |
module ActionController #:nodoc: | ||
module Layout #:nodoc: | ||
3 | | |
4 | | |
3 | def self.included(base) | |
4 | base.extend(ClassMethods) | |
base.class_eval do | ||
alias_method :render_with_no_layout, :render | ||
alias_method :render, :render_with_a_layout | ||
class << self | ||
alias_method :inherited_without_layout, :inherited | ||
11 | alias_method :inherited, :inherited_with_layout | |
end | ||
end | ||
13 | | |
end | ||
# Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in | ||
... | ... | |
# <tt>app/views/layouts/weblog.rhtml</tt> or <tt>app/views/layouts/weblog.rxml</tt> exists then it will be automatically set as | ||
# the layout for your WeblogController. You can create a layout with the name <tt>application.rhtml</tt> or <tt>application.rxml</tt> | ||
# and this will be set as the default controller if there is no layout with the same name as the current controller and there is | ||
69 | | |
70 | | |
71 | | |
69 | # no layout explicitly assigned with the +layout+ method. Nested controllers use the same folder structure for automatic layout. | |
70 | # assignment. So an Admin::WeblogController will look for a template named <tt>app/views/layouts/admin/weblog.rhtml</tt>. | |
71 | # Setting a layout explicitly will always override the automatic behaviour for the controller where the layout is set. | |
72 | # Explicitly setting the layout in a parent class, though, will not override the child class's layout assignement if the child | |
73 | # class has a layout with the same name. | |
# | ||
# == Inheritance for layouts | ||
# | ||
... | ... | |
end | ||
def layout_conditions #:nodoc: | ||
171 | | |
173 | @layout_conditions ||= read_inheritable_attribute("layout_conditions") | |
end | ||
175 | ||
176 | def default_layout #:nodoc: | |
177 | @default_layout ||= read_inheritable_attribute("layout") | |
178 | end | |
private | ||
175 | | |
181 | def inherited_with_layout(child) | |
inherited_without_layout(child) | ||
177 | | |
183 | child.send :include, Reloadable | |
184 | layout_match = child.name.underscore.sub(/_controller$/, '').sub(/^controllers\//, '') | |
185 | child.layout(layout_match) unless layout_list.grep(%r{layouts/#{layout_match}\.[a-z][0-9a-z]*$}).empty? | |
end | ||
def layout_list | ||
181 | | |
189 | Dir.glob("#{template_root}/layouts/**/*") | |
end | ||
def add_layout_conditions(conditions) | ||
... | ... | |
def normalize_conditions(conditions) | ||
conditions.inject({}) {|hash, (key, value)| hash.merge(key => [value].flatten.map {|action| action.to_s})} | ||
end | ||
199 | ||
200 | def layout_directory_exists_cache | |
201 | @@layout_directory_exists_cache ||= Hash.new do |h, dirname| | |
202 | h[dirname] = File.directory? dirname | |
203 | end | |
204 | end | |
end | ||
# Returns the name of the active layout. If the layout was specified as a method reference (through a symbol), this method | ||
... | ... | |
# object). If the layout was defined without a directory, layouts is assumed. So <tt>layout "weblog/standard"</tt> will return | ||
# weblog/standard, but <tt>layout "standard"</tt> will return layouts/standard. | ||
def active_layout(passed_layout = nil) | ||
198 | | |
212 | layout = passed_layout || self.class.default_layout | |
active_layout = case layout | ||
215 | when String then layout | |
when Symbol then send(layout) | ||
when Proc then layout.call(self) | ||
203 | | |
end | ||
205 | ||
206 | | |
219 | ||
220 | # Explicitly passed layout names with slashes are looked up relative to the template root, | |
221 | # but auto-discovered layouts derived from a nested controller will contain a slash, though be relative | |
222 | # to the 'layouts' directory so we have to check the file system to infer which case the layout name came from. | |
223 | if active_layout | |
224 | if active_layout.include?('/') && ! layout_directory?(active_layout) | |
225 | active_layout | |
226 | else | |
227 | "layouts/#{active_layout}" | |
228 | end | |
229 | end | |
end | ||
209 | | |
232 | def render_with_a_layout(options = nil, deprecated_status = nil, deprecated_layout = nil, &block) #:nodoc: | |
template_with_options = options.is_a?(Hash) | ||
if apply_layout?(template_with_options, options) && (layout = pick_layout(template_with_options, options, deprecated_layout)) | ||
... | ... | |
logger.info("Rendering #{options} within #{layout}") if logger | ||
if template_with_options | ||
217 | | |
240 | content_for_layout = render_with_no_layout(options, &block) | |
deprecated_status = options[:status] || deprecated_status | ||
else | ||
220 | | |
243 | content_for_layout = render_with_no_layout(options, deprecated_status, &block) | |
end | ||
erase_render_results | ||
... | ... | |
@template.instance_variable_set("@content_for_layout", content_for_layout) | ||
render_text(@template.render_file(layout, true), deprecated_status) | ||
else | ||
228 | | |
251 | render_with_no_layout(options, deprecated_status, &block) | |
end | ||
end | ||
private | ||
256 | ||
def apply_layout?(template_with_options, options) | ||
234 | | |
235 | | |
236 | | |
237 | | |
238 | | |
258 | return false if options == :update | |
259 | template_with_options ? candidate_for_layout?(options) : !template_exempt_from_layout? | |
end | ||
262 | def candidate_for_layout?(options) | |
263 | (options.has_key?(:layout) && options[:layout] != false) || | |
264 | options.values_at(:text, :xml, :file, :inline, :partial, :nothing).compact.empty? && | |
265 | !template_exempt_from_layout?(default_template_name(options[:action] || options[:template])) | |
266 | end | |
267 | ||
def pick_layout(template_with_options, options, deprecated_layout) | ||
if deprecated_layout | ||
deprecated_layout | ||
... | ... | |
true | ||
end | ||
end | ||
299 | ||
300 | # Does a layout directory for this class exist? | |
301 | # we cache this info in a class level hash | |
302 | def layout_directory?(layout_name) | |
303 | template_path = File.join(self.class.view_root, 'layouts', layout_name) | |
304 | dirname = File.dirname(template_path) | |
305 | self.class.send(:layout_directory_exists_cache)[dirname] | |
306 | end | |
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/pagination.rb:
prev. | current | |
:order => nil, | ||
:join => nil, | ||
:joins => nil, | ||
74 | :count => nil, | |
:include => nil, | ||
:select => nil, | ||
:parameter => 'page' | ||
... | ... | |
# and Model.count | ||
# <tt>:include</tt>:: optional eager loading parameter passed to Model.find(:all, *params) | ||
# and Model.count | ||
123 | # <tt>:select</tt>:: :select parameter passed to Model.find(:all, *params) | |
124 | # | |
125 | # <tt>:count</tt>:: parameter passed as :select option to Model.count(*params) | |
126 | # | |
def paginate(collection_id, options={}) | ||
Pagination.validate_options!(collection_id, options, true) | ||
paginator_and_collection_for(collection_id, options) | ||
... | ... | |
# Returns the total number of items in the collection to be paginated for | ||
# the +model+ and given +conditions+. Override this method to implement a | ||
# custom counter. | ||
166 | | |
167 | | |
171 | def count_collection_for_pagination(model, options) | |
172 | model.count(:conditions => options[:conditions], | |
173 | :joins => options[:join] || options[:joins], | |
174 | :include => options[:include], | |
175 | :select => options[:count]) | |
end | ||
169 | | |
177 | ||
# Returns a collection of items for the given +model+ and +options[conditions]+, | ||
# ordered by +options[order]+, for the current page in the given +paginator+. | ||
# Override this method to implement a custom finder. | ||
... | ... | |
def paginator_and_collection_for(collection_id, options) #:nodoc: | ||
klass = options[:class_name].constantize | ||
page = @params[options[:parameter]] | ||
188 | | |
189 | | |
190 | ||
196 | count = count_collection_for_pagination(klass, options) | |
paginator = Paginator.new(self, count, options[:per_page], page) | ||
collection = find_collection_for_pagination(klass, options, paginator) | ||
193 | | |
199 | ||
return paginator, collection | ||
end | ||
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/request.rb:
prev. | current | |
class AbstractRequest | ||
cattr_accessor :relative_url_root | ||
6 | # Returns the hash of environment variables for this request, | |
7 | # such as { 'RAILS_ENV' => 'production' }. | |
8 | attr_reader :env | |
9 | ||
# Returns both GET and POST parameters in a single hash. | ||
def parameters | ||
8 | | |
12 | @parameters ||= request_parameters.update(query_parameters).update(path_parameters).with_indifferent_access | |
end | ||
# Returns the HTTP request method as a lowercase symbol (:get, for example) | ||
def method | ||
13 | | |
17 | @request_method ||= @env['REQUEST_METHOD'].downcase.to_sym | |
end | ||
# Is this a GET request? Equivalent to request.method == :get | ||
... | ... | |
method == :head | ||
end | ||
41 | | |
42 | | |
45 | # Determine whether the body of a HTTP call is URL-encoded (default) | |
46 | # or matches one of the registered param_parsers. | |
# | ||
44 | | |
45 | | |
46 | | |
47 | | |
48 | | |
49 | | |
50 | | |
# For backward compatibility, the post format is extracted from the | ||
# X-Post-Data-Format HTTP header if present. | ||
53 | | |
54 | | |
55 | | |
56 | | |
57 | | |
58 | | |
59 | | |
60 | | |
61 | | |
62 | | |
63 | | |
50 | def content_type | |
51 | @content_type ||= | |
52 | begin | |
53 | content_type = @env['CONTENT_TYPE'].to_s.downcase | |
54 | ||
55 | if x_post_format = @env['HTTP_X_POST_DATA_FORMAT'] | |
56 | case x_post_format.to_s.downcase | |
57 | when 'yaml' | |
58 | content_type = 'application/x-yaml' | |
59 | when 'xml' | |
60 | content_type = 'application/xml' | |
61 | end | |
62 | end | |
63 | ||
64 | Mime::Type.lookup(content_type) | |
65 | end | |
end | ||
66 | | |
67 | | |
68 | | |
68 | def accepts | |
69 | @accepts ||= | |
70 | if @env['HTTP_ACCEPT'].to_s.strip.empty? | |
71 | [ content_type, Mime::ALL ] | |
72 | else | |
73 | Mime::Type.parse(@env['HTTP_ACCEPT']) | |
74 | end | |
end | ||
71 | | |
72 | | |
73 | | |
74 | | |
75 | ||
76 | | |
77 | | |
78 | | |
79 | | |
80 | ||
# Returns true if the request's "X-Requested-With" header contains | ||
# "XMLHttpRequest". (The Prototype Javascript library sends this header with | ||
# every Ajax request.) | ||
def xml_http_request? | ||
85 | | |
81 | not /XMLHttpRequest/i.match(@env['HTTP_X_REQUESTED_WITH']).nil? | |
end | ||
alias xhr? :xml_http_request? | ||
... | ... | |
# delimited list in the case of multiple chained proxies; the first is | ||
# the originating IP. | ||
def remote_ip | ||
96 | | |
92 | return @env['HTTP_CLIENT_IP'] if @env.include? 'HTTP_CLIENT_IP' | |
98 | | |
99 | | |
94 | if @env.include? 'HTTP_X_FORWARDED_FOR' then | |
95 | remote_ips = @env['HTTP_X_FORWARDED_FOR'].split(',').reject do |ip| | |
ip =~ /^unknown$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\./i | ||
end | ||
return remote_ips.first.strip unless remote_ips.empty? | ||
end | ||
106 | | |
102 | @env['REMOTE_ADDR'] | |
end | ||
# Returns the domain part of a host, such as rubyonrails.org in "www.rubyonrails.org". You can specify | ||
... | ... | |
# This is useful for services such as REST, XMLRPC and SOAP | ||
# which communicate over HTTP POST but don't use the traditional parameter format. | ||
def raw_post | ||
130 | | |
126 | @env['RAW_POST_DATA'] | |
end | ||
# Returns the request URI correctly, taking into account the idiosyncracies | ||
# of the various servers. | ||
def request_uri | ||
136 | | |
132 | if uri = @env['REQUEST_URI'] | |
(%r{^\w+\://[^/]+(/.*|$)$} =~ uri) ? $1 : uri # Remove domain, which webrick puts into the request_uri. | ||
else # REQUEST_URI is blank under IIS - get this from PATH_INFO and SCRIPT_NAME | ||
139 | | |
140 | | |
135 | script_filename = @env['SCRIPT_NAME'].to_s.match(%r{[^/]+$}) | |
136 | uri = @env['PATH_INFO'] | |
uri = uri.sub(/#{script_filename}\//, '') unless script_filename.nil? | ||
142 | | |
138 | unless (env_qs = @env['QUERY_STRING']).nil? || env_qs.empty? | |
uri << '?' << env_qs | ||
end | ||
uri | ||
... | ... | |
# Is this an SSL request? | ||
def ssl? | ||
156 | | |
152 | @env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] == 'https' | |
end | ||
# Returns the interpreted path to requested resource after all the installation directory of this application was taken into account | ||
... | ... | |
end | ||
# Returns the path minus the web server relative installation directory. | ||
170 | | |
166 | # This can be set with the environment variable RAILS_RELATIVE_URL_ROOT. | |
167 | # It can be automatically extracted for Apache setups. If the server is not | |
168 | # Apache, this method returns an empty string. | |
def relative_url_root | ||
172 | | |
173 | | |
170 | @@relative_url_root ||= case | |
171 | when @env["RAILS_RELATIVE_URL_ROOT"] | |
172 | @env["RAILS_RELATIVE_URL_ROOT"] | |
173 | when server_software == 'apache' | |
174 | @env["SCRIPT_NAME"].to_s.sub(/\/dispatch\.(fcgi|rb|cgi)$/, '') | |
175 | else | |
176 | '' | |
177 | end | |
end | ||
# Returns the port number of this request as an integer. | ||
def port | ||
178 | | |
182 | @port_as_int ||= @env['SERVER_PORT'].to_i | |
end | ||
# Returns the standard port number for this request's protocol | ||
... | ... | |
# Returns the lowercase name of the HTTP server software. | ||
def server_software | ||
216 | | |
220 | (@env['SERVER_SOFTWARE'] && /^([a-zA-Z]+)/ =~ @env['SERVER_SOFTWARE']) ? $1.downcase : nil | |
end | ||
#-- | ||
... | ... | |
def request_parameters #:nodoc: | ||
end | ||
228 | | |
229 | | |
230 | | |
231 | | |
232 | ||
# Returns the host for this request, such as example.com. | ||
def host | ||
end | ||
... | ... | |
def session #:nodoc: | ||
end | ||
242 | def session=(session) #:nodoc: | |
243 | @session = session | |
244 | end | |
245 | ||
def reset_session #:nodoc: | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/rescue.rb:
prev. | current | |
# the remote IP being 127.0.0.1. For example, this could include the IP of the developer machine when debugging | ||
# remotely. | ||
def local_request? #:doc: | ||
63 | | |
63 | [@request.remote_addr, @request.remote_ip] == ["127.0.0.1"] * 2 | |
end | ||
# Renders a detailed diagnostics screen on action exceptions. |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/routing.rb:
prev. | current | |
def initialize(key, options = {}) | ||
@key = key.to_sym | ||
103 | @optional = false | |
default, @condition = options[:default], options[:condition] | ||
self.default = default if options.key?(:default) | ||
end | ||
... | ... | |
class << self | ||
def assign_controller(g, controller) | ||
217 | | |
218 | expr = "::#{controller.split('/').collect {|c| c.camelize}.join('::')}Controller" | |
g.result :controller, expr, true | ||
end | ||
def traverse_to_controller(segments, start_at = 0) | ||
222 | | |
223 | mod = ::Object | |
length = segments.length | ||
index = start_at | ||
mod_name = controller_name = segment = nil | ||
226 | | |
227 | ||
while index < length | ||
return nil unless /^[A-Za-z][A-Za-z\d_]*$/ =~ (segment = segments[index]) | ||
index += 1 | ||
230 | | |
231 | ||
mod_name = segment.camelize | ||
controller_name = "#{mod_name}Controller" | ||
233 | | |
234 | | |
235 | | |
236 | | |
234 | ||
235 | begin | |
236 | # We use eval instead of const_get to avoid obtaining values from parent modules. | |
237 | controller = eval("mod::#{controller_name}", nil, __FILE__, __LINE__) | |
238 | expected_name = "#{mod.name}::#{controller_name}" | |
239 | ||
240 | # Detect the case when const_get returns an object from a parent namespace. | |
241 | if controller.is_a?(Class) && controller.ancestors.include?(ActionController::Base) && (mod == Object || controller.name == expected_name) | |
242 | return controller, (index - start_at) | |
243 | end | |
244 | rescue NameError => e | |
245 | raise unless /^uninitialized constant .*#{controller_name}$/ =~ e.message | |
246 | end | |
247 | ||
248 | begin | |
249 | next_mod = eval("mod::#{mod_name}", nil, __FILE__, __LINE__) | |
250 | # Check that we didn't get a module from a parent namespace | |
251 | mod = (mod == Object || next_mod.name == "#{mod.name}::#{mod_name}") ? next_mod : nil | |
252 | rescue NameError => e | |
253 | raise unless /^uninitialized constant .*#{mod_name}$/ =~ e.message | |
254 | end | |
255 | ||
256 | return nil unless mod | |
end | ||
end | ||
end | ||
... | ... | |
@generation_methods[controller.to_sym] = method_name | ||
end | ||
445 | | |
code = generation_code_for('routes', 'generate_default_path').to_s | ||
eval(code, nil, 'generated_code/routing/generation.rb') | ||
... | ... | |
route.write_recognition(g) | ||
end | ||
end | ||
482 | | |
501 | ||
eval g.to_s, nil, 'generated/routing/recognition.rb' | ||
return g.to_s | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/scaffolding.rb:
prev. | current | |
# This tiny piece of code will add all of the following methods to the controller: | ||
# | ||
# class WeblogController < ActionController::Base | ||
20 | # verify :method => :post, :only => [ :destroy, :create, :update ], | |
21 | # :redirect_to => { :action => :list } | |
22 | # | |
# def index | ||
# list | ||
# end | ||
... | ... | |
end | ||
module_eval <<-"end_eval", __FILE__, __LINE__ | ||
104 | ||
105 | verify :method => :post, :only => [ :destroy#{suffix}, :create#{suffix}, :update#{suffix} ], | |
106 | :redirect_to => { :action => :list#{suffix} } | |
107 | ||
108 | ||
def list#{suffix} | ||
@#{singular_name}_pages, @#{plural_name} = paginate :#{plural_name}, :per_page => 10 | ||
render#{suffix}_scaffold "list#{suffix}" |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/session/active_record_store.rb:
prev. | current | |
cattr_accessor :data_column_name | ||
self.data_column_name = 'data' | ||
62 | | |
63 | | |
64 | | |
65 | | |
62 | before_save :marshal_data! | |
63 | before_save :raise_on_session_data_overflow! | |
class << self | ||
# Don't try to reload ARStore::Session in dev mode. | ||
... | ... | |
@data ||= self.class.unmarshal(read_attribute(@@data_column_name)) || {} | ||
end | ||
123 | # Has the session been loaded yet? | |
124 | def loaded? | |
125 | !! @data | |
126 | end | |
127 | ||
private | ||
attr_writer :data | ||
def marshal_data! | ||
132 | return false if !loaded? | |
write_attribute(@@data_column_name, self.class.marshal(self.data)) | ||
end | ||
132 | | |
133 | | |
134 | | |
135 | | |
136 | ||
# Ensures that the data about to be stored in the database is not | ||
# larger than the data storage column. Raises | ||
# ActionController::SessionOverflowError. | ||
def raise_on_session_data_overflow! | ||
140 | return false if !loaded? | |
limit = self.class.data_column_size_limit | ||
if loaded? and limit and read_attribute(@@data_column_name).size > limit | ||
raise ActionController::SessionOverflowError | ||
... | ... | |
@data | ||
end | ||
235 | def loaded? | |
236 | !! @data | |
237 | end | |
238 | ||
def save | ||
240 | return false if !loaded? | |
marshaled_data = self.class.marshal(data) | ||
if @new_record | ||
... | ... | |
raise CGI::Session::NoSession, 'uninitialized session' | ||
end | ||
@session = @@session_class.new(:session_id => session_id, :data => {}) | ||
281 | | |
286 | # session saving can be lazy again, because of improved component implementation | |
287 | # therefore next line gets commented out: | |
288 | # @session.save | |
end | ||
end | ||
... | ... | |
end | ||
end | ||
327 | protected | |
328 | def logger | |
329 | ActionController::Base.logger rescue nil | |
330 | end | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/session/mem_cache_store.rb:
prev. | current | |
# Create a new CGI::Session::MemCache instance | ||
# | ||
28 | | |
28 | # This constructor is used internally by CGI::Session. The | |
# user does not generally need to call it directly. | ||
# | ||
# +session+ is the session for which this instance is being | ||
32 | | |
32 | # created. The session id must only contain alphanumeric | |
# characters; automatically generated session ids observe | ||
# this requirement. | ||
# | ||
36 | | |
36 | # +options+ is a hash of options for the initializer. The | |
# following options are recognized: | ||
# | ||
# cache:: an instance of a MemCache client to use as the | ||
# session cache. | ||
# | ||
42 | # expires:: an expiry time value to use for session entries in | |
43 | # the session cache. +expires+ is interpreted in seconds | |
44 | # relative to the current time if it’s less than 60*60*24*30 | |
45 | # (30 days), or as an absolute Unix time (e.g., Time#to_i) if | |
46 | # greater. If +expires+ is +0+, or not passed on +options+, | |
47 | # the entry will never expire. | |
48 | # | |
# This session's memcache entry will be created if it does | ||
# not exist, or retrieved if it does. | ||
def initialize(session, options = {}) | ||
id = session.session_id | ||
unless check_id(id) | ||
raise ArgumentError, "session_id '%s' is invalid" % id | ||
48 | | |
55 | end | |
@cache = options['cache'] || MemCache.new('localhost') | ||
50 | | |
51 | | |
57 | @expires = options['expires'] || 0 | |
58 | @session_key = "session:#{id}" | |
59 | @session_data = {} | |
end | ||
# Restore session state from the session's memcache entry. | ||
... | ... | |
# Returns the session state as a hash. | ||
def restore | ||
begin | ||
59 | | |
67 | @session_data = @cache[@session_key] || {} | |
rescue | ||
61 | | |
69 | @session_data = {} | |
end | ||
63 | | |
64 | | |
end | ||
# Save session state to the session's memcache entry. | ||
def update | ||
begin | ||
70 | | |
76 | @cache.set(@session_key, @session_data, @expires) | |
rescue | ||
# Ignore session update failures. | ||
end | ||
... | ... | |
rescue | ||
# Ignore session delete failures. | ||
end | ||
88 | | |
94 | @session_data = {} | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/session_management.rb:
prev. | current | |
module ActionController #:nodoc: | ||
module SessionManagement #:nodoc: | ||
9 | | |
10 | | |
9 | def self.included(base) | |
base.extend(ClassMethods) | ||
12 | | |
13 | | |
14 | | |
11 | ||
12 | base.send :alias_method, :process_without_session_management_support, :process | |
13 | base.send :alias_method, :process, :process_with_session_management_support | |
14 | ||
15 | base.send :alias_method, :process_cleanup_without_session_management_support, :process_cleanup | |
16 | base.send :alias_method, :process_cleanup, :process_cleanup_with_session_management_support | |
end | ||
module ClassMethods | ||
... | ... | |
end | ||
def process_with_session_management_support(request, response, method = :perform_action, *arguments) #:nodoc: | ||
114 | | |
115 | | |
116 | set_session_options(request) | |
process_without_session_management_support(request, response, method, *arguments) | ||
end | ||
118 | | |
119 | ||
private | ||
120 | | |
121 | | |
122 | | |
121 | def set_session_options(request) | |
122 | request.session_options = self.class.session_options_for(request, request.parameters["action"] || "index") | |
123 | end | |
124 | ||
125 | def process_cleanup_with_session_management_support | |
126 | process_cleanup_without_session_management_support | |
127 | clear_persistent_model_associations | |
128 | end | |
129 | ||
130 | # Clear cached associations in session data so they don't overflow | |
131 | # the database field. Only applies to ActiveRecordStore since there | |
132 | # is not a standard way to iterate over session data. | |
133 | def clear_persistent_model_associations #:doc: | |
134 | if defined?(@session) && @session.instance_variables.include?('@data') | |
135 | session_data = @session.instance_variable_get('@data') | |
136 | ||
137 | if session_data && session_data.respond_to?(:each_value) | |
138 | session_data.each_value do |obj| | |
139 | obj.clear_association_cache if obj.respond_to?(:clear_association_cache) | |
140 | end | |
141 | end | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/templates/rescues/_trace.rhtml:
prev. | current | |
names = traces.collect {|name, trace| name} | ||
%> | ||
10 | ||
10 | <p><code>RAILS_ROOT: <%= defined?(RAILS_ROOT) ? RAILS_ROOT : "unset" %></code></p> | |
<div id="traces"> | ||
<% names.each do |name| -%> |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/templates/rescues/diagnostics.rhtml:
prev. | current | |
<h1> | ||
2 | | |
3 | | |
2 | <%=h @exception.class.to_s %> | |
3 | <% if @request.parameters['controller'] %> | |
4 | in <%=h @request.parameters['controller'].humanize %>Controller<% if @request.parameters['action'] %>#<%=h @request.parameters['action'] %><% end %> | |
5 | <% end %> | |
</h1> | ||
<pre><%=h @exception.clean_message %></pre> | ||
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/templates/scaffolds/layout.rhtml:
prev. | current | |
display: table; | ||
} | ||
31 | | |
31 | #errorExplanation { | |
width: 400px; | ||
border: 2px solid red; | ||
padding: 7px; | ||
... | ... | |
background-color: #f0f0f0; | ||
} | ||
40 | | |
40 | #errorExplanation h2 { | |
text-align: left; | ||
font-weight: bold; | ||
padding: 5px 5px 5px 15px; | ||
... | ... | |
color: #fff; | ||
} | ||
50 | | |
50 | #errorExplanation p { | |
color: #333; | ||
margin-bottom: 0; | ||
padding: 5px; | ||
} | ||
56 | | |
56 | #errorExplanation ul li { | |
font-size: 12px; | ||
list-style: square; | ||
} |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/templates/scaffolds/list.rhtml:
prev. | current | |
<% end %> | ||
<td><%= link_to "Show", :action => "show#{@scaffold_suffix}", :id => entry %></td> | ||
<td><%= link_to "Edit", :action => "edit#{@scaffold_suffix}", :id => entry %></td> | ||
17 | | |
17 | <td><%= link_to "Destroy", {:action => "destroy#{@scaffold_suffix}", :id => entry}, { :confirm => "Are you sure?", :post => true} %></td> | |
</tr> | ||
<% end %> | ||
</table> |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/test_process.rb:
prev. | current | |
def reset_session | ||
@session = {} | ||
end | ||
44 | ||
45 | def raw_post | |
46 | if raw_post = env['RAW_POST_DATA'] | |
47 | raw_post | |
48 | else | |
49 | params = self.request_parameters.dup | |
50 | %w(controller action only_path).each do |k| | |
51 | params.delete(k) | |
52 | params.delete(k.to_sym) | |
53 | end | |
55 | params.map { |k,v| [ CGI.escape(k.to_s), CGI.escape(v.to_s) ].join('=') }.sort.join('&') | |
56 | end | |
57 | end | |
58 | ||
def port=(number) | ||
@env["SERVER_PORT"] = number.to_i | ||
@port_as_int = nil | ||
... | ... | |
def recycle! | ||
self.request_parameters = {} | ||
105 | | |
106 | | |
119 | self.query_parameters = {} | |
120 | self.path_parameters = {} | |
121 | @request_method, @accepts, @content_type = nil, nil, nil | |
end | ||
private | ||
... | ... | |
end | ||
end | ||
123 | | |
138 | # A refactoring of TestResponse to allow the same behavior to be applied | |
139 | # to the "real" CgiResponse class in integration tests. | |
140 | module TestResponseBehavior #:nodoc: | |
# the response code of the request | ||
def response_code | ||
headers['Status'][0,3].to_i rescue 0 | ||
... | ... | |
sio.rewind | ||
sio.read | ||
end | ||
251 | ||
268 | end | |
270 | class TestResponse < AbstractResponse #:nodoc: | |
271 | include TestResponseBehavior | |
272 | end | |
273 | ||
class TestSession #:nodoc: | ||
def initialize(attributes = {}) | ||
@attributes = attributes | ||
... | ... | |
def close() end | ||
def delete() @attributes = {} end | ||
end | ||
274 | ||
275 | ||
276 | ||
277 | | |
278 | | |
279 | | |
280 | | |
281 | | |
282 | | |
283 | | |
284 | | |
285 | | |
295 | ||
296 | # Essentially generates a modified Tempfile object similar to the object | |
297 | # you'd get from the standard library CGI module in a multipart | |
298 | # request. This means you can use an ActionController::TestUploadedFile | |
299 | # object in the params of a test request in order to simulate | |
300 | # a file upload. | |
301 | # | |
302 | # Usage example, within a functional test: | |
303 | # post :change_avatar, :avatar => ActionController::TestUploadedFile.new(Test::Unit::TestCase.fixture_path + '/files/spongebob.png', 'image/png') | |
304 | class TestUploadedFile | |
305 | # The filename, *not* including the path, of the "uploaded" file | |
306 | attr_reader :original_filename | |
307 | ||
308 | # The content type of the "uploaded" file | |
309 | attr_reader :content_type | |
310 | ||
311 | def initialize(path, content_type = 'text/plain') | |
312 | raise "file does not exist" unless File.exist?(path) | |
313 | @content_type = content_type | |
314 | @original_filename = path.sub(/^.*#{File::SEPARATOR}([^#{File::SEPARATOR}]+)$/) { $1 } | |
315 | @tempfile = Tempfile.new(@original_filename) | |
316 | FileUtils.copy_file(path, @tempfile.path) | |
317 | end | |
318 | ||
319 | def path #:nodoc: | |
320 | @tempfile.path | |
321 | end | |
322 | ||
323 | alias local_path path | |
324 | ||
325 | def method_missing(method_name, *args, &block) #:nodoc: | |
326 | @tempfile.send(method_name, *args, &block) | |
327 | end | |
328 | end | |
329 | ||
330 | module TestProcess | |
331 | def self.included(base) | |
332 | # execute the request simulating a specific http method and set/volley the response | |
333 | %w( get post put delete head ).each do |method| | |
334 | base.class_eval <<-EOV, __FILE__, __LINE__ | |
335 | def #{method}(action, parameters = nil, session = nil, flash = nil) | |
336 | @request.env['REQUEST_METHOD'] = "#{method.upcase}" if @request | |
337 | process(action, parameters, session, flash) | |
end | ||
339 | EOV | |
340 | end | |
341 | end | |
288 | | |
343 | # execute the request and set/volley the response | |
344 | def process(action, parameters = nil, session = nil, flash = nil) | |
345 | # Sanity check for required instance variables so we can give an | |
346 | # understandable error message. | |
347 | %w(controller request response).each do |iv_name| | |
348 | raise "@#{iv_name} is nil: make sure you set it in your test's setup method." if instance_variable_get("@#{iv_name}").nil? | |
349 | end | |
290 | | |
291 | | |
292 | | |
351 | @request.recycle! | |
294 | | |
295 | | |
353 | @html_document = nil | |
354 | @request.env['REQUEST_METHOD'] ||= "GET" | |
355 | @request.action = action.to_s | |
297 | | |
298 | | |
299 | | |
300 | | |
301 | | |
357 | parameters ||= {} | |
358 | @request.assign_parameters(@controller.class.controller_path, action.to_s, parameters) | |
303 | | |
304 | | |
305 | | |
306 | | |
307 | | |
308 | | |
309 | | |
310 | | |
311 | | |
360 | @request.session = ActionController::TestSession.new(session) unless session.nil? | |
361 | @request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash | |
362 | build_request_uri(action, parameters) | |
363 | @controller.process(@request, @response) | |
364 | end | |
313 | | |
314 | | |
315 | | |
316 | | |
317 | | |
318 | | |
319 | | |
366 | def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil) | |
367 | @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' | |
368 | @request.env['HTTP_ACCEPT'] = 'text/javascript, text/html, application/xml, text/xml, */*' | |
369 | returning self.send(request_method, action, parameters, session, flash) do | |
370 | @request.env.delete 'HTTP_X_REQUESTED_WITH' | |
371 | @request.env.delete 'HTTP_ACCEPT' | |
372 | end | |
373 | end | |
374 | alias xhr :xml_http_request | |
321 | | |
322 | | |
323 | | |
324 | | |
376 | def follow_redirect | |
377 | if @response.redirected_to[:controller] | |
378 | raise "Can't follow redirects outside of current controller (#{@response.redirected_to[:controller]})" | |
379 | end | |
326 | | |
327 | | |
381 | get(@response.redirected_to.delete(:action), @response.redirected_to.stringify_keys) | |
382 | end | |
329 | | |
330 | | |
331 | | |
332 | | |
333 | | |
334 | | |
335 | | |
384 | def assigns(key = nil) | |
385 | if key.nil? | |
386 | @response.template.assigns | |
387 | else | |
388 | @response.template.assigns[key.to_s] | |
389 | end | |
390 | end | |
337 | | |
338 | | |
339 | | |
392 | def session | |
393 | @response.session | |
394 | end | |
341 | | |
342 | | |
343 | | |
396 | def flash | |
397 | @response.flash | |
398 | end | |
345 | | |
346 | | |
347 | | |
400 | def cookies | |
401 | @response.cookies | |
402 | end | |
349 | | |
350 | | |
351 | | |
404 | def redirect_to_url | |
405 | @response.redirect_url | |
406 | end | |
353 | | |
354 | | |
355 | | |
356 | | |
408 | def build_request_uri(action, parameters) | |
409 | unless @request.env['REQUEST_URI'] | |
410 | options = @controller.send(:rewrite_options, parameters) | |
411 | options.update(:only_path => true, :action => action) | |
358 | | |
359 | | |
360 | | |
361 | | |
413 | url = ActionController::UrlRewriter.new(@request, parameters) | |
414 | @request.set_REQUEST_URI(url.rewrite(options)) | |
415 | end | |
416 | end | |
363 | | |
364 | | |
365 | | |
418 | def html_document | |
419 | @html_document ||= HTML::Document.new(@response.body) | |
420 | end | |
367 | | |
368 | | |
369 | | |
422 | def find_tag(conditions) | |
423 | html_document.find(conditions) | |
424 | end | |
371 | | |
372 | | |
373 | | |
426 | def find_all_tag(conditions) | |
427 | html_document.find_all(conditions) | |
428 | end | |
375 | | |
376 | | |
377 | | |
378 | | |
430 | def method_missing(selector, *args) | |
431 | return @controller.send(selector, *args) if ActionController::Routing::NamedRoutes::Helpers.include?(selector) | |
432 | return super | |
433 | end | |
434 | ||
435 | # Shortcut for ActionController::TestUploadedFile.new(Test::Unit::TestCase.fixture_path + path, type). Example: | |
436 | # post :change_avatar, :avatar => fixture_file_upload('/files/spongebob.png', 'image/png') | |
437 | def fixture_file_upload(path, mime_type = nil) | |
438 | ActionController::TestUploadedFile.new( | |
439 | Test::Unit::TestCase.respond_to?(:fixture_path) ? Test::Unit::TestCase.fixture_path + path : path, | |
440 | mime_type | |
441 | ) | |
442 | end | |
380 | | |
381 | | |
382 | | |
383 | | |
384 | | |
385 | | |
386 | | |
387 | | |
388 | | |
389 | | |
390 | | |
391 | | |
392 | | |
393 | | |
394 | | |
395 | | |
396 | | |
397 | | |
444 | # A helper to make it easier to test different route configurations. | |
445 | # This method temporarily replaces ActionController::Routing::Routes | |
446 | # with a new RouteSet instance. | |
447 | # | |
448 | # The new instance is yielded to the passed block. Typically the block | |
449 | # will create some routes using map.draw { map.connect ... }: | |
450 | # | |
451 | # with_routing do |set| | |
452 | # set.draw { set.connect ':controller/:id/:action' } | |
453 | # assert_equal( | |
454 | # ['/content/10/show', {}], | |
455 | # set.generate(:controller => 'content', :id => 10, :action => 'show') | |
456 | # ) | |
457 | # end | |
458 | # | |
459 | def with_routing | |
460 | real_routes = ActionController::Routing::Routes | |
461 | ActionController::Routing.send :remove_const, :Routes | |
399 | | |
400 | | |
401 | | |
402 | | |
403 | | |
404 | | |
405 | | |
406 | | |
407 | | |
408 | | |
463 | temporary_routes = ActionController::Routing::RouteSet.new | |
464 | ActionController::Routing.send :const_set, :Routes, temporary_routes | |
465 | ||
466 | yield temporary_routes | |
467 | ensure | |
468 | if ActionController::Routing.const_defined? :Routes | |
469 | ActionController::Routing.send(:remove_const, :Routes) | |
470 | end | |
471 | ActionController::Routing.const_set(:Routes, real_routes) if real_routes | |
end | ||
end | ||
end | ||
475 | ||
476 | module Test | |
477 | module Unit | |
478 | class TestCase #:nodoc: | |
479 | include ActionController::TestProcess | |
480 | end | |
481 | end | |
482 | end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/vendor/html-scanner/html/node.rb:
prev. | current | |
end | ||
end | ||
153 | if scanner.skip(/!\[CDATA\[/) | |
154 | scanner.scan_until(/\]\]>/) | |
155 | return CDATA.new(parent, line, pos, scanner.pre_match) | |
156 | end | |
157 | ||
closing = ( scanner.scan(/\//) ? :close : nil ) | ||
return Text.new(parent, line, pos, content) unless name = scanner.scan(/[\w:]+/) | ||
name.downcase! | ||
... | ... | |
content == node.content | ||
end | ||
end | ||
264 | ||
265 | # A CDATA node is simply a text node with a specialized way of displaying | |
266 | # itself. | |
267 | class CDATA < Text #:nodoc: | |
268 | def to_s | |
269 | "<![CDATA[#{super}]>" | |
270 | end | |
271 | end | |
# A Tag is any node that represents markup. It may be an opening tag, a | ||
# closing tag, or a self-closing tag. It has a name, and may have a hash of | ||
... | ... | |
conditions = validate_conditions(conditions) | ||
# check content of child nodes | ||
402 | | |
415 | if conditions[:content] | |
416 | if children.empty? | |
417 | return false unless match_condition("", conditions[:content]) | |
418 | else | |
419 | return false unless children.find { |child| child.match(conditions[:content]) } | |
420 | end | |
421 | end | |
# test the name | ||
return false unless match_condition(@name, conditions[:tag]) if conditions[:tag] |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/vendor/html-scanner/html/tokenizer.rb:
prev. | current | |
if @scanner.scan(/!--/) # comment | ||
tag << @scanner.matched | ||
tag << (@scanner.scan_until(/--\s*>/) || @scanner.scan_until(/\Z/)) | ||
55 | elsif @scanner.scan(/!\[CDATA\[/) | |
56 | tag << @scanner.matched | |
57 | tag << @scanner.scan_until(/\]\]>/) | |
elsif @scanner.scan(/!/) # doctype | ||
tag << @scanner.matched | ||
tag << consume_quoted_regions |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/vendor/html-scanner/html/version.rb:
prev. | current | |
MAJOR = 0 | ||
MINOR = 5 | ||
6 | | |
6 | TINY = 3 | |
STRING = [ MAJOR, MINOR, TINY ].join(".") | ||
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_controller/verification.rb:
prev. | current | |
# must match the current request method in order for the action(s) to | ||
# be safely called. (The key should be a symbol: <tt>:get</tt> or | ||
# <tt>:post</tt>, for example.) | ||
50 | # * <tt>:xhr</tt>: true/false option to ensure that the request is coming | |
51 | # from an Ajax call or not. | |
# * <tt>:add_flash</tt>: a hash of name/value pairs that should be merged | ||
# into the session's flash if the prerequisites cannot be satisfied. | ||
# * <tt>:redirect_to</tt>: the redirection parameters to be used when |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_pack/version.rb:
prev. | current | |
1 | ||
1 | module ActionPack #:nodoc: | |
module VERSION #:nodoc: | ||
MAJOR = 1 | ||
4 | | |
5 | | |
4 | MINOR = 12 | |
5 | TINY = 1 | |
STRING = [MAJOR, MINOR, TINY].join('.') | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view.rb:
prev. | current | |
#++ | ||
$:.unshift(File.dirname(__FILE__) + "/action_view/vendor") | ||
25 | ||
26 | ||
require 'action_view/base' | ||
require 'action_view/partials' | ||
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/base.rb:
prev. | current | |
class ActionViewError < StandardError #:nodoc: | ||
end | ||
8 | | |
9 | | |
8 | # Action View templates can be written in three ways. If the template file has a +.rhtml+ extension then it uses a mixture of ERb | |
9 | # (included in Ruby) and HTML. If the template file has a +.rxml+ extension then Jim Weirich's Builder::XmlMarkup library is used. | |
10 | # If the template file has a +.rjs+ extension then it will use ActionView::Helpers::PrototypeHelper::JavaScriptGenerator. | |
# | ||
# = ERb | ||
# | ||
... | ... | |
# xml.em("emphasized") # => <em>emphasized</em> | ||
# xml.em { xml.b("emp & bold") } # => <em><b>emph & bold</b></em> | ||
# xml.a("A Link", "href"=>"http://onestepback.org") # => <a href="http://onestepback.org">A Link</a> | ||
76 | | |
77 | # xml.target("name"=>"compile", "option"=>"fast") # => <target option="fast" name="compile"\> | |
# # NOTE: order of attributes is not specified. | ||
# | ||
# Any method with a block will be treated as an XML markup tag with nested markup in the block. For example, the following: | ||
... | ... | |
# end | ||
# | ||
# More builder documentation can be found at http://builder.rubyforge.org. | ||
119 | # | |
120 | # == JavaScriptGenerator | |
121 | # | |
122 | # JavaScriptGenerator templates end in +.rjs+. Unlike conventional templates which are used to | |
123 | # render the results of an action, these templates generate instructions on how to modify an already rendered page. This makes it easy to | |
124 | # modify multiple elements on your page in one declarative Ajax response. Actions with these templates are called in the background with Ajax | |
125 | # and make updates to the page where the request originated from. | |
126 | # | |
127 | # An instance of the JavaScriptGenerator object named +page+ is automatically made available to your template, which is implicitly wrapped in an ActionView::Helpers::PrototypeHelper#update_page block. | |
128 | # | |
129 | # When an .rjs action is called with +link_to_remote+, the generated JavaScript is automatically evaluated. Example: | |
130 | # | |
131 | # link_to_remote :url => {:action => 'delete'} | |
132 | # | |
133 | # The subsequently rendered +delete.rjs+ might look like: | |
134 | # | |
135 | # page.replace_html 'sidebar', :partial => 'sidebar' | |
136 | # page.remove "person-#{@person.id}" | |
137 | # page.visual_effect :highlight, 'user-list' | |
138 | # | |
139 | # This refreshes the sidebar, removes a person element and highlights the user list. | |
140 | # | |
141 | # See the ActionView::Helpers::PrototypeHelper::JavaScriptGenerator documentation for more details. | |
class Base | ||
include ERB::Util | ||
... | ... | |
@@cache_template_loading = false | ||
cattr_accessor :cache_template_loading | ||
160 | # Specify whether file extension lookup should be cached. | |
161 | # Should be +false+ for development environments. Defaults to +true+. | |
162 | @@cache_template_extensions = true | |
163 | cattr_accessor :cache_template_extensions | |
164 | ||
# Specify whether local_assigns should be able to use string keys. | ||
# Defaults to +true+. String keys are deprecated and will be removed | ||
# shortly. | ||
@@local_assigns_support_string_keys = true | ||
cattr_accessor :local_assigns_support_string_keys | ||
170 | ||
171 | # Specify whether RJS responses should be wrapped in a try/catch block | |
172 | # that alert()s the caught exception (and then re-raises it). | |
173 | @@debug_rjs = false | |
174 | cattr_accessor :debug_rjs | |
142 | | |
176 | @@template_handlers = HashWithIndifferentAccess.new | |
module CompiledTemplates #:nodoc: | ||
# holds compiled template code | ||
... | ... | |
# map method names to the names passed in local assigns so far | ||
@@template_args = {} | ||
# count the number of inline templates | ||
156 | | |
190 | @@inline_template_count = 0 | |
191 | # maps template paths without extension to their file extension returned by pick_template_extension. | |
192 | # if for a given path, path.ext1 and path.ext2 exist on the file system, the order of extensions | |
193 | # used by pick_template_extension determines whether ext1 or ext2 will be stored | |
194 | @@cached_template_extension = {} | |
class ObjectWrapper < Struct.new(:value) #:nodoc: | ||
end | ||
... | ... | |
# Renders the template present at <tt>template_path</tt>. If <tt>use_full_path</tt> is set to true, | ||
# it's relative to the template_root, otherwise it's absolute. The hash in <tt>local_assigns</tt> | ||
# is made available as local variables. | ||
191 | | |
192 | | |
229 | def render_file(template_path, use_full_path = true, local_assigns = {}) #:nodoc: | |
230 | @first_render ||= template_path | |
if use_full_path | ||
195 | | |
196 | | |
233 | template_path_without_extension, template_extension = path_and_extension(template_path) | |
234 | ||
235 | if template_extension | |
236 | template_file_name = full_template_path(template_path_without_extension, template_extension) | |
237 | else | |
238 | template_extension = pick_template_extension(template_path).to_s | |
239 | template_file_name = full_template_path(template_path, template_extension) | |
240 | end | |
else | ||
template_file_name = template_path | ||
template_extension = template_path.split('.').last | ||
... | ... | |
# Renders the template present at <tt>template_path</tt> (relative to the template_root). | ||
# The hash in <tt>local_assigns</tt> is made available as local variables. | ||
218 | | |
262 | def render(options = {}, old_local_assigns = {}, &block) #:nodoc: | |
if options.is_a?(String) | ||
render_file(options, true, old_local_assigns) | ||
265 | elsif options == :update | |
266 | update_page(&block) | |
elsif options.is_a?(Hash) | ||
options[:locals] ||= {} | ||
options[:use_full_path] = options[:use_full_path].nil? ? true : options[:use_full_path] | ||
... | ... | |
# Renders the +template+ which is given as a string as either rhtml or rxml depending on <tt>template_extension</tt>. | ||
# The hash in <tt>local_assigns</tt> is made available as local variables. | ||
239 | | |
285 | def render_template(template_extension, template, file_path = nil, local_assigns = {}) #:nodoc: | |
if handler = @@template_handlers[template_extension] | ||
template ||= read_template_file(file_path, template_extension) # Make sure that a lazyily-read template is loaded. | ||
delegate_render(handler, template, local_assigns) | ||
... | ... | |
# Either, but not both, of template and file_path may be nil. If file_path is given, the template | ||
# will only be read if it has to be compiled. | ||
# | ||
255 | | |
301 | def compile_and_render_template(extension, template = nil, file_path = nil, local_assigns = {}) #:nodoc: | |
# compile the given template, if necessary | ||
if compile_template?(template, file_path, local_assigns) | ||
template ||= read_template_file(file_path, extension) | ||
... | ... | |
end | ||
def pick_template_extension(template_path)#:nodoc: | ||
274 | | |
275 | | |
276 | | |
277 | | |
278 | | |
279 | | |
320 | if @@cache_template_extensions | |
321 | @@cached_template_extension[template_path] ||= find_template_extension_for(template_path) | |
else | ||
281 | | |
323 | find_template_extension_for(template_path) | |
end | ||
end | ||
... | ... | |
def builder_template_exists?(template_path)#:nodoc: | ||
template_exists?(template_path, :rxml) | ||
end | ||
338 | ||
339 | def javascript_template_exists?(template_path)#:nodoc: | |
340 | template_exists?(template_path, :rjs) | |
341 | end | |
def file_exists?(template_path)#:nodoc: | ||
298 | | |
344 | template_file_name, template_file_extension = path_and_extension(template_path) | |
345 | ||
346 | if template_file_extension | |
347 | template_exists?(template_file_name, template_file_extension) | |
348 | else | |
349 | cached_template_extension(template_path) || | |
350 | %w(erb builder javascript delegate).any? do |template_type| | |
351 | send("#{template_type}_template_exists?", template_path) | |
352 | end | |
353 | end | |
end | ||
# Returns true is the file may be rendered implicitly. | ||
... | ... | |
@@method_names.has_key?(file_path) || FileTest.exists?(file_path) | ||
end | ||
371 | def path_and_extension(template_path) | |
372 | template_path_without_extension = template_path.sub(/\.(\w+)$/, '') | |
373 | [ template_path_without_extension, $1 ] | |
374 | end | |
375 | ||
376 | def cached_template_extension(template_path) | |
377 | @@cache_template_extensions && @@cached_template_extension[template_path] | |
378 | end | |
379 | ||
380 | def find_template_extension_for(template_path) | |
381 | if match = delegate_template_exists?(template_path) | |
382 | match.first.to_sym | |
383 | elsif erb_template_exists?(template_path): :rhtml | |
384 | elsif builder_template_exists?(template_path): :rxml | |
385 | elsif javascript_template_exists?(template_path): :rjs | |
386 | else | |
387 | raise ActionViewError, "No rhtml, rxml, rjs or delegate template found for #{template_path}" | |
388 | end | |
389 | end | |
390 | ||
# This method reads a template file. | ||
def read_template_file(template_path, extension) | ||
File.read(template_path) | ||
... | ... | |
# Or if local_assigns has a new key, which isn't supported by the compiled code yet. | ||
# Or if the file has changed on disk and checking file mods hasn't been disabled. | ||
def compile_template?(template, file_name, local_assigns) | ||
348 | | |
423 | method_key = file_name || template | |
render_symbol = @@method_names[method_key] | ||
if @@compile_time[render_symbol] && supports_local_assigns?(render_symbol, local_assigns) | ||
... | ... | |
# Create source code for given template | ||
def create_template_source(extension, template, render_symbol, locals) | ||
362 | | |
363 | | |
364 | | |
365 | | |
437 | if template_requires_setup?(extension) | |
438 | body = case extension.to_sym | |
439 | when :rxml | |
440 | "xml = Builder::XmlMarkup.new(:indent => 2)\n" + | |
441 | "@controller.headers['Content-Type'] ||= 'application/xml'\n" + | |
442 | template | |
443 | when :rjs | |
444 | "@controller.headers['Content-Type'] ||= 'text/javascript'\n" + | |
445 | "update_page do |page|\n#{template}\nend" | |
446 | end | |
else | ||
body = ERB.new(template, nil, @@erb_trim_mode).src | ||
end | ||
... | ... | |
"def #{render_symbol}(local_assigns)\n#{locals_code}#{body}\nend" | ||
end | ||
463 | def template_requires_setup?(extension) | |
464 | templates_requiring_setup.include? extension.to_s | |
465 | end | |
466 | ||
467 | def templates_requiring_setup | |
468 | %w(rxml rjs) | |
469 | end | |
470 | ||
def assign_method_name(extension, template, file_name) | ||
method_name = '_run_' | ||
473 | method_name << "#{extension}_" if extension | |
385 | | |
386 | | |
387 | | |
388 | | |
389 | | |
390 | ||
if file_name | ||
file_path = File.expand_path(file_name) | ||
base_path = File.expand_path(@base_path) | ||
... | ... | |
l = base_path.length | ||
method_name_file_part = i ? file_path[i+l+1,file_path.length-l-1] : file_path.clone | ||
399 | | |
483 | method_name_file_part.sub!(/\.r(html|xml|js)$/,'') | |
method_name_file_part.tr!('/:-', '_') | ||
method_name_file_part.gsub!(/[^a-zA-Z0-9_]/){|s| s[0].to_s} | ||
... | ... | |
render_source = create_template_source(extension, template, render_symbol, local_assigns.keys) | ||
line_offset = @@template_args[render_symbol].size | ||
419 | | |
420 | ||
503 | if extension | |
504 | case extension.to_sym | |
505 | when :rxml, :rjs | |
506 | line_offset += 2 | |
507 | end | |
508 | end | |
509 | ||
begin | ||
unless file_name.blank? | ||
CompiledTemplates.module_eval(render_source, file_name, -line_offset) |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/compiled_templates.rb:
prev. | current | |
# | ||
# To use a compiled template module, create a new instance and include it into the class | ||
# in which you want the template to be rendered. | ||
13 | | |
13 | class CompiledTemplates < Module #:nodoc: | |
attr_reader :method_names | ||
def initialize |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/active_record_helper.rb:
prev. | current | |
def error_messages_for(object_name, options = {}) | ||
options = options.symbolize_keys | ||
object = instance_variable_get("@#{object_name}") | ||
106 | | |
106 | if object && !object.errors.empty? | |
content_tag("div", | ||
content_tag( | ||
options[:header_tag] || "h2", | ||
... | ... | |
content_tag("ul", object.errors.full_messages.collect { |msg| content_tag("li", msg) }), | ||
"id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation" | ||
) | ||
116 | else | |
117 | "" | |
end | ||
end | ||
... | ... | |
to_input_field_tag("text", options) | ||
when :date | ||
to_date_select_tag(options) | ||
142 | | |
144 | when :datetime, :timestamp | |
to_datetime_select_tag(options) | ||
when :boolean | ||
to_boolean_select_tag(options) |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/asset_tag_helper.rb:
prev. | current | |
# <tt>controllers/application.rb</tt> and <tt>helpers/application_helper.rb</tt>. | ||
def javascript_include_tag(*sources) | ||
options = sources.last.is_a?(Hash) ? sources.pop.stringify_keys : { } | ||
62 | | |
63 | | |
64 | | |
65 | | |
66 | | |
62 | ||
63 | if sources.include?(:defaults) | |
64 | sources = sources[0..(sources.index(:defaults))] + | |
65 | @@javascript_default_sources.dup + | |
66 | sources[(sources.index(:defaults) + 1)..sources.length] | |
67 | ||
68 | sources.delete(:defaults) | |
69 | sources << "application" if defined?(RAILS_ROOT) && File.exists?("#{RAILS_ROOT}/public/javascripts/application.js") | |
end | ||
71 | ||
sources.collect { |source| | ||
source = javascript_path(source) | ||
content_tag("script", "", { "type" => "text/javascript", "src" => source }.merge(options)) | ||
... | ... | |
# * file name, like "rss.gif", that gets expanded to "/images/rss.gif" | ||
# * file name without extension, like "logo", that gets expanded to "/images/logo.png" | ||
def image_tag(source, options = {}) | ||
134 | | |
138 | options.symbolize_keys! | |
options[:src] = image_path(source) | ||
options[:alt] ||= File.basename(options[:src], '.*').split('.').first.capitalize | ||
... | ... | |
private | ||
def compute_public_path(source, dir, ext) | ||
149 | | |
150 | | |
151 | | |
153 | source = "/#{dir}/#{source}" unless source.first == "/" || source.include?(":") | |
154 | source << ".#{ext}" unless source.split("/").last.include?(".") | |
155 | source << '?' + rails_asset_id(source) if defined?(RAILS_ROOT) && %r{^[-a-z]+://} !~ source | |
156 | source = "#{@controller.request.relative_url_root}#{source}" unless %r{^[-a-z]+://} =~ source | |
source = ActionController::Base.asset_host + source unless source.include?(":") | ||
source | ||
end | ||
160 | ||
161 | def rails_asset_id(source) | |
162 | ENV["RAILS_ASSET_ID"] || | |
163 | File.mtime("#{RAILS_ROOT}/public/#{source}").to_i.to_s rescue "" | |
164 | end | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/capture_helper.rb:
prev. | current | |
# instance variable. You can use this instance variable anywhere | ||
# in your templates and even in your layout. | ||
# | ||
46 | | |
46 | # Example of capture being used in a .rhtml page: | |
# | ||
# <% @greeting = capture do %> | ||
# Welcome To my shiny new web page! | ||
50 | | |
50 | # <% end %> | |
51 | # | |
52 | # Example of capture being used in a .rxml page: | |
53 | # | |
54 | # @greeting = capture do | |
55 | # 'Welcome To my shiny new web page!' | |
56 | # end | |
def capture(*args, &block) | ||
# execute the block | ||
53 | | |
54 | | |
55 | | |
59 | begin | |
60 | buffer = eval("_erbout", block.binding) | |
61 | rescue | |
62 | buffer = nil | |
63 | end | |
57 | | |
58 | | |
59 | | |
60 | | |
61 | | |
62 | | |
63 | | |
65 | if buffer.nil? | |
66 | capture_block(*args, &block) | |
67 | else | |
68 | capture_erb_with_buffer(buffer, *args, &block) | |
69 | end | |
end | ||
# Content_for will store the given block | ||
... | ... | |
def content_for(name, &block) | ||
eval "@content_for_#{name} = (@content_for_#{name} || '') + capture(&block)" | ||
end | ||
93 | ||
94 | private | |
95 | def capture_block(*args, &block) | |
96 | block.call(*args) | |
97 | end | |
98 | ||
99 | def capture_erb(*args, &block) | |
100 | buffer = eval("_erbout", block.binding) | |
101 | capture_erb_with_buffer(buffer, *args, &block) | |
102 | end | |
103 | ||
104 | def capture_erb_with_buffer(buffer, *args, &block) | |
105 | pos = buffer.length | |
106 | block.call(*args) | |
107 | ||
108 | # extract the block | |
109 | data = buffer[pos..-1] | |
110 | ||
111 | # replace it in the original with empty string | |
112 | buffer[pos..-1] = '' | |
113 | ||
114 | data | |
115 | end | |
116 | ||
117 | def erb_content_for(name, &block) | |
118 | eval "@content_for_#{name} = (@content_for_#{name} || '') + capture_erb(&block)" | |
119 | end | |
120 | ||
121 | def block_content_for(name, &block) | |
122 | eval "@content_for_#{name} = (@content_for_#{name} || '') + capture_block(&block)" | |
123 | end | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/date_helper.rb:
prev. | current | |
# date_select("user", "birthday", :order => [:month, :day]) | ||
# | ||
# The selects are prepared for multi-parameter assignment to an Active Record object. | ||
79 | | |
80 | | |
79 | def date_select(object_name, method, options = {}) | |
80 | InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_date_select_tag(options) | |
end | ||
# Returns a set of select tags (one for year, month, day, hour, and minute) pre-selected for accessing a specified datetime-based | ||
... | ... | |
# datetime_select("post", "written_on", :start_year => 1995) | ||
# | ||
# The selects are prepared for multi-parameter assignment to an Active Record object. | ||
90 | | |
91 | | |
90 | def datetime_select(object_name, method, options = {}) | |
91 | InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_datetime_select_tag(options) | |
end | ||
# Returns a set of html select-tags (one for year, month, and day) pre-selected with the +date+. | ||
... | ... | |
datetime_select | ||
end | ||
end | ||
296 | ||
297 | class FormBuilder | |
298 | def date_select(method, options = {}) | |
299 | @template.date_select(@object_name, method, options.merge(:object => @object)) | |
300 | end | |
301 | ||
302 | def datetime_select(method, options = {}) | |
303 | @template.datetime_select(@object_name, method, options.merge(:object => @object)) | |
304 | end | |
305 | end | |
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/form_helper.rb:
prev. | current | |
# | ||
# If the object name contains square brackets the id for the object will be inserted. Example: | ||
# | ||
50 | | |
50 | # <%= text_field "person[]", "name" %> | |
# | ||
# ...becomes: | ||
# | ||
... | ... | |
# There's also methods for helping to build form tags in link:classes/ActionView/Helpers/FormOptionsHelper.html, | ||
# link:classes/ActionView/Helpers/DateHelper.html, and link:classes/ActionView/Helpers/ActiveRecordHelper.html | ||
module FormHelper | ||
68 | # Creates a form and a scope around a specific model object, which is then used as a base for questioning about | |
69 | # values for the fields. Examples: | |
70 | # | |
71 | # <% form_for :person, @person, :url => { :action => "update" } do |f| %> | |
72 | # First name: <%= f.text_field :first_name %> | |
73 | # Last name : <%= f.text_field :last_name %> | |
74 | # Biography : <%= f.text_area :biography %> | |
75 | # Admin? : <%= f.check_box :admin %> | |
76 | # <% end %> | |
77 | # | |
78 | # Worth noting is that the form_for tag is called in a ERb evaluation block, not a ERb output block. So that's <tt><% %></tt>, | |
79 | # not <tt><%= %></tt>. Also worth noting is that the form_for yields a form_builder object, in this example as f, which emulates | |
80 | # the API for the stand-alone FormHelper methods, but without the object name. So instead of <tt>text_field :person, :name</tt>, | |
81 | # you get away with <tt>f.text_field :name</tt>. | |
82 | # | |
83 | # That in itself is a modest increase in comfort. The big news is that form_for allows us to more easily escape the instance | |
84 | # variable convention, so while the stand-alone approach would require <tt>text_field :person, :name, :object => person</tt> | |
85 | # to work with local variables instead of instance ones, the form_for calls remain the same. You simply declare once with | |
86 | # <tt>:person, person</tt> and all subsequent field calls save <tt>:person</tt> and <tt>:object => person</tt>. | |
87 | # | |
88 | # Also note that form_for doesn't create an exclusive scope. It's still possible to use both the stand-alone FormHelper methods | |
89 | # and methods from FormTagHelper. Example: | |
90 | # | |
91 | # <% form_for :person, @person, :url => { :action => "update" } do |f| %> | |
92 | # First name: <%= f.text_field :first_name %> | |
93 | # Last name : <%= f.text_field :last_name %> | |
94 | # Biography : <%= text_area :person, :biography %> | |
95 | # Admin? : <%= check_box_tag "person[admin]", @person.company.admin? %> | |
96 | # <% end %> | |
97 | # | |
98 | # Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base. | |
99 | # Like collection_select and datetime_select. | |
100 | # | |
101 | # Html attributes for the form tag can be given as :html => {...}. Example: | |
102 | # | |
103 | # <% form_for :person, @person, :html => {:id => 'person_form'} do |f| %> | |
104 | # ... | |
105 | # <% end %> | |
106 | # | |
107 | # You can also build forms using a customized FormBuilder class. Subclass FormBuilder and override or define some more helpers, | |
108 | # then use your custom builder like so: | |
109 | # | |
110 | # <% form_for :person, @person, :url => { :action => "update" }, :builder => LabellingFormBuilder do |f| %> | |
111 | # <%= f.text_field :first_name %> | |
112 | # <%= f.text_field :last_name %> | |
113 | # <%= text_area :person, :biography %> | |
114 | # <%= check_box_tag "person[admin]", @person.company.admin? %> | |
115 | # <% end %> | |
116 | # | |
117 | # In many cases you will want to wrap the above in another helper, such as: | |
118 | # | |
119 | # def labelled_form_for(name, object, options, &proc) | |
120 | # form_for(name, object, options.merge(:builder => LabellingFormBuiler), &proc) | |
121 | # end | |
122 | # | |
123 | def form_for(object_name, *args, &proc) | |
124 | raise ArgumentError, "Missing block" unless block_given? | |
125 | options = args.last.is_a?(Hash) ? args.pop : {} | |
126 | concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {}), proc.binding) | |
127 | fields_for(object_name, *(args << options), &proc) | |
128 | concat('</form>', proc.binding) | |
129 | end | |
130 | ||
131 | # Creates a scope around a specific model object like form_for, but doesn't create the form tags themselves. This makes | |
132 | # fields_for suitable for specifying additional model objects in the same form. Example: | |
133 | # | |
134 | # <% form_for :person, @person, :url => { :action => "update" } do |person_form| %> | |
135 | # First name: <%= person_form.text_field :first_name %> | |
136 | # Last name : <%= person_form.text_field :last_name %> | |
137 | # | |
138 | # <% fields_for :permission, @person.permission do |permission_fields| %> | |
139 | # Admin? : <%= permission_fields.check_box :admin %> | |
140 | # <% end %> | |
141 | # <% end %> | |
142 | # | |
143 | # Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base. | |
144 | # Like collection_select and datetime_select. | |
145 | def fields_for(object_name, *args, &proc) | |
146 | raise ArgumentError, "Missing block" unless block_given? | |
147 | options = args.last.is_a?(Hash) ? args.pop : {} | |
148 | object = args.first | |
149 | yield((options[:builder] || FormBuilder).new(object_name, object, self, options, proc)) | |
150 | end | |
151 | ||
# Returns an input tag of the "text" type tailored for accessing a specified attribute (identified by +method+) on an object | ||
# assigned to the template (identified by +object+). Additional options on the input tag can be passed as a | ||
# hash with +options+. | ||
... | ... | |
# Examples (call, result): | ||
# text_field("post", "title", "size" => 20) | ||
# <input type="text" id="post_title" name="post[title]" size="20" value="#{@post.title}" /> | ||
75 | | |
76 | | |
159 | def text_field(object_name, method, options = {}) | |
160 | InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("text", options) | |
end | ||
# Works just like text_field, but returns an input tag of the "password" type instead. | ||
80 | | |
81 | | |
164 | def password_field(object_name, method, options = {}) | |
165 | InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("password", options) | |
end | ||
# Works just like text_field, but returns an input tag of the "hidden" type instead. | ||
85 | | |
86 | | |
169 | def hidden_field(object_name, method, options = {}) | |
170 | InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("hidden", options) | |
end | ||
# Works just like text_field, but returns an input tag of the "file" type instead, which won't have a default value. | ||
90 | | |
91 | | |
174 | def file_field(object_name, method, options = {}) | |
175 | InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("file", options) | |
end | ||
# Returns a textarea opening and closing tag set tailored for accessing a specified attribute (identified by +method+) | ||
... | ... | |
# <textarea cols="20" rows="40" id="post_body" name="post[body]"> | ||
# #{@post.body} | ||
# </textarea> | ||
103 | | |
104 | | |
187 | def text_area(object_name, method, options = {}) | |
188 | InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_text_area_tag(options) | |
end | ||
# Returns a checkbox tag tailored for accessing a specified attribute (identified by +method+) on an object | ||
... | ... | |
# check_box("puppy", "gooddog", {}, "yes", "no") | ||
# <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" /> | ||
# <input name="puppy[gooddog]" type="hidden" value="no" /> | ||
123 | | |
124 | | |
207 | def check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0") | |
208 | InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_check_box_tag(options, checked_value, unchecked_value) | |
end | ||
# Returns a radio button tag for accessing a specified attribute (identified by +method+) on an object | ||
... | ... | |
# <input type="radio" id="post_category" name="post[category]" value="rails" checked="checked" /> | ||
# <input type="radio" id="post_category" name="post[category]" value="java" /> | ||
# | ||
137 | | |
138 | | |
221 | def radio_button(object_name, method, tag_value, options = {}) | |
222 | InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_radio_button_tag(tag_value, options) | |
end | ||
end | ||
... | ... | |
DEFAULT_TEXT_AREA_OPTIONS = { "cols" => 40, "rows" => 20 }.freeze unless const_defined?(:DEFAULT_TEXT_AREA_OPTIONS) | ||
DEFAULT_DATE_OPTIONS = { :discard_type => true }.freeze unless const_defined?(:DEFAULT_DATE_OPTIONS) | ||
152 | | |
153 | | |
236 | def initialize(object_name, method_name, template_object, local_binding = nil, object = nil) | |
237 | @object_name, @method_name = object_name.to_s.dup, method_name.to_s.dup | |
@template_object, @local_binding = template_object, local_binding | ||
239 | @object = object | |
if @object_name.sub!(/\[\]$/,"") | ||
@auto_index = @template_object.instance_variable_get("@#{Regexp.last_match.pre_match}").id_before_type_cast | ||
end | ||
... | ... | |
def to_text_area_tag(options = {}) | ||
options = DEFAULT_TEXT_AREA_OPTIONS.merge(options.stringify_keys) | ||
add_default_name_and_id(options) | ||
189 | | |
274 | content_tag("textarea", html_escape(options.delete('value') || value_before_type_cast), options) | |
end | ||
def to_check_box_tag(options = {}, checked_value = "1", unchecked_value = "0") | ||
... | ... | |
end | ||
def object | ||
243 | | |
328 | @object || @template_object.instance_variable_get("@#{@object_name}") | |
end | ||
def value | ||
247 | | |
332 | unless object.nil? | |
333 | object.send(@method_name) | |
334 | end | |
end | ||
def value_before_type_cast | ||
... | ... | |
"#{@object_name}_#{index}_#{@method_name}" | ||
end | ||
end | ||
376 | ||
377 | class FormBuilder #:nodoc: | |
378 | # The methods which wrap a form helper call. | |
379 | class_inheritable_accessor :field_helpers | |
380 | self.field_helpers = (FormHelper.instance_methods - ['form_for']) | |
381 | ||
382 | attr_accessor :object_name, :object | |
383 | ||
384 | def initialize(object_name, object, template, options, proc) | |
385 | @object_name, @object, @template, @options, @proc = object_name, object, template, options, proc | |
386 | end | |
387 | ||
388 | (field_helpers - %w(check_box radio_button)).each do |selector| | |
389 | src = <<-end_src | |
390 | def #{selector}(method, options = {}) | |
391 | @template.send(#{selector.inspect}, @object_name, method, options.merge(:object => @object)) | |
392 | end | |
393 | end_src | |
394 | class_eval src, __FILE__, __LINE__ | |
395 | end | |
396 | ||
397 | def check_box(method, options = {}, checked_value = "1", unchecked_value = "0") | |
398 | @template.check_box(@object_name, method, options.merge(:object => @object), checked_value, unchecked_value) | |
399 | end | |
400 | ||
401 | def radio_button(method, tag_value, options = {}) | |
402 | @template.radio_button(@object_name, method, tag_value, options.merge(:object => @object)) | |
403 | end | |
404 | end | |
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/form_options_helper.rb:
prev. | current | |
# | ||
# could become: | ||
# | ||
50 | | |
50 | # <select name="post[person_id]"> | |
# <option></option> | ||
# <option value="1" selected="selected">David</option> | ||
# <option value="2">Sam</option> | ||
... | ... | |
# to the database. Instead, a second model object is created when the create request is received. | ||
# This allows the user to submit a form page more than once with the expected results of creating multiple records. | ||
# In addition, this allows a single partial to be used to generate form inputs for both edit and create forms. | ||
62 | # | |
63 | # By default, post.person_id is the selected option. Specify :selected => value to use a different selection | |
64 | # or :selected => nil to leave all options unselected. | |
def select(object, method, choices, options = {}, html_options = {}) | ||
63 | | |
66 | InstanceTag.new(object, method, self, nil, options.delete(:object)).to_select_tag(choices, options, html_options) | |
end | ||
# Return select and option tags for the given object and method using options_from_collection_for_select to generate the list of option tags. | ||
def collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {}) | ||
68 | | |
71 | InstanceTag.new(object, method, self, nil, options.delete(:object)).to_collection_select_tag(collection, value_method, text_method, options, html_options) | |
end | ||
# Return select and option tags for the given object and method, using country_options_for_select to generate the list of option tags. | ||
def country_select(object, method, priority_countries = nil, options = {}, html_options = {}) | ||
73 | | |
76 | InstanceTag.new(object, method, self, nil, options.delete(:object)).to_country_select_tag(priority_countries, options, html_options) | |
end | ||
# Return select and option tags for the given object and method, using | ||
... | ... | |
# zone model object. (See #time_zone_options_for_select for more | ||
# information.) | ||
def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {}) | ||
85 | | |
88 | InstanceTag.new(object, method, self, nil, options.delete(:object)).to_time_zone_select_tag(priority_zones, options, html_options) | |
end | ||
# Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container | ||
... | ... | |
end | ||
# Returns a string of option tags for pretty much any time zone in the | ||
212 | | |
215 | # world. Supply a TimeZone name as +selected+ to have it marked as the | |
# selected option tag. You can also supply an array of TimeZone objects | ||
# as +priority_zones+, so that they will be listed above the rest of the | ||
# (long) list. (You can use TimeZone.us_zones as a convenience for | ||
... | ... | |
def to_select_tag(choices, options, html_options) | ||
html_options = html_options.stringify_keys | ||
add_default_name_and_id(html_options) | ||
299 | | |
302 | selected_value = options.has_key?(:selected) ? options[:selected] : value | |
303 | content_tag("select", add_options(options_for_select(choices, selected_value), options, value), html_options) | |
end | ||
def to_collection_select_tag(collection, value_method, text_method, options, html_options) | ||
... | ... | |
end | ||
end | ||
end | ||
342 | ||
343 | class FormBuilder | |
344 | def select(method, choices, options = {}, html_options = {}) | |
345 | @template.select(@object_name, method, choices, options.merge(:object => @object), html_options) | |
346 | end | |
347 | ||
348 | def collection_select(method, collection, value_method, text_method, options = {}, html_options = {}) | |
349 | @template.collection_select(@object_name, method, collection, value_method, text_method, options.merge(:object => @object), html_options) | |
350 | end | |
351 | ||
352 | def country_select(method, priority_countries = nil, options = {}, html_options = {}) | |
353 | @template.country_select(@object_name, method, priority_countries, options.merge(:object => @object), html_options) | |
354 | end | |
355 | ||
356 | def time_zone_select(method, priority_zones = nil, options = {}, html_options = {}) | |
357 | @template.time_zone_select(@object_name, method, priority_zones, options.merge(:object => @object), html_options) | |
358 | end | |
359 | end | |
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/form_tag_helper.rb:
prev. | current | |
# Options: | ||
# * <tt>:multipart</tt> - If set to true, the enctype is set to "multipart/form-data". | ||
# * <tt>:method</tt> - The method to use when submitting the form, usually either "get" or "post". | ||
18 | | |
18 | def form_tag(url_for_options = {}, options = {}, *parameters_for_url, &proc) | |
html_options = { "method" => "post" }.merge(options.stringify_keys) | ||
20 | ||
21 | | |
22 | | |
23 | | |
24 | | |
25 | ||
20 | html_options["enctype"] = "multipart/form-data" if html_options.delete("multipart") | |
html_options["action"] = url_for(url_for_options, *parameters_for_url) | ||
27 | | |
22 | tag :form, html_options, true | |
end | ||
alias_method :start_form_tag, :form_tag | ||
... | ... | |
# Options: | ||
# * <tt>:multiple</tt> - If set to true the selection will allow multiple choices. | ||
def select_tag(name, option_tags = nil, options = {}) | ||
50 | | |
45 | content_tag :select, option_tags, { "name" => name, "id" => name }.update(options.stringify_keys) | |
end | ||
# Creates a standard text field. | ||
... | ... | |
# | ||
# A hash of standard HTML options for the tag. | ||
def text_field_tag(name, value = nil, options = {}) | ||
62 | | |
57 | tag :input, { "type" => "text", "name" => name, "id" => name, "value" => value }.update(options.stringify_keys) | |
end | ||
# Creates a hidden field. | ||
... | ... | |
# # Outputs <textarea name="body" id="body" cols="25" rows="10"></textarea> | ||
# <%= text_area_tag "body", nil, :size => "25x10" %> | ||
def text_area_tag(name, content = nil, options = {}) | ||
100 | | |
101 | | |
102 | | |
103 | | |
95 | options.stringify_keys! | |
96 | ||
97 | if size = options.delete("size") | |
98 | options["cols"], options["rows"] = size.split("x") | |
end | ||
106 | | |
101 | content_tag :textarea, content, { "name" => name, "id" => name }.update(options.stringify_keys) | |
end | ||
# Creates a check box. | ||
def check_box_tag(name, value = "1", checked = false, options = {}) | ||
html_options = { "type" => "checkbox", "name" => name, "id" => name, "value" => value }.update(options.stringify_keys) | ||
html_options["checked"] = "checked" if checked | ||
113 | | |
108 | tag :input, html_options | |
end | ||
# Creates a radio button. | ||
def radio_button_tag(name, value, checked = false, options = {}) | ||
html_options = { "type" => "radio", "name" => name, "id" => name, "value" => value }.update(options.stringify_keys) | ||
html_options["checked"] = "checked" if checked | ||
120 | | |
115 | tag :input, html_options | |
end | ||
123 | | |
118 | # Creates a submit button with the text <tt>value</tt> as the caption. If options contains a pair with the key of "disable_with", | |
119 | # then the value will be used to rename a disabled version of the submit button. | |
def submit_tag(value = "Save changes", options = {}) | ||
125 | | |
121 | options.stringify_keys! | |
122 | ||
123 | if disable_with = options.delete("disable_with") | |
124 | options["onclick"] = "this.disabled=true;this.value='#{disable_with}';this.form.submit();#{options["onclick"]}" | |
125 | end | |
126 | ||
127 | tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options.stringify_keys) | |
end | ||
# Displays an image which when clicked will submit the form. | ||
# | ||
# <tt>source</tt> is passed to AssetTagHelper#image_path | ||
def image_submit_tag(source, options = {}) | ||
132 | | |
134 | tag :input, { "type" => "image", "src" => image_path(source) }.update(options.stringify_keys) | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/java_script_macros_helper.rb:
prev. | current | |
# | ||
# A form is automatically created and displayed when the user clicks the element, | ||
# something like this: | ||
15 | | |
16 | | |
17 | | |
18 | | |
19 | | |
15 | # <form id="myElement-in-place-edit-form" target="specified url"> | |
16 | # <input name="value" text="The content of myElement"/> | |
17 | # <input type="submit" value="ok"/> | |
18 | # <a onclick="javascript to cancel the editing">cancel</a> | |
19 | # </form> | |
# | ||
# The form is serialized and sent to the server using an AJAX call, the action on | ||
# the server should process the value and return the updated value in the body of | ||
... | ... | |
# | ||
# Addtional +options+ are: | ||
# <tt>:rows</tt>:: Number of rows (more than 1 will use a TEXTAREA) | ||
32 | # <tt>:cols</tt>:: Number of characters the text input should span (works for both INPUT and TEXTAREA) | |
33 | # <tt>:size</tt>:: Synonym for :cols when using a single line text input. | |
# <tt>:cancel_text</tt>:: The text on the cancel link. (default: "cancel") | ||
# <tt>:save_text</tt>:: The text on the save link. (default: "ok") | ||
36 | # <tt>:loading_text</tt>:: The text to display when submitting to the server (default: "Saving...") | |
# <tt>:external_control</tt>:: The id of an external control used to enter edit mode. | ||
38 | # <tt>:load_text_url</tt>:: URL where initial value of editor (content) is retrieved. | |
# <tt>:options</tt>:: Pass through options to the AJAX call (see prototype's Ajax.Updater) | ||
# <tt>:with</tt>:: JavaScript snippet that should return what is to be sent | ||
# in the AJAX call, +form+ is an implicit parameter | ||
42 | # <tt>:script</tt>:: Instructs the in-place editor to evaluate the remote JavaScript response (default: false) | |
def in_place_editor(field_id, options = {}) | ||
function = "new Ajax.InPlaceEditor(" | ||
function << "'#{field_id}', " | ||
... | ... | |
js_options = {} | ||
js_options['cancelText'] = %('#{options[:cancel_text]}') if options[:cancel_text] | ||
js_options['okText'] = %('#{options[:save_text]}') if options[:save_text] | ||
51 | js_options['loadingText'] = %('#{options[:loading_text]}') if options[:loading_text] | |
js_options['rows'] = options[:rows] if options[:rows] | ||
47 | | |
53 | js_options['cols'] = options[:cols] if options[:cols] | |
54 | js_options['size'] = options[:size] if options[:size] | |
55 | js_options['externalControl'] = "'#{options[:external_control]}'" if options[:external_control] | |
56 | js_options['loadTextURL'] = "'#{url_for(options[:load_text_url])}'" if options[:load_text_url] | |
js_options['ajaxOptions'] = options[:options] if options[:options] | ||
58 | js_options['evalScripts'] = options[:script] if options[:script] | |
js_options['callback'] = "function(form) { return #{options[:with]} }" if options[:with] | ||
function << (', ' + options_for_javascript(js_options)) unless js_options.empty? | ||
... | ... | |
# or nothing if no entries should be displayed for autocompletion. | ||
# | ||
# You'll probably want to turn the browser's built-in autocompletion off, | ||
75 | | |
85 | # so be sure to include a autocomplete="off" attribute with your text | |
# input field. | ||
87 | # | |
88 | # The autocompleter object is assigned to a Javascript variable named <tt>field_id</tt>_auto_completer. | |
89 | # This object is useful if you for example want to trigger the auto-complete suggestions through | |
90 | # other means than user input (for that specific case, call the <tt>activate</tt> method on that object). | |
# | ||
# Required +options+ are: | ||
# <tt>:url</tt>:: URL to call for autocompletion results | ||
... | ... | |
# <tt>:with</tt>:: A JavaScript expression specifying the | ||
# parameters for the XMLHttpRequest. This defaults | ||
# to 'fieldname=value'. | ||
104 | # <tt>:frequency</tt>:: Determines the time to wait after the last keystroke | |
105 | # for the AJAX request to be initiated. | |
# <tt>:indicator</tt>:: Specifies the DOM ID of an element which will be | ||
# displayed while autocomplete is running. | ||
# <tt>:tokens</tt>:: A string or an array of strings containing | ||
... | ... | |
# innerHTML is replaced. | ||
# <tt>:on_show</tt>:: Like on_hide, only now the expression is called | ||
# then the div is shown. | ||
124 | # <tt>:after_update_element</tt>:: A Javascript expression that is called when the | |
125 | # user has selected one of the proposed values. | |
126 | # The expression should take two variables: element and value. | |
127 | # Element is a DOM element for the field, value | |
128 | # is the value selected by the user. | |
129 | # <tt>:select</tt>:: Pick the class of the element from which the value for | |
130 | # insertion should be extracted. If this is not specified, | |
131 | # the entire element is used. | |
def auto_complete_field(field_id, options = {}) | ||
109 | | |
133 | function = "var #{field_id}_auto_completer = new Ajax.Autocompleter(" | |
function << "'#{field_id}', " | ||
function << "'" + (options[:update] || "#{field_id}_auto_complete") + "', " | ||
function << "'#{url_for(options[:url])}'" | ||
... | ... | |
js_options[:tokens] = array_or_string_for_javascript(options[:tokens]) if options[:tokens] | ||
js_options[:callback] = "function(element, value) { return #{options[:with]} }" if options[:with] | ||
js_options[:indicator] = "'#{options[:indicator]}'" if options[:indicator] | ||
118 | | |
142 | js_options[:select] = "'#{options[:select]}'" if options[:select] | |
143 | js_options[:frequency] = "#{options[:frequency]}" if options[:frequency] | |
144 | ||
145 | { :after_update_element => :afterUpdateElement, | |
146 | :on_show => :onShow, :on_hide => :onHide, :min_chars => :minChars }.each do |k,v| | |
js_options[v] = options[k] if options[k] | ||
end | ||
149 | ||
function << (', ' + options_for_javascript(js_options) + ')') | ||
javascript_tag(function) |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/javascript_helper.rb:
prev. | current | |
module ActionView | ||
module Helpers | ||
5 | | |
6 | | |
7 | | |
8 | | |
5 | # Provides functionality for working with JavaScript in your views. | |
6 | # | |
7 | # == Ajax, controls and visual effects | |
8 | # | |
9 | # * For information on using Ajax, see | |
10 | # ActionView::Helpers::PrototypeHelper. | |
11 | # * For information on using controls and visual effects, see | |
12 | # ActionView::Helpers::ScriptaculousHelper. | |
# | ||
10 | | |
11 | | |
14 | # == Including the JavaScript libraries into your pages | |
# | ||
13 | | |
14 | | |
15 | | |
16 | | |
17 | | |
18 | | |
19 | | |
20 | | |
21 | | |
16 | # Rails includes the Prototype JavaScript framework and the Scriptaculous | |
17 | # JavaScript controls and visual effects library. If you wish to use | |
18 | # these libraries and their helpers (ActionView::Helpers::PrototypeHelper | |
19 | # and ActionView::Helpers::ScriptaculousHelper), you must do one of the | |
20 | # following: | |
# | ||
23 | | |
22 | # * Use <tt><%= javascript_include_tag :defaults %></tt> in the HEAD | |
23 | # section of your page (recommended): This function will return | |
24 | # references to the JavaScript files created by the +rails+ command in | |
25 | # your <tt>public/javascripts</tt> directory. Using it is recommended as | |
26 | # the browser can then cache the libraries instead of fetching all the | |
27 | # functions anew on every request. | |
28 | # * Use <tt><%= javascript_include_tag 'prototype' %></tt>: As above, but | |
29 | # will only include the Prototype core library, which means you are able | |
30 | # to use all basic AJAX functionality. For the Scriptaculous-based | |
31 | # JavaScript helpers, like visual effects, autocompletion, drag and drop | |
32 | # and so on, you should use the method described above. | |
33 | # * Use <tt><%= define_javascript_functions %></tt>: this will copy all the | |
34 | # JavaScript support functions within a single script block. Not | |
35 | # recommended. | |
# | ||
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
30 | | |
31 | | |
32 | | |
37 | # For documentation on +javascript_include_tag+ see | |
38 | # ActionView::Helpers::AssetTagHelper. | |
39 | module JavaScriptHelper | |
40 | unless const_defined? :JAVASCRIPT_PATH | |
JAVASCRIPT_PATH = File.join(File.dirname(__FILE__), 'javascripts') | ||
end | ||
36 | | |
44 | # Returns a link that'll trigger a JavaScript +function+ using the | |
# onclick handler and return false after the fact. | ||
# | ||
# Examples: | ||
# link_to_function "Greeting", "alert('Hello world!')" | ||
# link_to_function(image_tag("delete"), "if confirm('Really?'){ do_delete(); }") | ||
def link_to_function(name, function, html_options = {}) | ||
51 | html_options.symbolize_keys! | |
content_tag( | ||
"a", name, | ||
45 | | |
54 | html_options.merge({ | |
55 | :href => html_options[:href] || "#", | |
56 | :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function}; return false;" | |
57 | }) | |
) | ||
end | ||
48 | ||
49 | | |
50 | | |
51 | | |
52 | | |
53 | | |
54 | | |
55 | | |
56 | | |
57 | | |
58 | | |
59 | | |
60 | | |
61 | | |
62 | | |
63 | | |
64 | | |
65 | | |
66 | | |
67 | | |
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
73 | | |
74 | | |
75 | | |
76 | | |
77 | | |
78 | | |
79 | | |
80 | | |
81 | | |
82 | | |
83 | | |
84 | | |
85 | | |
86 | | |
87 | | |
88 | | |
89 | | |
90 | | |
91 | | |
92 | | |
93 | | |
94 | | |
95 | | |
96 | | |
97 | | |
98 | | |
99 | | |
100 | | |
101 | | |
102 | | |
103 | | |
104 | | |
105 | | |
106 | | |
107 | | |
108 | | |
109 | | |
110 | | |
111 | | |
112 | | |
113 | | |
114 | | |
115 | | |
116 | | |
117 | | |
118 | | |
119 | | |
120 | | |
121 | | |
122 | | |
123 | | |
124 | | |
125 | | |
126 | | |
127 | | |
128 | | |
129 | | |
130 | | |
131 | | |
132 | | |
133 | | |
134 | | |
135 | | |
136 | | |
137 | ||
138 | | |
139 | | |
140 | | |
141 | | |
142 | | |
143 | | |
144 | | |
145 | | |
146 | ||
147 | | |
148 | | |
149 | | |
150 | | |
151 | | |
152 | | |
153 | | |
154 | | |
155 | | |
156 | | |
157 | | |
158 | | |
159 | | |
160 | ||
161 | | |
162 | | |
163 | | |
164 | | |
165 | ||
166 | | |
167 | | |
169 | | |
170 | | |
171 | | |
172 | | |
173 | ||
174 | | |
175 | | |
176 | | |
177 | | |
178 | | |
179 | ||
180 | | |
181 | | |
182 | | |
183 | | |
61 | # Returns a link that'll trigger a JavaScript +function+ using the | |
62 | # onclick handler. | |
# | ||
185 | | |
186 | | |
187 | | |
188 | | |
# Examples: | ||
190 | | |
191 | | |
192 | | |
193 | | |
194 | | |
195 | | |
196 | | |
197 | | |
198 | | |
199 | | |
200 | | |
201 | | |
202 | | |
203 | | |
204 | | |
205 | | |
206 | | |
207 | | |
208 | | |
209 | | |
210 | | |
211 | | |
212 | | |
213 | | |
214 | | |
215 | | |
216 | | |
217 | | |
218 | | |
219 | | |
220 | | |
221 | | |
222 | | |
223 | | |
224 | | |
225 | | |
226 | | |
227 | | |
228 | | |
229 | | |
230 | | |
231 | | |
232 | | |
233 | | |
234 | | |
235 | | |
236 | | |
237 | | |
238 | | |
239 | | |
240 | | |
241 | | |
242 | | |
243 | | |
244 | | |
245 | | |
65 | # button_to_function "Greeting", "alert('Hello world!')" | |
66 | # button_to_function "Delete", "if confirm('Really?'){ do_delete(); }") | |
67 | def button_to_function(name, function, html_options = {}) | |
68 | html_options.symbolize_keys! | |
69 | tag(:input, html_options.merge({ | |
70 | :type => "button", :value => name, | |
71 | :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};" | |
72 | })) | |
end | ||
247 | | |
248 | | |
249 | | |
250 | | |
251 | | |
252 | | |
254 | | |
255 | | |
256 | | |
257 | | |
258 | | |
259 | | |
260 | | |
261 | | |
262 | | |
263 | | |
264 | ||
265 | | |
266 | | |
267 | | |
268 | | |
269 | | |
270 | | |
271 | | |
272 | | |
273 | | |
274 | ||
275 | | |
276 | | |
277 | | |
278 | ||
279 | | |
280 | | |
281 | ||
282 | | |
283 | | |
284 | | |
285 | | |
286 | ||
287 | | |
288 | | |
289 | ||
# Includes the Action Pack JavaScript libraries inside a single <script> | ||
# tag. The function first includes prototype.js and then its core extensions, | ||
# (determined by filenames starting with "prototype"). | ||
293 | | |
78 | # Afterwards, any additional scripts will be included in undefined order. | |
# | ||
# Note: The recommended approach is to copy the contents of | ||
# lib/action_view/helpers/javascripts/ into your application's | ||
... | ... | |
javascript << '</script>' | ||
end | ||
315 | | |
316 | | |
317 | | |
318 | | |
319 | | |
320 | | |
321 | | |
322 | | |
323 | | |
324 | | |
325 | | |
326 | | |
327 | | |
328 | | |
329 | | |
330 | | |
331 | | |
332 | | |
333 | | |
334 | | |
335 | | |
336 | | |
337 | | |
338 | | |
339 | | |
340 | | |
341 | | |
342 | | |
343 | | |
344 | | |
345 | | |
346 | | |
347 | | |
348 | | |
349 | | |
350 | | |
351 | | |
352 | | |
353 | | |
354 | | |
355 | | |
356 | | |
357 | | |
358 | | |
359 | | |
360 | | |
361 | | |
362 | | |
363 | | |
364 | | |
365 | | |
366 | | |
367 | | |
368 | | |
369 | | |
370 | | |
371 | | |
372 | | |
373 | | |
374 | | |
375 | | |
376 | | |
377 | | |
378 | | |
379 | | |
380 | | |
381 | | |
382 | | |
383 | | |
384 | | |
385 | | |
386 | | |
387 | | |
388 | | |
389 | | |
390 | | |
391 | | |
392 | | |
393 | | |
394 | | |
395 | | |
396 | | |
397 | | |
398 | | |
399 | | |
400 | | |
401 | | |
402 | | |
403 | | |
404 | | |
405 | | |
406 | | |
407 | | |
408 | | |
409 | | |
410 | | |
411 | | |
412 | | |
413 | | |
414 | | |
415 | | |
416 | | |
417 | | |
418 | | |
419 | | |
420 | | |
421 | | |
422 | | |
423 | | |
424 | | |
425 | | |
426 | | |
427 | | |
428 | | |
429 | | |
430 | | |
431 | | |
432 | | |
433 | | |
434 | | |
435 | | |
436 | | |
437 | | |
438 | | |
439 | | |
440 | | |
441 | | |
442 | | |
443 | | |
444 | | |
445 | | |
446 | | |
447 | | |
448 | | |
449 | | |
450 | ||
# Escape carrier returns and single and double quotes for JavaScript segments. | ||
def escape_javascript(javascript) | ||
(javascript || '').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" } | ||
... | ... | |
"\n//#{cdata_section("\n#{content}\n//")}\n" | ||
end | ||
466 | | |
115 | protected | |
def options_for_javascript(options) | ||
'{' + options.map {|k, v| "#{k}:#{v}"}.sort.join(', ') + '}' | ||
end | ||
... | ... | |
end | ||
js_option | ||
end | ||
479 | | |
480 | | |
481 | | |
482 | | |
483 | | |
484 | | |
485 | | |
486 | | |
487 | ||
488 | | |
489 | | |
490 | | |
491 | | |
492 | | |
493 | | |
494 | | |
495 | | |
496 | | |
497 | | |
498 | ||
499 | | |
500 | | |
501 | | |
502 | | |
503 | | |
504 | | |
505 | | |
506 | | |
507 | | |
508 | | |
509 | | |
510 | | |
511 | | |
512 | | |
513 | | |
514 | | |
515 | | |
516 | | |
517 | | |
518 | | |
519 | | |
520 | | |
521 | | |
522 | | |
523 | | |
end | ||
JavascriptHelper = JavaScriptHelper unless const_defined? :JavascriptHelper |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/javascripts/controls.js:
prev. | current | |
return; | ||
} | ||
else | ||
144 | | |
145 | | |
144 | if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || | |
145 | (navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return; | |
this.changed = true; | ||
this.hasFocus = true; | ||
... | ... | |
setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); | ||
}, | ||
155 | activate: function() { | |
156 | this.changed = false; | |
157 | this.hasFocus = true; | |
158 | this.getUpdatedChoices(); | |
159 | }, | |
160 | ||
onHover: function(event) { | ||
var element = Event.findElement(event, 'LI'); | ||
if(this.index != element.autocompleteIndex) | ||
... | ... | |
this.options.updateElement(selectedElement); | ||
return; | ||
} | ||
224 | ||
225 | | |
230 | var value = ''; | |
231 | if (this.options.select) { | |
232 | var nodes = document.getElementsByClassName(this.options.select, selectedElement) || []; | |
233 | if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); | |
234 | } else | |
235 | value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); | |
236 | ||
var lastTokenPos = this.findLastToken(); | ||
if (lastTokenPos != -1) { | ||
var newValue = this.element.value.substr(0, lastTokenPos + 1); | ||
... | ... | |
Ajax.Autocompleter = Class.create(); | ||
Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), { | ||
initialize: function(element, update, url, options) { | ||
308 | | |
319 | this.baseInitialize(element, update, options); | |
this.options.asynchronous = true; | ||
this.options.onComplete = this.onComplete.bind(this); | ||
this.options.defaultParams = this.options.parameters || null; | ||
... | ... | |
this.element = $(element); | ||
this.options = Object.extend({ | ||
462 | okButton: true, | |
okText: "ok", | ||
464 | cancelLink: true, | |
cancelText: "cancel", | ||
savingText: "Saving...", | ||
clickToEditText: "Click to edit", | ||
... | ... | |
formClassName: 'inplaceeditor-form', | ||
highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor, | ||
highlightendcolor: "#FFFFFF", | ||
473 | | |
474 | | |
486 | externalControl: null, | |
487 | submitOnBlur: false, | |
488 | ajaxOptions: {}, | |
489 | evalScripts: false | |
}, options || {}); | ||
if(!this.options.formId && this.element.id) { | ||
... | ... | |
this.form.appendChild(br); | ||
} | ||
539 | | |
540 | | |
541 | | |
542 | | |
554 | if (this.options.okButton) { | |
555 | okButton = document.createElement("input"); | |
556 | okButton.type = "submit"; | |
557 | okButton.value = this.options.okText; | |
558 | okButton.className = 'editor_ok_button'; | |
559 | this.form.appendChild(okButton); | |
560 | } | |
544 | | |
545 | | |
546 | | |
547 | | |
548 | | |
562 | if (this.options.cancelLink) { | |
563 | cancelLink = document.createElement("a"); | |
564 | cancelLink.href = "#"; | |
565 | cancelLink.appendChild(document.createTextNode(this.options.cancelText)); | |
566 | cancelLink.onclick = this.onclickCancel.bind(this); | |
567 | cancelLink.className = 'editor_cancel'; | |
568 | this.form.appendChild(cancelLink); | |
569 | } | |
}, | ||
hasHTMLLineBreaks: function(string) { | ||
if (!this.options.handleLineBreaks) return false; | ||
... | ... | |
} else { | ||
text = this.getText(); | ||
} | ||
585 | ||
586 | var obj = this; | |
if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) { | ||
this.options.textarea = false; | ||
var textField = document.createElement("input"); | ||
591 | textField.obj = this; | |
textField.type = "text"; | ||
textField.name = "value"; | ||
textField.value = text; | ||
textField.style.backgroundColor = this.options.highlightcolor; | ||
596 | textField.className = 'editor_field'; | |
var size = this.options.size || this.options.cols || 0; | ||
if (size != 0) textField.size = size; | ||
599 | if (this.options.submitOnBlur) | |
600 | textField.onblur = this.onSubmit.bind(this); | |
this.editField = textField; | ||
} else { | ||
this.options.textarea = true; | ||
var textArea = document.createElement("textarea"); | ||
605 | textArea.obj = this; | |
textArea.name = "value"; | ||
textArea.value = this.convertHTMLLineBreaks(text); | ||
textArea.rows = this.options.rows; | ||
textArea.cols = this.options.cols || 40; | ||
610 | textArea.className = 'editor_field'; | |
611 | if (this.options.submitOnBlur) | |
612 | textArea.onblur = this.onSubmit.bind(this); | |
this.editField = textArea; | ||
} | ||
... | ... | |
// to be displayed indefinitely | ||
this.onLoading(); | ||
632 | | |
633 | | |
634 | | |
635 | | |
636 | | |
637 | | |
638 | | |
639 | | |
640 | | |
641 | | |
642 | | |
643 | | |
644 | | |
663 | if (this.options.evalScripts) { | |
664 | new Ajax.Request( | |
665 | this.url, Object.extend({ | |
666 | parameters: this.options.callback(form, value), | |
667 | onComplete: this.onComplete.bind(this), | |
668 | onFailure: this.onFailure.bind(this), | |
669 | asynchronous:true, | |
670 | evalScripts:true | |
671 | }, this.options.ajaxOptions)); | |
672 | } else { | |
673 | new Ajax.Updater( | |
674 | { success: this.element, | |
675 | // don't update on failure (this could be an option) | |
676 | failure: null }, | |
677 | this.url, Object.extend({ | |
678 | parameters: this.options.callback(form, value), | |
679 | onComplete: this.onComplete.bind(this), | |
680 | onFailure: this.onFailure.bind(this) | |
681 | }, this.options.ajaxOptions)); | |
682 | } | |
// stop the event to avoid a page refresh in Safari | ||
if (arguments.length > 1) { | ||
Event.stop(arguments[0]); | ||
... | ... | |
} | ||
}; | ||
764 | Ajax.InPlaceCollectionEditor = Class.create(); | |
765 | Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype); | |
766 | Object.extend(Ajax.InPlaceCollectionEditor.prototype, { | |
767 | createEditField: function() { | |
768 | if (!this.cached_selectTag) { | |
769 | var selectTag = document.createElement("select"); | |
770 | var collection = this.options.collection || []; | |
771 | var optionTag; | |
772 | collection.each(function(e,i) { | |
773 | optionTag = document.createElement("option"); | |
774 | optionTag.value = (e instanceof Array) ? e[0] : e; | |
775 | if(this.options.value==optionTag.value) optionTag.selected = true; | |
776 | optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e)); | |
777 | selectTag.appendChild(optionTag); | |
778 | }.bind(this)); | |
779 | this.cached_selectTag = selectTag; | |
780 | } | |
781 | ||
782 | this.editField = this.cached_selectTag; | |
783 | if(this.options.loadTextURL) this.loadExternalText(); | |
784 | this.form.appendChild(this.editField); | |
785 | this.options.callback = function(form, value) { | |
786 | return "value=" + encodeURIComponent(value); | |
787 | } | |
788 | } | |
789 | }); | |
790 | ||
// Delayed observer, like Form.Element.Observer, | ||
// but waits for delay after last key input | ||
// Ideal for live-search fields | ||
... | ... | |
this.timer = null; | ||
this.callback(this.element, $F(this.element)); | ||
} | ||
750 | ||
816 | }; |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/javascripts/dragdrop.js:
prev. | current | |
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) | ||
2 | // (c) 2005 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) | |
// | ||
// See scriptaculous.js for full license. | ||
... | ... | |
element = $(element); | ||
var options = Object.extend({ | ||
greedy: true, | ||
18 | | |
19 | hoverclass: null, | |
20 | tree: false | |
}, arguments[1] || {}); | ||
// cache containers | ||
... | ... | |
this.drops.push(options); | ||
}, | ||
42 | ||
43 | findDeepestChild: function(drops) { | |
44 | deepest = drops[0]; | |
45 | ||
46 | for (i = 1; i < drops.length; ++i) | |
47 | if (Element.isParent(drops[i].element, deepest.element)) | |
48 | deepest = drops[i]; | |
49 | ||
50 | return deepest; | |
51 | }, | |
isContained: function(element, drop) { | ||
42 | | |
43 | | |
54 | var containmentNode; | |
55 | if(drop.tree) { | |
56 | containmentNode = element.treeNode; | |
57 | } else { | |
58 | containmentNode = element.parentNode; | |
59 | } | |
60 | return drop._containers.detect(function(c) { return containmentNode == c }); | |
}, | ||
45 | ||
62 | ||
isAffected: function(point, element, drop) { | ||
return ( | ||
(drop.element!=element) && | ||
... | ... | |
show: function(point, element) { | ||
if(!this.drops.length) return; | ||
88 | var affected = []; | |
if(this.last_active) this.deactivate(this.last_active); | ||
this.drops.each( function(drop) { | ||
74 | | |
75 | | |
76 | | |
77 | | |
78 | | |
79 | | |
80 | | |
81 | | |
92 | if(Droppables.isAffected(point, element, drop)) | |
93 | affected.push(drop); | |
}); | ||
95 | ||
96 | if(affected.length>0) { | |
97 | drop = Droppables.findDeepestChild(affected); | |
98 | Position.within(drop.element, point[0], point[1]); | |
99 | if(drop.onHover) | |
100 | drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); | |
101 | ||
102 | Droppables.activate(drop); | |
103 | } | |
}, | ||
fire: function(event, element) { | ||
... | ... | |
this.activeDraggable = draggable; | ||
}, | ||
131 | | |
152 | deactivate: function() { | |
this.activeDraggable = null; | ||
}, | ||
... | ... | |
if(!this.activeDraggable) return; | ||
this._lastPointer = null; | ||
this.activeDraggable.endDrag(event); | ||
170 | this.activeDraggable = null; | |
}, | ||
keyPress: function(event) { | ||
... | ... | |
}, | ||
reverteffect: function(element, top_offset, left_offset) { | ||
var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; | ||
194 | | |
216 | element._revert = new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur}); | |
}, | ||
endeffect: function(element) { | ||
new Effect.Opacity(element, {duration:0.2, from:0.7, to:1.0}); | ||
}, | ||
zindex: 1000, | ||
revert: false, | ||
223 | scroll: false, | |
224 | scrollSensitivity: 20, | |
225 | scrollSpeed: 15, | |
snap: false // false, or xy or [x,y] or function(x,y){ return [x,y] } | ||
}, arguments[1] || {}); | ||
this.element = $(element); | ||
206 | | |
207 | | |
231 | if(options.handle && (typeof options.handle == 'string')) { | |
232 | var h = Element.childrenWithClassName(this.element, options.handle, true); | |
233 | if(h.length>0) this.handle = h[0]; | |
234 | } | |
if(!this.handle) this.handle = $(options.handle); | ||
if(!this.handle) this.handle = this.element; | ||
237 | ||
238 | if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) | |
239 | options.scroll = $(options.scroll); | |
Element.makePositioned(this.element); // fix IE | ||
... | ... | |
currentDelta: function() { | ||
return([ | ||
230 | | |
231 | | |
260 | parseInt(Element.getStyle(this.element,'left') || '0'), | |
261 | parseInt(Element.getStyle(this.element,'top') || '0')]); | |
}, | ||
initDrag: function(event) { | ||
... | ... | |
if(src.tagName && ( | ||
src.tagName=='INPUT' || | ||
src.tagName=='SELECT' || | ||
271 | src.tagName=='OPTION' || | |
src.tagName=='BUTTON' || | ||
src.tagName=='TEXTAREA')) return; | ||
... | ... | |
this.element.parentNode.insertBefore(this._clone, this.element); | ||
} | ||
303 | if(this.options.scroll) { | |
304 | if (this.options.scroll == window) { | |
305 | var where = this._getWindowScroll(this.options.scroll); | |
306 | this.originalScrollLeft = where.left; | |
307 | this.originalScrollTop = where.top; | |
308 | } else { | |
309 | this.originalScrollLeft = this.options.scroll.scrollLeft; | |
310 | this.originalScrollTop = this.options.scroll.scrollTop; | |
311 | } | |
312 | } | |
313 | ||
Draggables.notify('onStart', this, event); | ||
if(this.options.starteffect) this.options.starteffect(this.element); | ||
}, | ||
... | ... | |
this.draw(pointer); | ||
if(this.options.change) this.options.change(this); | ||
326 | if(this.options.scroll) { | |
327 | this.stopScrolling(); | |
328 | ||
329 | var p; | |
330 | if (this.options.scroll == window) { | |
331 | with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } | |
332 | } else { | |
333 | p = Position.page(this.options.scroll); | |
334 | p[0] += this.options.scroll.scrollLeft; | |
335 | p[1] += this.options.scroll.scrollTop; | |
336 | p.push(p[0]+this.options.scroll.offsetWidth); | |
337 | p.push(p[1]+this.options.scroll.offsetHeight); | |
338 | } | |
339 | var speed = [0,0]; | |
340 | if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); | |
341 | if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); | |
342 | if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); | |
343 | if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); | |
344 | this.startScrolling(speed); | |
345 | } | |
346 | ||
// fix AppleWebKit rendering | ||
if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); | ||
349 | ||
Event.stop(event); | ||
}, | ||
... | ... | |
}, | ||
keyPress: function(event) { | ||
323 | | |
387 | if(event.keyCode!=Event.KEY_ESC) return; | |
this.finishDrag(event, false); | ||
Event.stop(event); | ||
}, | ||
endDrag: function(event) { | ||
if(!this.dragging) return; | ||
394 | this.stopScrolling(); | |
this.finishDrag(event, true); | ||
Event.stop(event); | ||
}, | ||
... | ... | |
var d = this.currentDelta(); | ||
pos[0] -= d[0]; pos[1] -= d[1]; | ||
339 | | |
404 | if(this.options.scroll && (this.options.scroll != window)) { | |
405 | pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; | |
406 | pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; | |
407 | } | |
409 | var p = [0,1].map(function(i){ | |
410 | return (point[i]-pos[i]-this.offset[i]) | |
411 | }.bind(this)); | |
412 | ||
if(this.options.snap) { | ||
if(typeof this.options.snap == 'function') { | ||
p = this.options.snap(p[0],p[1]); | ||
... | ... | |
if((!this.options.constraint) || (this.options.constraint=='vertical')) | ||
style.top = p[1] + "px"; | ||
if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering | ||
432 | }, | |
433 | ||
434 | stopScrolling: function() { | |
435 | if(this.scrollInterval) { | |
436 | clearInterval(this.scrollInterval); | |
437 | this.scrollInterval = null; | |
438 | Draggables._lastScrollPointer = null; | |
439 | } | |
440 | }, | |
441 | ||
442 | startScrolling: function(speed) { | |
443 | this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; | |
444 | this.lastScrolled = new Date(); | |
445 | this.scrollInterval = setInterval(this.scroll.bind(this), 10); | |
446 | }, | |
447 | ||
448 | scroll: function() { | |
449 | var current = new Date(); | |
450 | var delta = current - this.lastScrolled; | |
451 | this.lastScrolled = current; | |
452 | if(this.options.scroll == window) { | |
453 | with (this._getWindowScroll(this.options.scroll)) { | |
454 | if (this.scrollSpeed[0] || this.scrollSpeed[1]) { | |
455 | var d = delta / 1000; | |
456 | this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); | |
457 | } | |
458 | } | |
459 | } else { | |
460 | this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; | |
461 | this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; | |
462 | } | |
463 | ||
464 | Position.prepare(); | |
465 | Droppables.show(Draggables._lastPointer, this.element); | |
466 | Draggables.notify('onDrag', this); | |
467 | Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); | |
468 | Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; | |
469 | Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; | |
470 | if (Draggables._lastScrollPointer[0] < 0) | |
471 | Draggables._lastScrollPointer[0] = 0; | |
472 | if (Draggables._lastScrollPointer[1] < 0) | |
473 | Draggables._lastScrollPointer[1] = 0; | |
474 | this.draw(Draggables._lastScrollPointer); | |
475 | ||
476 | if(this.options.change) this.options.change(this); | |
477 | }, | |
478 | ||
479 | _getWindowScroll: function(w) { | |
480 | var T, L, W, H; | |
481 | with (w.document) { | |
482 | if (w.document.documentElement && documentElement.scrollTop) { | |
483 | T = documentElement.scrollTop; | |
484 | L = documentElement.scrollLeft; | |
485 | } else if (w.document.body) { | |
486 | T = body.scrollTop; | |
487 | L = body.scrollLeft; | |
488 | } | |
489 | if (w.innerWidth) { | |
490 | W = w.innerWidth; | |
491 | H = w.innerHeight; | |
492 | } else if (w.document.documentElement && documentElement.clientWidth) { | |
493 | W = documentElement.clientWidth; | |
494 | H = documentElement.clientHeight; | |
495 | } else { | |
496 | W = body.offsetWidth; | |
497 | H = body.offsetHeight | |
498 | } | |
499 | } | |
500 | return { top: T, left: L, width: W, height: H }; | |
} | ||
} | ||
... | ... | |
} | ||
var Sortable = { | ||
385 | | |
526 | sortables: {}, | |
387 | | |
388 | | |
389 | | |
528 | _findRootElement: function(element) { | |
529 | while (element.tagName != "BODY") { | |
530 | if(element.id && Sortable.sortables[element.id]) return element; | |
531 | element = element.parentNode; | |
532 | } | |
}, | ||
534 | ||
535 | options: function(element) { | |
536 | element = Sortable._findRootElement($(element)); | |
537 | if(!element) return; | |
538 | return Sortable.sortables[element.id]; | |
539 | }, | |
destroy: function(element){ | ||
393 | | |
394 | | |
542 | var s = Sortable.options(element); | |
543 | ||
544 | if(s) { | |
Draggables.removeObserver(s.element); | ||
s.droppables.each(function(d){ Droppables.remove(d) }); | ||
s.draggables.invoke('destroy'); | ||
398 | | |
399 | | |
548 | ||
549 | delete Sortable.sortables[s.element.id]; | |
550 | } | |
}, | ||
401 | | |
552 | ||
create: function(element) { | ||
element = $(element); | ||
var options = Object.extend({ | ||
element: element, | ||
tag: 'li', // assumes li children, override with tag: 'tagname' | ||
dropOnEmpty: false, | ||
408 | | |
559 | tree: false, | |
560 | treeTag: 'ul', | |
overlap: 'vertical', // one of 'vertical', 'horizontal' | ||
constraint: 'vertical', // one of 'vertical', 'horizontal', false | ||
containment: element, // also takes array of elements (or id's); or false | ||
... | ... | |
only: false, | ||
hoverclass: null, | ||
ghosting: false, | ||
416 | | |
568 | scroll: false, | |
569 | scrollSensitivity: 20, | |
570 | scrollSpeed: 15, | |
571 | format: /^[^_]*_(.*)$/, | |
onChange: Prototype.emptyFunction, | ||
onUpdate: Prototype.emptyFunction | ||
}, arguments[1] || {}); | ||
... | ... | |
// build options for the draggables | ||
var options_for_draggable = { | ||
revert: true, | ||
582 | scroll: options.scroll, | |
583 | scrollSpeed: options.scrollSpeed, | |
584 | scrollSensitivity: options.scrollSensitivity, | |
ghosting: options.ghosting, | ||
constraint: options.constraint, | ||
handle: options.handle }; | ||
... | ... | |
var options_for_droppable = { | ||
overlap: options.overlap, | ||
containment: options.containment, | ||
610 | tree: options.tree, | |
hoverclass: options.hoverclass, | ||
453 | | |
454 | | |
612 | onHover: Sortable.onHover | |
613 | //greedy: !options.dropOnEmpty | |
} | ||
615 | ||
616 | var options_for_tree = { | |
617 | onHover: Sortable.onEmptyHover, | |
618 | overlap: options.overlap, | |
619 | containment: options.containment, | |
620 | hoverclass: options.hoverclass | |
621 | } | |
// fix for gecko engine | ||
Element.cleanWhitespace(element); | ||
... | ... | |
options.draggables = []; | ||
options.droppables = []; | ||
463 | | |
464 | ||
// drop on empty handling | ||
466 | | |
467 | | |
468 | | |
630 | if(options.dropOnEmpty || options.tree) { | |
631 | Droppables.add(element, options_for_tree); | |
options.droppables.push(element); | ||
} | ||
... | ... | |
options.draggables.push( | ||
new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); | ||
Droppables.add(e, options_for_droppable); | ||
642 | if(options.tree) e.treeNode = element; | |
options.droppables.push(e); | ||
}); | ||
645 | ||
646 | if(options.tree) { | |
647 | (Sortable.findTreeElements(element, options) || []).each( function(e) { | |
648 | Droppables.add(e, options_for_tree); | |
649 | e.treeNode = element; | |
650 | options.droppables.push(e); | |
651 | }); | |
652 | } | |
// keep reference | ||
483 | | |
655 | this.sortables[element.id] = options; | |
// for onupdate | ||
Draggables.addObserver(new SortableObserver(element, options.onUpdate)); | ||
... | ... | |
// return all suitable-for-sortable elements in a guaranteed order | ||
findElements: function(element, options) { | ||
492 | | |
493 | | |
494 | | |
495 | | |
496 | | |
497 | | |
498 | | |
499 | | |
500 | | |
501 | | |
502 | | |
503 | ||
504 | | |
664 | return Element.findChildren( | |
665 | element, options.only, options.tree ? true : false, options.tag); | |
}, | ||
667 | ||
668 | findTreeElements: function(element, options) { | |
669 | return Element.findChildren( | |
670 | element, options.only, options.tree ? true : false, options.treeTag); | |
671 | }, | |
onHover: function(element, dropon, overlap) { | ||
508 | | |
674 | if(Element.isParent(dropon, element)) return; | |
675 | ||
676 | if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { | |
677 | return; | |
678 | } else if(overlap>0.5) { | |
Sortable.mark(dropon, 'before'); | ||
if(dropon.previousSibling != element) { | ||
var oldParentNode = element.parentNode; | ||
... | ... | |
} | ||
} | ||
}, | ||
531 | ||
532 | | |
533 | | |
534 | | |
535 | | |
701 | ||
702 | onEmptyHover: function(element, dropon, overlap) { | |
703 | var oldParentNode = element.parentNode; | |
704 | var droponOptions = Sortable.options(dropon); | |
705 | ||
706 | if(!Element.isParent(dropon, element)) { | |
707 | var index; | |
708 | ||
709 | var children = Sortable.findElements(dropon, {tag: droponOptions.tag}); | |
710 | var child = null; | |
711 | ||
712 | if(children) { | |
713 | var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); | |
714 | ||
715 | for (index = 0; index < children.length; index += 1) { | |
716 | if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { | |
717 | offset -= Element.offsetSize (children[index], droponOptions.overlap); | |
718 | } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { | |
719 | child = index + 1 < children.length ? children[index + 1] : null; | |
720 | break; | |
721 | } else { | |
722 | child = children[index]; | |
723 | break; | |
724 | } | |
725 | } | |
726 | } | |
727 | ||
728 | dropon.insertBefore(element, child); | |
729 | ||
Sortable.options(oldParentNode).onChange(element); | ||
537 | | |
731 | droponOptions.onChange(element); | |
} | ||
}, | ||
... | ... | |
Element.show(Sortable._marker); | ||
}, | ||
763 | ||
764 | _tree: function(element, options, parent) { | |
765 | var children = Sortable.findElements(element, options) || []; | |
766 | ||
767 | for (var i = 0; i < children.length; ++i) { | |
768 | var match = children[i].id.match(options.format); | |
570 | | |
770 | if (!match) continue; | |
771 | ||
772 | var child = { | |
773 | id: encodeURIComponent(match ? match[1] : null), | |
774 | element: element, | |
775 | parent: parent, | |
776 | children: new Array, | |
777 | position: parent.children.length, | |
778 | container: Sortable._findChildrenElement(children[i], options.treeTag.toUpperCase()) | |
779 | } | |
780 | ||
781 | /* Get the element containing the children and recurse over it */ | |
782 | if (child.container) | |
783 | this._tree(child.container, options, child) | |
784 | ||
785 | parent.children.push (child); | |
786 | } | |
787 | ||
788 | return parent; | |
789 | }, | |
790 | ||
791 | /* Finds the first element of the given tag type within a parent element. | |
792 | Used for finding the first LI[ST] within a L[IST]I[TEM].*/ | |
793 | _findChildrenElement: function (element, containerTag) { | |
794 | if (element && element.hasChildNodes) | |
795 | for (var i = 0; i < element.childNodes.length; ++i) | |
796 | if (element.childNodes[i].tagName == containerTag) | |
797 | return element.childNodes[i]; | |
798 | ||
799 | return null; | |
800 | }, | |
801 | ||
802 | tree: function(element) { | |
element = $(element); | ||
var sortableOptions = this.options(element); | ||
var options = Object.extend({ | ||
574 | | |
806 | tag: sortableOptions.tag, | |
807 | treeTag: sortableOptions.treeTag, | |
only: sortableOptions.only, | ||
name: element.id, | ||
577 | | |
810 | format: sortableOptions.format | |
}, arguments[1] || {}); | ||
812 | ||
813 | var root = { | |
814 | id: null, | |
815 | parent: null, | |
816 | children: new Array, | |
817 | container: element, | |
818 | position: 0 | |
819 | } | |
820 | ||
821 | return Sortable._tree (element, options, root); | |
822 | }, | |
823 | ||
824 | /* Construct a [i] index for a particular node */ | |
825 | _constructIndex: function(node) { | |
826 | var index = ''; | |
827 | do { | |
828 | if (node.id) index = '[' + node.position + ']' + index; | |
829 | } while ((node = node.parent) != null); | |
830 | return index; | |
831 | }, | |
832 | ||
833 | sequence: function(element) { | |
834 | element = $(element); | |
835 | var options = Object.extend(this.options(element), arguments[1] || {}); | |
836 | ||
return $(this.findElements(element, options) || []).map( function(item) { | ||
580 | | |
581 | | |
582 | | |
838 | return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; | |
839 | }); | |
840 | }, | |
841 | ||
842 | setSequence: function(element, new_sequence) { | |
843 | element = $(element); | |
844 | var options = Object.extend(this.options(element), arguments[2] || {}); | |
845 | ||
846 | var nodeMap = {}; | |
847 | this.findElements(element, options).each( function(n) { | |
848 | if (n.id.match(options.format)) | |
849 | nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; | |
850 | n.parentNode.removeChild(n); | |
851 | }); | |
852 | ||
853 | new_sequence.each(function(ident) { | |
854 | var n = nodeMap[ident]; | |
855 | if (n) { | |
856 | n[1].appendChild(n[0]); | |
857 | delete nodeMap[ident]; | |
858 | } | |
859 | }); | |
860 | }, | |
861 | ||
862 | serialize: function(element) { | |
863 | element = $(element); | |
864 | var options = Object.extend(Sortable.options(element), arguments[1] || {}); | |
865 | var name = encodeURIComponent( | |
866 | (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); | |
867 | ||
868 | if (options.tree) { | |
869 | return Sortable.tree(element, arguments[1]).children.map( function (item) { | |
870 | return [name + Sortable._constructIndex(item) + "=" + | |
871 | encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); | |
872 | }).flatten().join('&'); | |
873 | } else { | |
874 | return Sortable.sequence(element, arguments[1]).map( function(item) { | |
875 | return name + "[]=" + encodeURIComponent(item); | |
876 | }).join('&'); | |
877 | } | |
} | ||
879 | } | |
880 | ||
881 | /* Returns true if child is contained within element */ | |
882 | Element.isParent = function(child, element) { | |
883 | if (!child.parentNode || child == element) return false; | |
884 | ||
885 | if (child.parentNode == element) return true; | |
886 | ||
887 | return Element.isParent(child.parentNode, element); | |
888 | } | |
889 | ||
890 | Element.findChildren = function(element, only, recursive, tagName) { | |
891 | if(!element.hasChildNodes()) return null; | |
892 | tagName = tagName.toUpperCase(); | |
893 | if(only) only = [only].flatten(); | |
894 | var elements = []; | |
895 | $A(element.childNodes).each( function(e) { | |
896 | if(e.tagName && e.tagName.toUpperCase()==tagName && | |
897 | (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) | |
898 | elements.push(e); | |
899 | if(recursive) { | |
900 | var grandchildren = Element.findChildren(e, only, recursive, tagName); | |
901 | if(grandchildren) elements.push(grandchildren); | |
902 | } | |
903 | }); | |
904 | ||
905 | return (elements.length>0 ? elements.flatten() : []); | |
906 | } | |
907 | ||
908 | Element.offsetSize = function (element, type) { | |
909 | if (type == 'vertical' || type == 'height') | |
910 | return element.offsetHeight; | |
911 | else | |
912 | return element.offsetWidth; | |
} | ||
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/javascripts/effects.js:
prev. | current | |
// | ||
// See scriptaculous.js for full license. | ||
9 | ||
10 | | |
// converts rgb() and #xxx to #xxxxxx format, | ||
// returns self (or first argument) if not convertable | ||
String.prototype.parseColor = function() { | ||
... | ... | |
} | ||
} | ||
return(color.length==7 ? color : (arguments[0] || this)); | ||
25 | ||
23 | } | |
27 | ||
28 | | |
29 | | |
30 | | |
31 | | |
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | | |
38 | | |
39 | | |
40 | | |
41 | | |
25 | /*--------------------------------------------------------------------------*/ | |
26 | ||
27 | Element.collectTextNodes = function(element) { | |
28 | return $A($(element).childNodes).collect( function(node) { | |
29 | return (node.nodeType==3 ? node.nodeValue : | |
30 | (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); | |
31 | }).flatten().join(''); | |
} | ||
44 | ||
45 | | |
46 | | |
34 | Element.collectTextNodesIgnoreClass = function(element, className) { | |
35 | return $A($(element).childNodes).collect( function(node) { | |
36 | return (node.nodeType==3 ? node.nodeValue : | |
37 | ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? | |
38 | Element.collectTextNodesIgnoreClass(node, className) : '')); | |
39 | }).flatten().join(''); | |
} | ||
49 | ||
42 | Element.setContentZoom = function(element, percent) { | |
43 | element = $(element); | |
Element.setStyle(element, {fontSize: (percent/100) + 'em'}); | ||
51 | | |
45 | if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); | |
} | ||
Element.getOpacity = function(element){ | ||
... | ... | |
Element.setStyle(element, | ||
{ filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') + | ||
'alpha(opacity='+value*100+')' }); | ||
78 | | |
72 | } | |
} | ||
Element.getInlineOpacity = function(element){ | ||
return $(element).style.opacity || ''; | ||
} | ||
85 | ||
86 | | |
87 | | |
79 | Element.childrenWithClassName = function(element, className, findFirst) { | |
80 | var classNameRegExp = new RegExp("(^|\\s)" + className + "(\\s|$)"); | |
81 | var results = $A($(element).getElementsByTagName('*'))[findFirst ? 'detect' : 'select']( function(c) { | |
82 | return (c.className && c.className.match(classNameRegExp)); | |
83 | }); | |
84 | if(!results) results = []; | |
85 | return results; | |
} | ||
88 | Element.forceRerendering = function(element) { | |
89 | try { | |
90 | element = $(element); | |
91 | var n = document.createTextNode(' '); | |
92 | element.appendChild(n); | |
93 | element.removeChild(n); | |
94 | } catch(e) { } | |
95 | }; | |
96 | ||
97 | /*--------------------------------------------------------------------------*/ | |
98 | ||
Array.prototype.call = function() { | ||
var args = arguments; | ||
this.each(function(f){ f.apply(this, args) }); | ||
... | ... | |
$A(elements).each( function(element, index) { | ||
new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); | ||
}); | ||
141 | }, | |
142 | PAIRS: { | |
143 | 'slide': ['SlideDown','SlideUp'], | |
144 | 'blind': ['BlindDown','BlindUp'], | |
145 | 'appear': ['Appear','Fade'] | |
146 | }, | |
147 | toggle: function(element, effect) { | |
148 | element = $(element); | |
149 | effect = (effect || 'appear').toLowerCase(); | |
150 | var options = Object.extend({ | |
151 | queue: { position:'end', scope:(element.id || 'global'), limit: 1 } | |
152 | }, arguments[2] || {}); | |
153 | Effect[element.visible() ? | |
154 | Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); | |
} | ||
}; | ||
... | ... | |
/* ------------- core effects ------------- */ | ||
169 | ||
170 | | |
192 | Effect.ScopedQueue = Class.create(); | |
193 | Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { | |
194 | initialize: function() { | |
195 | this.effects = []; | |
196 | this.interval = null; | |
197 | }, | |
_each: function(iterator) { | ||
this.effects._each(iterator); | ||
}, | ||
174 | | |
add: function(effect) { | ||
var timestamp = new Date().getTime(); | ||
178 | | |
204 | var position = (typeof effect.options.queue == 'string') ? | |
205 | effect.options.queue : effect.options.queue.position; | |
206 | ||
207 | switch(position) { | |
case 'front': | ||
// move unstarted effects after this effect | ||
this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { | ||
... | ... | |
effect.startOn += timestamp; | ||
effect.finishOn += timestamp; | ||
194 | | |
223 | ||
224 | if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) | |
225 | this.effects.push(effect); | |
226 | ||
if(!this.interval) | ||
this.interval = setInterval(this.loop.bind(this), 40); | ||
}, | ||
... | ... | |
var timePos = new Date().getTime(); | ||
this.effects.invoke('loop', timePos); | ||
} | ||
241 | }); | |
242 | ||
243 | Effect.Queues = { | |
244 | instances: $H(), | |
245 | get: function(queueName) { | |
246 | if(typeof queueName != 'string') return queueName; | |
247 | ||
248 | if(!this.instances[queueName]) | |
249 | this.instances[queueName] = new Effect.ScopedQueue(); | |
250 | ||
251 | return this.instances[queueName]; | |
252 | } | |
} | ||
210 | ||
254 | Effect.Queue = Effect.Queues.get('global'); | |
256 | Effect.DefaultOptions = { | |
257 | transition: Effect.Transitions.sinoidal, | |
258 | duration: 1.0, // seconds | |
259 | fps: 25.0, // max. 25fps due to Effect.Queue implementation | |
260 | sync: false, // true for combining | |
261 | from: 0.0, | |
262 | to: 1.0, | |
263 | delay: 0.0, | |
264 | queue: 'parallel' | |
265 | } | |
266 | ||
Effect.Base = function() {}; | ||
Effect.Base.prototype = { | ||
position: null, | ||
215 | | |
216 | | |
217 | | |
218 | | |
219 | | |
220 | | |
221 | | |
222 | | |
223 | | |
224 | | |
225 | | |
226 | | |
start: function(options) { | ||
228 | | |
271 | this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {}); | |
this.currentFrame = 0; | ||
this.state = 'idle'; | ||
this.startOn = this.options.delay*1000; | ||
this.finishOn = this.startOn + (this.options.duration*1000); | ||
this.event('beforeStart'); | ||
234 | | |
277 | if(!this.options.sync) | |
278 | Effect.Queues.get(typeof this.options.queue == 'string' ? | |
279 | 'global' : this.options.queue.scope).add(this); | |
}, | ||
loop: function(timePos) { | ||
if(timePos >= this.startOn) { | ||
... | ... | |
} | ||
}, | ||
cancel: function() { | ||
272 | | |
317 | if(!this.options.sync) | |
318 | Effect.Queues.get(typeof this.options.queue == 'string' ? | |
319 | 'global' : this.options.queue.scope).remove(this); | |
this.state = 'finished'; | ||
}, | ||
event: function(eventName) { | ||
... | ... | |
this.element = $(element); | ||
// make this work on IE on elements without 'layout' | ||
if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout)) | ||
310 | | |
357 | this.element.setStyle({zoom: 1}); | |
var options = Object.extend({ | ||
312 | | |
359 | from: this.element.getOpacity() || 0.0, | |
to: 1.0 | ||
}, arguments[1] || {}); | ||
this.start(options); | ||
}, | ||
update: function(position) { | ||
318 | | |
365 | this.element.setOpacity(position); | |
} | ||
}); | ||
322 | ||
323 | ||
324 | | |
325 | | |
326 | | |
327 | | |
328 | | |
369 | Effect.Move = Class.create(); | |
370 | Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), { | |
371 | initialize: function(element) { | |
372 | this.element = $(element); | |
373 | var options = Object.extend({ | |
374 | x: 0, | |
375 | y: 0, | |
376 | mode: 'relative' | |
377 | }, arguments[1] || {}); | |
378 | this.start(options); | |
}, | ||
setup: function() { | ||
// Bug in Opera: Opera returns the "real" position of a static element or | ||
// relative element that does not have top/left explicitly set. | ||
// ==> Always set top and left for position relative elements in your stylesheets | ||
// (to 0 if you do not need them) | ||
335 | | |
336 | | |
337 | | |
385 | this.element.makePositioned(); | |
386 | this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); | |
387 | this.originalTop = parseFloat(this.element.getStyle('top') || '0'); | |
388 | if(this.options.mode == 'absolute') { | |
389 | // absolute movement, so we need to calc deltaX and deltaY | |
390 | this.options.x = this.options.x - this.originalLeft; | |
391 | this.options.y = this.options.y - this.originalTop; | |
392 | } | |
}, | ||
update: function(position) { | ||
340 | | |
341 | | |
342 | | |
395 | this.element.setStyle({ | |
396 | left: this.options.x * position + this.originalLeft + 'px', | |
397 | top: this.options.y * position + this.originalTop + 'px' | |
}); | ||
} | ||
}); | ||
402 | // for backwards compatibility | |
403 | Effect.MoveBy = function(element, toTop, toLeft) { | |
404 | return new Effect.Move(element, | |
405 | Object.extend({ x: toLeft, y: toTop }, arguments[3] || {})); | |
406 | }; | |
407 | ||
Effect.Scale = Class.create(); | ||
Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), { | ||
initialize: function(element, percent) { | ||
... | ... | |
}, | ||
setup: function() { | ||
this.restoreAfterFinish = this.options.restoreAfterFinish || false; | ||
364 | | |
425 | this.elementPositioning = this.element.getStyle('position'); | |
this.originalStyle = {}; | ||
['top','left','width','height','fontSize'].each( function(k) { | ||
... | ... | |
this.originalTop = this.element.offsetTop; | ||
this.originalLeft = this.element.offsetLeft; | ||
374 | | |
435 | var fontSize = this.element.getStyle('font-size') || '100%'; | |
['em','px','%'].each( function(fontSizeType) { | ||
if(fontSize.indexOf(fontSizeType)>0) { | ||
this.fontSize = parseFloat(fontSize); | ||
... | ... | |
update: function(position) { | ||
var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); | ||
if(this.options.scaleContent && this.fontSize) | ||
396 | | |
457 | this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); | |
this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); | ||
}, | ||
finish: function(position) { | ||
400 | | |
461 | if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); | |
}, | ||
setDimensions: function(height, width) { | ||
var d = {}; | ||
... | ... | |
if(this.options.scaleX) d.left = -leftd + 'px'; | ||
} | ||
} | ||
417 | | |
478 | this.element.setStyle(d); | |
} | ||
}); | ||
... | ... | |
}, | ||
setup: function() { | ||
// Prevent executing on elements not in the layout flow | ||
430 | | |
491 | if(this.element.getStyle('display')=='none') { this.cancel(); return; } | |
// Disable background image during the effect | ||
this.oldStyle = { | ||
433 | | |
434 | | |
494 | backgroundImage: this.element.getStyle('background-image') }; | |
495 | this.element.setStyle({backgroundImage: 'none'}); | |
if(!this.options.endcolor) | ||
436 | | |
497 | this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); | |
if(!this.options.restorecolor) | ||
438 | | |
499 | this.options.restorecolor = this.element.getStyle('background-color'); | |
// init color calculations | ||
this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); | ||
this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); | ||
}, | ||
update: function(position) { | ||
444 | | |
505 | this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ | |
return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) }); | ||
}, | ||
finish: function() { | ||
448 | | |
509 | this.element.setStyle(Object.extend(this.oldStyle, { | |
backgroundColor: this.options.restorecolor | ||
})); | ||
} | ||
... | ... | |
/* ------------- combination effects ------------- */ | ||
Effect.Fade = function(element) { | ||
482 | | |
543 | element = $(element); | |
544 | var oldOpacity = element.getInlineOpacity(); | |
var options = Object.extend({ | ||
484 | | |
546 | from: element.getOpacity() || 1.0, | |
to: 0.0, | ||
486 | | |
548 | afterFinishInternal: function(effect) { | |
if(effect.options.to!=0) return; | ||
488 | | |
489 | | |
490 | | |
550 | effect.element.hide(); | |
551 | effect.element.setStyle({opacity: oldOpacity}); | |
552 | }}, arguments[1] || {}); | |
return new Effect.Opacity(element,options); | ||
} | ||
Effect.Appear = function(element) { | ||
557 | element = $(element); | |
var options = Object.extend({ | ||
496 | | |
559 | from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), | |
to: 1.0, | ||
498 | | |
499 | | |
500 | | |
501 | | |
561 | // force Safari to render floated elements properly | |
562 | afterFinishInternal: function(effect) { | |
563 | effect.element.forceRerendering(); | |
564 | }, | |
565 | beforeSetup: function(effect) { | |
566 | effect.element.setOpacity(effect.options.from); | |
567 | effect.element.show(); | |
568 | }}, arguments[1] || {}); | |
return new Effect.Opacity(element,options); | ||
} | ||
Effect.Puff = function(element) { | ||
element = $(element); | ||
507 | | |
574 | var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position') }; | |
return new Effect.Parallel( | ||
[ new Effect.Scale(element, 200, | ||
{ sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), | ||
new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], | ||
Object.extend({ duration: 1.0, | ||
513 | | |
514 | | |
515 | | |
516 | | |
517 | | |
580 | beforeSetupInternal: function(effect) { | |
581 | effect.effects[0].element.setStyle({position: 'absolute'}); }, | |
582 | afterFinishInternal: function(effect) { | |
583 | effect.effects[0].element.hide(); | |
584 | effect.effects[0].element.setStyle(oldStyle); } | |
}, arguments[1] || {}) | ||
); | ||
} | ||
Effect.BlindUp = function(element) { | ||
element = $(element); | ||
524 | | |
591 | element.makeClipping(); | |
return new Effect.Scale(element, 0, | ||
Object.extend({ scaleContent: false, | ||
scaleX: false, | ||
restoreAfterFinish: true, | ||
529 | | |
530 | | |
596 | afterFinishInternal: function(effect) { | |
597 | effect.element.hide(); | |
598 | effect.element.undoClipping(); | |
599 | } | |
}, arguments[1] || {}) | ||
); | ||
} | ||
Effect.BlindDown = function(element) { | ||
element = $(element); | ||
537 | | |
538 | | |
606 | var elementDimensions = element.getDimensions(); | |
return new Effect.Scale(element, 100, | ||
Object.extend({ scaleContent: false, | ||
scaleX: false, | ||
scaleFrom: 0, | ||
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, | ||
restoreAfterFinish: true, | ||
545 | | |
546 | | |
547 | | |
548 | | |
549 | | |
550 | | |
551 | | |
552 | | |
553 | | |
613 | afterSetup: function(effect) { | |
614 | effect.element.makeClipping(); | |
615 | effect.element.setStyle({height: '0px'}); | |
616 | effect.element.show(); | |
617 | }, | |
618 | afterFinishInternal: function(effect) { | |
619 | effect.element.undoClipping(); | |
620 | } | |
}, arguments[1] || {}) | ||
); | ||
} | ||
Effect.SwitchOff = function(element) { | ||
element = $(element); | ||
560 | | |
627 | var oldOpacity = element.getInlineOpacity(); | |
return new Effect.Appear(element, { | ||
duration: 0.4, | ||
from: 0, | ||
... | ... | |
new Effect.Scale(effect.element, 1, { | ||
duration: 0.3, scaleFromCenter: true, | ||
scaleX: false, scaleContent: false, restoreAfterFinish: true, | ||
569 | | |
570 | | |
571 | | |
572 | | |
573 | | |
574 | | |
575 | | |
636 | beforeSetup: function(effect) { | |
637 | effect.element.makePositioned(); | |
638 | effect.element.makeClipping(); | |
639 | }, | |
640 | afterFinishInternal: function(effect) { | |
641 | effect.element.hide(); | |
642 | effect.element.undoClipping(); | |
643 | effect.element.undoPositioned(); | |
644 | effect.element.setStyle({opacity: oldOpacity}); | |
645 | } | |
}) | ||
} | ||
}); | ||
... | ... | |
Effect.DropOut = function(element) { | ||
element = $(element); | ||
var oldStyle = { | ||
584 | | |
585 | | |
586 | | |
654 | top: element.getStyle('top'), | |
655 | left: element.getStyle('left'), | |
656 | opacity: element.getInlineOpacity() }; | |
return new Effect.Parallel( | ||
588 | | |
658 | [ new Effect.Move(element, {x: 0, y: 100, sync: true }), | |
new Effect.Opacity(element, { sync: true, to: 0.0 }) ], | ||
Object.extend( | ||
{ duration: 0.5, | ||
592 | | |
593 | | |
594 | | |
595 | | |
596 | | |
662 | beforeSetup: function(effect) { | |
663 | effect.effects[0].element.makePositioned(); | |
664 | }, | |
665 | afterFinishInternal: function(effect) { | |
666 | effect.effects[0].element.hide(); | |
667 | effect.effects[0].element.undoPositioned(); | |
668 | effect.effects[0].element.setStyle(oldStyle); | |
669 | } | |
}, arguments[1] || {})); | ||
} | ||
Effect.Shake = function(element) { | ||
element = $(element); | ||
var oldStyle = { | ||
603 | | |
604 | | |
605 | | |
606 | | |
607 | | |
608 | | |
609 | | |
610 | | |
611 | | |
612 | | |
613 | | |
614 | | |
615 | | |
616 | | |
617 | | |
618 | | |
619 | | |
676 | top: element.getStyle('top'), | |
677 | left: element.getStyle('left') }; | |
678 | return new Effect.Move(element, | |
679 | { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { | |
680 | new Effect.Move(effect.element, | |
681 | { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { | |
682 | new Effect.Move(effect.element, | |
683 | { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { | |
684 | new Effect.Move(effect.element, | |
685 | { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { | |
686 | new Effect.Move(effect.element, | |
687 | { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { | |
688 | new Effect.Move(effect.element, | |
689 | { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { | |
690 | effect.element.undoPositioned(); | |
691 | effect.element.setStyle(oldStyle); | |
692 | }}) }}) }}) }}) }}) }}); | |
} | ||
Effect.SlideDown = function(element) { | ||
element = $(element); | ||
624 | | |
697 | element.cleanWhitespace(); | |
// SlideDown need to have the content of the element wrapped in a container element with fixed height! | ||
626 | | |
627 | | |
699 | var oldInnerBottom = $(element.firstChild).getStyle('bottom'); | |
700 | var elementDimensions = element.getDimensions(); | |
return new Effect.Scale(element, 100, Object.extend({ | ||
scaleContent: false, | ||
scaleX: false, | ||
scaleFrom: 0, | ||
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, | ||
restoreAfterFinish: true, | ||
634 | | |
635 | | |
636 | | |
637 | | |
638 | | |
639 | | |
640 | | |
641 | | |
642 | | |
643 | | |
644 | | |
645 | | |
646 | | |
647 | | |
648 | | |
707 | afterSetup: function(effect) { | |
708 | effect.element.makePositioned(); | |
709 | effect.element.firstChild.makePositioned(); | |
710 | if(window.opera) effect.element.setStyle({top: ''}); | |
711 | effect.element.makeClipping(); | |
712 | effect.element.setStyle({height: '0px'}); | |
713 | effect.element.show(); }, | |
714 | afterUpdateInternal: function(effect) { | |
715 | effect.element.firstChild.setStyle({bottom: | |
716 | (effect.dims[0] - effect.element.clientHeight) + 'px' }); | |
717 | }, | |
718 | afterFinishInternal: function(effect) { | |
719 | effect.element.undoClipping(); | |
720 | // IE will crash if child is undoPositioned first | |
721 | if(/MSIE/.test(navigator.userAgent)){ | |
722 | effect.element.undoPositioned(); | |
723 | effect.element.firstChild.undoPositioned(); | |
724 | }else{ | |
725 | effect.element.firstChild.undoPositioned(); | |
726 | effect.element.undoPositioned(); | |
727 | } | |
728 | effect.element.firstChild.setStyle({bottom: oldInnerBottom}); } | |
}, arguments[1] || {}) | ||
); | ||
} | ||
Effect.SlideUp = function(element) { | ||
element = $(element); | ||
655 | | |
656 | | |
735 | element.cleanWhitespace(); | |
736 | var oldInnerBottom = $(element.firstChild).getStyle('bottom'); | |
return new Effect.Scale(element, 0, | ||
Object.extend({ scaleContent: false, | ||
scaleX: false, | ||
scaleMode: 'box', | ||
scaleFrom: 100, | ||
restoreAfterFinish: true, | ||
663 | | |
664 | | |
665 | | |
666 | | |
667 | | |
668 | | |
669 | | |
670 | | |
671 | | |
672 | | |
673 | | |
674 | | |
675 | | |
676 | | |
743 | beforeStartInternal: function(effect) { | |
744 | effect.element.makePositioned(); | |
745 | effect.element.firstChild.makePositioned(); | |
746 | if(window.opera) effect.element.setStyle({top: ''}); | |
747 | effect.element.makeClipping(); | |
748 | effect.element.show(); }, | |
749 | afterUpdateInternal: function(effect) { | |
750 | effect.element.firstChild.setStyle({bottom: | |
751 | (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, | |
752 | afterFinishInternal: function(effect) { | |
753 | effect.element.hide(); | |
754 | effect.element.undoClipping(); | |
755 | effect.element.firstChild.undoPositioned(); | |
756 | effect.element.undoPositioned(); | |
757 | effect.element.setStyle({bottom: oldInnerBottom}); } | |
}, arguments[1] || {}) | ||
); | ||
} | ||
... | ... | |
Effect.Squish = function(element) { | ||
return new Effect.Scale(element, window.opera ? 1 : 0, | ||
{ restoreAfterFinish: true, | ||
685 | | |
686 | | |
687 | | |
688 | | |
689 | | |
766 | beforeSetup: function(effect) { | |
767 | effect.element.makeClipping(effect.element); }, | |
768 | afterFinishInternal: function(effect) { | |
769 | effect.element.hide(effect.element); | |
770 | effect.element.undoClipping(effect.element); } | |
}); | ||
} | ||
... | ... | |
element = $(element); | ||
var options = Object.extend({ | ||
direction: 'center', | ||
697 | | |
778 | moveTransition: Effect.Transitions.sinoidal, | |
scaleTransition: Effect.Transitions.sinoidal, | ||
opacityTransition: Effect.Transitions.full | ||
}, arguments[1] || {}); | ||
... | ... | |
left: element.style.left, | ||
height: element.style.height, | ||
width: element.style.width, | ||
706 | | |
787 | opacity: element.getInlineOpacity() }; | |
708 | | |
789 | var dims = element.getDimensions(); | |
var initialMoveX, initialMoveY; | ||
var moveX, moveY; | ||
... | ... | |
break; | ||
} | ||
740 | | |
821 | return new Effect.Move(element, { | |
822 | x: initialMoveX, | |
823 | y: initialMoveY, | |
duration: 0.01, | ||
742 | | |
743 | | |
744 | | |
745 | | |
746 | | |
825 | beforeSetup: function(effect) { | |
826 | effect.element.hide(); | |
827 | effect.element.makeClipping(); | |
828 | effect.element.makePositioned(); | |
829 | }, | |
afterFinishInternal: function(effect) { | ||
new Effect.Parallel( | ||
[ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), | ||
750 | | |
833 | new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), | |
new Effect.Scale(effect.element, 100, { | ||
scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, | ||
sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) | ||
], Object.extend({ | ||
755 | | |
756 | | |
757 | | |
758 | | |
759 | | |
760 | | |
838 | beforeSetup: function(effect) { | |
839 | effect.effects[0].element.setStyle({height: '0px'}); | |
840 | effect.effects[0].element.show(); | |
841 | }, | |
842 | afterFinishInternal: function(effect) { | |
843 | effect.effects[0].element.undoClipping(); | |
844 | effect.effects[0].element.undoPositioned(); | |
845 | effect.effects[0].element.setStyle(oldStyle); | |
846 | } | |
}, options) | ||
) | ||
} | ||
... | ... | |
element = $(element); | ||
var options = Object.extend({ | ||
direction: 'center', | ||
771 | | |
857 | moveTransition: Effect.Transitions.sinoidal, | |
scaleTransition: Effect.Transitions.sinoidal, | ||
opacityTransition: Effect.Transitions.none | ||
}, arguments[1] || {}); | ||
... | ... | |
left: element.style.left, | ||
height: element.style.height, | ||
width: element.style.width, | ||
780 | | |
866 | opacity: element.getInlineOpacity() }; | |
782 | | |
868 | var dims = element.getDimensions(); | |
var moveX, moveY; | ||
switch (options.direction) { | ||
... | ... | |
return new Effect.Parallel( | ||
[ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), | ||
new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), | ||
810 | | |
896 | new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) | |
], Object.extend({ | ||
812 | | |
813 | | |
814 | | |
815 | | |
816 | | |
898 | beforeStartInternal: function(effect) { | |
899 | effect.effects[0].element.makePositioned(); | |
900 | effect.effects[0].element.makeClipping(); }, | |
901 | afterFinishInternal: function(effect) { | |
902 | effect.effects[0].element.hide(); | |
903 | effect.effects[0].element.undoClipping(); | |
904 | effect.effects[0].element.undoPositioned(); | |
905 | effect.effects[0].element.setStyle(oldStyle); } | |
}, options) | ||
); | ||
} | ||
... | ... | |
Effect.Pulsate = function(element) { | ||
element = $(element); | ||
var options = arguments[1] || {}; | ||
824 | | |
913 | var oldOpacity = element.getInlineOpacity(); | |
var transition = options.transition || Effect.Transitions.sinoidal; | ||
var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) }; | ||
reverser.bind(transition); | ||
return new Effect.Opacity(element, | ||
Object.extend(Object.extend({ duration: 3.0, from: 0, | ||
830 | | |
919 | afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } | |
}, options), {transition: reverser})); | ||
} | ||
... | ... | |
new Effect.Scale(element, 1, { | ||
scaleContent: false, | ||
scaleY: false, | ||
849 | | |
850 | | |
851 | | |
852 | | |
938 | afterFinishInternal: function(effect) { | |
939 | effect.element.hide(); | |
940 | effect.element.undoClipping(); | |
941 | effect.element.setStyle(oldStyle); | |
942 | } }); | |
}}, arguments[1] || {})); | ||
854 | ||
944 | }; | |
945 | ||
946 | ['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', | |
947 | 'collectTextNodes','collectTextNodesIgnoreClass','childrenWithClassName'].each( | |
948 | function(f) { Element.Methods[f] = Element[f]; } | |
949 | ); | |
950 | ||
951 | Element.Methods.visualEffect = function(element, effect, options) { | |
952 | s = effect.gsub(/_/, '-').camelize(); | |
953 | effect_class = s.charAt(0).toUpperCase() + s.substring(1); | |
954 | new Effect[effect_class](element, options); | |
955 | return $(element); | |
956 | }; | |
957 | ||
958 | Element.addMethods(); | |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/javascripts/prototype.js:
prev. | current | |
1 | ||
1 | /* Prototype JavaScript framework, version 1.5.0_rc0 | |
* (c) 2005 Sam Stephenson <sam@conio.net> | ||
* | ||
4 | | |
5 | | |
6 | | |
* Prototype is freely distributable under the terms of an MIT-style license. | ||
8 | | |
* For details, see the Prototype web site: http://prototype.conio.net/ | ||
* | ||
/*--------------------------------------------------------------------------*/ | ||
var Prototype = { | ||
14 | | |
10 | Version: '1.5.0_rc0', | |
ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', | ||
emptyFunction: function() {}, | ||
... | ... | |
var Abstract = new Object(); | ||
Object.extend = function(destination, source) { | ||
32 | | |
28 | for (var property in source) { | |
destination[property] = source[property]; | ||
} | ||
return destination; | ||
... | ... | |
} | ||
} | ||
} | ||
119 | Object.extend(String.prototype, { | |
120 | gsub: function(pattern, replacement) { | |
121 | var result = '', source = this, match; | |
122 | replacement = arguments.callee.prepareReplacement(replacement); | |
124 | ||
124 | while (source.length > 0) { | |
125 | if (match = source.match(pattern)) { | |
126 | result += source.slice(0, match.index); | |
127 | result += (replacement(match) || '').toString(); | |
128 | source = source.slice(match.index + match[0].length); | |
129 | } else { | |
130 | result += source, source = ''; | |
131 | } | |
132 | } | |
133 | return result; | |
134 | }, | |
126 | ||
127 | | |
136 | sub: function(pattern, replacement, count) { | |
137 | replacement = this.gsub.prepareReplacement(replacement); | |
138 | count = count === undefined ? 1 : count; | |
129 | | |
130 | | |
131 | | |
132 | | |
140 | return this.gsub(pattern, function(match) { | |
141 | if (--count < 0) return match[0]; | |
142 | return replacement(match); | |
143 | }); | |
144 | }, | |
134 | | |
135 | | |
146 | scan: function(pattern, iterator) { | |
147 | this.gsub(pattern, iterator); | |
148 | return this; | |
149 | }, | |
137 | | |
138 | | |
151 | truncate: function(length, truncation) { | |
152 | length = length || 30; | |
153 | truncation = truncation === undefined ? '...' : truncation; | |
154 | return this.length > length ? | |
155 | this.slice(0, length - truncation.length) + truncation : this; | |
156 | }, | |
140 | | |
141 | ||
142 | ||
158 | strip: function() { | |
159 | return this.replace(/^\s+/, '').replace(/\s+$/, ''); | |
160 | }, | |
161 | ||
stripTags: function() { | ||
return this.replace(/<\/?[^>]+>/gi, ''); | ||
}, | ||
... | ... | |
}, | ||
evalScripts: function() { | ||
160 | | |
179 | return this.extractScripts().map(function(script) { return eval(script) }); | |
}, | ||
escapeHTML: function() { | ||
... | ... | |
}, | ||
inspect: function() { | ||
206 | | |
225 | return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'"; | |
} | ||
}); | ||
229 | String.prototype.gsub.prepareReplacement = function(replacement) { | |
230 | if (typeof replacement == 'function') return replacement; | |
231 | var template = new Template(replacement); | |
232 | return function(match) { return template.evaluate(match) }; | |
233 | } | |
234 | ||
String.prototype.parseQuery = String.prototype.toQueryParams; | ||
237 | var Template = Class.create(); | |
238 | Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; | |
239 | Template.prototype = { | |
240 | initialize: function(template, pattern) { | |
241 | this.template = template.toString(); | |
242 | this.pattern = pattern || Template.Pattern; | |
243 | }, | |
244 | ||
245 | evaluate: function(object) { | |
246 | return this.template.gsub(this.pattern, function(match) { | |
247 | var before = match[1]; | |
248 | if (before == '\\') return match[2]; | |
249 | return before + (object[match[3]] || '').toString(); | |
250 | }); | |
251 | } | |
252 | } | |
253 | ||
var $break = new Object(); | ||
var $continue = new Object(); | ||
... | ... | |
var result; | ||
this.each(function(value, index) { | ||
value = (iterator || Prototype.K)(value, index); | ||
316 | | |
358 | if (result == undefined || value >= result) | |
result = value; | ||
}); | ||
return result; | ||
... | ... | |
var result; | ||
this.each(function(value, index) { | ||
value = (iterator || Prototype.K)(value, index); | ||
326 | | |
368 | if (result == undefined || value < result) | |
result = value; | ||
}); | ||
return result; | ||
... | ... | |
var collections = [this].concat(args).map($A); | ||
return this.map(function(value, index) { | ||
378 | | |
379 | | |
420 | return iterator(collections.pluck(index)); | |
}); | ||
}, | ||
... | ... | |
Object.extend(Array.prototype, Enumerable); | ||
409 | ||
450 | if (!Array.prototype._reverse) | |
451 | Array.prototype._reverse = Array.prototype.reverse; | |
Object.extend(Array.prototype, { | ||
_each: function(iterator) { | ||
... | ... | |
flatten: function() { | ||
return this.inject([], function(array, value) { | ||
438 | | |
480 | return array.concat(value && value.constructor == Array ? | |
value.flatten() : [value]); | ||
}); | ||
}, | ||
... | ... | |
return (inline !== false ? this : this.toArray())._reverse(); | ||
}, | ||
460 | | |
461 | | |
462 | | |
463 | | |
464 | | |
465 | | |
466 | | |
467 | ||
inspect: function() { | ||
return '[' + this.map(Object.inspect).join(', ') + ']'; | ||
} | ||
}); | ||
var Hash = { | ||
_each: function(iterator) { | ||
474 | | |
508 | for (var key in this) { | |
var value = this[key]; | ||
if (typeof value == 'function') continue; | ||
... | ... | |
var Ajax = { | ||
getTransport: function() { | ||
return Try.these( | ||
586 | function() {return new XMLHttpRequest()}, | |
function() {return new ActiveXObject('Msxml2.XMLHTTP')}, | ||
553 | | |
554 | | |
588 | function() {return new ActiveXObject('Microsoft.XMLHTTP')} | |
) || false; | ||
}, | ||
... | ... | |
this.options = { | ||
method: 'post', | ||
asynchronous: true, | ||
640 | contentType: 'application/x-www-form-urlencoded', | |
parameters: '' | ||
} | ||
Object.extend(this.options, options || {}); | ||
... | ... | |
setRequestHeaders: function() { | ||
var requestHeaders = | ||
['X-Requested-With', 'XMLHttpRequest', | ||
665 | | |
700 | 'X-Prototype-Version', Prototype.Version, | |
701 | 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*']; | |
if (this.options.method == 'post') { | ||
668 | | |
669 | | |
704 | requestHeaders.push('Content-type', this.options.contentType); | |
/* Force "Connection: close" for Mozilla browsers to work around | ||
* a bug where XMLHttpReqeuest sends an incorrect Content-length | ||
... | ... | |
evalJSON: function() { | ||
try { | ||
700 | | |
735 | return eval('(' + this.header('X-JSON') + ')'); | |
} catch (e) {} | ||
}, | ||
... | ... | |
this.updater = new Ajax.Updater(this.container, this.url, this.options); | ||
} | ||
}); | ||
869 | function $() { | |
870 | var results = [], element; | |
871 | for (var i = 0; i < arguments.length; i++) { | |
872 | element = arguments[i]; | |
873 | if (typeof element == 'string') | |
874 | element = document.getElementById(element); | |
875 | results.push(Element.extend(element)); | |
876 | } | |
877 | return results.length < 2 ? results[0] : results; | |
878 | } | |
879 | ||
document.getElementsByClassName = function(className, parentElement) { | ||
var children = ($(parentElement) || document.body).getElementsByTagName('*'); | ||
return $A(children).inject([], function(elements, child) { | ||
if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) | ||
838 | | |
884 | elements.push(Element.extend(child)); | |
return elements; | ||
}); | ||
} | ||
/*--------------------------------------------------------------------------*/ | ||
845 | ||
891 | if (!window.Element) | |
var Element = new Object(); | ||
893 | ||
894 | Element.extend = function(element) { | |
895 | if (!element) return; | |
896 | if (_nativeExtensions) return element; | |
897 | ||
898 | if (!element._extended && element.tagName && element != window) { | |
899 | var methods = Element.Methods, cache = Element.extend.cache; | |
900 | for (property in methods) { | |
901 | var value = methods[property]; | |
902 | if (typeof value == 'function') | |
903 | element[property] = cache.findOrStore(value); | |
904 | } | |
905 | } | |
906 | ||
907 | element._extended = true; | |
908 | return element; | |
} | ||
849 | ||
911 | Element.extend.cache = { | |
912 | findOrStore: function(value) { | |
913 | return this[value] = this[value] || function() { | |
914 | return value.apply(null, [this].concat($A(arguments))); | |
915 | } | |
916 | } | |
917 | } | |
918 | ||
919 | Element.Methods = { | |
visible: function(element) { | ||
return $(element).style.display != 'none'; | ||
}, | ||
... | ... | |
setTimeout(function() {html.evalScripts()}, 10); | ||
}, | ||
955 | replace: function(element, html) { | |
956 | element = $(element); | |
957 | if (element.outerHTML) { | |
958 | element.outerHTML = html.stripScripts(); | |
959 | } else { | |
960 | var range = element.ownerDocument.createRange(); | |
961 | range.selectNodeContents(element); | |
962 | element.parentNode.replaceChild( | |
963 | range.createContextualFragment(html.stripScripts()), element); | |
964 | } | |
965 | setTimeout(function() {html.evalScripts()}, 10); | |
966 | }, | |
967 | ||
getHeight: function(element) { | ||
element = $(element); | ||
return element.offsetHeight; | ||
... | ... | |
return $(element).innerHTML.match(/^\s*$/); | ||
}, | ||
1006 | childOf: function(element, ancestor) { | |
1007 | element = $(element), ancestor = $(ancestor); | |
1008 | while (element = element.parentNode) | |
1009 | if (element == ancestor) return true; | |
1010 | return false; | |
1011 | }, | |
1012 | ||
scrollTo: function(element) { | ||
element = $(element); | ||
var x = element.x ? element.x : element.offsetLeft, | ||
... | ... | |
setStyle: function(element, style) { | ||
element = $(element); | ||
950 | | |
1040 | for (var name in style) | |
element.style[name.camelize()] = style[name]; | ||
}, | ||
... | ... | |
element.style.overflow = element._overflow; | ||
element._overflow = undefined; | ||
} | ||
1016 | ||
1106 | } | |
1108 | Object.extend(Element, Element.Methods); | |
1109 | ||
1110 | var _nativeExtensions = false; | |
1111 | ||
1112 | if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) { | |
1113 | var HTMLElement = {} | |
1114 | HTMLElement.prototype = document.createElement('div').__proto__; | |
1115 | } | |
1116 | ||
1117 | Element.addMethods = function(methods) { | |
1118 | Object.extend(Element.Methods, methods || {}); | |
1119 | ||
1120 | if(typeof HTMLElement != 'undefined') { | |
1121 | var methods = Element.Methods, cache = Element.extend.cache; | |
1122 | for (property in methods) { | |
1123 | var value = methods[property]; | |
1124 | if (typeof value == 'function') | |
1125 | HTMLElement.prototype[property] = cache.findOrStore(value); | |
1126 | } | |
1127 | _nativeExtensions = true; | |
1128 | } | |
1129 | } | |
1130 | ||
1131 | Element.addMethods(); | |
1132 | ||
var Toggle = new Object(); | ||
Toggle.display = Element.toggle; | ||
... | ... | |
try { | ||
this.element.insertAdjacentHTML(this.adjacency, this.content); | ||
} catch (e) { | ||
1036 | | |
1151 | var tagName = this.element.tagName.toLowerCase(); | |
1152 | if (tagName == 'tbody' || tagName == 'tr') { | |
this.insertContent(this.contentFromAnonymousTable()); | ||
} else { | ||
throw e; | ||
... | ... | |
} | ||
Object.extend(Element.ClassNames.prototype, Enumerable); | ||
1267 | var Selector = Class.create(); | |
1268 | Selector.prototype = { | |
1269 | initialize: function(expression) { | |
1270 | this.params = {classNames: []}; | |
1271 | this.expression = expression.toString().strip(); | |
1272 | this.parseExpression(); | |
1273 | this.compileMatcher(); | |
1274 | }, | |
1275 | ||
1276 | parseExpression: function() { | |
1277 | function abort(message) { throw 'Parse error in selector: ' + message; } | |
1278 | ||
1279 | if (this.expression == '') abort('empty expression'); | |
1280 | ||
1281 | var params = this.params, expr = this.expression, match, modifier, clause, rest; | |
1282 | while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) { | |
1283 | params.attributes = params.attributes || []; | |
1284 | params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''}); | |
1285 | expr = match[1]; | |
1286 | } | |
1287 | ||
1288 | if (expr == '*') return this.params.wildcard = true; | |
1289 | ||
1290 | while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) { | |
1291 | modifier = match[1], clause = match[2], rest = match[3]; | |
1292 | switch (modifier) { | |
1293 | case '#': params.id = clause; break; | |
1294 | case '.': params.classNames.push(clause); break; | |
1295 | case '': | |
1296 | case undefined: params.tagName = clause.toUpperCase(); break; | |
1297 | default: abort(expr.inspect()); | |
1298 | } | |
1299 | expr = rest; | |
1300 | } | |
1301 | ||
1302 | if (expr.length > 0) abort(expr.inspect()); | |
1303 | }, | |
1304 | ||
1305 | buildMatchExpression: function() { | |
1306 | var params = this.params, conditions = [], clause; | |
1307 | ||
1308 | if (params.wildcard) | |
1309 | conditions.push('true'); | |
1310 | if (clause = params.id) | |
1311 | conditions.push('element.id == ' + clause.inspect()); | |
1312 | if (clause = params.tagName) | |
1313 | conditions.push('element.tagName.toUpperCase() == ' + clause.inspect()); | |
1314 | if ((clause = params.classNames).length > 0) | |
1315 | for (var i = 0; i < clause.length; i++) | |
1316 | conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')'); | |
1317 | if (clause = params.attributes) { | |
1318 | clause.each(function(attribute) { | |
1319 | var value = 'element.getAttribute(' + attribute.name.inspect() + ')'; | |
1320 | var splitValueBy = function(delimiter) { | |
1321 | return value + ' && ' + value + '.split(' + delimiter.inspect() + ')'; | |
1322 | } | |
1323 | ||
1324 | switch (attribute.operator) { | |
1325 | case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break; | |
1326 | case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break; | |
1327 | case '|=': conditions.push( | |
1328 | splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect() | |
1329 | ); break; | |
1330 | case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break; | |
1331 | case '': | |
1332 | case undefined: conditions.push(value + ' != null'); break; | |
1333 | default: throw 'Unknown operator ' + attribute.operator + ' in selector'; | |
1334 | } | |
1335 | }); | |
1336 | } | |
1337 | ||
1338 | return conditions.join(' && '); | |
1339 | }, | |
1340 | ||
1341 | compileMatcher: function() { | |
1342 | this.match = new Function('element', 'if (!element.tagName) return false; \ | |
1343 | return ' + this.buildMatchExpression()); | |
1344 | }, | |
1345 | ||
1346 | findElements: function(scope) { | |
1347 | var element; | |
1348 | ||
1349 | if (element = $(this.params.id)) | |
1350 | if (this.match(element)) | |
1351 | if (!scope || Element.childOf(element, scope)) | |
1352 | return [element]; | |
1353 | ||
1354 | scope = (scope || document).getElementsByTagName(this.params.tagName || '*'); | |
1355 | ||
1356 | var results = []; | |
1357 | for (var i = 0; i < scope.length; i++) | |
1358 | if (this.match(element = scope[i])) | |
1359 | results.push(Element.extend(element)); | |
1360 | ||
1361 | return results; | |
1362 | }, | |
1363 | ||
1364 | toString: function() { | |
1365 | return this.expression; | |
1366 | } | |
1367 | } | |
1368 | ||
1369 | function $$() { | |
1370 | return $A(arguments).map(function(expression) { | |
1371 | return expression.strip().split(/\s+/).inject([null], function(results, expr) { | |
1372 | var selector = new Selector(expr); | |
1373 | return results.map(selector.findElements.bind(selector)).flatten(); | |
1374 | }); | |
1375 | }).flatten(); | |
1376 | } | |
var Field = { | ||
clear: function() { | ||
for (var i = 0; i < arguments.length; i++) | ||
... | ... | |
form = $(form); | ||
var elements = new Array(); | ||
1199 | | |
1425 | for (var tagName in Form.Element.Serializers) { | |
var tagElements = form.getElementsByTagName(tagName); | ||
for (var j = 0; j < tagElements.length; j++) | ||
elements.push(tagElements[j]); | ||
... | ... | |
var value = '', opt, index = element.selectedIndex; | ||
if (index >= 0) { | ||
opt = element.options[index]; | ||
1321 | | |
1322 | | |
1323 | | |
1547 | value = opt.value || opt.text; | |
} | ||
return [element.name, value]; | ||
}, | ||
selectMany: function(element) { | ||
1329 | | |
1553 | var value = []; | |
for (var i = 0; i < element.length; i++) { | ||
var opt = element.options[i]; | ||
1332 | | |
1333 | | |
1334 | | |
1335 | | |
1336 | | |
1337 | | |
1556 | if (opt.selected) | |
1557 | value.push(opt.value || opt.text); | |
} | ||
return [element.name, value]; | ||
} | ||
... | ... | |
}); | ||
/* prevent memory leaks in IE */ | ||
1554 | ||
1774 | if (navigator.appVersion.match(/\bMSIE\b/)) | |
1775 | Event.observe(window, 'unload', Event.unloadCache, false); | |
var Position = { | ||
// set to true if needed, warning: firefox performance problems | ||
// NOT neeeded for page scrolling, only if draggable contained in |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/number_helper.rb:
prev. | current | |
# human_size(1234567) => 1.2 MB | ||
# human_size(1234567890) => 1.1 GB | ||
def number_to_human_size(size) | ||
88 | | |
89 | | |
90 | | |
91 | | |
92 | | |
93 | | |
94 | | |
95 | | |
96 | | |
88 | case | |
89 | when size < 1.kilobyte: '%d Bytes' % size | |
90 | when size < 1.megabyte: '%.1f KB' % (size / 1.0.kilobyte) | |
91 | when size < 1.gigabyte: '%.1f MB' % (size / 1.0.megabyte) | |
92 | when size < 1.terabyte: '%.1f GB' % (size / 1.0.gigabyte) | |
93 | else '%.1f TB' % (size / 1.0.terabyte) | |
94 | end.sub('.0', '') | |
95 | rescue | |
96 | nil | |
end | ||
alias_method :human_size, :number_to_human_size # deprecated alias |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/pagination_helper.rb:
prev. | current | |
# | ||
# <%= link_to "Previous page", { :page => paginator.current.previous } if paginator.current.previous %> | ||
# | ||
9 | | |
9 | # <%= link_to "Next page", { :page => paginator.current.next } if paginator.current.next %> | |
module PaginationHelper | ||
unless const_defined?(:DEFAULT_OPTIONS) | ||
DEFAULT_OPTIONS = { |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/text_helper.rb:
prev. | current | |
# if the +text+ is longer than +length+. | ||
def truncate(text, length = 30, truncate_string = "...") | ||
if text.nil? then return end | ||
23 | ||
23 | l = length - truncate_string.length | |
if $KCODE == "NONE" | ||
25 | | |
25 | text.length > length ? text[0...l] + truncate_string : text | |
else | ||
chars = text.split(//) | ||
28 | | |
28 | chars.length > length ? chars[0...l].join + truncate_string : text | |
end | ||
end | ||
... | ... | |
end | ||
begin | ||
80 | | |
80 | require_library_or_gem "redcloth" | |
# Returns the text with all the Textile codes turned into HTML-tags. | ||
# <i>This method is only available if RedCloth can be required</i>. | ||
... | ... | |
end | ||
begin | ||
107 | | |
107 | require_library_or_gem "bluecloth" | |
# Returns the text with all the Markdown codes turned into HTML-tags. | ||
# <i>This method is only available if BlueCloth can be required</i>. | ||
... | ... | |
# truncate(text, 15) | ||
# end | ||
def auto_link(text, link = :all, href_options = {}, &block) | ||
145 | return '' if text.blank? | |
case link | ||
when :all then auto_link_urls(auto_link_email_addresses(text, &block), href_options, &block) | ||
when :email_addresses then auto_link_email_addresses(text, &block) | ||
... | ... | |
(?:www\.) # www.* | ||
) | ||
( | ||
327 | | |
328 | ([\w]+:?[=?&\/.-]?)* # url segment | |
\w+[\/]? # url tail | ||
(?:\#\w*)? # trailing anchor | ||
) |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/helpers/url_helper.rb:
prev. | current | |
include JavaScriptHelper | ||
# Returns the URL for the set of +options+ provided. This takes the same options | ||
13 | | |
13 | # as url_for. For a list, see the documentation for ActionController::Base#url_for. | |
# Note that it'll set :only_path => true so you'll get /controller/action instead of the | ||
# http://example.com/controller/action part (makes it harder to parse httpd log files) | ||
16 | # | |
17 | # When called from a view, url_for returns an HTML escaped url. If you need an unescaped | |
18 | # url, pass :escape => false to url_for. | |
19 | # | |
def url_for(options = {}, *parameters_for_method_reference) | ||
17 | | |
18 | | |
21 | if options.kind_of? Hash | |
22 | options = { :only_path => true }.update(options.symbolize_keys) | |
23 | escape = options.key?(:escape) ? options.delete(:escape) : true | |
24 | else | |
25 | escape = true | |
26 | end | |
27 | url = @controller.send(:url_for, options, *parameters_for_method_reference) | |
28 | escape ? html_escape(url) : url | |
end | ||
# Creates a link tag of the given +name+ using an URL created by the set of +options+. See the valid options in | ||
22 | | |
32 | # the documentation for ActionController::Base#url_for. It's also possible to pass a string instead of an options hash to | |
# get a link tag that just points without consideration. If nil is passed as a name, the link itself will become the name. | ||
# | ||
# The html_options has three special features. One for creating javascript confirm alerts where if you pass :confirm => 'Are you sure?', | ||
... | ... | |
else | ||
tag_options = nil | ||
end | ||
49 | | |
50 | | |
59 | url = options.is_a?(String) ? options : self.url_for(options, *parameters_for_method_reference) | |
60 | "<a href=\"#{url}\"#{tag_options}>#{name || url}</a>" | |
end | ||
# Generates a form containing a sole button that submits to the | ||
... | ... | |
if confirm = html_options.delete("confirm") | ||
html_options["onclick"] = "return #{confirm_javascript_function(confirm)};" | ||
end | ||
107 | ||
108 | | |
109 | | |
110 | | |
111 | ||
117 | ||
118 | url = options.is_a?(String) ? options : url_for(options) | |
119 | name ||= url | |
120 | ||
html_options.merge!("type" => "submit", "value" => name) | ||
"<form method=\"post\" action=\"#{h url}\" class=\"button-to\"><div>" + | ||
... | ... | |
for i in 0...tmp.length | ||
string << sprintf("%%%x",tmp[i]) | ||
end | ||
221 | | |
230 | "<script type=\"text/javascript\">eval(unescape('#{string}'))</script>" | |
elsif encode == 'hex' | ||
for i in 0...email_address.length | ||
if email_address[i,1] =~ /\w/ | ||
... | ... | |
# Returns true if the current page uri is generated by the options passed (in url_for format). | ||
def current_page?(options) | ||
238 | | |
247 | CGI.escapeHTML(url_for(options)) == @controller.request.request_uri | |
end | ||
private | ||
... | ... | |
end | ||
def post_javascript_function | ||
272 | | |
281 | "var f = document.createElement('form'); this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href; f.submit();" | |
end | ||
# Processes the _html_options_ hash, converting the boolean |
rool/rails/typo/trunk/vendor/rails/actionpack/lib/action_view/partials.rb:
prev. | current | |
add_counter_to_local_assigns!(partial_name, local_assigns) | ||
add_object_to_local_assigns!(partial_name, local_assigns, object) | ||
57 | | |
57 | if logger | |
58 | ActionController::Base.benchmark("Rendered #{path}/_#{partial_name}", Logger::DEBUG, false) do | |
59 | render("#{path}/_#{partial_name}", local_assigns) | |
60 | end | |
61 | else | |
render("#{path}/_#{partial_name}", local_assigns) | ||
end | ||
end | ||
... | ... | |
counter_name = partial_counter_name(partial_name) | ||
local_assigns[counter_name] = 1 unless local_assigns.has_key?(counter_name) | ||
end | ||
114 | | |
118 | ||
def add_object_to_local_assigns!(partial_name, local_assigns, object) | ||
116 | | |
117 | | |
120 | local_assigns[partial_name.intern] ||= | |
121 | if object.is_a?(ActionView::Base::ObjectWrapper) | |
122 | object.value | |
123 | else | |
124 | object | |
125 | end || controller.instance_variable_get("@#{partial_name}") | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/test/abstract_unit.rb:
prev. | current | |
$:.unshift(File.dirname(__FILE__) + '/../lib') | ||
2 | ||
2 | $:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib/active_support') | |
$:.unshift(File.dirname(__FILE__) + '/fixtures/helpers') | ||
5 | require 'yaml' | |
require 'test/unit' | ||
require 'action_controller' | ||
8 | require 'breakpoint' | |
require 'action_controller/test_process' | ||
ActionController::Base.logger = nil | ||
ActionController::Base.ignore_missing_templates = false | ||
12 | ||
13 | ||
14 | ActionController::Routing::Routes.reload rescue nil | |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/action_pack_assertions_test.rb:
prev. | current | |
def errors | ||
Class.new do | ||
90 | | |
90 | def full_messages; []; end | |
end.new | ||
end | ||
... | ... | |
def errors | ||
Class.new do | ||
109 | | |
109 | def full_messages; ['...stuff...']; end | |
end.new | ||
end | ||
end.new | ||
... | ... | |
assert_equal @response.body, 'request method: POST' | ||
end | ||
177 | | |
178 | | |
179 | | |
180 | | |
181 | | |
182 | | |
183 | | |
184 | | |
185 | | |
186 | | |
187 | | |
177 | # the following test fails because the request_method is now cached on the request instance | |
178 | # test the get/post switch within one test action | |
179 | # def test_get_post_switch | |
180 | # post :raise_on_get | |
181 | # assert_equal @response.body, 'request method: POST' | |
182 | # get :raise_on_post | |
183 | # assert_equal @response.body, 'request method: GET' | |
184 | # post :raise_on_get | |
185 | # assert_equal @response.body, 'request method: POST' | |
186 | # get :raise_on_post | |
187 | # assert_equal @response.body, 'request method: GET' | |
188 | # end | |
# test the assertion of goodies in the template | ||
def test_assert_template_has | ||
... | ... | |
@controller = ActionPackAssertionsController.new | ||
@request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new | ||
end | ||
482 | ||
def test_rendering_xml_sets_content_type | ||
process :hello_xml_world | ||
483 | | |
485 | assert_equal('application/xml', @controller.headers['Content-Type']) | |
end | ||
487 | ||
def test_rendering_xml_respects_content_type | ||
@response.headers['Content-Type'] = 'application/pdf' | ||
process :hello_xml_world | ||
assert_equal('application/pdf', @controller.headers['Content-Type']) | ||
end | ||
490 | ||
494 | end |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/base_test.rb:
prev. | current | |
require 'test/unit' | ||
require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late | ||
5 | ||
6 | ||
7 | ||
8 | ||
9 | ||
10 | ||
11 | ||
12 | ||
13 | ||
14 | ||
15 | ||
16 | | |
17 | | |
18 | | |
19 | | |
20 | | |
21 | | |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
30 | | |
31 | | |
32 | | |
33 | | |
5 | # Provide some controller to run the tests on. | |
6 | module Submodule | |
7 | class ContainedEmptyController < ActionController::Base | |
end | ||
35 | | |
36 | | |
37 | | |
38 | | |
9 | class ContainedNonEmptyController < ActionController::Base | |
def public_action | ||
end | ||
hide_action :hidden_action | ||
def hidden_action | ||
end | ||
16 | ||
17 | def another_hidden_action | |
18 | end | |
19 | hide_action :another_hidden_action | |
end | ||
21 | class SubclassedController < ContainedNonEmptyController | |
22 | hide_action :public_action # Hiding it here should not affect the superclass. | |
23 | end | |
end | ||
25 | class EmptyController < ActionController::Base | |
26 | include ActionController::Caching | |
27 | end | |
28 | class NonEmptyController < ActionController::Base | |
29 | def public_action | |
30 | end | |
31 | ||
32 | hide_action :hidden_action | |
33 | def hidden_action | |
34 | end | |
35 | end | |
class ControllerClassTests < Test::Unit::TestCase | ||
def test_controller_path | ||
50 | | |
51 | | |
39 | assert_equal 'empty', EmptyController.controller_path | |
40 | assert_equal 'submodule/contained_empty', Submodule::ContainedEmptyController.controller_path | |
end | ||
def test_controller_name | ||
54 | | |
55 | | |
43 | assert_equal 'empty', EmptyController.controller_name | |
44 | assert_equal 'contained_empty', Submodule::ContainedEmptyController.controller_name | |
end | ||
end | ||
class ControllerInstanceTests < Test::Unit::TestCase | ||
def setup | ||
61 | | |
62 | | |
63 | | |
50 | @empty = EmptyController.new | |
51 | @contained = Submodule::ContainedEmptyController.new | |
52 | @empty_controllers = [@empty, @contained, Submodule::SubclassedController.new] | |
65 | | |
66 | | |
54 | @non_empty_controllers = [NonEmptyController.new, | |
55 | Submodule::ContainedNonEmptyController.new] | |
end | ||
def test_action_methods |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/benchmark_test.rb:
prev. | current | |
require File.dirname(__FILE__) + '/../abstract_unit' | ||
require 'test/unit' | ||
4 | ||
5 | ||
6 | ||
7 | | |
8 | | |
9 | | |
10 | | |
4 | # Provide some static controllers. | |
5 | class BenchmarkedController < ActionController::Base | |
6 | def public_action | |
7 | render :nothing => true | |
8 | end | |
12 | | |
13 | | |
14 | | |
10 | def rescue_action(e) | |
11 | raise e | |
end | ||
end | ||
... | ... | |
end | ||
def setup | ||
25 | | |
22 | @controller = BenchmarkedController.new | |
# benchmark doesn't do anything unless a logger is set | ||
@controller.logger = MockLogger.new | ||
@request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/capture_test.rb:
prev. | current | |
def content_for | ||
render :layout => "talk_from_action" | ||
end | ||
10 | ||
11 | def erb_content_for | |
12 | render :layout => "talk_from_action" | |
13 | end | |
14 | ||
15 | def block_content_for | |
16 | render :layout => "talk_from_action" | |
17 | end | |
18 | ||
19 | def non_erb_block_content_for | |
20 | render :layout => "talk_from_action" | |
21 | end | |
def rescue_action(e) raise end | ||
end | ||
... | ... | |
def test_content_for | ||
get :content_for | ||
37 | | |
49 | assert_equal expected_content_for_output, @response.body | |
end | ||
51 | ||
52 | def test_erb_content_for | |
53 | get :content_for | |
54 | assert_equal expected_content_for_output, @response.body | |
55 | end | |
56 | ||
57 | def test_block_content_for | |
58 | get :block_content_for | |
59 | assert_equal expected_content_for_output, @response.body | |
60 | end | |
61 | ||
62 | def test_non_erb_block_content_for | |
63 | get :non_erb_block_content_for | |
64 | assert_equal expected_content_for_output, @response.body | |
65 | end | |
def test_update_element_with_capture | ||
get :update_element_with_capture | ||
... | ... | |
@response.body.strip | ||
) | ||
end | ||
75 | ||
76 | private | |
77 | def expected_content_for_output | |
78 | "<title>Putting stuff in the title!</title>\n\nGreat stuff!" | |
79 | end | |
end |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/cgi_test.rb:
prev. | current | |
class CGIRequestTest < Test::Unit::TestCase | ||
def setup | ||
@request_hash = {"HTTP_MAX_FORWARDS"=>"10", "SERVER_NAME"=>"glu.ttono.us:8007", "FCGI_ROLE"=>"RESPONDER", "HTTP_X_FORWARDED_HOST"=>"glu.ttono.us", "HTTP_ACCEPT_ENCODING"=>"gzip, deflate", "HTTP_USER_AGENT"=>"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/312.5.1 (KHTML, like Gecko) Safari/312.3.1", "PATH_INFO"=>"", "HTTP_ACCEPT_LANGUAGE"=>"en", "HTTP_HOST"=>"glu.ttono.us:8007", "SERVER_PROTOCOL"=>"HTTP/1.1", "REDIRECT_URI"=>"/dispatch.fcgi", "SCRIPT_NAME"=>"/dispatch.fcgi", "SERVER_ADDR"=>"207.7.108.53", "REMOTE_ADDR"=>"207.7.108.53", "SERVER_SOFTWARE"=>"lighttpd/1.4.5", "HTTP_COOKIE"=>"_session_id=c84ace84796670c052c6ceb2451fb0f2; is_admin=yes", "HTTP_X_FORWARDED_SERVER"=>"glu.ttono.us", "REQUEST_URI"=>"/admin", "DOCUMENT_ROOT"=>"/home/kevinc/sites/typo/public", "SERVER_PORT"=>"8007", "QUERY_STRING"=>"", "REMOTE_PORT"=>"63137", "GATEWAY_INTERFACE"=>"CGI/1.1", "HTTP_X_FORWARDED_FOR"=>"65.88.180.234", "HTTP_ACCEPT"=>"*/*", "SCRIPT_FILENAME"=>"/home/kevinc/sites/typo/public/dispatch.fcgi", "REDIRECT_STATUS"=>"200", "REQUEST_METHOD"=>"GET"} | ||
316 | # cookie as returned by some Nokia phone browsers (no space after semicolon separator) | |
317 | @alt_cookie_fmt_request_hash = {"HTTP_COOKIE"=>"_session_id=c84ace84796670c052c6ceb2451fb0f2;is_admin=yes"} | |
@fake_cgi = Struct.new(:env_table).new(@request_hash) | ||
@request = ActionController::CgiRequest.new(@fake_cgi) | ||
end | ||
... | ... | |
@request_hash.delete "HTTP_X_FORWARDED_HOST" | ||
@request_hash['HTTP_HOST'] = "rubyonrails.org:8080" | ||
assert_equal "rubyonrails.org:8080", @request.host_with_port | ||
330 | ||
331 | @request_hash['HTTP_X_FORWARDED_HOST'] = "www.firsthost.org, www.secondhost.org" | |
332 | assert_equal "www.secondhost.org", @request.host | |
end | ||
335 | def test_http_host_with_default_port_overrides_server_port | |
336 | @request_hash.delete "HTTP_X_FORWARDED_HOST" | |
337 | @request_hash['HTTP_HOST'] = "rubyonrails.org" | |
338 | assert_equal "rubyonrails.org", @request.host_with_port | |
339 | end | |
340 | ||
341 | def test_host_with_port_defaults_to_server_name_if_no_host_headers | |
342 | @request_hash.delete "HTTP_X_FORWARDED_HOST" | |
343 | @request_hash.delete "HTTP_HOST" | |
344 | assert_equal "glu.ttono.us:8007", @request.host_with_port | |
345 | end | |
346 | ||
347 | def test_host_with_port_falls_back_to_server_addr_if_necessary | |
348 | @request_hash.delete "HTTP_X_FORWARDED_HOST" | |
349 | @request_hash.delete "HTTP_HOST" | |
350 | @request_hash.delete "SERVER_NAME" | |
351 | assert_equal "207.7.108.53:8007", @request.host_with_port | |
352 | end | |
353 | ||
354 | def test_cookie_syntax_resilience | |
355 | cookies = CGI::Cookie::parse(@request_hash["HTTP_COOKIE"]); | |
356 | assert_equal ["c84ace84796670c052c6ceb2451fb0f2"], cookies["_session_id"] | |
357 | assert_equal ["yes"], cookies["is_admin"] | |
358 | ||
359 | alt_cookies = CGI::Cookie::parse(@alt_cookie_fmt_request_hash["HTTP_COOKIE"]); | |
360 | assert_equal ["c84ace84796670c052c6ceb2451fb0f2"], alt_cookies["_session_id"] | |
361 | assert_equal ["yes"], alt_cookies["is_admin"] | |
362 | end | |
end |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/custom_handler_test.rb:
prev. | current | |
class CustomHandlerTest < Test::Unit::TestCase | ||
def setup | ||
ActionView::Base.register_template_handler "foo", CustomHandler | ||
18 | ActionView::Base.register_template_handler :foo2, CustomHandler | |
@view = ActionView::Base.new | ||
end | ||
... | ... | |
result ) | ||
end | ||
29 | def test_custom_render2 | |
30 | result = @view.render_template( "foo2", "hello <%= one %>", nil, :one => "two" ) | |
31 | assert_equal( | |
32 | [ "hello <%= one %>", { :one => "two" }, @view ], | |
33 | result ) | |
34 | end | |
35 | ||
def test_unhandled_extension | ||
# uses the ERb handler by default if the extension isn't recognized | ||
result = @view.render_template( "bar", "hello <%= one %>", nil, :one => "two" ) |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/fake_controllers.rb:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
1 | class << Object; alias_method :const_available?, :const_defined?; end | |
6 | | |
7 | | |
8 | ||
9 | | |
10 | | |
11 | | |
12 | | |
13 | | |
14 | | |
15 | | |
16 | | |
17 | | |
18 | | |
3 | class ContentController < Class.new(ActionController::Base) | |
end | ||
5 | class NotAController | |
6 | end | |
7 | module Admin | |
8 | class << self; alias_method :const_available?, :const_defined?; end | |
9 | class UserController < Class.new(ActionController::Base); end | |
10 | class NewsFeedController < Class.new(ActionController::Base); end | |
11 | end | |
ActionController::Routing::Routes.draw do |map| | ||
map.route_one 'route_one', :controller => 'elsewhere', :action => 'flash_me' |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/filters_test.rb:
prev. | current | |
class FilterTest < Test::Unit::TestCase | ||
class TestController < ActionController::Base | ||
before_filter :ensure_login | ||
6 | after_filter :clean_up | |
def show | ||
render :inline => "ran action" | ||
... | ... | |
@ran_filter ||= [] | ||
@ran_filter << "ensure_login" | ||
end | ||
17 | ||
18 | def clean_up | |
19 | @ran_after_filter ||= [] | |
20 | @ran_after_filter << "clean_up" | |
21 | end | |
end | ||
class RenderingController < ActionController::Base | ||
... | ... | |
class PrependingController < TestController | ||
prepend_before_filter :wonderful_life | ||
102 | | |
108 | # skip_before_filter :fire_flash | |
private | ||
def wonderful_life | ||
... | ... | |
end | ||
end | ||
117 | class ConditionalSkippingController < TestController | |
118 | skip_before_filter :ensure_login, :only => [ :login ] | |
119 | skip_after_filter :clean_up, :only => [ :login ] | |
120 | ||
121 | before_filter :find_user, :only => [ :change_password ] | |
122 | ||
123 | def login | |
124 | render :inline => "ran action" | |
125 | end | |
126 | ||
127 | def change_password | |
128 | render :inline => "ran action" | |
129 | end | |
130 | ||
131 | protected | |
132 | def find_user | |
133 | @ran_filter ||= [] | |
134 | @ran_filter << "find_user" | |
135 | end | |
136 | end | |
137 | ||
138 | class ConditionalParentOfConditionalSkippingController < ConditionalFilterController | |
139 | before_filter :conditional_in_parent, :only => [:show, :another_action] | |
140 | after_filter :conditional_in_parent, :only => [:show, :another_action] | |
141 | ||
142 | private | |
143 | ||
144 | def conditional_in_parent | |
145 | @ran_filter ||= [] | |
146 | @ran_filter << 'conditional_in_parent' | |
147 | end | |
148 | end | |
149 | ||
150 | class ChildOfConditionalParentController < ConditionalParentOfConditionalSkippingController | |
151 | skip_before_filter :conditional_in_parent, :only => :another_action | |
152 | skip_after_filter :conditional_in_parent, :only => :another_action | |
153 | end | |
154 | ||
class ProcController < PrependingController | ||
before_filter(proc { |c| c.assigns["ran_proc_filter"] = true }) | ||
end | ||
... | ... | |
class MixedFilterController < PrependingController | ||
cattr_accessor :execution_log | ||
216 | ||
def initialize | ||
@@execution_log = "" | ||
end | ||
... | ... | |
end | ||
def test_added_filter_to_inheritance_graph | ||
221 | | |
266 | assert_equal [ :ensure_login ], TestController.before_filters | |
end | ||
def test_base_class_in_isolation | ||
225 | | |
270 | assert_equal [ ], ActionController::Base.before_filters | |
end | ||
def test_prepending_filter | ||
... | ... | |
end | ||
end | ||
391 | def test_conditional_skipping_of_filters | |
392 | assert_nil test_process(ConditionalSkippingController, "login").template.assigns["ran_filter"] | |
393 | assert_equal %w( ensure_login find_user ), test_process(ConditionalSkippingController, "change_password").template.assigns["ran_filter"] | |
394 | ||
395 | assert_nil test_process(ConditionalSkippingController, "login").template.controller.instance_variable_get("@ran_after_filter") | |
396 | assert_equal %w( clean_up ), test_process(ConditionalSkippingController, "change_password").template.controller.instance_variable_get("@ran_after_filter") | |
397 | end | |
398 | ||
399 | def test_conditional_skipping_of_filters_when_parent_filter_is_also_conditional | |
400 | assert_equal %w( conditional_in_parent conditional_in_parent ), test_process(ChildOfConditionalParentController).template.assigns['ran_filter'] | |
401 | assert_nil test_process(ChildOfConditionalParentController, 'another_action').template.assigns['ran_filter'] | |
402 | end | |
403 | ||
private | ||
def test_process(controller, action = "show") | ||
request = ActionController::TestRequest.new |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/flash_test.rb:
prev. | current | |
end | ||
def setup | ||
44 | | |
44 | @request = ActionController::TestRequest.new | |
45 | @response = ActionController::TestResponse.new | |
46 | @controller = TestController.new | |
end | ||
def test_flash | ||
48 | | |
49 | | |
50 | get :set_flash | |
51 | | |
52 | | |
53 | | |
54 | | |
52 | get :use_flash | |
53 | assert_equal "hello", @response.template.assigns["flash_copy"]["that"] | |
54 | assert_equal "hello", @response.template.assigns["flashy"] | |
56 | | |
57 | | |
56 | get :use_flash | |
57 | assert_nil @response.template.assigns["flash_copy"]["that"], "On second flash" | |
end | ||
def test_keep_flash | ||
61 | | |
62 | | |
61 | get :set_flash | |
64 | | |
65 | | |
66 | | |
67 | | |
63 | get :use_flash_and_keep_it | |
64 | assert_equal "hello", @response.template.assigns["flash_copy"]["that"] | |
65 | assert_equal "hello", @response.template.assigns["flashy"] | |
69 | | |
70 | | |
71 | | |
67 | get :use_flash | |
68 | assert_equal "hello", @response.template.assigns["flash_copy"]["that"], "On second flash" | |
73 | | |
74 | | |
70 | get :use_flash | |
71 | assert_nil @response.template.assigns["flash_copy"]["that"], "On third flash" | |
end | ||
def test_flash_now | ||
78 | | |
79 | | |
80 | | |
81 | | |
82 | | |
75 | get :set_flash_now | |
76 | assert_equal "hello", @response.template.assigns["flash_copy"]["that"] | |
77 | assert_equal "bar" , @response.template.assigns["flash_copy"]["foo"] | |
78 | assert_equal "hello", @response.template.assigns["flashy"] | |
84 | | |
85 | | |
86 | | |
87 | | |
88 | | |
80 | get :attempt_to_use_flash_now | |
81 | assert_nil @response.template.assigns["flash_copy"]["that"] | |
82 | assert_nil @response.template.assigns["flash_copy"]["foo"] | |
83 | assert_nil @response.template.assigns["flashy"] | |
end | ||
90 | | |
91 | | |
92 | | |
93 | | |
94 | | |
95 | | |
96 | | |
97 | | |
98 | | |
99 | | |
100 | ||
85 | end | |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/fragment_store_setting_test.rb:
prev. | current | |
ActionController::Caching::Fragments::MemCacheStore, | ||
ActionController::Base.fragment_cache_store | ||
) | ||
34 | | |
34 | assert_equal %w(localhost), ActionController::Base.fragment_cache_store.addresses | |
end | ||
def test_object_assigned_fragment_cache_store |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/new_render_test.rb:
prev. | current | |
end | ||
end | ||
12 | module NewRenderTestHelper | |
13 | def rjs_helper_method_from_module | |
14 | page.visual_effect :highlight | |
15 | end | |
16 | end | |
17 | ||
class NewRenderTestController < ActionController::Base | ||
layout :determine_layout | ||
... | ... | |
def render_action_hello_world | ||
render :action => "hello_world" | ||
end | ||
39 | ||
40 | def render_action_hello_world_as_symbol | |
41 | render :action => :hello_world | |
42 | end | |
def render_text_hello_world | ||
render :text => "hello world" | ||
... | ... | |
render :text => "hello world", :layout => true | ||
end | ||
53 | def hello_world_with_layout_false | |
54 | render :layout => false | |
55 | end | |
56 | ||
def render_custom_code | ||
render :text => "hello world", :status => "404 Moved" | ||
end | ||
... | ... | |
@secret = 'in the sauce' | ||
render :file => 'test/render_file_with_ivar', :use_full_path => true | ||
end | ||
76 | ||
77 | def render_file_not_using_full_path_with_relative_path | |
78 | @secret = 'in the sauce' | |
79 | render :file => 'test/../test/render_file_with_ivar', :use_full_path => true | |
80 | end | |
82 | def render_file_not_using_full_path_with_dot_in_path | |
83 | @secret = 'in the sauce' | |
84 | render :file => 'test/dot.directory/render_file_with_ivar', :use_full_path => true | |
85 | end | |
86 | ||
def render_xml_hello | ||
@name = "David" | ||
render :template => "test/hello" | ||
... | ... | |
render :action => "potential_conflicts" | ||
end | ||
197 | def hello_world_from_rxml_using_action | |
198 | render :action => "hello_world.rxml" | |
199 | end | |
200 | ||
201 | def hello_world_from_rxml_using_template | |
202 | render :template => "test/hello_world.rxml" | |
203 | end | |
204 | ||
205 | helper NewRenderTestHelper | |
206 | helper do | |
207 | def rjs_helper_method(value) | |
208 | page.visual_effect :highlight, value | |
209 | end | |
210 | end | |
211 | ||
212 | def enum_rjs_test | |
213 | render :update do |page| | |
214 | page.select('.product').each do |value| | |
215 | page.rjs_helper_method_from_module | |
216 | page.rjs_helper_method(value) | |
217 | page.sortable(value, :url => { :action => "order" }) | |
218 | page.draggable(value) | |
219 | end | |
220 | end | |
221 | end | |
222 | ||
223 | def delete_with_js | |
224 | @project_id = 4 | |
225 | end | |
226 | ||
227 | def render_js_with_explicit_template | |
228 | @project_id = 4 | |
229 | render :template => 'test/delete_with_js' | |
230 | end | |
231 | ||
232 | def render_js_with_explicit_action_template | |
233 | @project_id = 4 | |
234 | render :action => 'delete_with_js' | |
235 | end | |
236 | ||
237 | def update_page | |
238 | render :update do |page| | |
239 | page.replace_html 'balance', '$37,000,000.00' | |
240 | page.visual_effect :highlight, 'balance' | |
241 | end | |
242 | end | |
243 | ||
244 | def update_page_with_instance_variables | |
245 | @money = '$37,000,000.00' | |
246 | @div_id = 'balance' | |
247 | render :update do |page| | |
248 | page.replace_html @div_id, @money | |
249 | page.visual_effect :highlight, @div_id | |
250 | end | |
251 | end | |
252 | ||
def action_talk_to_layout | ||
# Action template sets variable that's picked up by layout | ||
end | ||
... | ... | |
when "hello_world", "layout_test", "rendering_without_layout", | ||
"rendering_nothing_on_layout", "render_text_hello_world", | ||
"render_text_hello_world_with_layout", | ||
274 | "hello_world_with_layout_false", | |
"partial_only", "partial_only_with_layout", | ||
"accessing_params_in_template", | ||
"accessing_params_in_template_with_layout", | ||
197 | | |
278 | "render_with_explicit_template", | |
279 | "render_js_with_explicit_template", | |
280 | "render_js_with_explicit_action_template", | |
281 | "delete_with_js", "update_page", "update_page_with_instance_variables" | |
282 | ||
"layouts/standard" | ||
when "builder_layout_test" | ||
"layouts/builder" | ||
... | ... | |
assert_template "test/hello_world" | ||
end | ||
331 | def test_do_with_render_action_as_symbol | |
332 | get :render_action_hello_world_as_symbol | |
333 | assert_template "test/hello_world" | |
334 | end | |
335 | ||
def test_do_with_render_text | ||
get :render_text_hello_world | ||
assert_equal "hello world", @response.body | ||
... | ... | |
assert_equal "<html>hello world, I'm here!</html>", @response.body | ||
end | ||
346 | def test_do_with_render_action_and_layout_false | |
347 | get :hello_world_with_layout_false | |
348 | assert_equal 'Hello world!', @response.body | |
349 | end | |
350 | ||
def test_do_with_render_custom_code | ||
get :render_custom_code | ||
assert_response :missing | ||
... | ... | |
assert_equal "The secret is in the sauce\n", @response.body | ||
end | ||
366 | def test_render_file_not_using_full_path_with_relative_path | |
367 | get :render_file_not_using_full_path_with_relative_path | |
368 | assert_equal "The secret is in the sauce\n", @response.body | |
369 | end | |
370 | ||
371 | def test_render_file_not_using_full_path_with_dot_in_path | |
372 | get :render_file_not_using_full_path_with_dot_in_path | |
373 | assert_equal "The secret is in the sauce\n", @response.body | |
374 | end | |
375 | ||
def test_render_file_with_locals | ||
get :render_file_with_locals | ||
assert_equal "The secret is in the sauce\n", @response.body | ||
... | ... | |
assert_equal "<html>\n <p>Hello David</p>\n<p>This is grand!</p>\n</html>\n", @response.body | ||
end | ||
413 | def test_enum_rjs_test | |
414 | get :enum_rjs_test | |
415 | assert_equal <<-EOS.strip, @response.body | |
416 | $$(".product").each(function(value, index) { | |
417 | new Effect.Highlight(element,{}); | |
418 | new Effect.Highlight(value,{}); | |
419 | Sortable.create(value, {onUpdate:function(){new Ajax.Request('/test/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(value)})}}); | |
420 | new Draggable(value, {}); | |
421 | }); | |
422 | EOS | |
423 | end | |
424 | ||
def test_render_xml_with_default | ||
get :greeting | ||
assert_equal "<p>This is grand!</p>\n", @response.body | ||
end | ||
430 | def test_render_rjs_with_default | |
431 | get :delete_with_js | |
432 | assert_equal %!["person"].each(Element.remove);\nnew Effect.Highlight(\"project-4\",{});!, @response.body | |
433 | end | |
434 | ||
435 | def test_render_rjs_template_explicitly | |
436 | get :render_js_with_explicit_template | |
437 | assert_equal %!["person"].each(Element.remove);\nnew Effect.Highlight(\"project-4\",{});!, @response.body | |
438 | end | |
439 | ||
440 | def test_rendering_rjs_action_explicitly | |
441 | get :render_js_with_explicit_action_template | |
442 | assert_equal %!["person"].each(Element.remove);\nnew Effect.Highlight(\"project-4\",{});!, @response.body | |
443 | end | |
444 | ||
def test_layout_rendering | ||
get :layout_test | ||
assert_equal "<html>Hello world!</html>", @response.body | ||
... | ... | |
assert_equal "world", assigns["hello"] | ||
end | ||
572 | def test_update_page | |
573 | get :update_page | |
574 | assert_template nil | |
575 | assert_equal 'text/javascript; charset=UTF-8', @response.headers['Content-Type'] | |
576 | assert_equal 2, @response.body.split($/).length | |
577 | end | |
578 | ||
579 | def test_update_page_with_instance_variables | |
580 | get :update_page_with_instance_variables | |
581 | assert_template nil | |
582 | assert_equal 'text/javascript; charset=UTF-8', @response.headers['Content-Type'] | |
583 | assert_match /balance/, @response.body | |
584 | assert_match /\$37/, @response.body | |
585 | end | |
586 | ||
def test_yield_content_for | ||
get :yield_content_for | ||
assert_equal "<title>Putting stuff in the title!</title>\n\nGreat stuff!\n", @response.body | ||
end | ||
591 | ||
592 | ||
593 | def test_overwritting_rendering_relative_file_with_extension | |
594 | get :hello_world_from_rxml_using_template | |
595 | assert_equal "<html>\n <p>Hello</p>\n</html>\n", @response.body | |
596 | ||
597 | get :hello_world_from_rxml_using_action | |
598 | assert_equal "<html>\n <p>Hello</p>\n</html>\n", @response.body | |
599 | end | |
end |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/redirect_test.rb:
prev. | current | |
end | ||
def rescue_errors(e) raise e end | ||
30 | ||
31 | def rescue_action(e) raise end | |
protected | ||
def dashbord_url(id, message) | ||
... | ... | |
assert_redirected_to :action => "other_host", :only_path => false, :host => 'other.test.host' | ||
end | ||
61 | def test_redirect_error_with_pretty_diff | |
62 | get :host_redirect | |
63 | begin | |
64 | assert_redirected_to :action => "other_host", :only_path => true | |
65 | rescue Test::Unit::AssertionFailedError => err | |
66 | redirection_msg, diff_msg = err.message.scan(/<\{[^\}]+\}>/).collect { |s| s[2..-3] } | |
67 | assert_match %r(:only_path=>false), redirection_msg | |
68 | assert_match %r(:host=>"other.test.host"), redirection_msg | |
69 | assert_match %r(:action=>"other_host"), redirection_msg | |
70 | assert_match %r(:only_path=>true), diff_msg | |
71 | assert_match %r(:host=>"other.test.host"), diff_msg | |
72 | end | |
73 | end | |
74 | ||
def test_module_redirect | ||
get :module_redirect | ||
assert_redirect_url "http://test.host/module_test/module_redirect/hello_world" | ||
... | ... | |
get :redirect_to_back | ||
assert_redirect_url "http://www.example.com/coming/from" | ||
end | ||
95 | ||
96 | def test_redirect_to_back_with_no_referer | |
97 | assert_raises(ActionController::RedirectBackError) { | |
98 | @request.env["HTTP_REFERER"] = nil | |
99 | get :redirect_to_back | |
100 | } | |
101 | end | |
end | ||
module ModuleTest |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/render_test.rb:
prev. | current | |
def render_action_hello_world | ||
render_action "hello_world" | ||
end | ||
33 | | |
33 | ||
34 | def render_action_hello_world_with_symbol | |
35 | render_action :hello_world | |
36 | end | |
37 | ||
def render_text_hello_world | ||
render_text "hello world" | ||
end | ||
... | ... | |
def setup | ||
@request = ActionController::TestRequest.new | ||
@response = ActionController::TestResponse.new | ||
118 | @controller = TestController.new | |
@request.host = "www.nextangle.com" | ||
end | ||
def test_simple_show | ||
119 | | |
120 | | |
121 | | |
122 | | |
124 | get :hello_world | |
125 | assert_response 200 | |
126 | assert_template "test/hello_world" | |
end | ||
def test_do_with_render | ||
126 | | |
127 | | |
130 | get :render_hello_world | |
131 | assert_template "test/hello_world" | |
end | ||
def test_do_with_render_from_variable | ||
131 | | |
132 | | |
135 | get :render_hello_world_from_variable | |
136 | assert_equal "hello david", @response.body | |
end | ||
def test_do_with_render_action | ||
136 | | |
137 | | |
140 | get :render_action_hello_world | |
141 | assert_template "test/hello_world" | |
end | ||
144 | def test_do_with_render_action_with_symbol | |
145 | get :render_action_hello_world_with_symbol | |
146 | assert_template "test/hello_world" | |
147 | end | |
148 | ||
def test_do_with_render_text | ||
141 | | |
142 | | |
150 | get :render_text_hello_world | |
151 | assert_equal "hello world", @response.body | |
end | ||
def test_do_with_render_custom_code | ||
146 | | |
147 | | |
155 | get :render_custom_code | |
156 | assert_response 404 | |
end | ||
def test_attempt_to_access_object_method | ||
151 | | |
152 | | |
160 | assert_raises(ActionController::UnknownAction, "No action responded to [clone]") { get :clone } | |
end | ||
def test_private_methods | ||
156 | | |
157 | | |
164 | assert_raises(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout } | |
end | ||
def test_access_to_request_in_view | ||
... | ... | |
ActionController::Base.view_controller_internals = false | ||
ActionController::Base.protected_variables_cache = nil | ||
166 | | |
167 | | |
168 | | |
173 | get :hello_world | |
174 | assert_nil assigns["request"] | |
ActionController::Base.view_controller_internals = true | ||
ActionController::Base.protected_variables_cache = nil | ||
173 | | |
174 | | |
175 | | |
179 | get :hello_world | |
180 | assert_kind_of ActionController::AbstractRequest, assigns["request"] | |
ActionController::Base.view_controller_internals = view_internals_old_value | ||
ActionController::Base.protected_variables_cache = nil | ||
end | ||
def test_render_xml | ||
182 | | |
183 | | |
187 | get :render_xml_hello | |
188 | assert_equal "<html>\n <p>Hello David</p>\n<p>This is grand!</p>\n</html>\n", @response.body | |
end | ||
def test_render_xml_with_default | ||
187 | | |
188 | | |
192 | get :greeting | |
193 | assert_equal "<p>This is grand!</p>\n", @response.body | |
end | ||
def test_layout_rendering | ||
192 | | |
193 | | |
197 | get :layout_test | |
198 | assert_equal "<html>Hello world!</html>", @response.body | |
end | ||
def test_render_xml_with_layouts | ||
197 | | |
198 | | |
202 | get :builder_layout_test | |
203 | assert_equal "<wrapper>\n<html>\n <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n", @response.body | |
end | ||
# def test_partials_list | ||
202 | | |
207 | # get :partials_list | |
# assert_equal "goodbyeHello: davidHello: marygoodbye\n", process_request.body | ||
# end | ||
def test_partial_only | ||
207 | | |
208 | | |
212 | get :partial_only | |
213 | assert_equal "only partial", @response.body | |
end | ||
def test_render_to_string | ||
212 | | |
213 | | |
217 | get :hello_in_a_string | |
218 | assert_equal "How's there? goodbyeHello: davidHello: marygoodbye\n", @response.body | |
end | ||
def test_render_to_string_resets_assigns | ||
217 | | |
218 | | |
222 | get :render_to_string_test | |
223 | assert_equal "The value of foo is: ::this is a test::\n", @response.body | |
end | ||
def test_nested_rendering | ||
222 | | |
223 | | |
227 | @controller = Fun::GamesController.new | |
228 | get :hello_world | |
229 | assert_equal "Living in a nested world", @response.body | |
end | ||
def test_accessing_params_in_template | ||
227 | | |
228 | | |
229 | | |
233 | get :accessing_params_in_template, :name => "David" | |
234 | assert_equal "Hello: David", @response.body | |
end | ||
def test_accessing_local_assigns_in_inline_template | ||
233 | | |
234 | | |
235 | | |
238 | get :accessing_local_assigns_in_inline_template, :local_name => "Local David" | |
239 | assert_equal "Goodbye, Local David", @response.body | |
end | ||
def test_accessing_local_assigns_in_inline_template_with_string_keys | ||
239 | | |
240 | | |
241 | | |
243 | get :accessing_local_assigns_in_inline_template_with_string_keys, :local_name => "Local David" | |
244 | assert_equal "Goodbye, Local David", @response.body | |
end | ||
243 | ||
244 | | |
245 | | |
246 | | |
247 | | |
end |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/request_test.rb:
prev. | current | |
@request.relative_url_root = nil | ||
@request.env['SCRIPT_NAME'] = "/collaboration/hieraki" | ||
assert_equal "/collaboration/hieraki", @request.relative_url_root | ||
108 | ||
109 | @request.relative_url_root = nil | |
110 | @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi" | |
111 | @request.env['SERVER_SOFTWARE'] = 'lighttpd/1.2.3' | |
112 | @request.env['RAILS_RELATIVE_URL_ROOT'] = "/hieraki" | |
113 | assert_equal "/hieraki", @request.relative_url_root | |
114 | ||
115 | # @env overrides path guess | |
116 | @request.relative_url_root = nil | |
117 | @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi" | |
118 | @request.env['SERVER_SOFTWARE'] = 'apache/1.2.3 some random text' | |
119 | @request.env['RAILS_RELATIVE_URL_ROOT'] = "/real_url" | |
120 | assert_equal "/real_url", @request.relative_url_root | |
end | ||
def test_request_uri | ||
... | ... | |
assert @request.xml_http_request? | ||
assert @request.xhr? | ||
end | ||
253 | ||
254 | def test_reports_ssl | |
255 | assert !@request.ssl? | |
256 | @request.env['HTTPS'] = 'on' | |
257 | assert @request.ssl? | |
258 | end | |
259 | ||
260 | def test_reports_ssl_when_proxied_via_lighttpd | |
261 | assert !@request.ssl? | |
262 | @request.env['HTTP_X_FORWARDED_PROTO'] = 'https' | |
263 | assert @request.ssl? | |
264 | end | |
end |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/routing_test.rb:
prev. | current | |
require File.dirname(__FILE__) + '/../abstract_unit' | ||
2 | require 'test/unit' | |
require File.dirname(__FILE__) + '/fake_controllers' | ||
3 | ||
require 'stringio' | ||
RunTimeTests = ARGV.include? 'time' | ||
... | ... | |
def setup | ||
@source = Source.new | ||
end | ||
15 | | |
15 | ||
def test_initial_state | ||
assert_equal [], source.lines | ||
assert_equal 0, source.indentation_level | ||
... | ... | |
def setup | ||
@generator = CodeGenerator.new | ||
end | ||
57 | ||
57 | ||
def test_initial_state | ||
assert_equal [], generator.source.lines | ||
assert_equal [], generator.locals | ||
... | ... | |
def test_all_static | ||
c = %w(hello world how are you).collect {|str| Static.new(str)} | ||
127 | | |
127 | g.result :controller, "::ContentController", true | |
g.constant_result :action, 'index' | ||
go c | ||
... | ... | |
assert_nil execute('hello/world/how') | ||
assert_nil execute('hello/world/how/are') | ||
assert_nil execute('hello/world/how/are/you/today') | ||
136 | | |
136 | assert_equal({:controller => ::ContentController, :action => 'index'}, execute('hello/world/how/are/you')) | |
end | ||
def test_basic_dynamic | ||
c = [Static.new("hi"), Dynamic.new(:action)] | ||
141 | | |
141 | g.result :controller, "::ContentController", true | |
go c | ||
assert_nil execute('boo') | ||
assert_nil execute('boo/blah') | ||
assert_nil execute('hi') | ||
assert_nil execute('hi/dude/what') | ||
148 | | |
148 | assert_equal({:controller => ::ContentController, :action => 'dude'}, execute('hi/dude')) | |
end | ||
def test_basic_dynamic_backwards | ||
... | ... | |
def test_dynamic_with_default | ||
c = [Static.new("hi"), Dynamic.new(:action, :default => 'index')] | ||
166 | | |
166 | g.result :controller, "::ContentController", true | |
go c | ||
assert_nil execute('boo') | ||
assert_nil execute('boo/blah') | ||
assert_nil execute('hi/dude/what') | ||
172 | | |
173 | | |
174 | | |
172 | assert_equal({:controller => ::ContentController, :action => 'index'}, execute('hi')) | |
173 | assert_equal({:controller => ::ContentController, :action => 'index'}, execute('hi/index')) | |
174 | assert_equal({:controller => ::ContentController, :action => 'dude'}, execute('hi/dude')) | |
end | ||
def test_dynamic_with_string_condition | ||
c = [Static.new("hi"), Dynamic.new(:action, :condition => 'index')] | ||
179 | | |
179 | g.result :controller, "::ContentController", true | |
go c | ||
assert_nil execute('boo') | ||
assert_nil execute('boo/blah') | ||
assert_nil execute('hi') | ||
assert_nil execute('hi/dude/what') | ||
186 | | |
186 | assert_equal({:controller => ::ContentController, :action => 'index'}, execute('hi/index')) | |
assert_nil execute('hi/dude') | ||
end | ||
def test_dynamic_with_string_condition_backwards | ||
c = [Dynamic.new(:action, :condition => 'index'), Static.new("hi")] | ||
192 | | |
192 | g.result :controller, "::ContentController", true | |
go c | ||
assert_nil execute('boo') | ||
... | ... | |
assert_nil execute('hi') | ||
assert_nil execute('dude/what/hi') | ||
assert_nil execute('index/what') | ||
200 | | |
200 | assert_equal({:controller => ::ContentController, :action => 'index'}, execute('index/hi')) | |
assert_nil execute('dude/hi') | ||
end | ||
def test_dynamic_with_regexp_condition | ||
c = [Static.new("hi"), Dynamic.new(:action, :condition => /^[a-z]+$/)] | ||
206 | | |
206 | g.result :controller, "::ContentController", true | |
go c | ||
assert_nil execute('boo') | ||
... | ... | |
assert_nil execute('hi/138708jkhdf') | ||
assert_nil execute('hi/dkjfl8792343dfsf') | ||
assert_nil execute('hi/dude/what') | ||
216 | | |
217 | | |
216 | assert_equal({:controller => ::ContentController, :action => 'index'}, execute('hi/index')) | |
217 | assert_equal({:controller => ::ContentController, :action => 'dude'}, execute('hi/dude')) | |
end | ||
def test_dynamic_with_regexp_and_default | ||
c = [Static.new("hi"), Dynamic.new(:action, :condition => /^[a-z]+$/, :default => 'index')] | ||
222 | | |
222 | g.result :controller, "::ContentController", true | |
go c | ||
assert_nil execute('boo') | ||
... | ... | |
assert_nil execute('hi/FOXY') | ||
assert_nil execute('hi/138708jkhdf') | ||
assert_nil execute('hi/dkjfl8792343dfsf') | ||
230 | | |
231 | | |
232 | | |
230 | assert_equal({:controller => ::ContentController, :action => 'index'}, execute('hi')) | |
231 | assert_equal({:controller => ::ContentController, :action => 'index'}, execute('hi/index')) | |
232 | assert_equal({:controller => ::ContentController, :action => 'dude'}, execute('hi/dude')) | |
assert_nil execute('hi/dude/what') | ||
end | ||
def test_path | ||
c = [Static.new("hi"), Path.new(:file)] | ||
238 | | |
238 | g.result :controller, "::ContentController", true | |
g.constant_result :action, "download" | ||
go c | ||
assert_nil execute('boo') | ||
assert_nil execute('boo/blah') | ||
245 | | |
246 | | |
245 | assert_equal({:controller => ::ContentController, :action => 'download', :file => []}, execute('hi')) | |
246 | assert_equal({:controller => ::ContentController, :action => 'download', :file => %w(books agile_rails_dev.pdf)}, | |
execute('hi/books/agile_rails_dev.pdf')) | ||
248 | | |
248 | assert_equal({:controller => ::ContentController, :action => 'download', :file => ['dude']}, execute('hi/dude')) | |
assert_equal 'dude/what', execute('hi/dude/what')[:file].to_s | ||
end | ||
def test_path_with_dynamic | ||
c = [Dynamic.new(:action), Path.new(:file)] | ||
254 | | |
254 | g.result :controller, "::ContentController", true | |
go c | ||
assert_nil execute('') | ||
259 | | |
260 | | |
259 | assert_equal({:controller => ::ContentController, :action => 'download', :file => []}, execute('download')) | |
260 | assert_equal({:controller => ::ContentController, :action => 'download', :file => %w(books agile_rails_dev.pdf)}, | |
execute('download/books/agile_rails_dev.pdf')) | ||
262 | | |
262 | assert_equal({:controller => ::ContentController, :action => 'download', :file => ['dude']}, execute('download/dude')) | |
assert_equal 'dude/what', execute('hi/dude/what')[:file].to_s | ||
end | ||
... | ... | |
assert_nil execute('hi/13870948') | ||
assert_nil execute('hi/content/dog') | ||
assert_nil execute('hi/admin/user/foo') | ||
290 | | |
291 | | |
290 | assert_equal({:controller => ::ContentController, :action => 'hi'}, execute('hi/content')) | |
291 | assert_equal({:controller => ::Admin::UserController, :action => 'hi'}, execute('hi/admin/user')) | |
end | ||
def test_controller_with_regexp | ||
... | ... | |
assert_nil execute('hi') | ||
assert_nil execute('hi/x') | ||
assert_nil execute('hi/content') | ||
303 | | |
304 | | |
303 | assert_equal({:controller => ::Admin::UserController, :action => 'hi'}, execute('hi/admin/user')) | |
304 | assert_equal({:controller => ::Admin::NewsFeedController, :action => 'hi'}, execute('hi/admin/news_feed')) | |
assert_nil execute('hi/admin/user/foo') | ||
end | ||
... | ... | |
go c | ||
# Make sure we get the right answers | ||
313 | | |
314 | | |
315 | | |
313 | assert_equal({:controller => ::ContentController, :action => 'index'}, execute('content')) | |
314 | assert_equal({:controller => ::ContentController, :action => 'list'}, execute('content/list')) | |
315 | assert_equal({:controller => ::ContentController, :action => 'show', :id => '10'}, execute('content/show/10')) | |
317 | | |
318 | | |
319 | | |
317 | assert_equal({:controller => ::Admin::UserController, :action => 'index'}, execute('admin/user')) | |
318 | assert_equal({:controller => ::Admin::UserController, :action => 'list'}, execute('admin/user/list')) | |
319 | assert_equal({:controller => ::Admin::UserController, :action => 'show', :id => 'nseckar'}, execute('admin/user/show/nseckar')) | |
assert_nil execute('content/show/10/20') | ||
assert_nil execute('food') | ||
... | ... | |
end | ||
def test_default_route | ||
360 | | |
360 | g.result :controller, "::ContentController", true | |
g.constant_result :action, 'index' | ||
go [] | ||
... | ... | |
assert_nil execute('hello/world/how') | ||
assert_nil execute('hello/world/how/are') | ||
assert_nil execute('hello/world/how/are/you/today') | ||
369 | | |
369 | assert_equal({:controller => ::ContentController, :action => 'index'}, execute([])) | |
end | ||
end | ||
... | ... | |
end | ||
class RouteTests < Test::Unit::TestCase | ||
537 | ||
538 | ||
def route(*args) | ||
@route = ::ActionController::Routing::Route.new(*args) unless args.empty? | ||
return @route | ||
... | ... | |
assert_nil rec('hello/turn') | ||
assert_nil rec('turn/world') | ||
assert_equal( | ||
569 | | |
571 | {:known => 'known_value', :controller => ::ContentController, :action => 'index'}, | |
rec('hello/world') | ||
) | ||
... | ... | |
assert_nil rec('hello') | ||
assert_nil rec('foo/bar') | ||
585 | | |
586 | | |
587 | assert_equal({:controller => ::ContentController, :action => 'show_person', :name => 'rails'}, rec('hello/rails')) | |
588 | assert_equal({:controller => ::ContentController, :action => 'show_person', :name => 'Nicholas Seckar'}, rec('hello/Nicholas+Seckar')) | |
assert_nil gen(:controller => 'content', :action => 'show_dude', :name => 'rails') | ||
assert_nil gen(:controller => 'content', :action => 'show_person') | ||
... | ... | |
route ':controller/:action/:id', :action => 'index', :id => nil | ||
assert_nil rec('hello') | ||
assert_nil rec('foo bar') | ||
599 | | |
600 | | |
601 | assert_equal({:controller => ::ContentController, :action => 'index'}, rec('content')) | |
602 | assert_equal({:controller => ::Admin::UserController, :action => 'index'}, rec('admin/user')) | |
602 | | |
603 | | |
604 | | |
604 | assert_equal({:controller => ::Admin::UserController, :action => 'index'}, rec('admin/user/index')) | |
605 | assert_equal({:controller => ::Admin::UserController, :action => 'list'}, rec('admin/user/list')) | |
606 | assert_equal({:controller => ::Admin::UserController, :action => 'show', :id => '10'}, rec('admin/user/show/10')) | |
606 | | |
607 | | |
608 | assert_equal({:controller => ::ContentController, :action => 'list'}, rec('content/list')) | |
609 | assert_equal({:controller => ::ContentController, :action => 'show', :id => '10'}, rec('content/show/10')) | |
assert_equal '/content', gen(:controller => 'content', :action => 'index') | ||
... | ... | |
end | ||
def test_default_setup | ||
630 | | |
631 | | |
632 | | |
632 | assert_equal({:controller => ::ContentController, :action => 'index'}.stringify_keys, rs.recognize_path(%w(content))) | |
633 | assert_equal({:controller => ::ContentController, :action => 'list'}.stringify_keys, rs.recognize_path(%w(content list))) | |
634 | assert_equal({:controller => ::ContentController, :action => 'show', :id => '10'}.stringify_keys, rs.recognize_path(%w(content show 10))) | |
634 | | |
636 | assert_equal({:controller => ::Admin::UserController, :action => 'show', :id => '10'}.stringify_keys, rs.recognize_path(%w(admin user show 10))) | |
assert_equal ['/admin/user/show/10', []], rs.generate({:controller => 'admin/user', :action => 'show', :id => 10}) | ||
... | ... | |
assert_equal ['/admin/stuff', []], rs.generate({:controller => 'stuff'}, {:controller => 'admin/user', :action => 'list', :id => '10'}) | ||
assert_equal ['/stuff', []], rs.generate({:controller => '/stuff'}, {:controller => 'admin/user', :action => 'list', :id => '10'}) | ||
end | ||
644 | ||
646 | ||
def test_ignores_leading_slash | ||
@rs.draw {|m| m.connect '/:controller/:action/:id'} | ||
test_default_setup | ||
... | ... | |
map.connect ':controller/:admintoken/:action/:id', :controller => /admin\/.+/ | ||
map.connect ':controller/:action/:id' | ||
end | ||
721 | | |
723 | assert_equal({:controller => ::Admin::UserController, :admintoken => "foo", :action => "index"}.stringify_keys, | |
rs.recognize_path(%w(admin user foo))) | ||
723 | | |
725 | assert_equal({:controller => ::ContentController, :action => "foo"}.stringify_keys, | |
rs.recognize_path(%w(content foo))) | ||
assert_equal ['/admin/user/foo', []], rs.generate(:controller => "admin/user", :admintoken => "foo", :action => "index") | ||
assert_equal ['/content/foo',[]], rs.generate(:controller => "content", :action => "foo") | ||
... | ... | |
rs.path 'file/*path', :controller => 'content', :action => 'show_file' | ||
rs.connect ':controller/:action/:id' | ||
end | ||
795 | | |
results = rs.recognize_path %w(file hello+world how+are+you%3F) | ||
assert results, "Recognition should have succeeded" | ||
assert_equal ['hello world', 'how are you?'], results['path'] | ||
... | ... | |
assert results, "Recognition should have succeeded" | ||
assert_equal [], results['path'] | ||
end | ||
805 | ||
806 | def test_non_controllers_cannot_be_matched | |
807 | rs.draw do | |
808 | rs.connect ':controller/:action/:id' | |
809 | end | |
810 | assert_nil rs.recognize_path(%w(not_a show 10)), "Shouldn't recognize non-controllers as controllers!" | |
811 | end | |
def test_paths_do_not_accept_defaults | ||
assert_raises(ActionController::RoutingError) do | ||
... | ... | |
assert_equal ['/page', []], rs.generate(:controller => 'content', :action => 'show_page', :id => '1') | ||
assert_equal ['/page/10', []], rs.generate(:controller => 'content', :action => 'show_page', :id => 10) | ||
841 | | |
849 | ctrl = ::ContentController | |
assert_equal({'controller' => ctrl, 'action' => 'show_page', 'id' => 1}, rs.recognize_path(%w(page))) | ||
assert_equal({'controller' => ctrl, 'action' => 'show_page', 'id' => '1'}, rs.recognize_path(%w(page 1))) | ||
... | ... | |
end | ||
def test_recognition_with_uppercase_controller_name | ||
853 | | |
854 | | |
855 | | |
861 | assert_equal({'controller' => ::ContentController, 'action' => 'index'}, rs.recognize_path(%w(Content))) | |
862 | assert_equal({'controller' => ::ContentController, 'action' => 'list'}, rs.recognize_path(%w(Content list))) | |
863 | assert_equal({'controller' => ::ContentController, 'action' => 'show', 'id' => '10'}, rs.recognize_path(%w(Content show 10))) | |
857 | | |
858 | | |
865 | assert_equal({'controller' => ::Admin::NewsFeedController, 'action' => 'index'}, rs.recognize_path(%w(Admin NewsFeed))) | |
866 | assert_equal({'controller' => ::Admin::NewsFeedController, 'action' => 'index'}, rs.recognize_path(%w(Admin News_Feed))) | |
end | ||
def test_both_requirement_and_optional |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/test_test.rb:
prev. | current | |
flash["test"] = ">#{flash["test"]}<" | ||
render :text => 'ignore me' | ||
end | ||
10 | | |
10 | ||
11 | def render_raw_post | |
12 | raise Test::Unit::AssertionFailedError, "#raw_post is blank" if request.raw_post.blank? | |
13 | render :text => request.raw_post | |
14 | end | |
15 | ||
def test_params | ||
render :text => params.inspect | ||
end | ||
... | ... | |
def test_remote_addr | ||
render :text => (request.remote_addr || "not specified") | ||
end | ||
52 | ||
53 | def test_file_upload | |
54 | render :text => params[:file].size | |
55 | end | |
56 | ||
57 | def redirect_to_symbol | |
58 | redirect_to :generate_url, :id => 5 | |
59 | end | |
60 | ||
61 | private | |
62 | ||
63 | def rescue_action(e) | |
64 | raise e | |
65 | end | |
66 | ||
67 | def generate_url(opts) | |
68 | url_for(opts.merge(:action => "test_uri")) | |
69 | end | |
end | ||
def setup | ||
... | ... | |
ActionController::Routing::Routes.reload | ||
end | ||
83 | def test_raw_post_handling | |
84 | params = {:page => {:name => 'page name'}, 'some key' => 123} | |
85 | get :render_raw_post, params.dup | |
86 | ||
87 | raw_post = params.map {|k,v| [CGI::escape(k.to_s), CGI::escape(v.to_s)].join('=')}.sort.join('&') | |
88 | assert_equal raw_post, @response.body | |
89 | end | |
90 | ||
def test_process_without_flash | ||
process :set_flash | ||
assert_equal '><', flash['test'] | ||
... | ... | |
assert_nil @request.env['HTTP_X_REQUESTED_WITH'] | ||
end | ||
361 | def test_header_properly_reset_after_get_request | |
362 | get :test_params | |
363 | @request.recycle! | |
364 | assert_nil @request.instance_variable_get("@request_method") | |
365 | end | |
366 | ||
%w(controller response request).each do |variable| | ||
%w(get post put delete head process).each do |method| | ||
define_method("test_#{variable}_missing_for_#{method}_raises_error") do | ||
... | ... | |
end | ||
end | ||
end | ||
383 | ||
384 | FILES_DIR = File.dirname(__FILE__) + '/../fixtures/multipart' | |
385 | ||
386 | def test_test_uploaded_file | |
387 | filename = 'mona_lisa.jpg' | |
388 | path = "#{FILES_DIR}/#{filename}" | |
389 | content_type = 'image/png' | |
390 | ||
391 | file = ActionController::TestUploadedFile.new(path, content_type) | |
392 | assert_equal filename, file.original_filename | |
393 | assert_equal content_type, file.content_type | |
394 | assert_equal file.path, file.local_path | |
395 | assert_equal File.read(path), file.read | |
396 | end | |
397 | ||
398 | def test_fixture_file_upload | |
399 | post :test_file_upload, :file => fixture_file_upload(FILES_DIR + "/mona_lisa.jpg", "image/jpg") | |
400 | assert_equal 159528, @response.body | |
401 | end | |
402 | ||
403 | def test_test_uploaded_file_exception_when_file_doesnt_exist | |
404 | assert_raise(RuntimeError) { ActionController::TestUploadedFile.new('non_existent_file') } | |
405 | end | |
406 | ||
407 | def test_assert_redirected_to_symbol | |
408 | get :redirect_to_symbol | |
409 | assert_redirected_to :generate_url | |
410 | end | |
end |
rool/rails/typo/trunk/vendor/rails/actionpack/test/controller/verification_test.rb:
prev. | current | |
assert_redirected_to :action => "unguarded" | ||
end | ||
210 | | |
210 | def test_guarded_post_and_calls_render_succeeds | |
post :must_be_post | ||
assert_equal "Was a post!", @response.body | ||
213 | end | |
215 | def test_guarded_post_and_calls_render_fails | |
get :must_be_post | ||
assert_response 500 | ||
assert_equal "Must be post", @response.body |
rool/rails/typo/trunk/vendor/rails/actionpack/test/template/active_record_helper_test.rb:
prev. | current | |
assert_dom_equal %(<div class="errorExplanation" id="errorExplanation"><h2>1 error prohibited this post from being saved</h2><p>There were problems with the following fields:</p><ul><li>Author name can't be empty</li></ul></div>), error_messages_for("post") | ||
assert_equal %(<div class="errorDeathByClass" id="errorDeathById"><h1>1 error prohibited this post from being saved</h1><p>There were problems with the following fields:</p><ul><li>Author name can't be empty</li></ul></div>), error_messages_for("post", :class => "errorDeathByClass", :id => "errorDeathById", :header_tag => "h1") | ||
end | ||
122 | ||
123 | def test_error_messages_for_handles_nil | |
124 | assert_equal "", error_messages_for("notthere") | |
125 | end | |
def test_form_with_string_multipart | ||
assert_dom_equal( |
rool/rails/typo/trunk/vendor/rails/actionpack/test/template/asset_tag_helper_test.rb:
prev. | current | |
ActionView::Helpers::AssetTagHelper::reset_javascript_include_default | ||
end | ||
30 | def teardown | |
31 | Object.send(:remove_const, :RAILS_ROOT) if defined?(RAILS_ROOT) | |
32 | ENV["RAILS_ASSET_ID"] = nil | |
33 | end | |
34 | ||
AutoDiscoveryToTag = { | ||
%(auto_discovery_link_tag) => %(<link href="http://www.example.com" rel="alternate" title="RSS" type="application/rss+xml" />), | ||
%(auto_discovery_link_tag(:atom)) => %(<link href="http://www.example.com" rel="alternate" title="ATOM" type="application/atom+xml" />), | ||
... | ... | |
%(javascript_include_tag("xmlhr")) => %(<script src="/javascripts/xmlhr.js" type="text/javascript"></script>), | ||
%(javascript_include_tag("xmlhr", :lang => "vbscript")) => %(<script lang="vbscript" src="/javascripts/xmlhr.js" type="text/javascript"></script>), | ||
%(javascript_include_tag("common.javascript", "/elsewhere/cools")) => %(<script src="/javascripts/common.javascript" type="text/javascript"></script>\n<script src="/elsewhere/cools.js" type="text/javascript"></script>), | ||
52 | | |
57 | %(javascript_include_tag(:defaults)) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>), | |
58 | %(javascript_include_tag(:defaults, "test")) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/test.js" type="text/javascript"></script>), | |
59 | %(javascript_include_tag("test", :defaults)) => %(<script src="/javascripts/test.js" type="text/javascript"></script>\n<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>) | |
} | ||
StylePathToTag = { | ||
... | ... | |
%(image_tag("xml")) => %(<img alt="Xml" src="/images/xml.png" />), | ||
%(image_tag("rss", :alt => "rss syndication")) => %(<img alt="rss syndication" src="/images/rss.png" />), | ||
%(image_tag("gold", :size => "45x70")) => %(<img alt="Gold" height="70" src="/images/gold.png" width="45" />), | ||
84 | %(image_tag("symbolize", "size" => "45x70")) => %(<img alt="Symbolize" height="70" src="/images/symbolize.png" width="45" />), | |
85 | %(image_tag("http://www.rubyonrails.com/images/rails")) => %(<img alt="Rails" src="http://www.rubyonrails.com/images/rails.png" />) | |
} | ||
def test_auto_discovery | ||
... | ... | |
ActionView::Helpers::AssetTagHelper::register_javascript_include_default 'lib1', '/elsewhere/blub/lib2' | ||
assert_dom_equal %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/slider.js" type="text/javascript"></script>\n<script src="/javascripts/lib1.js" type="text/javascript"></script>\n<script src="/elsewhere/blub/lib2.js" type="text/javascript"></script>), javascript_include_tag(:defaults) | ||
end | ||
97 | ||
106 | ||
def test_style_path | ||
StylePathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } | ||
end | ||
... | ... | |
ImageLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } | ||
end | ||
123 | def test_timebased_asset_id | |
124 | Object.send(:const_set, :RAILS_ROOT, File.dirname(__FILE__) + "/../fixtures/") | |
125 | expected_time = File.stat(File.expand_path(File.dirname(__FILE__) + "/../fixtures/public/images/rails.png")).mtime.to_i.to_s | |
126 | assert_equal %(<img alt="Rails" src="/images/rails.png?#{expected_time}" />), image_tag("rails.png") | |
127 | end | |
128 | ||
129 | def test_skipping_asset_id_on_complete_url | |
130 | Object.send(:const_set, :RAILS_ROOT, File.dirname(__FILE__) + "/../fixtures/") | |
131 | assert_equal %(<img alt="Rails" src="http://www.example.com/rails.png" />), image_tag("http://www.example.com/rails.png") | |
132 | end | |
133 | ||
134 | def test_preset_asset_id | |
135 | Object.send(:const_set, :RAILS_ROOT, File.dirname(__FILE__) + "/../fixtures/") | |
136 | ENV["RAILS_ASSET_ID"] = "4500" | |
137 | assert_equal %(<img alt="Rails" src="/images/rails.png?4500" />), image_tag("rails.png") | |
138 | end | |
end | ||
class AssetTagHelperNonVhostTest < Test::Unit::TestCase | ||
... | ... | |
%(image_tag("rss", :alt => "rss syndication")) => %(<img alt="rss syndication" src="/calloboration/hieraki/images/rss.png" />), | ||
%(image_tag("gold", :size => "45x70")) => %(<img alt="Gold" height="70" src="/calloboration/hieraki/images/gold.png" width="45" />), | ||
%(image_tag("http://www.example.com/images/icon.gif")) => %(<img alt="Icon" src="http://www.example.com/images/icon.gif" />), | ||
202 | %(image_tag("symbolize", "size" => "45x70")) => %(<img alt="Symbolize" height="70" src="/calloboration/hieraki/images/symbolize.png" width="45" />) | |
} | ||
def test_auto_discovery |
rool/rails/typo/trunk/vendor/rails/actionpack/test/template/date_helper_test.rb:
prev. | current | |
require 'test/unit' | ||
2 | ||
require File.dirname(__FILE__) + "/../abstract_unit" | ||
class DateHelperTest < Test::Unit::TestCase | ||
include ActionView::Helpers::DateHelper | ||
6 | include ActionView::Helpers::FormHelper | |
8 | silence_warnings do | |
9 | Post = Struct.new("Post", :written_on, :updated_at) | |
10 | end | |
11 | ||
def test_distance_in_words | ||
from = Time.mktime(2004, 3, 6, 21, 41, 18) | ||
... | ... | |
assert_equal expected, select_date(0, :start_year => 2003, :end_year => 2005, :prefix => "date[first]") | ||
end | ||
504 | def test_date_select_within_fields_for | |
505 | @post = Post.new | |
506 | @post.written_on = Date.new(2004, 6, 15) | |
507 | ||
508 | _erbout = '' | |
509 | ||
510 | fields_for :post, @post do |f| | |
511 | _erbout.concat f.date_select(:written_on) | |
512 | end | |
513 | ||
514 | expected = "<select name='post[written_on(1i)]'>\n<option value='1999'>1999</option>\n<option value='2000'>2000</option>\n<option value='2001'>2001</option>\n<option value='2002'>2002</option>\n<option value='2003'>2003</option>\n<option selected='selected' value='2004'>2004</option>\n<option value='2005'>2005</option>\n<option value='2006'>2006</option>\n<option value='2007'>2007</option>\n<option value='2008'>2008</option>\n<option value='2009'>2009</option>\n</select>\n" + | |
515 | "<select name='post[written_on(2i)]'>\n<option value='1'>January</option>\n<option value='2'>February</option>\n<option value='3'>March</option>\n<option value='4'>April</option>\n<option value='5'>May</option>\n<option selected='selected' value='6'>June</option>\n<option value='7'>July</option>\n<option value='8'>August</option>\n<option value='9'>September</option>\n<option value='10'>October</option>\n<option value='11'>November</option>\n<option value='12'>December</option>\n</select>\n" + | |
516 | "<select name='post[written_on(3i)]'>\n<option value='1'>1</option>\n<option value='2'>2</option>\n<option value='3'>3</option>\n<option value='4'>4</option>\n<option value='5'>5</option>\n<option value='6'>6</option>\n<option value='7'>7</option>\n<option value='8'>8</option>\n<option value='9'>9</option>\n<option value='10'>10</option>\n<option value='11'>11</option>\n<option value='12'>12</option>\n<option value='13'>13</option>\n<option value='14'>14</option>\n<option selected='selected' value='15'>15</option>\n<option value='16'>16</option>\n<option value='17'>17</option>\n<option value='18'>18</option>\n<option value='19'>19</option>\n<option value='20'>20</option>\n<option value='21'>21</option>\n<option value='22'>22</option>\n<option value='23'>23</option>\n<option value='24'>24</option>\n<option value='25'>25</option>\n<option value='26'>26</option>\n<option value='27'>27</option>\n<option value='28'>28</option>\n<option value='29'>29</option>\n<option value='30'>30</option>\n<option value='31'>31</option>\n</select>\n" | |
517 | ||
518 | assert_dom_equal(expected, _erbout) | |
519 | end | |
520 | ||
521 | def test_datetime_select_within_fields_for | |
522 | @post = Post.new | |
523 | @post.updated_at = Time.local(2004, 6, 15, 16, 35) | |
524 | ||
525 | _erbout = '' | |
526 | ||
527 | fields_for :post, @post do |f| | |
528 | _erbout.concat f.datetime_select(:updated_at) | |
529 | end | |
530 | ||
531 | expected = "<select name='post[updated_at(1i)]'>\n<option value='1999'>1999</option>\n<option value='2000'>2000</option>\n<option value='2001'>2001</option>\n<option value='2002'>2002</option>\n<option value='2003'>2003</option>\n<option selected='selected' value='2004'>2004</option>\n<option value='2005'>2005</option>\n<option value='2006'>2006</option>\n<option value='2007'>2007</option>\n<option value='2008'>2008</option>\n<option value='2009'>2009</option>\n</select>\n<select name='post[updated_at(2i)]'>\n<option value='1'>January</option>\n<option value='2'>February</option>\n<option value='3'>March</option>\n<option value='4'>April</option>\n<option value='5'>May</option>\n<option selected='selected' value='6'>June</option>\n<option value='7'>July</option>\n<option value='8'>August</option>\n<option value='9'>September</option>\n<option value='10'>October</option>\n<option value='11'>November</option>\n<option value='12'>December</option>\n</select>\n<select name='post[updated_at(3i)]'>\n<option value='1'>1</option>\n<option value='2'>2</option>\n<option value='3'>3</option>\n<option value='4'>4</option>\n<option value='5'>5</option>\n<option value='6'>6</option>\n<option value='7'>7</option>\n<option value='8'>8</option>\n<option value='9'>9</option>\n<option value='10'>10</option>\n<option value='11'>11</option>\n<option value='12'>12</option>\n<option value='13'>13</option>\n<option value='14'>14</option>\n<option selected='selected' value='15'>15</option>\n<option value='16'>16</option>\n<option value='17'>17</option>\n<option value='18'>18</option>\n<option value='19'>19</option>\n<option value='20'>20</option>\n<option value='21'>21</option>\n<option value='22'>22</option>\n<option value='23'>23</option>\n<option value='24'>24</option>\n<option value='25'>25</option>\n<option value='26'>26</option>\n<option value='27'>27</option>\n<option value='28'>28</option>\n<option value='29'>29</option>\n<option value='30'>30</option>\n<option value='31'>31</option>\n</select>\n — <select name='post[updated_at(4i)]'>\n<option value='00'>00</option>\n<option value='01'>01</option>\n<option value='02'>02</option>\n<option value='03'>03</option>\n<option value='04'>04</option>\n<option value='05'>05</option>\n<option value='06'>06</option>\n<option value='07'>07</option>\n<option value='08'>08</option>\n<option value='09'>09</option>\n<option value='10'>10</option>\n<option value='11'>11</option>\n<option value='12'>12</option>\n<option value='13'>13</option>\n<option value='14'>14</option>\n<option value='15'>15</option>\n<option selected='selected' value='16'>16</option>\n<option value='17'>17</option>\n<option value='18'>18</option>\n<option value='19'>19</option>\n<option value='20'>20</option>\n<option value='21'>21</option>\n<option value='22'>22</option>\n<option value='23'>23</option>\n</select>\n : <select name='post[updated_at(5i)]'>\n<option value='00'>00</option>\n<option value='01'>01</option>\n<option value='02'>02</option>\n<option value='03'>03</option>\n<option value='04'>04</option>\n<option value='05'>05</option>\n<option value='06'>06</option>\n<option value='07'>07</option>\n<option value='08'>08</option>\n<option value='09'>09</option>\n<option value='10'>10</option>\n<option value='11'>11</option>\n<option value='12'>12</option>\n<option value='13'>13</option>\n<option value='14'>14</option>\n<option value='15'>15</option>\n<option value='16'>16</option>\n<option value='17'>17</option>\n<option value='18'>18</option>\n<option value='19'>19</option>\n<option value='20'>20</option>\n<option value='21'>21</option>\n<option value='22'>22</option>\n<option value='23'>23</option>\n<option value='24'>24</option>\n<option value='25'>25</option>\n<option value='26'>26</option>\n<option value='27'>27</option>\n<option value='28'>28</option>\n<option value='29'>29</option>\n<option value='30'>30</option>\n<option value='31'>31</option>\n<option value='32'>32</option>\n<option value='33'>33</option>\n<option value='34'>34</option>\n<option selected='selected' value='35'>35</option>\n<option value='36'>36</option>\n<option value='37'>37</option>\n<option value='38'>38</option>\n<option value='39'>39</option>\n<option value='40'>40</option>\n<option value='41'>41</option>\n<option value='42'>42</option>\n<option value='43'>43</option>\n<option value='44'>44</option>\n<option value='45'>45</option>\n<option value='46'>46</option>\n<option value='47'>47</option>\n<option value='48'>48</option>\n<option value='49'>49</option>\n<option value='50'>50</option>\n<option value='51'>51</option>\n<option value='52'>52</option>\n<option value='53'>53</option>\n<option value='54'>54</option>\n<option value='55'>55</option>\n<option value='56'>56</option>\n<option value='57'>57</option>\n<option value='58'>58</option>\n<option value='59'>59</option>\n</select>\n" | |
532 | ||
533 | assert_dom_equal(expected, _erbout) | |
534 | end | |
535 | ||
def test_date_select_with_zero_value_and_no_start_year | ||
expected = %(<select name="date[first][year]">\n) | ||
(Date.today.year-5).upto(Date.today.year+1) { |y| expected << %(<option value="#{y}">#{y}</option>\n) } | ||
... | ... | |
def test_date_select_with_zero_value_and_no_end_year | ||
expected = %(<select name="date[first][year]">\n) | ||
519 | | |
555 | last_year = Time.now.year + 5 | |
556 | 2003.upto(last_year) { |y| expected << %(<option value="#{y}">#{y}</option>\n) } | |
expected << "</select>\n" | ||
expected << %(<select name="date[first][month]">\n) |
rool/rails/typo/trunk/vendor/rails/actionpack/test/template/form_helper_test.rb:
prev. | current | |
1 | ||
2 | ||
3 | ||
4 | ||
1 | require File.dirname(__FILE__) + '/../abstract_unit' | |
class FormHelperTest < Test::Unit::TestCase | ||
include ActionView::Helpers::FormHelper | ||
5 | include ActionView::Helpers::FormTagHelper | |
6 | include ActionView::Helpers::UrlHelper | |
7 | include ActionView::Helpers::TagHelper | |
8 | include ActionView::Helpers::TextHelper | |
silence_warnings do | ||
Post = Struct.new("Post", :title, :author_name, :body, :secret, :written_on, :cost) | ||
... | ... | |
@post.body = "Back to the hill and over it again!" | ||
@post.secret = 1 | ||
@post.written_on = Date.new(2004, 6, 15) | ||
31 | ||
32 | @controller = Class.new do | |
33 | attr_reader :url_for_options | |
34 | def url_for(options, *parameters_for_method_reference) | |
35 | @url_for_options = options | |
36 | "http://www.example.com" | |
37 | end | |
38 | end | |
39 | @controller = @controller.new | |
end | ||
def test_text_field | ||
... | ... | |
assert_dom_equal expected, text_field("post", "title", :maxlength => 35) | ||
end | ||
73 | def test_text_field_doesnt_change_param_values | |
74 | object_name = 'post[]' | |
75 | expected = '<input id="post_123_title" name="post[123][title]" size="30" type="text" value="Hello World" />' | |
76 | assert_equal expected, text_field(object_name, "title") | |
77 | assert_equal object_name, "post[]" | |
78 | end | |
79 | ||
def test_check_box | ||
assert_dom_equal( | ||
'<input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" /><input name="post[secret]" type="hidden" value="0" />', | ||
... | ... | |
text_area("post", "body") | ||
) | ||
end | ||
121 | ||
138 | ||
139 | def test_text_area_with_alternate_value | |
140 | assert_dom_equal( | |
141 | '<textarea cols="40" id="post_body" name="post[body]" rows="20">Testing alternate values.</textarea>', | |
142 | text_area("post", "body", :value => 'Testing alternate values.') | |
143 | ) | |
144 | end | |
145 | ||
def test_date_selects | ||
assert_dom_equal( | ||
'<textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea>', | ||
... | ... | |
radio_button("post[]", "title", "Goodbye World") | ||
) | ||
end | ||
214 | ||
215 | def test_form_for | |
216 | _erbout = '' | |
217 | ||
218 | form_for(:post, @post, :html => { :id => 'create-post' }) do |f| | |
219 | _erbout.concat f.text_field(:title) | |
220 | _erbout.concat f.text_area(:body) | |
221 | _erbout.concat f.check_box(:secret) | |
222 | end | |
223 | ||
224 | expected = | |
225 | "<form action='http://www.example.com' id='create-post' method='post'>" + | |
226 | "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + | |
227 | "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + | |
228 | "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + | |
229 | "<input name='post[secret]' type='hidden' value='0' />" + | |
230 | "</form>" | |
231 | ||
232 | assert_dom_equal expected, _erbout | |
233 | end | |
234 | ||
235 | def test_form_for_without_object | |
236 | _erbout = '' | |
237 | ||
238 | form_for(:post, :html => { :id => 'create-post' }) do |f| | |
239 | _erbout.concat f.text_field(:title) | |
240 | _erbout.concat f.text_area(:body) | |
241 | _erbout.concat f.check_box(:secret) | |
242 | end | |
243 | ||
244 | expected = | |
245 | "<form action='http://www.example.com' id='create-post' method='post'>" + | |
246 | "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + | |
247 | "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + | |
248 | "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + | |
249 | "<input name='post[secret]' type='hidden' value='0' />" + | |
250 | "</form>" | |
251 | ||
252 | assert_dom_equal expected, _erbout | |
253 | end | |
254 | ||
255 | def test_fields_for | |
256 | _erbout = '' | |
257 | ||
258 | fields_for(:post, @post) do |f| | |
259 | _erbout.concat f.text_field(:title) | |
260 | _erbout.concat f.text_area(:body) | |
261 | _erbout.concat f.check_box(:secret) | |
262 | end | |
263 | ||
264 | expected = | |
265 | "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + | |
266 | "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + | |
267 | "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + | |
268 | "<input name='post[secret]' type='hidden' value='0' />" | |
269 | ||
270 | assert_dom_equal expected, _erbout | |
271 | end | |
272 | ||
273 | def test_fields_for_without_object | |
274 | _erbout = '' | |
275 | fields_for(:post) do |f| | |
276 | _erbout.concat f.text_field(:title) | |
277 | _erbout.concat f.text_area(:body) | |
278 | _erbout.concat f.check_box(:secret) | |
279 | end | |
280 | ||
281 | expected = | |
282 | "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + | |
283 | "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + | |
284 | "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + | |
285 | "<input name='post[secret]' type='hidden' value='0' />" | |
286 | ||
287 | assert_dom_equal expected, _erbout | |
288 | end | |
289 | ||
290 | def test_form_builder_does_not_have_form_for_method | |
291 | assert ! ActionView::Helpers::FormBuilder.instance_methods.include?('form_for') | |
292 | end | |
293 | ||
294 | def test_form_for_and_fields_for | |
295 | _erbout = '' | |
296 | ||
297 | form_for(:post, @post, :html => { :id => 'create-post' }) do |post_form| | |
298 | _erbout.concat post_form.text_field(:title) | |
299 | _erbout.concat post_form.text_area(:body) | |
300 | ||
301 | fields_for(:parent_post, @post) do |parent_fields| | |
302 | _erbout.concat parent_fields.check_box(:secret) | |
303 | end | |
304 | end | |
305 | ||
306 | expected = | |
307 | "<form action='http://www.example.com' id='create-post' method='post'>" + | |
308 | "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + | |
309 | "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + | |
310 | "<input name='parent_post[secret]' checked='checked' type='checkbox' id='parent_post_secret' value='1' />" + | |
311 | "<input name='parent_post[secret]' type='hidden' value='0' />" + | |
312 | "</form>" | |
313 | ||
314 | assert_dom_equal expected, _erbout | |
315 | end | |
316 | ||
317 | class LabelledFormBuilder < ActionView::Helpers::FormBuilder | |
318 | (field_helpers - %w(hidden_field)).each do |selector| | |
319 | src = <<-END_SRC | |
320 | def #{selector}(field, *args, &proc) | |
321 | "<label for='\#{field}'>\#{field.to_s.humanize}:</label> " + super + "<br/>" | |
322 | end | |
323 | END_SRC | |
324 | class_eval src, __FILE__, __LINE__ | |
325 | end | |
326 | end | |
327 | ||
328 | def test_form_for_with_labelled_builder | |
329 | _erbout = '' | |
330 | ||
331 | form_for(:post, @post, :builder => LabelledFormBuilder) do |f| | |
332 | _erbout.concat f.text_field(:title) | |
333 | _erbout.concat f.text_area(:body) | |
334 | _erbout.concat f.check_box(:secret) | |
335 | end | |
336 | ||
337 | expected = | |
338 | "<form action='http://www.example.com' method='post'>" + | |
339 | "<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" + | |
340 | "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" + | |
341 | "<label for='secret'>Secret:</label> <input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + | |
342 | "<input name='post[secret]' type='hidden' value='0' /><br/>" + | |
343 | "</form>" | |
344 | ||
345 | assert_dom_equal expected, _erbout | |
346 | end | |
347 | ||
348 | # Perhaps this test should be moved to prototype helper tests. | |
349 | def test_remote_form_for_with_labelled_builder | |
350 | self.extend ActionView::Helpers::PrototypeHelper | |
351 | _erbout = '' | |
352 | ||
353 | remote_form_for(:post, @post, :builder => LabelledFormBuilder) do |f| | |
354 | _erbout.concat f.text_field(:title) | |
355 | _erbout.concat f.text_area(:body) | |
356 | _erbout.concat f.check_box(:secret) | |
357 | end | |
358 | ||
359 | expected = | |
360 | %(<form action="http://www.example.com" onsubmit="new Ajax.Request('http://www.example.com', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" method="post">) + | |
361 | "<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" + | |
362 | "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" + | |
363 | "<label for='secret'>Secret:</label> <input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + | |
364 | "<input name='post[secret]' type='hidden' value='0' /><br/>" + | |
365 | "</form>" | |
366 | ||
367 | assert_dom_equal expected, _erbout | |
368 | end | |
369 | ||
370 | def test_fields_for_with_labelled_builder | |
371 | _erbout = '' | |
372 | ||
373 | fields_for(:post, @post, :builder => LabelledFormBuilder) do |f| | |
374 | _erbout.concat f.text_field(:title) | |
375 | _erbout.concat f.text_area(:body) | |
376 | _erbout.concat f.check_box(:secret) | |
377 | end | |
378 | ||
379 | expected = | |
380 | "<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" + | |
381 | "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" + | |
382 | "<label for='secret'>Secret:</label> <input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + | |
383 | "<input name='post[secret]' type='hidden' value='0' /><br/>" | |
384 | ||
385 | assert_dom_equal expected, _erbout | |
386 | end | |
387 | ||
388 | def test_form_for_with_html_options_adds_options_to_form_tag | |
389 | _erbout = '' | |
390 | ||
391 | form_for(:post, @post, :html => {:id => 'some_form', :class => 'some_class'}) do |f| end | |
392 | expected = "<form action=\"http://www.example.com\" class=\"some_class\" id=\"some_form\" method=\"post\"></form>" | |
393 | ||
394 | assert_dom_equal expected, _erbout | |
395 | end | |
396 | ||
397 | def test_form_for_with_string_url_option | |
398 | _erbout = '' | |
399 | ||
400 | form_for(:post, @post, :url => 'http://www.otherdomain.com') do |f| end | |
401 | ||
402 | assert_equal 'http://www.otherdomain.com', @controller.url_for_options | |
403 | end | |
404 | ||
405 | def test_form_for_with_hash_url_option | |
406 | _erbout = '' | |
407 | ||
408 | form_for(:post, @post, :url => {:controller => 'controller', :action => 'action'}) do |f| end | |
409 | ||
410 | assert_equal 'controller', @controller.url_for_options[:controller] | |
411 | assert_equal 'action', @controller.url_for_options[:action] | |
412 | end | |
413 | ||
414 | def test_remote_form_for_with_html_options_adds_options_to_form_tag | |
415 | self.extend ActionView::Helpers::PrototypeHelper | |
416 | _erbout = '' | |
417 | ||
418 | remote_form_for(:post, @post, :html => {:id => 'some_form', :class => 'some_class'}) do |f| end | |
419 | expected = "<form action=\"http://www.example.com\" class=\"some_class\" id=\"some_form\" method=\"post\" onsubmit=\"new Ajax.Request('http://www.example.com', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\"></form>" | |
420 | ||
421 | assert_dom_equal expected, _erbout | |
422 | end | |
end |
rool/rails/typo/trunk/vendor/rails/actionpack/test/template/form_options_helper_test.rb:
prev. | current | |
ActionView::Helpers::FormOptionsHelper::TimeZone = MockTimeZone | ||
class FormOptionsHelperTest < Test::Unit::TestCase | ||
26 | include ActionView::Helpers::FormHelper | |
include ActionView::Helpers::FormOptionsHelper | ||
silence_warnings do | ||
... | ... | |
) | ||
end | ||
226 | def test_select_under_fields_for | |
227 | @post = Post.new | |
228 | @post.category = "<mus>" | |
229 | ||
230 | _erbout = '' | |
231 | ||
232 | fields_for :post, @post do |f| | |
233 | _erbout.concat f.select(:category, %w( abe <mus> hest)) | |
234 | end | |
235 | ||
236 | assert_dom_equal( | |
237 | "<select id=\"post_category\" name=\"post[category]\"><option value=\"abe\">abe</option>\n<option value=\"<mus>\" selected=\"selected\"><mus></option>\n<option value=\"hest\">hest</option></select>", | |
238 | _erbout | |
239 | ) | |
240 | end | |
241 | ||
def test_select_with_blank | ||
@post = Post.new | ||
@post.category = "<mus>" | ||
... | ... | |
select("post", "category", %w( abe <mus> hest), :prompt => true, :include_blank => true) | ||
) | ||
end | ||
286 | ||
287 | def test_select_with_selected_value | |
288 | @post = Post.new | |
289 | @post.category = "<mus>" | |
290 | assert_dom_equal( | |
291 | "<select id=\"post_category\" name=\"post[category]\"><option value=\"abe\" selected=\"selected\">abe</option>\n<option value=\"<mus>\"><mus></option>\n<option value=\"hest\">hest</option></select>", | |
292 | select("post", "category", %w( abe <mus> hest ), :selected => 'abe') | |
293 | ) | |
294 | end | |
296 | def test_select_with_selected_nil | |
297 | @post = Post.new | |
298 | @post.category = "<mus>" | |
299 | assert_dom_equal( | |
300 | "<select id=\"post_category\" name=\"post[category]\"><option value=\"abe\">abe</option>\n<option value=\"<mus>\"><mus></option>\n<option value=\"hest\">hest</option></select>", | |
301 | select("post", "category", %w( abe <mus> hest ), :selected => nil) | |
302 | ) | |
303 | end | |
304 | ||
def test_collection_select | ||
@posts = [ | ||
Post.new("<Abe> went home", "<Abe>", "To a little house", "shh!"), | ||
... | ... | |
) | ||
end | ||
321 | def test_collection_select_under_fields_for | |
322 | @posts = [ | |
323 | Post.new("<Abe> went home", "<Abe>", "To a little house", "shh!"), | |
324 | Post.new("Babe went home", "Babe", "To a little house", "shh!"), | |
325 | Post.new("Cabe went home", "Cabe", "To a little house", "shh!") | |
326 | ] | |
327 | ||
328 | @post = Post.new | |
329 | @post.author_name = "Babe" | |
330 | ||
331 | _erbout = '' | |
332 | ||
333 | fields_for :post, @post do |f| | |
334 | _erbout.concat f.collection_select(:author_name, @posts, :author_name, :author_name) | |
335 | end | |
336 | ||
337 | assert_dom_equal( | |
338 | "<select id=\"post_author_name\" name=\"post[author_name]\"><option value=\"<Abe>\"><Abe></option>\n<option value=\"Babe\" selected=\"selected\">Babe</option>\n<option value=\"Cabe\">Cabe</option></select>", | |
339 | _erbout | |
340 | ) | |
341 | end | |
342 | ||
def test_collection_select_with_blank_and_style | ||
@posts = [ | ||
Post.new("<Abe> went home", "<Abe>", "To a little house", "shh!"), | ||
... | ... | |
html | ||
end | ||
384 | def test_time_zone_select_under_fields_for | |
385 | @firm = Firm.new("D") | |
386 | ||
387 | _erbout = '' | |
388 | ||
389 | fields_for :firm, @firm do |f| | |
390 | _erbout.concat f.time_zone_select(:time_zone) | |
391 | end | |
392 | ||
393 | assert_dom_equal( | |
394 | "<select id=\"firm_time_zone\" name=\"firm[time_zone]\">" + | |
395 | "<option value=\"A\">A</option>\n" + | |
396 | "<option value=\"B\">B</option>\n" + | |
397 | "<option value=\"C\">C</option>\n" + | |
398 | "<option value=\"D\" selected=\"selected\">D</option>\n" + | |
399 | "<option value=\"E\">E</option>" + | |
400 | "</select>", | |
401 | _erbout | |
402 | ) | |
403 | end | |
404 | ||
def test_time_zone_select_with_blank | ||
@firm = Firm.new("D") | ||
html = time_zone_select("firm", "time_zone", nil, :include_blank => true) |
rool/rails/typo/trunk/vendor/rails/actionpack/test/template/form_tag_helper_test.rb:
prev. | current | |
expected = %(<input id="admin" name="title" type="text" value="Hello!" />) | ||
assert_dom_equal expected, actual | ||
end | ||
96 | ||
97 | def test_submit_tag | |
98 | assert_dom_equal( | |
99 | %(<input name='commit' type='submit' value='Save' onclick="this.disabled=true;this.value='Saving...';this.form.submit();alert('hello!')" />), | |
100 | submit_tag("Save", :disable_with => "Saving...", :onclick => "alert('hello!')") | |
101 | ) | |
102 | end | |
103 | ||
104 | def test_pass | |
105 | assert_equal 1, 1 | |
106 | end | |
end | ||
rool/rails/typo/trunk/vendor/rails/actionpack/test/template/java_script_macros_helper_test.rb:
prev. | current | |
def test_auto_complete_field | ||
26 | | |
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>), | |
auto_complete_field("some_input", :url => { :action => "autocomplete" }); | ||
28 | | |
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>), | |
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :tokens => ','); | ||
30 | | |
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>), | |
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :tokens => [',']); | ||
32 | | |
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>), | |
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :min_chars => 3); | ||
34 | | |
35 | | |
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)}"); | |
end | ||
def test_auto_complete_result | ||
... | ... | |
def test_text_field_with_auto_complete | ||
assert_match "<style>", | ||
text_field_with_auto_complete(:message, :recipient) | ||
53 | | |
58 | 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>), | |
text_field_with_auto_complete(:message, :recipient, {}, :skip_style => true) | ||
end | ||
61 | ||
62 | def test_in_place_editor_external_control | |
63 | assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Ajax.InPlaceEditor('some_input', 'http://www.example.com/inplace_edit', {externalControl:'blah'})\n//]]>\n</script>), | |
64 | in_place_editor('some_input', {:url => {:action => 'inplace_edit'}, :external_control => 'blah'}) | |
65 | end | |
66 | ||
67 | def test_in_place_editor_size | |
68 | assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Ajax.InPlaceEditor('some_input', 'http://www.example.com/inplace_edit', {size:4})\n//]]>\n</script>), | |
69 | in_place_editor('some_input', {:url => {:action => 'inplace_edit'}, :size => 4}) | |
70 | end | |
71 | ||
72 | def test_in_place_editor_cols_no_rows | |
73 | assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Ajax.InPlaceEditor('some_input', 'http://www.example.com/inplace_edit', {cols:4})\n//]]>\n</script>), | |
74 | in_place_editor('some_input', {:url => {:action => 'inplace_edit'}, :cols => 4}) | |
75 | end | |
76 | ||
77 | def test_in_place_editor_cols_with_rows | |
78 | assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Ajax.InPlaceEditor('some_input', 'http://www.example.com/inplace_edit', {cols:40, rows:5})\n//]]>\n</script>), | |
79 | in_place_editor('some_input', {:url => {:action => 'inplace_edit'}, :rows => 5, :cols => 40}) | |
80 | end | |
81 | ||
82 | def test_inplace_editor_loading_text | |
83 | assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Ajax.InPlaceEditor('some_input', 'http://www.example.com/inplace_edit', {loadingText:'Why are we waiting?'})\n//]]>\n</script>), | |
84 | in_place_editor('some_input', {:url => {:action => 'inplace_edit'}, :loading_text => 'Why are we waiting?'}) | |
85 | end | |
86 | ||
87 | def test_in_place_editor_url | |
88 | assert_match "Ajax.InPlaceEditor('id-goes-here', 'http://www.example.com/action_to_set_value')", | |
89 | in_place_editor( 'id-goes-here', :url => { :action => "action_to_set_value" }) | |
90 | end | |
91 | ||
92 | def test_in_place_editor_load_text_url | |
93 | assert_match "Ajax.InPlaceEditor('id-goes-here', 'http://www.example.com/action_to_set_value', {loadTextURL:'http://www.example.com/action_to_get_value'})", | |
94 | in_place_editor( 'id-goes-here', | |
95 | :url => { :action => "action_to_set_value" }, | |
96 | :load_text_url => { :action => "action_to_get_value" }) | |
97 | end | |
98 | ||
99 | def test_in_place_editor_eval_scripts | |
100 | assert_match "Ajax.InPlaceEditor('id-goes-here', 'http://www.example.com/action_to_set_value', {evalScripts:true})", | |
101 | in_place_editor( 'id-goes-here', | |
102 | :url => { :action => "action_to_set_value" }, | |
103 | :script => true ) | |
104 | end | |
105 | ||
end |
rool/rails/typo/trunk/vendor/rails/actionpack/test/template/javascript_helper_test.rb:
prev. | current | |
include ActionView::Helpers::FormHelper | ||
include ActionView::Helpers::CaptureHelper | ||
12 | | |
13 | | |
14 | | |
15 | | |
16 | | |
17 | | |
18 | | |
19 | | |
20 | | |
21 | | |
22 | | |
def test_define_javascript_functions | ||
# check if prototype.js is included first | ||
assert_not_nil define_javascript_functions.split("\n")[1].match(/Prototype JavaScript framework/) | ||
... | ... | |
link_to_function("Greeting", "alert('Hello world!')") | ||
end | ||
40 | | |
41 | | |
42 | | |
43 | | |
44 | | |
45 | | |
46 | | |
47 | | |
48 | | |
29 | def test_link_to_function_with_existing_onclick | |
30 | assert_dom_equal %(<a href="#" onclick="confirm('Sanity!'); alert('Hello world!'); return false;">Greeting</a>), | |
31 | link_to_function("Greeting", "alert('Hello world!')", :onclick => "confirm('Sanity!')") | |
end | ||
50 | | |
51 | | |
52 | | |
53 | | |
33 | ||
34 | def test_button_to_function | |
35 | assert_dom_equal %(<input type="button" onclick="alert('Hello world!');" value="Greeting" />), | |
36 | button_to_function("Greeting", "alert('Hello world!')") | |
end | ||
55 | | |
56 | | |
57 | | |
58 | | |
59 | | |
60 | | |
61 | | |
62 | | |
63 | | |
64 | | |
65 | | |
66 | | |
67 | | |
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
73 | | |
74 | | |
75 | | |
76 | | |
77 | | |
78 | | |
79 | | |
80 | | |
81 | | |
82 | | |
83 | | |
84 | | |
85 | | |
86 | | |
87 | | |
88 | | |
89 | | |
90 | | |
91 | | |
92 | | |
93 | | |
94 | | |
95 | | |
96 | | |
97 | | |
98 | | |
99 | | |
100 | | |
101 | | |
102 | | |
103 | | |
104 | | |
105 | | |
106 | | |
107 | | |
108 | | |
109 | | |
110 | | |
111 | | |
112 | | |
113 | | |
114 | | |
115 | | |
116 | | |
117 | | |
118 | | |
119 | | |
120 | | |
121 | | |
122 | | |
123 | | |
124 | | |
125 | | |
126 | | |
127 | | |
128 | | |
129 | | |
130 | | |
131 | | |
132 | | |
133 | | |
134 | | |
135 | | |
136 | | |
137 | | |
138 | | |
139 | | |
140 | | |
141 | | |
142 | | |
143 | | |
144 | | |
145 | | |
146 | | |
147 | | |
148 | | |
149 | | |
150 | | |
151 | | |
152 | | |
153 | | |
154 | | |
155 | | |
156 | | |
157 | | |
158 | | |
159 | | |
160 | | |
161 | | |
162 | | |
163 | | |
164 | | |
165 | | |
166 | | |
167 | | |
168 | | |
169 | | |
170 | | |
171 | | |
172 | | |
173 | | |
174 | | |
175 | | |
176 | | |
177 | | |
178 | | |
179 | | |
180 | | |
181 | | |
182 | | |
183 | | |
end |
rool/rails/typo/trunk/vendor/rails/actionpack/test/template/number_helper_test.rb:
prev. | current | |
end | ||
def test_number_to_human_size | ||
37 | | |
38 | | |
39 | | |
40 | | |
41 | | |
42 | | |
43 | | |
44 | | |
45 | | |
46 | | |
47 | | |
48 | | |
49 | | |
37 | assert_equal '0 Bytes', human_size(0) | |
38 | assert_equal '3 Bytes', human_size(3.14159265) | |
39 | assert_equal '123 Bytes', human_size(123.0) | |
40 | assert_equal '123 Bytes', human_size(123) | |
41 | assert_equal '1.2 KB', human_size(1234) | |
42 | assert_equal '12.1 KB', human_size(12345) | |
43 | assert_equal '1.2 MB', human_size(1234567) | |
44 | assert_equal '1.1 GB', human_size(1234567890) | |
45 | assert_equal '1.1 TB', human_size(1234567890123) | |
46 | assert_equal '444 KB', human_size(444.kilobytes) | |
47 | assert_equal '1023 MB', human_size(1023.megabytes) | |
48 | assert_equal '3 TB', human_size(3.terabytes) | |
49 | assert_nil human_size('x') | |
50 | assert_nil human_size(nil) | |
end | ||
def test_number_with_precision |
rool/rails/typo/trunk/vendor/rails/actionpack/test/template/text_helper_test.rb:
prev. | current | |
1 | ||
1 | require File.dirname(__FILE__) + '/../abstract_unit' | |
require "#{File.dirname(__FILE__)}/../testing_sandbox" | ||
3 | ||
4 | ||
5 | ||
6 | ||
class TextHelperTest < Test::Unit::TestCase | ||
include ActionView::Helpers::TextHelper | ||
... | ... | |
def test_truncate | ||
assert_equal "Hello World!", truncate("Hello World!", 12) | ||
27 | | |
23 | assert_equal "Hello Wor...", truncate("Hello World!!", 12) | |
end | ||
def test_truncate_multibyte_without_kcode | ||
result = execute_in_sandbox(<<-'CODE') | ||
28 | require File.dirname(__FILE__) + '/../../activesupport/lib/active_support/core_ext/kernel' | |
require "#{File.dirname(__FILE__)}/../lib/action_view/helpers/text_helper" | ||
include ActionView::Helpers::TextHelper | ||
truncate("\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224", 10) | ||
CODE | ||
37 | | |
34 | assert_equal "\354\225\210\353\205\225\355...", result | |
end | ||
def test_truncate_multibyte_with_kcode | ||
... | ... | |
$KCODE = "u" | ||
require 'jcode' | ||
42 | require File.dirname(__FILE__) + '/../../activesupport/lib/active_support/core_ext/kernel' | |
require "#{File.dirname(__FILE__)}/../lib/action_view/helpers/text_helper" | ||
include ActionView::Helpers::TextHelper | ||
truncate("\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254\353\236 \354\225\204\353\235\274\353\246\254\354\230\244", 10) | ||
CODE | ||
50 | | |
48 | assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254\353\236 ...", result | |
end | ||
def test_strip_links | ||
... | ... | |
link3_result = %{<a href="#{link3_raw}">#{link3_raw}</a>} | ||
link4_raw = 'http://foo.example.com/controller/action?parm=value&p2=v2#anchor123' | ||
link4_result = %{<a href="#{link4_raw}">#{link4_raw}</a>} | ||
129 | link5_raw = 'http://foo.example.com:3000/controller/action' | |
130 | link5_result = %{<a href="#{link5_raw}">#{link5_raw}</a>} | |
assert_equal %(hello #{email_result}), auto_link("hello #{email_raw}", :email_addresses) | ||
assert_equal %(Go to #{link_result}), auto_link("Go to #{link_raw}", :urls) | ||
... | ... | |
assert_equal %(<p>Go to #{link3_result}. seriously, #{link3_result}? i think I'll say hello to #{email_result}. instead.</p>), auto_link(%(<p>Go to #{link3_raw}. seriously, #{link3_raw}? i think I'll say hello to #{email_raw}. instead.</p>)) | ||
assert_equal %(<p>Link #{link4_result}</p>), auto_link("<p>Link #{link4_raw}</p>") | ||
assert_equal %(<p>#{link4_result} Link</p>), auto_link("<p>#{link4_raw} Link</p>") | ||
155 | assert_equal %(<p>#{link5_result} Link</p>), auto_link("<p>#{link5_raw} Link</p>") | |
156 | assert_equal '', auto_link(nil) | |
157 | assert_equal '', auto_link('') | |
end | ||
def test_auto_link_at_eol | ||
... | ... | |
url = "http://api.rubyonrails.com/Foo.html" | ||
email = "fantabulous@shiznadel.ic" | ||
168 | | |
171 | assert_equal %(<p><a href="#{url}">#{url[0...7]}...</a><br /><a href="mailto:#{email}">#{email[0...7]}...</a><br /></p>), auto_link("<p>#{url}<br />#{email}<br /></p>") { |url| truncate(url, 10) } | |
end | ||
def test_sanitize_form |
rool/rails/typo/trunk/vendor/rails/actionpack/test/template/url_helper_test.rb:
prev. | current | |
def setup | ||
@controller = Class.new do | ||
16 | attr_accessor :url | |
def url_for(options, *parameters_for_method_reference) | ||
17 | | |
18 | url | |
end | ||
end | ||
@controller = @controller.new | ||
22 | @controller.url = "http://www.example.com" | |
end | ||
22 | ||
24 | ||
25 | def test_url_for_escapes_urls | |
26 | @controller.url = "http://www.example.com?a=b&c=d" | |
27 | assert_equal "http://www.example.com?a=b&c=d", url_for(:a => 'b', :c => 'd') | |
28 | assert_equal "http://www.example.com?a=b&c=d", url_for(:a => 'b', :c => 'd', :escape => true) | |
29 | assert_equal "http://www.example.com?a=b&c=d", url_for(:a => 'b', :c => 'd', :escape => false) | |
30 | end | |
31 | ||
# todo: missing test cases | ||
def test_button_to_with_straight_url | ||
assert_dom_equal "<form method=\"post\" action=\"http://www.example.com\" class=\"button-to\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", button_to("Hello", "http://www.example.com") | ||
... | ... | |
end | ||
def test_link_tag_with_query | ||
59 | | |
68 | assert_dom_equal "<a href=\"http://www.example.com?q1=v1&q2=v2\">Hello</a>", link_to("Hello", "http://www.example.com?q1=v1&q2=v2") | |
end | ||
def test_link_tag_with_query_and_no_name | ||
63 | | |
72 | assert_dom_equal "<a href=\"http://www.example.com?q1=v1&q2=v2\">http://www.example.com?q1=v1&q2=v2</a>", link_to(nil, "http://www.example.com?q1=v1&q2=v2") | |
end | ||
75 | def test_link_tag_with_img | |
76 | assert_dom_equal "<a href=\"http://www.example.com\"><img src='/favicon.jpg' /></a>", link_to("<img src='/favicon.jpg' />", "http://www.example.com") | |
77 | end | |
78 | ||
79 | def test_link_with_nil_html_options | |
80 | assert_dom_equal "<a href=\"http://www.example.com\">Hello</a>", link_to("Hello", {:action => 'myaction'}, nil) | |
81 | end | |
82 | ||
def test_link_tag_with_custom_onclick | ||
assert_dom_equal "<a href=\"http://www.example.com\" onclick=\"alert('yay!')\">Hello</a>", link_to("Hello", "http://www.example.com", :onclick => "alert('yay!')") | ||
end | ||
69 | ||
86 | ||
def test_link_tag_with_javascript_confirm | ||
assert_dom_equal( | ||
"<a href=\"http://www.example.com\" onclick=\"return confirm('Are you sure?');\">Hello</a>", | ||
... | ... | |
def test_link_tag_using_post_javascript | ||
assert_dom_equal( | ||
113 | | |
130 | "<a href=\"http://www.example.com\" onclick=\"var f = document.createElement('form'); this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href; f.submit();return false;\">Hello</a>", | |
link_to("Hello", "http://www.example.com", :post => true) | ||
) | ||
end | ||
def test_link_tag_using_post_javascript_and_confirm | ||
assert_dom_equal( | ||
120 | | |
137 | "<a href=\"http://www.example.com\" onclick=\"if (confirm('Are you serious?')) { var f = document.createElement('form'); this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href; f.submit(); };return false;\">Hello</a>", | |
link_to("Hello", "http://www.example.com", :post => true, :confirm => "Are you serious?") | ||
) | ||
end | ||
... | ... | |
assert_equal "Showing", link_to_if(false, "Showing", :action => "show", :controller => "weblog", :id => 1) | ||
end | ||
150 | ||
def xtest_link_unless_current | ||
@request = RequestMock.new("http://www.example.com") | ||
assert_equal "Showing", link_to_unless_current("Showing", :action => "show", :controller => "weblog") | ||
... | ... | |
@request = RequestMock.new("http://www.example.com") | ||
assert_equal "Showing", link_to_unless_current("Showing", :action => "show", :controller => "weblog", :id => 1) | ||
end | ||
160 | ||
176 | ||
def test_mail_to | ||
assert_dom_equal "<a href=\"mailto:david@loudthinking.com\">david@loudthinking.com</a>", mail_to("david@loudthinking.com") | ||
assert_dom_equal "<a href=\"mailto:david@loudthinking.com\">David Heinemeier Hansson</a>", mail_to("david@loudthinking.com", "David Heinemeier Hansson") | ||
... | ... | |
end | ||
def test_mail_to_with_javascript | ||
173 | | |
189 | assert_dom_equal "<script type=\"text/javascript\">eval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript") | |
end | ||
def test_mail_with_options | ||
... | ... | |
mail_to("me@example.com", "My email", :cc => "ccaddress@example.com", :bcc => "bccaddress@example.com", :subject => "This is an example email", :body => "This is the body of the message.") | ||
) | ||
end | ||
198 | ||
199 | def test_mail_to_with_img | |
200 | assert_dom_equal %(<a href="mailto:feedback@example.com"><img src="/feedback.png" /></a>), mail_to('feedback@example.com', '<img src="/feedback.png" />') | |
201 | end | |
def test_mail_to_with_hex | ||
assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">My email</a>", mail_to("me@domain.com", "My email", :encode => "hex") | ||
... | ... | |
assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">me(at)domain.com</a>", mail_to("me@domain.com", nil, :encode => "hex", :replace_at => "(at)") | ||
assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">My email</a>", mail_to("me@domain.com", "My email", :encode => "hex", :replace_at => "(at)") | ||
assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">me(at)domain(dot)com</a>", mail_to("me@domain.com", nil, :encode => "hex", :replace_at => "(at)", :replace_dot => "(dot)") | ||
192 | | |
212 | assert_dom_equal "<script type=\"text/javascript\">eval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") | |
end | ||
194 | ||
195 | | |
196 | | |
197 | | |
end |
rool/rails/typo/trunk/vendor/rails/actionwebservice/CHANGELOG:
prev. | current | |
1 | *1.1.2* (April 9th, 2005) | |
2 | ||
3 | * Rely on Active Record 1.14.2 | |
4 | ||
5 | ||
6 | *1.1.1* (April 6th, 2005) | |
7 | ||
8 | * Do not convert driver options to strings (#4499) | |
9 | ||
10 | ||
11 | *1.1.0* (March 27th, 2005) | |
12 | ||
13 | * Make ActiveWebService::Struct type reloadable | |
14 | ||
15 | * Fix scaffolding action when one of the members of a structural type has date or time type | |
16 | ||
17 | * Remove extra index hash when generating scaffold html for parameters of structural type #4374 [joe@mjg2.com] | |
18 | ||
19 | * Fix Scaffold Fails with Struct as a Parameter #4363 [joe@mjg2.com] | |
20 | ||
21 | * Fix soap type registration of multidimensional arrays (#4232) | |
22 | ||
23 | * Fix that marshaler couldn't handle ActiveRecord models defined in a different namespace (#2392). | |
24 | ||
25 | * Fix that marshaler couldn't handle structs with members of ActiveRecord type (#1889). | |
26 | ||
27 | * Fix that marshaler couldn't handle nil values for inner structs (#3576). | |
28 | ||
29 | * Fix that changes to ActiveWebService::API::Base required restarting of the server (#2390). | |
30 | ||
31 | * Fix scaffolding for signatures with :date, :time and :base64 types (#3321, #2769, #2078). | |
32 | ||
33 | * Fix for incorrect casting of TrueClass/FalseClass instances (#2633, #3421). | |
34 | ||
35 | * Fix for incompatibility problems with SOAP4R 1.5.5 (#2553) [Kent Sibilev] | |
36 | ||
37 | ||
*1.0.0* (December 13th, 2005) | ||
* Become part of Rails 1.0 | ||
... | ... | |
3 | ||
*0.9.4* (December 7th, 2005) | ||
... | ... | |
* Fix that XML-RPC date/time values did not have well-defined behaviour (#2516, #2534). This fix has one caveat, in that we can't support pre-1970 dates from XML-RPC clients. | ||
14 | ||
*0.9.3* (November 7th, 2005) | ||
* Upgraded to Action Pack 1.11.0 and Active Record 1.13.0 |
rool/rails/typo/trunk/vendor/rails/actionwebservice/Rakefile:
prev. | current | |
t.verbose = true | ||
} | ||
33 | SCHEMA_PATH = File.join(File.dirname(__FILE__), *%w(test fixtures db_definitions)) | |
35 | desc 'Build the MySQL test database' | |
36 | task :build_database do | |
37 | %x( mysqladmin create activewebservice_unittest ) | |
38 | %x( mysql activewebservice_unittest < #{File.join(SCHEMA_PATH, 'mysql.sql')} ) | |
39 | end | |
40 | ||
41 | ||
# Generate the RDoc documentation | ||
Rake::RDocTask.new { |rdoc| | ||
rdoc.rdoc_dir = 'doc' | ||
rdoc.title = "Action Web Service -- Web services for Action Pack" | ||
38 | | |
46 | rdoc.options << '--line-numbers' << '--inline-source' | |
rdoc.template = "#{ENV['template']}.rb" if ENV['template'] | ||
rdoc.rdoc_files.include('README') | ||
rdoc.rdoc_files.include('CHANGELOG') | ||
... | ... | |
s.rubyforge_project = "aws" | ||
s.homepage = "http://www.rubyonrails.org" | ||
66 | | |
67 | | |
74 | s.add_dependency('actionpack', '= 1.12.1' + PKG_BUILD) | |
75 | s.add_dependency('activerecord', '= 1.14.2' + PKG_BUILD) | |
s.has_rdoc = true | ||
s.requirements << 'none' | ||
... | ... | |
end | ||
desc "Publish the release files to RubyForge." | ||
155 | ||
156 | | |
163 | task :release => [ :package ] do | |
164 | `rubyforge login` | |
158 | | |
159 | | |
160 | | |
161 | ||
162 | | |
163 | | |
164 | | |
165 | | |
166 | ||
167 | | |
168 | | |
169 | | |
170 | | |
171 | | |
172 | | |
173 | | |
174 | ||
175 | | |
176 | | |
177 | | |
178 | | |
179 | | |
180 | | |
181 | | |
182 | | |
183 | ||
184 | | |
185 | | |
186 | | |
187 | ||
188 | | |
189 | | |
190 | | |
191 | | |
192 | ||
193 | | |
194 | | |
195 | ||
196 | | |
197 | | |
198 | | |
199 | | |
200 | ||
201 | | |
202 | ||
203 | | |
204 | | |
205 | | |
206 | | |
207 | | |
208 | | |
209 | | |
210 | | |
211 | | |
212 | | |
213 | ||
214 | | |
215 | | |
216 | | |
217 | | |
218 | | |
219 | | |
220 | | |
221 | | |
222 | | |
223 | | |
224 | | |
225 | | |
226 | | |
227 | | |
228 | | |
229 | | |
230 | | |
231 | | |
232 | | |
233 | | |
234 | | |
235 | | |
236 | | |
237 | | |
238 | ||
239 | | |
240 | | |
241 | | |
242 | ||
243 | | |
244 | | |
245 | | |
246 | | |
247 | | |
248 | | |
249 | | |
250 | ||
251 | | |
252 | | |
253 | | |
254 | ||
255 | | |
256 | | |
257 | | |
258 | ||
259 | | |
260 | | |
261 | | |
262 | | |
263 | ||
264 | | |
265 | | |
166 | for ext in %w( gem tgz zip ) | |
167 | release_command = "rubyforge add_release #{PKG_NAME} #{PKG_NAME} 'REL #{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" | |
168 | puts release_command | |
169 | system(release_command) | |
end | ||
267 | ||
171 | end | |
rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/api.rb:
prev. | current | |
# See ActionWebService::Container::Direct::ClassMethods for an example | ||
# of use. | ||
class Base | ||
17 | # Action WebService API subclasses should be reloaded by the dispatcher in Rails | |
18 | # when Dependencies.mechanism = :load. | |
19 | include Reloadable::Subclasses | |
20 | ||
# Whether to transform the public API method names into camel-cased names | ||
class_inheritable_option :inflect_names, true | ||
rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/base.rb:
prev. | current | |
# api_method :delete_person, :expects => [:int] | ||
# end | ||
# | ||
28 | | |
28 | # class SearchCriteria < ActionWebService::Struct | |
# member :firstname, :string | ||
# member :lastname, :string | ||
# member :email, :string | ||
# end | ||
class Base | ||
34 | # Action WebService subclasses should be reloaded by the dispatcher in Rails | |
35 | # when Dependencies.mechanism = :load. | |
36 | include Reloadable::Subclasses | |
37 | ||
# Whether to report exceptions back to the caller in the protocol's exception | ||
# format | ||
class_inheritable_option :web_service_exception_reporting, true |
rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/casting.rb:
prev. | current | |
def cast(value, signature_type) # :nodoc: | ||
return value if signature_type.nil? # signature.length != params.length | ||
return nil if value.nil? | ||
44 | # XMLRPC protocol doesn't support nil values. It uses false instead. | |
45 | # It should never happen for SOAP. | |
46 | if signature_type.structured? && value.equal?(false) | |
47 | return nil | |
48 | end | |
unless signature_type.array? || signature_type.structured? | ||
return value if canonical_type(value.class) == signature_type.type | ||
end | ||
... | ... | |
when :float | ||
Float(value) | ||
when :time | ||
99 | value = "#{value['2']}/#{value['3']}/#{value['1']} #{value['4']}:#{value['5']}:#{value['6']}" if value.kind_of?(Hash) | |
Time.parse(value.to_s) | ||
when :date | ||
102 | value = "#{value['2']}/#{value['3']}/#{value['1']}" if value.kind_of?(Hash) | |
Date.parse(value.to_s) | ||
when :datetime | ||
105 | value = "#{value['2']}/#{value['3']}/#{value['1']} #{value['4']}:#{value['5']}:#{value['6']}" if value.kind_of?(Hash) | |
DateTime.parse(value.to_s) | ||
end | ||
end | ||
... | ... | |
value.each_pair do |name, val| | ||
type = klass.respond_to?(:member_type) ? klass.member_type(name) : nil | ||
val = cast(val, type) if type | ||
119 | # See http://dev.rubyonrails.com/ticket/3567 | |
120 | val = val.to_time if val.is_a?(XMLRPC::DateTime) | |
obj.__send__("#{name}=", val) if obj.respond_to?(name) | ||
end | ||
elsif value.respond_to?(:attributes) |
rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/client/soap_client.rb:
prev. | current | |
@soap_action_base ||= URI.parse(endpoint_uri).path | ||
@driver = create_soap_rpc_driver(api, endpoint_uri) | ||
@driver_options.each do |name, value| | ||
53 | | |
53 | @driver.options[name.to_s] = value | |
end | ||
end | ||
... | ... | |
if expects | ||
expects.each do |type| | ||
type_binding = @protocol.marshaler.lookup_type(type) | ||
83 | | |
83 | if SOAP::Version >= "1.5.5" | |
84 | param_def << ['in', type.name.to_s, [type_binding.type.type_class.to_s]] | |
85 | else | |
86 | param_def << ['in', type.name, type_binding.mapping] | |
87 | end | |
end | ||
end | ||
if returns | ||
type_binding = @protocol.marshaler.lookup_type(returns[0]) | ||
88 | | |
92 | if SOAP::Version >= "1.5.5" | |
93 | param_def << ['retval', 'return', [type_binding.type.type_class.to_s]] | |
94 | else | |
95 | param_def << ['retval', 'return', type_binding.mapping] | |
96 | end | |
end | ||
driver.add_method(qname, action, method.name.to_s, param_def) | ||
end |
rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/protocol/soap_protocol/marshaler.rb:
prev. | current | |
end | ||
def ruby_to_soap(obj) | ||
35 | | |
35 | soap = SOAP::Mapping.obj2soap(obj, @registry) | |
36 | soap.elename = XSD::QName.new if SOAP::Version >= "1.5.5" && soap.elename == XSD::QName::EMPTY | |
37 | soap | |
end | ||
def register_type(type) | ||
return @type2binding[type] if @type2binding.has_key?(type) | ||
41 | | |
42 | | |
43 | | |
44 | | |
43 | if type.array? | |
44 | array_mapping = @registry.find_mapped_soap_class(Array) | |
45 | qname = XSD::QName.new(@namespace, soap_type_name(type.element_type.type_class.name) + 'Array') | |
46 | element_type_binding = register_type(type.element_type) | |
47 | @type2binding[type] = SoapBinding.new(self, qname, type, array_mapping, element_type_binding) | |
48 | elsif (mapping = @registry.find_mapped_soap_class(type.type_class) rescue nil) | |
qname = mapping[2] ? mapping[2][:type] : nil | ||
qname ||= soap_base_type_name(mapping[0]) | ||
47 | | |
51 | @type2binding[type] = SoapBinding.new(self, qname, type, mapping) | |
else | ||
49 | | |
50 | | |
51 | | |
52 | | |
53 | | |
54 | | |
55 | | |
53 | qname = XSD::QName.new(@namespace, soap_type_name(type.type_class.name)) | |
54 | @registry.add(type.type_class, | |
55 | SOAP::SOAPStruct, | |
56 | typed_struct_factory(type.type_class), | |
57 | { :type => qname }) | |
58 | mapping = @registry.find_mapped_soap_class(type.type_class) | |
59 | @type2binding[type] = SoapBinding.new(self, qname, type, mapping) | |
end | ||
58 | | |
59 | | |
60 | | |
61 | | |
62 | | |
62 | if type.structured? | |
63 | type.each_member do |m_name, m_type| | |
64 | register_type(m_type) | |
65 | end | |
end | ||
64 | ||
65 | | |
67 | ||
@type2binding[type] | ||
end | ||
alias :lookup_type :register_type | ||
def annotate_arrays(binding, value) | ||
71 | | |
73 | if value.nil? | |
74 | return | |
75 | elsif binding.type.array? | |
mark_typed_array(value, binding.element_binding.qname) | ||
if binding.element_binding.type.custom? | ||
value.each do |element| |
rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb:
prev. | current | |
end | ||
def encode_response(method_name, return_value, return_type, protocol_options={}) | ||
53 | | |
54 | | |
53 | if return_value && return_type | |
return_value = value_to_xmlrpc_wire_format(return_value, return_type) | ||
end | ||
56 | return_value = false if return_value.nil? | |
raw_response = XMLRPC::Marshal.dump_response(return_value) | ||
Response.new(raw_response, 'text/xml', return_value) | ||
end |
rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/scaffolding.rb:
prev. | current | |
when :xmlrpc | ||
@protocol = Protocol::XmlRpc::XmlRpcProtocol.create(self) | ||
end | ||
68 | | |
bm = Benchmark.measure do | ||
@protocol.register_api(@scaffold_service.api) | ||
post_params = params['method_params'] ? params['method_params'].dup : nil | ||
params = [] | ||
73 | | |
74 | | |
75 | | |
76 | | |
77 | | |
72 | @scaffold_method.expects.each_with_index do |spec, i| | |
73 | params << post_params[i.to_s] | |
74 | end if @scaffold_method.expects | |
params = @scaffold_method.cast_expects(params) | ||
method_name = public_method_name(@scaffold_service.name, @scaffold_method.public_name) | ||
@method_request_xml = @protocol.encode_request(method_name, params, @scaffold_method.expects) | ||
... | ... | |
end | ||
def reset_invocation_response | ||
133 | | |
134 | | |
135 | | |
136 | | |
137 | | |
138 | | |
139 | | |
140 | | |
130 | erase_render_results | |
131 | @response.headers = ::ActionController::AbstractResponse::DEFAULT_HEADERS.merge("cookie" => []) | |
end | ||
def public_method_name(service_name, method_name) | ||
... | ... | |
end | ||
module Helpers # :nodoc: | ||
176 | | |
167 | def method_parameter_input_fields(method, type, field_name_base, idx, was_structured=false) | |
if type.array? | ||
return content_tag('em', "Typed array input fields not supported yet (#{type.name})") | ||
end | ||
if type.structured? | ||
172 | return content_tag('em', "Nested structural types not supported yet (#{type.name})") if was_structured | |
parameters = "" | ||
type.each_member do |member_name, member_type| | ||
label = method_parameter_label(member_name, member_type) | ||
nested_content = method_parameter_input_fields( | ||
method, | ||
member_type, | ||
187 | | |
179 | "#{field_name_base}[#{idx}][#{member_name}]", | |
180 | idx, | |
181 | true) | |
if member_type.custom? | ||
parameters << content_tag('li', label) | ||
parameters << content_tag('ul', nested_content) | ||
... | ... | |
end | ||
content_tag('ul', parameters) | ||
else | ||
191 | # If the data source was structured previously we already have the index set | |
192 | field_name_base = "#{field_name_base}[#{idx}]" unless was_structured | |
193 | ||
case type.type | ||
when :int | ||
199 | | |
196 | text_field_tag "#{field_name_base}" | |
when :string | ||
201 | | |
198 | text_field_tag "#{field_name_base}" | |
199 | when :base64 | |
200 | text_area_tag "#{field_name_base}", nil, :size => "40x5" | |
when :bool | ||
203 | | |
204 | | |
202 | radio_button_tag("#{field_name_base}", "true") + " True" + | |
203 | radio_button_tag("#{field_name_base}", "false") + "False" | |
when :float | ||
206 | | |
207 | | |
208 | | |
205 | text_field_tag "#{field_name_base}" | |
206 | when :time, :datetime | |
207 | time = Time.now | |
208 | i = 0 | |
209 | %w|year month day hour minute second|.map do |name| | |
210 | i += 1 | |
211 | send("select_#{name}", time, :prefix => "#{field_name_base}[#{i}]", :discard_type => true) | |
212 | end.join | |
when :date | ||
210 | | |
214 | date = Date.today | |
215 | i = 0 | |
216 | %w|year month day|.map do |name| | |
217 | i += 1 | |
218 | send("select_#{name}", date, :prefix => "#{field_name_base}[#{i}]", :discard_type => true) | |
219 | end.join | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/struct.rb:
prev. | current | |
# Active Record model classes are already implicitly supported in method | ||
# signatures. | ||
class Struct | ||
22 | # Action WebService Struct subclasses should be reloaded by the dispatcher in Rails | |
23 | # when Dependencies.mechanism = :load. | |
24 | include Reloadable::Subclasses | |
# If a Hash is given as argument to an ActionWebService::Struct constructor, | ||
# it can contain initial values for the structure member. |
rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/support/signature_types.rb:
prev. | current | |
case name | ||
when :int, :integer, :fixnum, :bignum | ||
:int | ||
56 | | |
56 | when :string, :text | |
:string | ||
58 | | |
58 | when :base64, :binary | |
:base64 | ||
when :bool, :boolean | ||
:bool | ||
... | ... | |
elsif @type_class.respond_to?(:columns) | ||
i = -1 | ||
@type_class.columns.each do |column| | ||
206 | | |
206 | yield column.name, canonical_signature_entry(column.type, i += 1) | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/templates/scaffolds/layout.rhtml:
prev. | current | |
display: table; | ||
} | ||
29 | | |
29 | #errorExplanation { | |
width: 400px; | ||
31 | | |
32 | | |
33 | | |
34 | | |
35 | | |
31 | border: 2px solid red; | |
32 | padding: 7px; | |
33 | padding-bottom: 12px; | |
34 | margin-bottom: 20px; | |
35 | background-color: #f0f0f0; | |
} | ||
38 | | |
39 | | |
40 | | |
41 | | |
42 | | |
43 | | |
44 | | |
45 | | |
38 | #errorExplanation h2 { | |
39 | text-align: left; | |
40 | font-weight: bold; | |
41 | padding: 5px 5px 5px 15px; | |
42 | font-size: 12px; | |
43 | margin: -7px; | |
44 | background-color: #c00; | |
45 | color: #fff; | |
} | ||
48 | | |
49 | | |
50 | | |
51 | | |
48 | #errorExplanation p { | |
49 | color: #333; | |
50 | margin-bottom: 0; | |
51 | padding: 5px; | |
} | ||
54 | | |
55 | | |
56 | | |
54 | #errorExplanation ul li { | |
55 | font-size: 12px; | |
56 | list-style: square; | |
} | ||
</style> | ||
</head> |
rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/templates/scaffolds/parameters.rhtml:
prev. | current | |
</p> | ||
<% if @scaffold_method.expects %> | ||
13 | ||
<strong>Method Parameters:</strong><br /> | ||
16 | ||
15 | <% @scaffold_method.expects.each_with_index do |type, i| %> | |
<p> | ||
<label for="method_params[<%= i %>]"><%= method_parameter_label(type.name, type) %> </label><br /> | ||
19 | | |
18 | <%= method_parameter_input_fields(@scaffold_method, type, "method_params", i) %> | |
</p> | ||
21 | | |
<% end %> | ||
<% end %> | ||
<%= submit_tag "Invoke" %> | ||
25 | <%= end_form_tag %> | |
<p> | ||
<%= link_to "Back", :action => @scaffold_action_name %> |
rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/test_invoke.rb:
prev. | current | |
end | ||
protocol.register_api(api) | ||
method = api.api_methods[api_method_name.to_sym] | ||
55 | raise ArgumentError, "wrong number of arguments for rpc call (#{args.length} for #{method.expects.length})" unless args.length == method.expects.length | |
protocol.encode_request(public_method_name(service_name, api_method_name), args.dup, method.expects) | ||
end | ||
rool/rails/typo/trunk/vendor/rails/actionwebservice/lib/action_web_service/version.rb:
prev. | current | |
module ActionWebService | ||
2 | | |
2 | module VERSION #:nodoc: | |
MAJOR = 1 | ||
4 | | |
5 | | |
4 | MINOR = 1 | |
5 | TINY = 2 | |
STRING = [MAJOR, MINOR, TINY].join('.') | ||
end |
rool/rails/typo/trunk/vendor/rails/actionwebservice/test/abstract_client.rb:
prev. | current | |
firstnames == other.firstnames && lastname == other.lastname | ||
end | ||
end | ||
15 | ||
16 | class Inner < ActionWebService::Struct | |
17 | member :name, :string | |
18 | end | |
19 | ||
20 | class Outer < ActionWebService::Struct | |
21 | member :name, :string | |
22 | member :inner, Inner | |
23 | end | |
25 | class User < ActiveRecord::Base | |
26 | end | |
27 | ||
28 | module Accounting | |
29 | class User < ActiveRecord::Base | |
30 | end | |
31 | end | |
32 | ||
33 | class WithModel < ActionWebService::Struct | |
34 | member :user, User | |
35 | member :users, [User] | |
36 | end | |
37 | ||
38 | class WithMultiDimArray < ActionWebService::Struct | |
39 | member :pref, [[:string]] | |
40 | end | |
41 | ||
class API < ActionWebService::API::Base | ||
api_method :void | ||
18 | | |
19 | | |
20 | | |
21 | | |
22 | | |
44 | api_method :normal, :expects => [:int, :int], :returns => [:int] | |
45 | api_method :array_return, :returns => [[Person]] | |
46 | api_method :struct_pass, :expects => [[Person]], :returns => [:bool] | |
47 | api_method :nil_struct_return, :returns => [Person] | |
48 | api_method :inner_nil, :returns => [Outer] | |
49 | api_method :client_container, :returns => [:int] | |
50 | api_method :named_parameters, :expects => [{:key=>:string}, {:id=>:int}] | |
api_method :thrower | ||
52 | api_method :user_return, :returns => [User] | |
53 | api_method :with_model_return, :returns => [WithModel] | |
54 | api_method :scoped_model_return, :returns => [Accounting::User] | |
55 | api_method :multi_dim_return, :returns => [WithMultiDimArray] | |
end | ||
25 | ||
57 | ||
class NullLogOut | ||
def <<(*args); end | ||
end | ||
... | ... | |
@value_struct_pass = @method_params | ||
true | ||
end | ||
100 | ||
101 | def nil_struct_return | |
102 | nil | |
103 | end | |
104 | ||
105 | def inner_nil | |
106 | Outer.new :name => 'outer', :inner => nil | |
107 | end | |
def client_container | ||
50 | ||
... | ... | |
def thrower | ||
raise "Hi" | ||
end | ||
120 | ||
121 | def user_return | |
122 | User.find(1) | |
123 | end | |
124 | ||
125 | def with_model_return | |
126 | WithModel.new :user => User.find(1), :users => User.find(:all) | |
127 | end | |
128 | ||
129 | def scoped_model_return | |
130 | Accounting::User.find(1) | |
131 | end | |
132 | ||
133 | def multi_dim_return | |
134 | WithMultiDimArray.new :pref => [%w{pref1 value1}, %w{pref2 value2}] | |
135 | end | |
end | ||
class AbstractClientLet < WEBrick::HTTPServlet::AbstractServlet |
rool/rails/typo/trunk/vendor/rails/actionwebservice/test/abstract_unit.rb:
prev. | current | |
$:.unshift(File.dirname(__FILE__) + '/../../activerecord/lib') | ||
require 'test/unit' | ||
8 | ||
require 'action_web_service' | ||
require 'action_controller' | ||
require 'action_controller/test_process' | ||
ActionController::Base.logger = nil | ||
ActionController::Base.ignore_missing_templates = true | ||
14 | ||
15 | begin | |
16 | PATH_TO_AR = File.dirname(__FILE__) + '/../../activerecord' | |
17 | require "#{PATH_TO_AR}/lib/active_record" unless Object.const_defined?(:ActiveRecord) | |
18 | require "#{PATH_TO_AR}/lib/active_record/fixtures" unless Object.const_defined?(:Fixtures) | |
19 | rescue Object => e | |
20 | fail "\nFailed to load activerecord: #{e}" | |
21 | end | |
22 | ||
23 | ActiveRecord::Base.establish_connection( | |
24 | :adapter => "mysql", | |
25 | :username => "rails", | |
26 | :encoding => "utf8", | |
27 | :database => "activewebservice_unittest" | |
28 | ) | |
29 | ActiveRecord::Base.connection | |
30 | ||
31 | Test::Unit::TestCase.fixture_path = "#{File.dirname(__FILE__)}/fixtures/" | |
32 | ||
33 | # restore default raw_post functionality | |
34 | class ActionController::TestRequest | |
35 | def raw_post | |
36 | super | |
37 | end | |
38 | end | |
rool/rails/typo/trunk/vendor/rails/actionwebservice/test/client_soap_test.rb:
prev. | current | |
class TC_ClientSoap < Test::Unit::TestCase | ||
include ClientTest | ||
include ClientSoapTest | ||
52 | ||
53 | fixtures :users | |
def setup | ||
@server = SoapServer.instance | ||
... | ... | |
assert_equal(true, @client.struct_pass([new_person])) | ||
assert_equal([[new_person]], @container.value_struct_pass) | ||
end | ||
93 | ||
94 | def test_nil_struct_return | |
95 | assert_nil @client.nil_struct_return | |
96 | end | |
97 | ||
98 | def test_inner_nil | |
99 | outer = @client.inner_nil | |
100 | assert_equal 'outer', outer.name | |
101 | assert_nil outer.inner | |
102 | end | |
def test_client_container | ||
assert_equal(50, ClientContainer.new.get_client.client_container) | ||
... | ... | |
assert_equal([5, 6], @container.value_normal) | ||
@container.value_normal = nil | ||
end | ||
121 | ||
122 | def test_model_return | |
123 | user = @client.user_return | |
124 | assert_equal 1, user.id | |
125 | assert_equal 'Kent', user.name | |
126 | assert user.active? | |
127 | assert_kind_of Date, user.created_on | |
128 | assert_equal Date.today, user.created_on | |
129 | end | |
130 | ||
131 | def test_with_model | |
132 | with_model = @client.with_model_return | |
133 | assert_equal 'Kent', with_model.user.name | |
134 | assert_equal 2, with_model.users.size | |
135 | with_model.users.each do |user| | |
136 | assert_kind_of User, user | |
137 | end | |
138 | end | |
139 | ||
140 | def test_scoped_model_return | |
141 | scoped_model = @client.scoped_model_return | |
142 | assert_kind_of Accounting::User, scoped_model | |
143 | assert_equal 'Kent', scoped_model.name | |
144 | end | |
145 | ||
146 | def test_multi_dim_return | |
147 | md_struct = @client.multi_dim_return | |
148 | assert_kind_of Array, md_struct.pref | |
149 | assert_equal 2, md_struct.pref.size | |
150 | assert_kind_of Array, md_struct.pref[0] | |
151 | end | |
end |
rool/rails/typo/trunk/vendor/rails/actionwebservice/test/client_xmlrpc_test.rb:
prev. | current | |
test_request.env['HTTP_CONTENT_TYPE'] = 'text/xml' | ||
test_request.env['RAW_POST_DATA'] = req.body | ||
response = ActionController::TestResponse.new | ||
15 | | |
15 | @controller.process(test_request, response) | |
res.header['content-type'] = 'text/xml' | ||
res.body = response.body | ||
# puts res.body | ||
... | ... | |
class TC_ClientXmlRpc < Test::Unit::TestCase | ||
include ClientTest | ||
include ClientXmlRpcTest | ||
47 | ||
48 | fixtures :users | |
def setup | ||
@server = XmlRpcServer.instance | ||
... | ... | |
assert_equal(true, @client.struct_pass([new_person])) | ||
assert_equal([[new_person]], @container.value_struct_pass) | ||
end | ||
88 | ||
89 | def test_nil_struct_return | |
90 | assert_equal false, @client.nil_struct_return | |
91 | end | |
93 | def test_inner_nil | |
94 | outer = @client.inner_nil | |
95 | assert_equal 'outer', outer.name | |
96 | assert_nil outer.inner | |
97 | end | |
98 | ||
def test_client_container | ||
assert_equal(50, ClientContainer.new.get_client.client_container) | ||
end | ||
def test_named_parameters | ||
assert(@container.value_named_parameters.nil?) | ||
93 | | |
105 | assert_equal(false, @client.named_parameters("xxx", 7)) | |
assert_equal(["xxx", 7], @container.value_named_parameters) | ||
end | ||
... | ... | |
@client.normal | ||
end | ||
end | ||
120 | ||
121 | def test_model_return | |
122 | user = @client.user_return | |
123 | assert_equal 1, user.id | |
124 | assert_equal 'Kent', user.name | |
125 | assert user.active? | |
126 | assert_kind_of Time, user.created_on | |
127 | assert_equal Time.utc(Time.now.year, Time.now.month, Time.now.day), user.created_on | |
128 | end | |
129 | ||
130 | def test_with_model | |
131 | with_model = @client.with_model_return | |
132 | assert_equal 'Kent', with_model.user.name | |
133 | assert_equal 2, with_model.users.size | |
134 | with_model.users.each do |user| | |
135 | assert_kind_of User, user | |
136 | end | |
137 | end | |
138 | ||
139 | def test_scoped_model_return | |
140 | scoped_model = @client.scoped_model_return | |
141 | assert_kind_of Accounting::User, scoped_model | |
142 | assert_equal 'Kent', scoped_model.name | |
143 | end | |
144 | ||
145 | def test_multi_dim_return | |
146 | md_struct = @client.multi_dim_return | |
147 | assert_kind_of Array, md_struct.pref | |
148 | assert_equal 2, md_struct.pref.size | |
149 | assert_kind_of Array, md_struct.pref[0] | |
150 | end | |
end |
rool/rails/typo/trunk/vendor/rails/actionwebservice/test/scaffolded_controller_test.rb:
prev. | current | |
ActionController::Routing::Routes.draw do |map| | ||
map.connect '', :controller => 'scaffolded' | ||
5 | map.connect ':controller/:action/:id' | |
end | ||
8 | ActionController::Base.template_root = '.' | |
9 | ||
class ScaffoldPerson < ActionWebService::Struct | ||
8 | | |
9 | | |
11 | member :id, :int | |
12 | member :name, :string | |
13 | member :birth, :date | |
def ==(other) | ||
self.id == other.id && self.name == other.name | ||
... | ... | |
class ScaffoldedControllerTestAPI < ActionWebService::API::Base | ||
api_method :hello, :expects => [{:integer=>:int}, :string], :returns => [:bool] | ||
22 | api_method :hello_struct_param, :expects => [{:person => ScaffoldPerson}], :returns => [:bool] | |
23 | api_method :date_of_birth, :expects => [ScaffoldPerson], :returns => [:string] | |
api_method :bye, :returns => [[ScaffoldPerson]] | ||
25 | api_method :date_diff, :expects => [{:start_date => :date}, {:end_date => :date}], :returns => [:int] | |
26 | api_method :time_diff, :expects => [{:start_time => :time}, {:end_time => :time}], :returns => [:int] | |
27 | api_method :base64_upcase, :expects => [:base64], :returns => [:base64] | |
end | ||
class ScaffoldedController < ActionController::Base | ||
... | ... | |
def hello(int, string) | ||
0 | ||
end | ||
37 | ||
38 | def hello_struct_param(person) | |
39 | 0 | |
40 | end | |
41 | ||
42 | def date_of_birth(person) | |
43 | person.birth.to_s | |
44 | end | |
def bye | ||
[ScaffoldPerson.new(:id => 1, :name => "leon"), ScaffoldPerson.new(:id => 2, :name => "paul")] | ||
... | ... | |
def rescue_action(e) | ||
raise e | ||
end | ||
53 | ||
54 | def date_diff(start_date, end_date) | |
55 | end_date - start_date | |
56 | end | |
57 | ||
58 | def time_diff(start_time, end_time) | |
59 | end_time - start_time | |
60 | end | |
61 | ||
62 | def base64_upcase(data) | |
63 | data.upcase | |
64 | end | |
end | ||
class ScaffoldedControllerTest < Test::Unit::TestCase | ||
... | ... | |
get :scaffold_invoke_method_params, :service => 'scaffolded', :method => 'Hello' | ||
assert_rendered_file 'parameters.rhtml' | ||
end | ||
83 | ||
84 | def test_scaffold_invoke_method_params_with_struct | |
85 | get :scaffold_invoke_method_params, :service => 'scaffolded', :method => 'HelloStructParam' | |
86 | assert_rendered_file 'parameters.rhtml' | |
87 | assert_tag :tag => 'input', :attributes => {:name => "method_params[0][name]"} | |
88 | end | |
def test_scaffold_invoke_submit_hello | ||
post :scaffold_invoke_submit, :service => 'scaffolded', :method => 'Hello', :method_params => {'0' => '5', '1' => 'hello world'} | ||
... | ... | |
persons = [ScaffoldPerson.new(:id => 1, :name => "leon"), ScaffoldPerson.new(:id => 2, :name => "paul")] | ||
assert_equal persons, @controller.instance_eval{ @method_return_value } | ||
end | ||
102 | ||
103 | def test_scaffold_date_params | |
104 | get :scaffold_invoke_method_params, :service => 'scaffolded', :method => 'DateDiff' | |
105 | (0..1).each do |param| | |
106 | (1..3).each do |date_part| | |
107 | assert_tag :tag => 'select', :attributes => {:name => "method_params[#{param}][#{date_part}]"}, | |
108 | :children => {:greater_than => 1, :only => {:tag => 'option'}} | |
109 | end | |
110 | end | |
111 | ||
112 | post :scaffold_invoke_submit, :service => 'scaffolded', :method => 'DateDiff', | |
113 | :method_params => {'0' => {'1' => '2006', '2' => '2', '3' => '1'}, '1' => {'1' => '2006', '2' => '2', '3' => '2'}} | |
114 | assert_equal 1, @controller.instance_eval{ @method_return_value } | |
115 | end | |
116 | ||
117 | def test_scaffold_struct_date_params | |
118 | post :scaffold_invoke_submit, :service => 'scaffolded', :method => 'DateOfBirth', | |
119 | :method_params => {'0' => {'birth' => {'1' => '2006', '2' => '2', '3' => '1'}, 'id' => '1', 'name' => 'person'}} | |
120 | assert_equal '2006-02-01', @controller.instance_eval{ @method_return_value } | |
121 | end | |
122 | ||
123 | def test_scaffold_time_params | |
124 | get :scaffold_invoke_method_params, :service => 'scaffolded', :method => 'TimeDiff' | |
125 | (0..1).each do |param| | |
126 | (1..6).each do |date_part| | |
127 | assert_tag :tag => 'select', :attributes => {:name => "method_params[#{param}][#{date_part}]"}, | |
128 | :children => {:greater_than => 1, :only => {:tag => 'option'}} | |
129 | end | |
130 | end | |
131 | ||
132 | post :scaffold_invoke_submit, :service => 'scaffolded', :method => 'TimeDiff', | |
133 | :method_params => {'0' => {'1' => '2006', '2' => '2', '3' => '1', '4' => '1', '5' => '1', '6' => '1'}, | |
134 | '1' => {'1' => '2006', '2' => '2', '3' => '2', '4' => '1', '5' => '1', '6' => '1'}} | |
135 | assert_equal 86400, @controller.instance_eval{ @method_return_value } | |
136 | end | |
137 | ||
138 | def test_scaffold_base64 | |
139 | get :scaffold_invoke_method_params, :service => 'scaffolded', :method => 'Base64Upcase' | |
140 | assert_tag :tag => 'textarea', :attributes => {:name => 'method_params[0]'} | |
141 | ||
142 | post :scaffold_invoke_submit, :service => 'scaffolded', :method => 'Base64Upcase', :method_params => {'0' => 'scaffold'} | |
143 | assert_equal 'SCAFFOLD', @controller.instance_eval{ @method_return_value } | |
144 | end | |
end |
rool/rails/typo/trunk/vendor/rails/actionwebservice/test/test_invoke_test.rb:
prev. | current | |
end | ||
end | ||
end | ||
79 | ||
80 | def test_layered_fail_with_wrong_number_of_arguments | |
81 | [:soap, :xmlrpc].each do |protocol| | |
82 | @protocol = protocol | |
83 | [:one, :two].each do |service| | |
84 | @controller = TestInvokeLayeredController.new | |
85 | assert_raise(ArgumentError) { invoke_layered service, :add, 1 } | |
86 | end | |
87 | end | |
88 | end | |
89 | ||
90 | def test_delegated_fail_with_wrong_number_of_arguments | |
91 | @controller = TestInvokeDelegatedController.new | |
92 | assert_raise(ArgumentError) { invoke_delegated :service, :add, 1 } | |
93 | end | |
94 | ||
95 | def test_direct_fail_with_wrong_number_of_arguments | |
96 | @controller = TestInvokeDirectController.new | |
97 | assert_raise(ArgumentError) { invoke :add, 1 } | |
98 | end | |
99 | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/CHANGELOG:
prev. | current | |
1 | ||
1 | *1.14.2* (April 9th, 2005) | |
2 | ||
3 | * Fixed calculations for the Oracle Adapter (closes #4626) [Michael Schoen] | |
4 | ||
5 | ||
6 | *1.14.1* (April 6th, 2005) | |
7 | ||
8 | * Fix type_name_with_module to handle type names that begin with '::'. Closes #4614. [Nicholas Seckar] | |
9 | ||
10 | * Fixed that that multiparameter assignment doesn't work with aggregations (closes #4620) [Lars Pind] | |
11 | ||
12 | * Enable Limit/Offset in Calculations (closes #4558) [lmarlow@yahoo.com] | |
13 | ||
14 | * Fixed that loading including associations returns all results if Load IDs For Limited Eager Loading returns none (closes #4528) [Rick] | |
15 | ||
16 | * Fixed HasManyAssociation#find bugs when :finder_sql is set #4600 [lagroue@free.fr] | |
17 | ||
18 | * Allow AR::Base#respond_to? to behave when @attributes is nil [zenspider] | |
19 | ||
20 | * Support eager includes when going through a polymorphic has_many association. [Rick] | |
21 | ||
22 | * Added support for eagerly including polymorphic has_one associations. (closes #4525) [Rick] | |
23 | ||
24 | class Post < ActiveRecord::Base | |
25 | has_one :tagging, :as => :taggable | |
26 | end | |
27 | ||
28 | Post.find :all, :include => :tagging | |
29 | ||
30 | * Added descriptive error messages for invalid has_many :through associations: going through :has_one or :has_and_belongs_to_many [Rick] | |
31 | ||
32 | * Added support for going through a polymorphic has_many association: (closes #4401) [Rick] | |
33 | ||
34 | class PhotoCollection < ActiveRecord::Base | |
35 | has_many :photos, :as => :photographic | |
36 | belongs_to :firm | |
37 | end | |
38 | ||
39 | class Firm < ActiveRecord::Base | |
40 | has_many :photo_collections | |
41 | has_many :photos, :through => :photo_collections | |
42 | end | |
43 | ||
44 | * Multiple fixes and optimizations in PostgreSQL adapter, allowing ruby-postgres gem to work properly. [ruben.nine@gmail.com] | |
45 | ||
46 | * Fixed that AssociationCollection#delete_all should work even if the records of the association are not loaded yet. [Florian Weber] | |
47 | ||
48 | * Changed those private ActiveRecord methods to take optional third argument :auto instead of nil for performance optimizations. (closes #4456) [Stefan] | |
49 | ||
50 | * Private ActiveRecord methods add_limit!, add_joins!, and add_conditions! take an OPTIONAL third argument 'scope' (closes #4456) [Rick] | |
51 | ||
52 | * DEPRECATED: Using additional attributes on has_and_belongs_to_many associations. Instead upgrade your association to be a real join model [DHH] | |
53 | ||
54 | * Fixed that records returned from has_and_belongs_to_many associations with additional attributes should be marked as read only (fixes #4512) [DHH] | |
55 | ||
56 | * Do not implicitly mark recordss of has_many :through as readonly but do mark habtm records as readonly (eventually only on join tables without rich attributes). [Marcel Mollina Jr.] | |
57 | ||
58 | * Fixed broken OCIAdapter #4457 [schoenm@earthlink.net] | |
59 | ||
60 | ||
61 | *1.14.0* (March 27th, 2005) | |
62 | ||
63 | * Replace 'rescue Object' with a finer grained rescue. Closes #4431. [Nicholas Seckar] | |
64 | ||
65 | * Fixed eager loading so that an aliased table cannot clash with a has_and_belongs_to_many join table [Rick] | |
66 | ||
67 | * Add support for :include to with_scope [andrew@redlinesoftware.com] | |
68 | ||
69 | * Support the use of public synonyms with the Oracle adapter; required ruby-oci8 v0.1.14 #4390 [schoenm@earthlink.net] | |
70 | ||
71 | * Change periods (.) in table aliases to _'s. Closes #4251 [jeff@ministrycentered.com] | |
72 | ||
73 | * Changed has_and_belongs_to_many join to INNER JOIN for Mysql 3.23.x. Closes #4348 [Rick] | |
74 | ||
75 | * Fixed issue that kept :select options from being scoped [Rick] | |
76 | ||
77 | * Fixed db_schema_import when binary types are present #3101 [DHH] | |
78 | ||
79 | * Fixed that MySQL enums should always be returned as strings #3501 [DHH] | |
80 | ||
81 | * Change has_many :through to use the :source option to specify the source association. :class_name is now ignored. [Rick Olson] | |
82 | ||
83 | class Connection < ActiveRecord::Base | |
84 | belongs_to :user | |
85 | belongs_to :channel | |
86 | end | |
87 | ||
88 | class Channel < ActiveRecord::Base | |
89 | has_many :connections | |
90 | has_many :contacts, :through => :connections, :class_name => 'User' # OLD | |
91 | has_many :contacts, :through => :connections, :source => :user # NEW | |
92 | end | |
93 | ||
94 | * Fixed DB2 adapter so nullable columns will be determines correctly now and quotes from column default values will be removed #4350 [contact@maik-schmidt.de] | |
95 | ||
96 | * Allow overriding of find parameters in scoped has_many :through calls [Rick Olson] | |
97 | ||
98 | In this example, :include => false disables the default eager association from loading. :select changes the standard | |
99 | select clause. :joins specifies a join that is added to the end of the has_many :through query. | |
100 | ||
101 | class Post < ActiveRecord::Base | |
102 | has_many :tags, :through => :taggings, :include => :tagging do | |
103 | def add_joins_and_select | |
104 | find :all, :select => 'tags.*, authors.id as author_id', :include => false, | |
105 | :joins => 'left outer join posts on taggings.taggable_id = posts.id left outer join authors on posts.author_id = authors.id' | |
106 | end | |
107 | end | |
108 | end | |
109 | ||
110 | * Fixed that schema changes while the database was open would break any connections to a SQLite database (now we reconnect if that error is throw) [DHH] | |
111 | ||
112 | * Don't classify the has_one class when eager loading, it is already singular. Add tests. (closes #4117) [jonathan@bluewire.net.nz] | |
113 | ||
114 | * Quit ignoring default :include options in has_many :through calls [Mark James] | |
115 | ||
116 | * Allow has_many :through associations to find the source association by setting a custom class (closes #4307) [jonathan@bluewire.net.nz] | |
117 | ||
118 | * Eager Loading support added for has_many :through => :has_many associations (see below). [Rick Olson] | |
119 | ||
120 | * Allow has_many :through to work on has_many associations (closes #3864) [sco@scottraymond.net] Example: | |
121 | ||
122 | class Firm < ActiveRecord::Base | |
123 | has_many :clients | |
124 | has_many :invoices, :through => :clients | |
125 | end | |
126 | ||
127 | class Client < ActiveRecord::Base | |
128 | belongs_to :firm | |
129 | has_many :invoices | |
130 | end | |
131 | ||
132 | class Invoice < ActiveRecord::Base | |
133 | belongs_to :client | |
134 | end | |
135 | ||
136 | * Raise error when trying to select many polymorphic objects with has_many :through or :include (closes #4226) [josh@hasmanythrough.com] | |
137 | ||
138 | * Fixed has_many :through to include :conditions set on the :through association. closes #4020 [jonathan@bluewire.net.nz] | |
139 | ||
140 | * Fix that has_many :through honors the foreign key set by the belongs_to association in the join model (closes #4259) [andylien@gmail.com / Rick] | |
141 | ||
142 | * SQL Server adapter gets some love #4298 [rtomayko@gmail.com] | |
143 | ||
144 | * Added OpenBase database adapter that builds on top of the http://www.spice-of-life.net/ruby-openbase/ driver. All functionality except LIMIT/OFFSET is supported #3528 [derrickspell@cdmplus.com] | |
145 | ||
146 | * Rework table aliasing to account for truncated table aliases. Add smarter table aliasing when doing eager loading of STI associations. This allows you to use the association name in the order/where clause. [Jonathan Viney / Rick Olson] #4108 Example (SpecialComment is using STI): | |
147 | ||
148 | Author.find(:all, :include => { :posts => :special_comments }, :order => 'special_comments.body') | |
149 | ||
150 | * Add AbstractAdapter#table_alias_for to create table aliases according to the rules of the current adapter. [Rick] | |
151 | ||
152 | * Provide access to the underlying database connection through Adapter#raw_connection. Enables the use of db-specific methods without complicating the adapters. #2090 [Koz] | |
153 | ||
154 | * Remove broken attempts at handling columns with a default of 'now()' in the postgresql adapter. #2257 [Koz] | |
155 | ||
156 | * Added connection#current_database that'll return of the current database (only works in MySQL, SQL Server, and Oracle so far -- please help implement for the rest of the adapters) #3663 [Tom ward] | |
157 | ||
158 | * Fixed that Migration#execute would have the table name prefix appended to its query #4110 [mark.imbriaco@pobox.com] | |
159 | ||
160 | * Make all tinyint(1) variants act like boolean in mysql (tinyint(1) unsigned, etc.) [Jamis Buck] | |
161 | ||
162 | * Use association's :conditions when eager loading. [jeremyevans0@gmail.com] #4144 | |
163 | ||
164 | * Alias the has_and_belongs_to_many join table on eager includes. #4106 [jeremyevans0@gmail.com] | |
165 | ||
166 | This statement would normally error because the projects_developers table is joined twice, and therefore joined_on would be ambiguous. | |
167 | ||
168 | Developer.find(:all, :include => {:projects => :developers}, :conditions => 'join_project_developers.joined_on IS NOT NULL') | |
169 | ||
170 | * Oracle adapter gets some love #4230 [schoenm@earthlink.net] | |
171 | ||
172 | * Changes :text to CLOB rather than BLOB [Moses Hohman] | |
173 | * Fixes an issue with nil numeric length/scales (several) | |
174 | * Implements support for XMLTYPE columns [wilig / Kubo Takehiro] | |
175 | * Tweaks a unit test to get it all green again | |
176 | * Adds support for #current_database | |
177 | ||
178 | * Added Base.abstract_class? that marks which classes are not part of the Active Record hierarchy #3704 [Rick Olson] | |
179 | ||
180 | class CachedModel < ActiveRecord::Base | |
181 | self.abstract_class = true | |
182 | end | |
183 | ||
184 | class Post < CachedModel | |
185 | end | |
186 | ||
187 | CachedModel.abstract_class? | |
188 | => true | |
189 | ||
190 | Post.abstract_class? | |
191 | => false | |
192 | ||
193 | Post.base_class | |
194 | => Post | |
195 | ||
196 | Post.table_name | |
197 | => 'posts' | |
198 | ||
199 | * Allow :dependent options to be used with polymorphic joins. #3820 [Rick Olson] | |
200 | ||
201 | class Foo < ActiveRecord::Base | |
202 | has_many :attachments, :as => :attachable, :dependent => :delete_all | |
203 | end | |
204 | ||
205 | * Nicer error message on has_many :through when :through reflection can not be found. #4042 [court3nay@gmail.com] | |
206 | ||
207 | * Upgrade to Transaction::Simple 1.3 [Jamis Buck] | |
208 | ||
209 | * Catch FixtureClassNotFound when using instantiated fixtures on a fixture that has no ActiveRecord model [Rick Olson] | |
210 | ||
211 | * Allow ordering of calculated results and/or grouped fields in calculations [solo@gatelys.com] | |
212 | ||
213 | * Make ActiveRecord::Base#save! return true instead of nil on success. #4173 [johan@johansorensen.com] | |
214 | ||
215 | * Dynamically set allow_concurrency. #4044 [Stefan Kaes] | |
216 | ||
217 | * Added Base#to_xml that'll turn the current record into a XML representation [DHH]. Example: | |
218 | ||
219 | topic.to_xml | |
220 | ||
221 | ...returns: | |
222 | ||
223 | <?xml version="1.0" encoding="UTF-8"?> | |
224 | <topic> | |
225 | <title>The First Topic</title> | |
226 | <author-name>David</author-name> | |
227 | <id type="integer">1</id> | |
228 | <approved type="boolean">false</approved> | |
229 | <replies-count type="integer">0</replies-count> | |
230 | <bonus-time type="datetime">2000-01-01 08:28:00</bonus-time> | |
231 | <written-on type="datetime">2003-07-16 09:28:00</written-on> | |
232 | <content>Have a nice day</content> | |
233 | <author-email-address>david@loudthinking.com</author-email-address> | |
234 | <parent-id></parent-id> | |
235 | <last-read type="date">2004-04-15</last-read> | |
236 | </topic> | |
237 | ||
238 | ...and you can configure with: | |
239 | ||
240 | topic.to_xml(:skip_instruct => true, :except => [ :id, bonus_time, :written_on, replies_count ]) | |
241 | ||
242 | ...that'll return: | |
243 | ||
244 | <topic> | |
245 | <title>The First Topic</title> | |
246 | <author-name>David</author-name> | |
247 | <approved type="boolean">false</approved> | |
248 | <content>Have a nice day</content> | |
249 | <author-email-address>david@loudthinking.com</author-email-address> | |
250 | <parent-id></parent-id> | |
251 | <last-read type="date">2004-04-15</last-read> | |
252 | </topic> | |
253 | ||
254 | You can even do load first-level associations as part of the document: | |
255 | ||
256 | firm.to_xml :include => [ :account, :clients ] | |
257 | ||
258 | ...that'll return something like: | |
259 | ||
260 | <?xml version="1.0" encoding="UTF-8"?> | |
261 | <firm> | |
262 | <id type="integer">1</id> | |
263 | <rating type="integer">1</rating> | |
264 | <name>37signals</name> | |
265 | <clients> | |
266 | <client> | |
267 | <rating type="integer">1</rating> | |
268 | <name>Summit</name> | |
269 | </client> | |
270 | <client> | |
271 | <rating type="integer">1</rating> | |
272 | <name>Microsoft</name> | |
273 | </client> | |
274 | </clients> | |
275 | <account> | |
276 | <id type="integer">1</id> | |
277 | <credit-limit type="integer">50</credit-limit> | |
278 | </account> | |
279 | </firm> | |
280 | ||
281 | * Allow :counter_cache to take a column name for custom counter cache columns [Jamis Buck] | |
282 | ||
283 | * Documentation fixes for :dependent [robby@planetargon.com] | |
284 | ||
285 | * Stop the MySQL adapter crashing when views are present. #3782 [Jonathan Viney] | |
286 | ||
287 | * Don't classify the belongs_to class, it is already singular #4117 [keithm@infused.org] | |
288 | ||
289 | * Allow set_fixture_class to take Classes instead of strings for a class in a module. Raise FixtureClassNotFound if a fixture can't load. [Rick Olson] | |
290 | ||
291 | * Fix quoting of inheritance column for STI eager loading #4098 [Jonathan Viney <jonathan@bluewire.net.nz>] | |
292 | ||
293 | * Added smarter table aliasing for eager associations for multiple self joins #3580 [Rick Olson] | |
294 | ||
295 | * The first time a table is referenced in a join, no alias is used. | |
296 | * After that, the parent class name and the reflection name are used. | |
297 | ||
298 | Tree.find(:all, :include => :children) # LEFT OUTER JOIN trees AS tree_children ... | |
299 | ||
300 | * Any additional join references get a numerical suffix like '_2', '_3', etc. | |
301 | ||
302 | * Fixed eager loading problems with single-table inheritance #3580 [Rick Olson]. Post.find(:all, :include => :special_comments) now returns all posts, and any special comments that the posts may have. And made STI work with has_many :through and polymorphic belongs_to. | |
303 | ||
304 | * Added cascading eager loading that allows for queries like Author.find(:all, :include=> { :posts=> :comments }), which will fetch all authors, their posts, and the comments belonging to those posts in a single query (using LEFT OUTER JOIN) #3913 [anna@wota.jp]. Examples: | |
305 | ||
306 | # cascaded in two levels | |
307 | >> Author.find(:all, :include=>{:posts=>:comments}) | |
308 | => authors | |
309 | +- posts | |
310 | +- comments | |
311 | ||
312 | # cascaded in two levels and normal association | |
313 | >> Author.find(:all, :include=>[{:posts=>:comments}, :categorizations]) | |
314 | => authors | |
315 | +- posts | |
316 | +- comments | |
317 | +- categorizations | |
318 | ||
319 | # cascaded in two levels with two has_many associations | |
320 | >> Author.find(:all, :include=>{:posts=>[:comments, :categorizations]}) | |
321 | => authors | |
322 | +- posts | |
323 | +- comments | |
324 | +- categorizations | |
325 | ||
326 | # cascaded in three levels | |
327 | >> Company.find(:all, :include=>{:groups=>{:members=>{:favorites}}}) | |
328 | => companies | |
329 | +- groups | |
330 | +- members | |
331 | +- favorites | |
332 | ||
333 | * Make counter cache work when replacing an association #3245 [eugenol@gmail.com] | |
334 | ||
335 | * Make migrations verbose [Jamis Buck] | |
336 | ||
337 | * Make counter_cache work with polymorphic belongs_to [Jamis Buck] | |
338 | ||
339 | * Fixed that calling HasOneProxy#build_model repeatedly would cause saving to happen #4058 [anna@wota.jp] | |
340 | ||
341 | * Added Sybase database adapter that relies on the Sybase Open Client bindings (see http://raa.ruby-lang.org/project/sybase-ctlib) #3765 [John Sheets]. It's almost completely Active Record compliant (including migrations), but has the following caveats: | |
342 | ||
343 | * Does not support DATE SQL column types; use DATETIME instead. | |
344 | * Date columns on HABTM join tables are returned as String, not Time. | |
345 | * Insertions are potentially broken for :polymorphic join tables | |
346 | * BLOB column access not yet fully supported | |
347 | ||
348 | * Clear stale, cached connections left behind by defunct threads. [Jeremy Kemper] | |
349 | ||
350 | * CHANGED DEFAULT: set ActiveRecord::Base.allow_concurrency to false. Most AR usage is in single-threaded applications. [Jeremy Kemper] | |
351 | ||
352 | * Renamed the "oci" adapter to "oracle", but kept the old name as an alias #4017 [schoenm@earthlink.net] | |
353 | ||
354 | * Fixed that Base.save should always return false if the save didn't succeed, including if it has halted by before_save's #1861, #2477 [DHH] | |
355 | ||
356 | * Speed up class -> connection caching and stale connection verification. #3979 [Stefan Kaes] | |
357 | ||
358 | * Add set_fixture_class to allow the use of table name accessors with models which use set_table_name. [Kevin Clark] | |
359 | ||
360 | * Added that fixtures to placed in subdirectories of the main fixture files are also loaded #3937 [dblack@wobblini.net] | |
361 | ||
362 | * Define attribute query methods to avoid method_missing calls. #3677 [jonathan@bluewire.net.nz] | |
363 | ||
364 | * ActiveRecord::Base.remove_connection explicitly closes database connections and doesn't corrupt the connection cache. Introducing the disconnect! instance method for the PostgreSQL, MySQL, and SQL Server adapters; implementations for the others are welcome. #3591 [Simon Stapleton, Tom Ward] | |
365 | ||
366 | * Added support for nested scopes #3407 [anna@wota.jp]. Examples: | |
367 | ||
368 | Developer.with_scope(:find => { :conditions => "salary > 10000", :limit => 10 }) do | |
369 | Developer.find(:all) # => SELECT * FROM developers WHERE (salary > 10000) LIMIT 10 | |
370 | ||
371 | # inner rule is used. (all previous parameters are ignored) | |
372 | Developer.with_exclusive_scope(:find => { :conditions => "name = 'Jamis'" }) do | |
373 | Developer.find(:all) # => SELECT * FROM developers WHERE (name = 'Jamis') | |
374 | end | |
375 | ||
376 | # parameters are merged | |
377 | Developer.with_scope(:find => { :conditions => "name = 'Jamis'" }) do | |
378 | Developer.find(:all) # => SELECT * FROM developers WHERE (( salary > 10000 ) AND ( name = 'Jamis' )) LIMIT 10 | |
379 | end | |
380 | end | |
381 | ||
382 | * Fixed db2 connection with empty user_name and auth options #3622 [phurley@gmail.com] | |
383 | ||
384 | * Fixed validates_length_of to work on UTF-8 strings by using characters instead of bytes #3699 [Masao Mutoh] | |
385 | ||
386 | * Fixed that reflections would bleed across class boundaries in single-table inheritance setups #3796 [lars@pind.com] | |
387 | ||
388 | * Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Base.maxmium, and the generic Base.calculate. All can be used with :group and :having. Calculations and statitics need no longer require custom SQL. #3958 [Rick Olson]. Examples: | |
389 | ||
390 | Person.average :age | |
391 | Person.minimum :age | |
392 | Person.maximum :age | |
393 | Person.sum :salary, :group => :last_name | |
394 | ||
395 | * Renamed Errors#count to Errors#size but kept an alias for the old name (and included an alias for length too) #3920 [contact@lukeredpath.co.uk] | |
396 | ||
397 | * Reflections don't attempt to resolve module nesting of association classes. Simplify type computation. [Jeremy Kemper] | |
398 | ||
399 | * Improved the Oracle OCI Adapter with better performance for column reflection (from #3210), fixes to migrations (from #3476 and #3742), tweaks to unit tests (from #3610), and improved documentation (from #2446) #3879 [Aggregated by schoenm@earthlink.net] | |
400 | ||
401 | * Fixed that the schema_info table used by ActiveRecord::Schema.define should respect table pre- and suffixes #3834 [rubyonrails@atyp.de] | |
402 | ||
403 | * Added :select option to Base.count that'll allow you to select something else than * to be counted on. Especially important for count queries using DISTINCT #3839 [skaes] | |
404 | ||
405 | * Correct syntax error in mysql DDL, and make AAACreateTablesTest run first [Bob Silva] | |
406 | ||
407 | * Allow :include to be used with has_many :through associations #3611 [Michael Schoen] | |
408 | ||
409 | * PostgreSQL: smarter schema dumps using pk_and_sequence_for(table). #2920 [Blair Zajac] | |
410 | ||
411 | * SQLServer: more compatible limit/offset emulation. #3779 [Tom Ward] | |
412 | ||
413 | * Polymorphic join support for has_one associations (has_one :foo, :as => :bar) #3785 [Rick Olson] | |
414 | ||
415 | * PostgreSQL: correctly parse negative integer column defaults. #3776 [bellis@deepthought.org] | |
416 | ||
417 | * Fix problems with count when used with :include [Jeremy Hopple and Kevin Clark] | |
418 | ||
419 | * ActiveRecord::RecordInvalid now states which validations failed in its default error message [Tobias Luetke] | |
420 | ||
421 | * Using AssociationCollection#build with arrays of hashes should call build, not create [DHH] | |
422 | ||
423 | * Remove definition of reloadable? from ActiveRecord::Base to make way for new Reloadable code. [Nicholas Seckar] | |
424 | ||
425 | * Fixed schema handling for DB2 adapter that didn't work: an initial schema could be set, but it wasn't used when getting tables and indexes #3678 [Maik Schmidt] | |
426 | ||
427 | * Support the :column option for remove_index with the PostgreSQL adapter. #3661 [shugo@ruby-lang.org] | |
428 | ||
429 | * Add documentation for add_index and remove_index. #3600 [Manfred Stienstra <m.stienstra@fngtps.com>] | |
430 | ||
431 | * If the OCI library is not available, raise an exception indicating as much. #3593 [schoenm@earthlink.net] | |
432 | ||
433 | * Add explicit :order in finder tests as postgresql orders results differently by default. #3577. [Rick Olson] | |
434 | ||
435 | * Make dynamic finders honor additional passed in :conditions. #3569 [Oleg Pudeyev <pudeyo@rpi.edu>, Marcel Molina Jr.] | |
436 | ||
437 | * Show a meaningful error when the DB2 adapter cannot be loaded due to missing dependencies. [Nicholas Seckar] | |
438 | ||
439 | * Make .count work for has_many associations with multi line finder sql [schoenm@earthlink.net] | |
440 | ||
441 | * Add AR::Base.base_class for querying the ancestor AR::Base subclass [Jamis Buck] | |
442 | ||
443 | * Allow configuration of the column used for optimistic locking [wilsonb@gmail.com] | |
444 | ||
445 | * Don't hardcode 'id' in acts as list. [ror@philippeapril.com] | |
446 | ||
447 | * Fix date errors for SQLServer in association tests. #3406 [kevin.clark@gmal.com] | |
448 | ||
449 | * Escape database name in MySQL adapter when creating and dropping databases. #3409 [anna@wota.jp] | |
450 | ||
451 | * Disambiguate table names for columns in validates_uniquness_of's WHERE clause. #3423 [alex.borovsky@gmail.com] | |
452 | ||
453 | * .with_scope imposed create parameters now bypass attr_protected [Tobias Luetke] | |
454 | ||
455 | * Don't raise an exception when there are more keys than there are named bind variables when sanitizing conditions. [Marcel Molina Jr.] | |
456 | ||
457 | * Multiple enhancements and adjustments to DB2 adaptor. #3377 [contact@maik-schmidt.de] | |
458 | ||
459 | * Sanitize scoped conditions. [Marcel Molina Jr.] | |
460 | ||
461 | * Added option to Base.reflection_of_all_associations to specify a specific association to scope the call. For example Base.reflection_of_all_associations(:has_many) [DHH] | |
462 | ||
463 | * Added ActiveRecord::SchemaDumper.ignore_tables which tells SchemaDumper which tables to ignore. Useful for tables with funky column like the ones required for tsearch2. [TobiasLuetke] | |
464 | ||
465 | * SchemaDumper now doesn't fail anymore when there are unknown column types in the schema. Instead the table is ignored and a Comment is left in the schema.rb. [TobiasLuetke] | |
466 | ||
467 | * Fixed that saving a model with multiple habtm associations would only save the first one. #3244 [yanowitz-rubyonrails@quantumfoam.org, Florian Weber] | |
468 | ||
469 | * Fix change_column to work with PostgreSQL 7.x and 8.x. #3141 [wejn@box.cz, Rick Olson, Scott Barron] | |
470 | ||
471 | * removed :piggyback in favor of just allowing :select on :through associations. [Tobias Luetke] | |
472 | ||
473 | * made method missing delegation to class methods on relation target work on :through associations. [Tobias Luetke] | |
474 | ||
475 | * made .find() work on :through relations. [Tobias Luetke] | |
476 | ||
477 | * Fix typo in association docs. #3296. [Blair Zajac] | |
478 | ||
479 | * Fixed :through relations when using STI inherited classes would use the inherited class's name as foreign key on the join model [Tobias Luetke] | |
480 | ||
*1.13.2* (December 13th, 2005) | ||
* Become part of Rails 1.0 | ||
* MySQL: allow encoding option for mysql.rb driver. [Jeremy Kemper] | ||
487 | * Added option inheritance for find calls on has_and_belongs_to_many and has_many assosociations [DHH]. Example: | |
488 | ||
489 | class Post | |
490 | has_many :recent_comments, :class_name => "Comment", :limit => 10, :include => :author | |
491 | end | |
492 | ||
493 | post.recent_comments.find(:all) # Uses LIMIT 10 and includes authors | |
494 | post.recent_comments.find(:all, :limit => nil) # Uses no limit but include authors | |
495 | post.recent_comments.find(:all, :limit => nil, :include => nil) # Uses no limit and doesn't include authors | |
496 | ||
497 | * Added option to specify :group, :limit, :offset, and :select options from find on has_and_belongs_to_many and has_many assosociations [DHH] | |
498 | ||
* MySQL: fixes for the bundled mysql.rb driver. #3160 [Justin Forder] | ||
10 | ||
11 | ||
* SQLServer: fix obscure optimistic locking bug. #3068 [kajism@yahoo.com] | ||
* SQLServer: support uniqueidentifier columns. #2930 [keithm@infused.org] | ||
... | ... | |
* Oracle: active? performs a select instead of a commit. #3133 [Michael Schoen] | ||
24 | ||
25 | ||
26 | ||
* MySQL: more robust test for nullified result hashes. #3124 [Stefan Kaes] | ||
* Reloading an instance refreshes its aggregations as well as its associations. #3024 [François Beausolei] | ||
... | ... | |
* MySQL: work around ruby-mysql/mysql-ruby inconsistency with mysql.stat. Eliminate usage of mysql.ping because it doesn't guarantee reconnect. Explicitly close and reopen the connection instead. [Jeremy Kemper] | ||
39 | ||
525 | * Added preliminary support for polymorphic associations [DHH] | |
527 | * Added preliminary support for join models [DHH] | |
528 | ||
529 | * Allow validate_uniqueness_of to be scoped by more than just one column. #1559. [jeremy@jthopple.com, Marcel Molina Jr.] | |
530 | ||
* Firebird: active? and reconnect! methods for handling stale connections. #428 [Ken Kunz <kennethkunz@gmail.com>] | ||
* Firebird: updated for FireRuby 0.4.0. #3009 [Ken Kunz <kennethkunz@gmail.com>] | ||
45 | ||
46 | ||
* MySQL and PostgreSQL: active? compatibility with the pure-Ruby driver. #428 [Jeremy Kemper] | ||
* Oracle: active? check pings the database rather than testing the last command status. #428 [Michael Schoen] | ||
... | ... | |
* Fixed bug where using update_attribute after pushing a record to a habtm association of the object caused duplicate rows in the join table. #2888 [colman@rominato.com, Florian Weber, Michael Schoen] | ||
545 | * MySQL, PostgreSQL: reconnect! also reconfigures the connection. Otherwise, the connection 'loses' its settings if it times out and is reconnected. #2978 [Shugo Maeda] | |
546 | ||
547 | * has_and_belongs_to_many: use JOIN instead of LEFT JOIN. [Jeremy Kemper] | |
548 | ||
* MySQL: introduce :encoding option to specify the character set for client, connection, and results. Only available for MySQL 4.1 and later with the mysql-ruby driver. Do SHOW CHARACTER SET in mysql client to see available encodings. #2975 [Shugo Maeda] | ||
* Add tasks to create, drop and rebuild the MySQL and PostgreSQL test databases. [Marcel Molina Jr.] | ||
... | ... | |
* Rename Version constant to VERSION. #2802 [Marcel Molina Jr.] | ||
563 | * Introducing the Firebird adapter. Quote columns and use attribute_condition more consistently. Setup guide: http://wiki.rubyonrails.com/rails/pages/Firebird+Adapter #1874 [Ken Kunz <kennethkunz@gmail.com>] | |
564 | ||
565 | * SQLServer: active? and reconnect! methods for handling stale connections. #428 [kajism@yahoo.com, Tom Ward <tom@popdog.net>] | |
566 | ||
567 | * Associations handle case-equality more consistently: item.parts.is_a?(Array) and item.parts === Array. #1345 [MarkusQ@reality.com] | |
568 | ||
* SQLServer: insert uses given primary key value if not nil rather than SELECT @@IDENTITY. #2866 [kajism@yahoo.com, Tom Ward <tom@popdog.net>] | ||
571 | * Oracle: active? and reconnect! methods for handling stale connections. Optionally retry queries after reconnect. #428 [Michael Schoen <schoenm@earthlink.net>] | |
572 | ||
* Correct documentation for Base.delete_all. #1568 [Newhydra] | ||
* Oracle: test case for column default parsing. #2788 [Michael Schoen <schoenm@earthlink.net>] | ||
* Update documentation for Migrations. #2861 [Tom Werner <tom@cube6media.com>] | ||
579 | * When AbstractAdapter#log rescues an exception, attempt to detect and reconnect to an inactive database connection. Connection adapter must respond to the active? and reconnect! instance methods. Initial support for PostgreSQL, MySQL, and SQLite. Make certain that all statements which may need reconnection are performed within a logged block: for example, this means no avoiding log(sql, name) { } if @logger.nil? #428 [Jeremy Kemper] | |
580 | ||
* Oracle: Much faster column reflection. #2848 [Michael Schoen <schoenm@earthlink.net>] | ||
* Base.reset_sequence_name analogous to reset_table_name (mostly useful for testing). Base.define_attr_method allows nil values. [Jeremy Kemper] | ||
... | ... | |
end | ||
end | ||
1673 | | |
2175 | This will add an error to the tune of "is too short (minimum is 3 characters)" or "is too long (minimum is 20 characters)" if | |
the password is outside the boundry. The messages can be changed by passing a third and forth parameter as message strings. | ||
* Implemented a clone method that works properly with AR. It returns a clone of the record that |
rool/rails/typo/trunk/vendor/rails/activerecord/RUNNING_UNIT_TESTS:
prev. | current | |
The easiest way to run the unit tests is through Rake. The default task runs | ||
the entire test suite for all the adapters. You can also run the suite on just | ||
one adapter by using the tasks test_mysql_ruby, test_ruby_mysql, test_sqlite, | ||
18 | ||
18 | or test_postgresql. For more information, checkout the full array of rake tasks with "rake -T" | |
Rake can be found at http://rake.rubyforge.org | ||
rool/rails/typo/trunk/vendor/rails/activerecord/Rakefile:
prev. | current | |
RUBY_FORGE_USER = "webster132" | ||
PKG_FILES = FileList[ | ||
21 | | |
21 | "lib/**/*", "test/**/*", "examples/**/*", "doc/**/*", "[A-Z]*", "install.rb", "Rakefile" | |
].exclude(/\bCVS\b|~$/) | ||
... | ... | |
# Run the unit tests | ||
30 | ||
30 | for adapter in %w( mysql postgresql sqlite sqlite3 firebird sqlserver sqlserver_odbc db2 oracle sybase openbase ) | |
Rake::TestTask.new("test_#{adapter}") { |t| | ||
t.libs << "test" << "test/connections/native_#{adapter}" | ||
t.pattern = "test/*_test{,_#{adapter}}.rb" | ||
... | ... | |
%x( createdb activerecord_unittest ) | ||
%x( createdb activerecord_unittest2 ) | ||
%x( psql activerecord_unittest -f #{File.join(SCHEMA_PATH, 'postgresql.sql')} ) | ||
62 | | |
62 | %x( psql activerecord_unittest2 -f #{File.join(SCHEMA_PATH, 'postgresql2.sql')} ) | |
end | ||
desc 'Drop the PostgreSQL test databases' | ||
... | ... | |
Rake::RDocTask.new { |rdoc| | ||
rdoc.rdoc_dir = 'doc' | ||
rdoc.title = "Active Record -- Object-relation mapping put on rails" | ||
79 | | |
79 | rdoc.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object' | |
rdoc.template = "#{ENV['template']}.rb" if ENV['template'] | ||
rdoc.rdoc_files.include('README', 'RUNNING_UNIT_TESTS', 'CHANGELOG') | ||
rdoc.rdoc_files.include('lib/**/*.rb') | ||
... | ... | |
s.summary = "Implements the ActiveRecord pattern for ORM." | ||
s.description = %q{Implements the ActiveRecord pattern (Fowler, PoEAA) for ORM. It ties database tables and classes together for business objects, like Customer or Subscription, that can find, save, and destroy themselves without resorting to manual SQL.} | ||
104 | | |
104 | s.files = [ "Rakefile", "install.rb", "README", "RUNNING_UNIT_TESTS", "CHANGELOG" ] | |
dist_dirs.each do |dir| | ||
s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) } | ||
end | ||
109 | | |
109 | s.add_dependency('activesupport', '= 1.3.1' + PKG_BUILD) | |
s.files.delete "test/fixtures/fixture_database.sqlite" | ||
s.files.delete "test/fixtures/fixture_database_2.sqlite" | ||
... | ... | |
end | ||
desc "Publish the release files to RubyForge." | ||
173 | ||
174 | | |
173 | task :release => [ :package ] do | |
174 | `rubyforge login` | |
176 | | |
177 | | |
178 | | |
179 | ||
180 | | |
181 | | |
182 | | |
183 | | |
184 | ||
185 | | |
186 | | |
187 | | |
188 | | |
189 | | |
190 | | |
191 | | |
192 | ||
193 | | |
194 | | |
195 | | |
196 | | |
197 | | |
198 | | |
199 | | |
200 | | |
201 | ||
202 | | |
203 | | |
204 | | |
205 | ||
206 | | |
207 | | |
208 | | |
209 | | |
210 | ||
211 | | |
212 | | |
213 | ||
214 | | |
215 | | |
216 | | |
217 | | |
218 | ||
219 | | |
220 | ||
221 | | |
222 | | |
223 | | |
224 | | |
225 | | |
226 | | |
227 | | |
228 | | |
229 | | |
230 | | |
231 | ||
232 | | |
233 | | |
234 | | |
235 | | |
236 | | |
237 | | |
238 | | |
239 | | |
240 | | |
241 | | |
242 | | |
243 | | |
244 | | |
245 | | |
246 | | |
247 | | |
248 | | |
249 | | |
250 | | |
251 | | |
252 | | |
253 | | |
254 | | |
255 | | |
256 | ||
257 | | |
258 | | |
259 | | |
260 | ||
261 | | |
262 | | |
263 | | |
264 | | |
265 | | |
266 | | |
267 | | |
268 | ||
269 | | |
270 | | |
271 | | |
272 | ||
273 | | |
274 | | |
275 | | |
276 | ||
277 | | |
278 | | |
279 | | |
280 | | |
281 | ||
282 | | |
283 | | |
176 | for ext in %w( gem tgz zip ) | |
177 | release_command = "rubyforge add_release #{PKG_NAME} #{PKG_NAME} 'REL #{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" | |
178 | puts release_command | |
179 | system(release_command) | |
end | ||
285 | ||
181 | end | |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record.rb:
prev. | current | |
require 'active_record/observer' | ||
require 'active_record/validations' | ||
require 'active_record/callbacks' | ||
41 | require 'active_record/reflection' | |
require 'active_record/associations' | ||
require 'active_record/aggregations' | ||
require 'active_record/transactions' | ||
44 | ||
require 'active_record/timestamp' | ||
require 'active_record/acts/list' | ||
require 'active_record/acts/tree' | ||
... | ... | |
require 'active_record/locking' | ||
require 'active_record/migration' | ||
require 'active_record/schema' | ||
52 | require 'active_record/calculations' | |
ActiveRecord::Base.class_eval do | ||
include ActiveRecord::Validations | ||
... | ... | |
include ActiveRecord::Acts::Tree | ||
include ActiveRecord::Acts::List | ||
include ActiveRecord::Acts::NestedSet | ||
67 | include ActiveRecord::Calculations | |
end | ||
unless defined?(RAILS_CONNECTION_ADAPTERS) | ||
69 | | |
71 | RAILS_CONNECTION_ADAPTERS = %w( mysql postgresql sqlite firebird sqlserver db2 oracle sybase openbase ) | |
end | ||
RAILS_CONNECTION_ADAPTERS.each do |adapter| | ||
... | ... | |
end | ||
require 'active_record/query_cache' | ||
79 | require 'active_record/schema_dumper' |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/acts/list.rb:
prev. | current | |
def bottom_item(except = nil) | ||
conditions = scope_condition | ||
177 | | |
177 | conditions = "#{conditions} AND #{self.class.primary_key} != #{except.id}" if except | |
acts_as_list_class.find(:first, :conditions => conditions, :order => "#{position_column} DESC") | ||
end | ||
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/acts/tree.rb:
prev. | current | |
configuration.update(options) if options.is_a?(Hash) | ||
belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key], :counter_cache => configuration[:counter_cache] | ||
48 | | |
48 | has_many :children, :class_name => name, :foreign_key => configuration[:foreign_key], :order => configuration[:order], :dependent => :destroy | |
50 | | |
50 | class_eval <<-EOV | |
51 | include ActiveRecord::Acts::Tree::InstanceMethods | |
52 | ||
def self.roots | ||
52 | | |
54 | find(:all, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}}) | |
end | ||
56 | ||
def self.root | ||
55 | | |
58 | find(:first, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}}) | |
end | ||
57 | | |
60 | EOV | |
61 | end | |
62 | end | |
59 | | |
60 | | |
61 | | |
62 | | |
63 | | |
64 | | |
65 | | |
66 | | |
64 | module InstanceMethods | |
65 | # Returns list of ancestors, starting from parent until root. | |
66 | # | |
67 | # subchild1.ancestors # => [child1, root] | |
68 | def ancestors | |
69 | node, nodes = self, [] | |
70 | nodes << node = node.parent until not node.has_parent? | |
71 | nodes | |
72 | end | |
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
74 | def root | |
75 | node = self | |
76 | node = node.parent until not node.has_parent? | |
77 | node | |
78 | end | |
74 | | |
75 | | |
76 | | |
80 | def siblings | |
81 | self_and_siblings - [self] | |
82 | end | |
78 | | |
79 | | |
80 | | |
81 | ||
84 | def self_and_siblings | |
85 | has_parent? ? parent.children : self.class.roots | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/aggregations.rb:
prev. | current | |
module ActiveRecord | ||
module Aggregations # :nodoc: | ||
3 | | |
4 | | |
3 | def self.included(base) | |
base.extend(ClassMethods) | ||
end | ||
... | ... | |
reader_method(name, class_name, mapping) | ||
writer_method(name, class_name, mapping) | ||
136 | ||
137 | create_reflection(:composed_of, part_id, options, self) | |
end | ||
private |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/associations.rb:
prev. | current | |
require 'active_record/associations/association_proxy' | ||
require 'active_record/associations/association_collection' | ||
require 'active_record/associations/belongs_to_association' | ||
4 | require 'active_record/associations/belongs_to_polymorphic_association' | |
require 'active_record/associations/has_one_association' | ||
require 'active_record/associations/has_many_association' | ||
7 | require 'active_record/associations/has_many_through_association' | |
require 'active_record/associations/has_and_belongs_to_many_association' | ||
require 'active_record/deprecated_associations' | ||
module ActiveRecord | ||
12 | class HasManyThroughAssociationNotFoundError < ActiveRecordError #:nodoc: | |
13 | def initialize(reflection) | |
14 | @reflection = reflection | |
15 | end | |
16 | ||
17 | def message | |
18 | "Could not find the association #{@reflection.options[:through].inspect} in model #{@reflection.klass}" | |
19 | end | |
20 | end | |
21 | ||
22 | class HasManyThroughAssociationPolymorphicError < ActiveRecordError #:nodoc: | |
23 | def initialize(owner_class_name, reflection, source_reflection) | |
24 | @owner_class_name = owner_class_name | |
25 | @reflection = reflection | |
26 | @source_reflection = source_reflection | |
27 | end | |
28 | ||
29 | def message | |
30 | "Cannot have a has_many :through association '#{@owner_class_name}##{@reflection.name}' on the polymorphic object '#{@source_reflection.class_name}##{@source_reflection.name}'." | |
31 | end | |
32 | end | |
33 | ||
34 | class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError #:nodoc: | |
35 | def initialize(reflection) | |
36 | @reflection = reflection | |
37 | @through_reflection = reflection.through_reflection | |
38 | @source_reflection_names = reflection.source_reflection_names | |
39 | @source_associations = reflection.through_reflection.klass.reflect_on_all_associations.collect { |a| a.name.inspect } | |
40 | end | |
41 | ||
42 | def message | |
43 | "Could not find the source association(s) #{@source_reflection_names.collect(&:inspect).to_sentence :connector => 'or'} in model #{@through_reflection.klass}. Try 'has_many #{@reflection.name.inspect}, :through => #{@through_reflection.name.inspect}, :source => <name>'. Is it one of #{@source_associations.to_sentence :connector => 'or'}?" | |
44 | end | |
45 | end | |
46 | ||
47 | class HasManyThroughSourceAssociationMacroError < ActiveRecordError #:nodoc | |
48 | def initialize(reflection) | |
49 | @reflection = reflection | |
50 | @through_reflection = reflection.through_reflection | |
51 | @source_reflection = reflection.source_reflection | |
52 | end | |
53 | ||
54 | def message | |
55 | "Invalid source reflection macro :#{@source_reflection.macro}#{" :through" if @source_reflection.options[:through]} for has_many #{@reflection.name.inspect}, :through => #{@through_reflection.name.inspect}. Use :source to specify the source reflection." | |
56 | end | |
57 | end | |
58 | ||
59 | class EagerLoadPolymorphicError < ActiveRecordError #:nodoc: | |
60 | def initialize(reflection) | |
61 | @reflection = reflection | |
62 | end | |
63 | ||
64 | def message | |
65 | "Can not eagerly load the polymorphic association #{@reflection.name.inspect}" | |
66 | end | |
67 | end | |
68 | ||
module Associations # :nodoc: | ||
def self.append_features(base) | ||
super | ||
... | ... | |
# === Association extensions | ||
# | ||
# The proxy objects that controls the access to associations can be extended through anonymous modules. This is especially | ||
126 | | |
185 | # beneficial for adding new finders, creators, and other factory-type methods that are only used as part of this association. | |
# Example: | ||
# | ||
# class Account < ActiveRecord::Base | ||
# has_many :people do | ||
# def find_or_create_by_name(name) | ||
132 | | |
133 | | |
134 | | |
191 | # first_name, last_name = name.split(" ", 2) | |
# find_or_create_by_first_name_and_last_name(first_name, last_name) | ||
# end | ||
# end | ||
... | ... | |
# | ||
# module FindOrCreateByNameExtension | ||
# def find_or_create_by_name(name) | ||
148 | | |
149 | | |
150 | | |
205 | # first_name, last_name = name.split(" ", 2) | |
# find_or_create_by_first_name_and_last_name(first_name, last_name) | ||
# end | ||
# end | ||
... | ... | |
# has_many :people, :extend => FindOrCreateByNameExtension | ||
# end | ||
# | ||
218 | # === Association Join Models | |
219 | # | |
220 | # Has Many associations can be configured with the :through option to use an explicit join model to retrieve the data. This | |
221 | # operates similarly to a <tt>has_and_belongs_to_many</tt> association. The advantage is that you're able to add validations, | |
222 | # callbacks, and extra attributes on the join model. Consider the following schema: | |
223 | # | |
224 | # class Author < ActiveRecord::Base | |
225 | # has_many :authorships | |
226 | # has_many :books, :through => :authorships | |
227 | # end | |
228 | # | |
229 | # class Authorship < ActiveRecord::Base | |
230 | # belongs_to :author | |
231 | # belongs_to :book | |
232 | # end | |
233 | # | |
234 | # @author = Author.find :first | |
235 | # @author.authorships.collect { |a| a.book } # selects all books that the author's authorships belong to. | |
236 | # @author.books # selects all books by using the Authorship join model | |
237 | # | |
238 | # You can also go through a has_many association on the join model: | |
239 | # | |
240 | # class Firm < ActiveRecord::Base | |
241 | # has_many :clients | |
242 | # has_many :invoices, :through => :clients | |
243 | # end | |
244 | # | |
245 | # class Client < ActiveRecord::Base | |
246 | # belongs_to :firm | |
247 | # has_many :invoices | |
248 | # end | |
249 | # | |
250 | # class Invoice < ActiveRecord::Base | |
251 | # belongs_to :client | |
252 | # end | |
253 | # | |
254 | # @firm = Firm.find :first | |
255 | # @firm.clients.collect { |c| c.invoices }.flatten # select all invoices for all clients of the firm | |
256 | # @firm.invoices # selects all invoices by going through the Client join model. | |
257 | # | |
258 | # === Polymorphic Associations | |
259 | # | |
260 | # Polymorphic associations on models are not restricted on what types of models they can be associated with. Rather, they | |
261 | # specify an interface that a has_many association must adhere to. | |
262 | # | |
263 | # class Asset < ActiveRecord::Base | |
264 | # belongs_to :attachable, :polymorphic => true | |
265 | # end | |
266 | # | |
267 | # class Post < ActiveRecord::Base | |
268 | # has_many :assets, :as => :attachable # The <tt>:as</tt> option specifies the polymorphic interface to use. | |
269 | # end | |
270 | # | |
271 | # @asset.attachable = @post | |
272 | # | |
273 | # This works by using a type column in addition to a foreign key to specify the associated record. In the Asset example, you'd need | |
274 | # an attachable_id integer column and an attachable_type string column. | |
275 | # | |
# == Caching | ||
# | ||
# All of the methods are built on a simple caching principle that will keep the result of the last query around unless specifically | ||
... | ... | |
# in both conditions and orders. So :order => "posts.id DESC" will work while :order => "id DESC" will not. This may require that | ||
# you alter the :order and :conditions on the association definitions themselves. | ||
# | ||
223 | | |
336 | # It's currently not possible to use eager loading on multiple associations from the same table. Eager loading will not pull | |
# additional attributes on join tables, so "rich associations" with has_and_belongs_to_many is not a good fit for eager loading. | ||
338 | # | |
339 | # == Table Aliasing | |
# | ||
341 | # ActiveRecord uses table aliasing in the case that a table is referenced multiple times in a join. If a table is referenced only once, | |
342 | # the standard table name is used. The second time, the table is aliased as #{reflection_name}_#{parent_table_name}. Indexes are appended | |
343 | # for any more successive uses of the table name. | |
344 | # | |
345 | # Post.find :all, :include => :comments | |
346 | # # => SELECT ... FROM posts LEFT OUTER JOIN comments ON ... | |
347 | # Post.find :all, :include => :special_comments # STI | |
348 | # # => SELECT ... FROM posts LEFT OUTER JOIN comments ON ... AND comments.type = 'SpecialComment' | |
349 | # Post.find :all, :include => [:comments, :special_comments] # special_comments is the reflection name, posts is the parent table name | |
350 | # # => SELECT ... FROM posts LEFT OUTER JOIN comments ON ... LEFT OUTER JOIN comments special_comments_posts | |
351 | # | |
352 | # Acts as tree example: | |
353 | # | |
354 | # TreeMixin.find :all, :include => :children | |
355 | # # => SELECT ... FROM mixins LEFT OUTER JOIN mixins childrens_mixins ... | |
356 | # TreeMixin.find :all, :include => {:children => :parent} # using cascading eager includes | |
357 | # # => SELECT ... FROM mixins LEFT OUTER JOIN mixins childrens_mixins ... | |
358 | # LEFT OUTER JOIN parents_mixins ... | |
359 | # TreeMixin.find :all, :include => {:children => {:parent => :children}} | |
360 | # # => SELECT ... FROM mixins LEFT OUTER JOIN mixins childrens_mixins ... | |
361 | # LEFT OUTER JOIN parents_mixins ... | |
362 | # LEFT OUTER JOIN mixins childrens_mixins_2 | |
363 | # | |
364 | # Has and Belongs to Many join tables use the same idea, but add a _join suffix: | |
365 | # | |
366 | # Post.find :all, :include => :categories | |
367 | # # => SELECT ... FROM posts LEFT OUTER JOIN categories_posts ... LEFT OUTER JOIN categories ... | |
368 | # Post.find :all, :include => {:categories => :posts} | |
369 | # # => SELECT ... FROM posts LEFT OUTER JOIN categories_posts ... LEFT OUTER JOIN categories ... | |
370 | # LEFT OUTER JOIN categories_posts posts_categories_join LEFT OUTER JOIN posts posts_categories | |
371 | # Post.find :all, :include => {:categories => {:posts => :categories}} | |
372 | # # => SELECT ... FROM posts LEFT OUTER JOIN categories_posts ... LEFT OUTER JOIN categories ... | |
373 | # LEFT OUTER JOIN categories_posts posts_categories_join LEFT OUTER JOIN posts posts_categories | |
374 | # LEFT OUTER JOIN categories_posts categories_posts_join LEFT OUTER JOIN categories categories_posts | |
375 | # | |
376 | # If you wish to specify your own custom joins using a :joins option, those table names will take precedence over the eager associations.. | |
377 | # | |
378 | # Post.find :all, :include => :comments, :joins => "inner join comments ..." | |
379 | # # => SELECT ... FROM posts LEFT OUTER JOIN comments_posts ON ... INNER JOIN comments ... | |
380 | # Post.find :all, :include => [:comments, :special_comments], :joins => "inner join comments ..." | |
381 | # # => SELECT ... FROM posts LEFT OUTER JOIN comments comments_posts ON ... | |
382 | # LEFT OUTER JOIN comments special_comments_posts ... | |
383 | # INNER JOIN comments ... | |
384 | # | |
385 | # Table aliases are automatically truncated according to the maximum length of table identifiers according to the specific database. | |
386 | # | |
# == Modules | ||
# | ||
# By default, associations will look for objects within the current module scope. Consider: | ||
... | ... | |
# * <tt>collection=objects</tt> - replaces the collections content by deleting and adding objects as appropriate. | ||
# * <tt>collection_singular_ids=ids</tt> - replace the collection by the objects identified by the primary keys in +ids+ | ||
# * <tt>collection.clear</tt> - removes every object from the collection. This destroys the associated objects if they | ||
276 | | |
437 | # are <tt>:dependent</tt>, deletes them directly from the database if they are <tt>:dependent => :delete_all</tt>, | |
# and sets their foreign keys to NULL otherwise. | ||
# * <tt>collection.empty?</tt> - returns true if there are no associated objects. | ||
# * <tt>collection.size</tt> - returns the number of associated objects. | ||
... | ... | |
# * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name | ||
# of this class in lower-case and "_id" suffixed. So a +Person+ class that makes a has_many association will use "person_id" | ||
# as the default foreign_key. | ||
315 | | |
476 | # * <tt>:dependent</tt> - if set to :destroy all the associated objects are destroyed | |
# alongside this object by calling their destroy method. If set to :delete_all all associated | ||
# objects are deleted *without* calling their destroy method. If set to :nullify all associated | ||
# objects' foreign keys are set to NULL *without* calling their save callbacks. | ||
480 | # NOTE: :dependent => true is deprecated and has been replaced with :dependent => :destroy. | |
# May not be set if :exclusively_dependent is also set. | ||
# * <tt>:exclusively_dependent</tt> - Deprecated; equivalent to :dependent => :delete_all. If set to true all | ||
# the associated object are deleted in one SQL statement without having their | ||
... | ... | |
# specified but +:counter_sql+, +:counter_sql+ will be generated by replacing SELECT ... FROM with SELECT COUNT(*) FROM. | ||
# * <tt>:extend</tt> - specify a named module for extending the proxy, see "Association extensions". | ||
# * <tt>:include</tt> - specify second-order associations that should be eager loaded when the collection is loaded. | ||
493 | # * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause. | |
494 | # * <tt>:limit</tt>: An integer determining the limit on the number of rows that should be returned. | |
495 | # * <tt>:offset</tt>: An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows. | |
496 | # * <tt>:select</tt>: By default, this is * as in SELECT * FROM, but can be changed if you for example want to do a join, but not | |
497 | # include the joined columns. | |
498 | # * <tt>:as</tt>: Specifies a polymorphic interface (See #belongs_to). | |
499 | # * <tt>:through</tt>: Specifies a Join Model to perform the query through. Options for <tt>:class_name</tt> and <tt>:foreign_key</tt> | |
500 | # are ignored, as the association uses the source reflection. You can only use a <tt>:through</tt> query through a <tt>belongs_to</tt> | |
501 | # or <tt>has_many</tt> association. | |
502 | # * <tt>:source</tt>: Specifies the source association name used by <tt>has_many :through</tt> queries. Only use it if the name cannot be | |
503 | # inferred from the association. <tt>has_many :subscribers, :through => :subscriptions</tt> will look for either +:subscribers+ or | |
504 | # +:subscriber+ on +Subscription+, unless a +:source+ is given. | |
# | ||
# Option examples: | ||
# has_many :comments, :order => "posted_on" | ||
# has_many :comments, :include => :author | ||
# has_many :people, :class_name => "Person", :conditions => "deleted = 0", :order => "name" | ||
336 | | |
510 | # has_many :tracks, :order => "position", :dependent => :destroy | |
511 | # has_many :comments, :dependent => :nullify | |
512 | # has_many :tags, :as => :taggable | |
513 | # has_many :subscribers, :through => :subscriptions, :source => :user | |
# has_many :subscribers, :class_name => "Person", :finder_sql => | ||
# 'SELECT DISTINCT people.* ' + | ||
# 'FROM people p, post_subscriptions ps ' + | ||
# 'WHERE ps.post_id = #{id} AND ps.person_id = p.id ' + | ||
# 'ORDER BY p.first_name' | ||
def has_many(association_id, options = {}, &extension) | ||
343 | | |
344 | | |
345 | | |
346 | | |
347 | | |
348 | | |
520 | reflection = create_has_many_reflection(association_id, options, &extension) | |
350 | | |
522 | configure_dependency_for_has_many(reflection) | |
352 | | |
353 | | |
354 | | |
355 | | |
356 | ||
357 | | |
358 | ||
359 | | |
360 | | |
361 | | |
524 | if options[:through] | |
525 | collection_reader_method(reflection, HasManyThroughAssociation) | |
526 | else | |
527 | add_multiple_associated_save_callbacks(reflection.name) | |
528 | add_association_callbacks(reflection.name, reflection.options) | |
529 | collection_accessor_methods(reflection, HasManyAssociation) | |
end | ||
364 | | |
365 | | |
366 | | |
367 | | |
368 | | |
369 | | |
370 | | |
371 | | |
372 | | |
373 | | |
374 | | |
375 | | |
376 | | |
377 | | |
378 | ||
379 | ||
380 | | |
381 | | |
382 | ||
383 | | |
384 | | |
385 | | |
386 | | |
387 | | |
388 | | |
389 | | |
390 | | |
391 | | |
392 | | |
393 | | |
532 | add_deprecated_api_for_has_many(reflection.name) | |
end | ||
# Adds the following methods for retrieval and query of a single associated object. | ||
... | ... | |
# * <tt>:include</tt> - specify second-order associations that should be eager loaded when this object is loaded. | ||
# | ||
# Option examples: | ||
434 | | |
573 | # has_one :credit_card, :dependent => :destroy # destroys the associated credit card | |
574 | # has_one :credit_card, :dependent => :nullify # updates the associated records foriegn key value to null rather than destroying it | |
# has_one :last_comment, :class_name => "Comment", :order => "posted_on" | ||
# has_one :project_manager, :class_name => "Person", :conditions => "role = 'project_manager'" | ||
def has_one(association_id, options = {}) | ||
438 | | |
578 | reflection = create_has_one_reflection(association_id, options) | |
440 | | |
441 | | |
442 | ||
443 | | |
444 | ||
module_eval do | ||
after_save <<-EOF | ||
447 | | |
582 | association = instance_variable_get("@#{reflection.name}") | |
unless association.nil? | ||
449 | | |
584 | association["#{reflection.primary_key_name}"] = id | |
association.save(true) | ||
451 | | |
end | ||
EOF | ||
end | ||
456 | | |
457 | | |
458 | | |
590 | association_accessor_methods(reflection, HasOneAssociation) | |
591 | association_constructor_method(:build, reflection, HasOneAssociation) | |
592 | association_constructor_method(:create, reflection, HasOneAssociation) | |
460 | | |
461 | | |
462 | | |
463 | | |
464 | | |
465 | | |
466 | | |
467 | | |
468 | | |
469 | | |
594 | configure_dependency_for_has_one(reflection) | |
# deprecated api | ||
472 | | |
473 | | |
597 | deprecated_has_association_method(reflection.name) | |
598 | deprecated_association_comparison_method(reflection.name, reflection.class_name) | |
end | ||
# Adds the following methods for retrieval and query for a single associated object that this object holds an id to. | ||
... | ... | |
# * <tt>:counter_cache</tt> - caches the number of belonging objects on the associate class through use of increment_counter | ||
# and decrement_counter. The counter cache is incremented when an object of this class is created and decremented when it's | ||
# destroyed. This requires that a column named "#{table_name}_count" (such as comments_count for a belonging Comment class) | ||
510 | | |
635 | # is used on the associate class (such as a Post class). You can also specify a custom counter cache column by given that | |
636 | # name instead of a true/false value to this option (e.g., <tt>:counter_cache => :my_custom_counter</tt>.) | |
# * <tt>:include</tt> - specify second-order associations that should be eager loaded when this object is loaded. | ||
638 | # * <tt>:polymorphic</tt> - specify this association is a polymorphic association by passing true. | |
# | ||
# Option examples: | ||
# belongs_to :firm, :foreign_key => "client_of" | ||
# belongs_to :author, :class_name => "Person", :foreign_key => "author_id" | ||
# belongs_to :valid_coupon, :class_name => "Coupon", :foreign_key => "coupon_id", | ||
# :conditions => 'discounts > #{payments_count}' | ||
645 | # belongs_to :attachable, :polymorphic => true | |
def belongs_to(association_id, options = {}) | ||
519 | | |
647 | reflection = create_belongs_to_reflection(association_id, options) | |
648 | ||
649 | if reflection.options[:polymorphic] | |
650 | association_accessor_methods(reflection, BelongsToPolymorphicAssociation) | |
521 | | |
522 | | |
652 | module_eval do | |
653 | before_save <<-EOF | |
654 | association = instance_variable_get("@#{reflection.name}") | |
655 | if !association.nil? | |
656 | if association.new_record? | |
657 | association.save(true) | |
658 | end | |
659 | ||
660 | if association.updated? | |
661 | self["#{reflection.primary_key_name}"] = association.id | |
662 | self["#{reflection.options[:foreign_type]}"] = association.class.base_class.name.to_s | |
663 | end | |
664 | end | |
665 | EOF | |
666 | end | |
667 | else | |
668 | association_accessor_methods(reflection, BelongsToAssociation) | |
669 | association_constructor_method(:build, reflection, BelongsToAssociation) | |
670 | association_constructor_method(:create, reflection, BelongsToAssociation) | |
524 | | |
672 | module_eval do | |
673 | before_save <<-EOF | |
674 | association = instance_variable_get("@#{reflection.name}") | |
675 | if !association.nil? | |
676 | if association.new_record? | |
677 | association.save(true) | |
678 | end | |
679 | ||
680 | if association.updated? | |
681 | self["#{reflection.primary_key_name}"] = association.id | |
682 | end | |
683 | end | |
684 | EOF | |
685 | end | |
686 | ||
687 | # deprecated api | |
688 | deprecated_has_association_method(reflection.name) | |
689 | deprecated_association_comparison_method(reflection.name, reflection.class_name) | |
690 | end | |
526 | | |
692 | if options[:counter_cache] | |
693 | cache_column = options[:counter_cache] == true ? | |
694 | "#{self.to_s.underscore.pluralize}_count" : | |
695 | options[:counter_cache] | |
528 | | |
529 | | |
530 | | |
531 | ||
532 | | |
533 | | |
534 | | |
535 | | |
536 | | |
537 | | |
538 | | |
539 | | |
540 | | |
541 | | |
542 | | |
543 | | |
544 | | |
545 | | |
module_eval( | ||
547 | | |
548 | | |
698 | "after_create '#{reflection.name}.class.increment_counter(\"#{cache_column}\", #{reflection.primary_key_name})" + | |
699 | " unless #{reflection.name}.nil?'" | |
) | ||
module_eval( | ||
552 | | |
553 | | |
703 | "before_destroy '#{reflection.name}.class.decrement_counter(\"#{cache_column}\", #{reflection.primary_key_name})" + | |
704 | " unless #{reflection.name}.nil?'" | |
) | ||
end | ||
556 | ||
557 | | |
558 | | |
559 | | |
end | ||
# Associates two classes via an intermediate join table. Unless the join table is explicitly specified as | ||
# an option, it is guessed using the lexical order of the class names. So a join between Developer and Project | ||
# will give the default join table name of "developers_projects" because "D" outranks "P". | ||
# | ||
566 | | |
567 | | |
568 | | |
569 | | |
570 | | |
713 | # Deprecated: Any additional fields added to the join table will be placed as attributes when pulling records out through | |
714 | # has_and_belongs_to_many associations. Records returned from join tables with additional attributes will be marked as | |
715 | # ReadOnly (because we can't save changes to the additional attrbutes). It's strongly recommended that you upgrade any | |
716 | # associations with attributes to a real join model (see introduction). | |
# | ||
# Adds the following methods for retrieval and query. | ||
# +collection+ is replaced with the symbol passed as the first argument, so | ||
... | ... | |
# * <tt>collection.push_with_attributes(object, join_attributes)</tt> - adds one to the collection by creating an association in the join table that | ||
# also holds the attributes from <tt>join_attributes</tt> (should be a hash with the column names as keys). This can be used to have additional | ||
# attributes on the join, which will be injected into the associated objects when they are retrieved through the collection. | ||
582 | | |
728 | # (collection.concat_with_attributes is an alias to this method). This method is now deprecated. | |
# * <tt>collection.delete(object, ...)</tt> - removes one or more objects from the collection by removing their associations from the join table. | ||
# This does not destroy the objects. | ||
# * <tt>collection=objects</tt> - replaces the collections content by deleting and adding objects as appropriate. | ||
... | ... | |
# with a manual one | ||
# * <tt>:extend</tt> - anonymous module for extending the proxy, see "Association extensions". | ||
# * <tt>:include</tt> - specify second-order associations that should be eager loaded when the collection is loaded. | ||
776 | # * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause. | |
777 | # * <tt>:limit</tt>: An integer determining the limit on the number of rows that should be returned. | |
778 | # * <tt>:offset</tt>: An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows. | |
779 | # * <tt>:select</tt>: By default, this is * as in SELECT * FROM, but can be changed if you for example want to do a join, but not | |
780 | # include the joined columns. | |
# | ||
# Option examples: | ||
# has_and_belongs_to_many :projects | ||
... | ... | |
# has_and_belongs_to_many :active_projects, :join_table => 'developers_projects', :delete_sql => | ||
# 'DELETE FROM developers_projects WHERE active=1 AND developer_id = #{id} AND project_id = #{record.id}' | ||
def has_and_belongs_to_many(association_id, options = {}, &extension) | ||
639 | | |
640 | | |
641 | | |
642 | | |
643 | | |
790 | reflection = create_has_and_belongs_to_many_reflection(association_id, options, &extension) | |
791 | ||
792 | add_multiple_associated_save_callbacks(reflection.name) | |
793 | collection_accessor_methods(reflection, HasAndBelongsToManyAssociation) | |
645 | | |
646 | ||
647 | | |
648 | | |
649 | ||
650 | | |
651 | ||
652 | | |
653 | ||
654 | | |
655 | | |
656 | | |
657 | ||
# Don't use a before_destroy callback since users' before_destroy | ||
# callbacks will be executed after the association is wiped out. | ||
660 | | |
797 | old_method = "destroy_without_habtm_shim_for_#{reflection.name}" | |
class_eval <<-end_eval | ||
alias_method :#{old_method}, :destroy_without_callbacks | ||
def destroy_without_callbacks | ||
664 | | |
801 | #{reflection.name}.clear | |
#{old_method} | ||
end | ||
end_eval | ||
669 | | |
806 | add_association_callbacks(reflection.name, options) | |
# deprecated api | ||
672 | | |
673 | | |
674 | | |
675 | | |
809 | deprecated_collection_count_method(reflection.name) | |
810 | deprecated_add_association_relation(reflection.name) | |
811 | deprecated_remove_association_relation(reflection.name) | |
812 | deprecated_has_collection_method(reflection.name) | |
end | ||
private | ||
... | ... | |
table_name_prefix + join_table + table_name_suffix | ||
end | ||
689 | | |
690 | | |
691 | | |
692 | | |
693 | | |
694 | | |
695 | | |
826 | def association_accessor_methods(reflection, association_proxy_class) | |
827 | define_method(reflection.name) do |*params| | |
828 | force_reload = params.first unless params.empty? | |
829 | association = instance_variable_get("@#{reflection.name}") | |
697 | | |
698 | | |
699 | | |
700 | | |
701 | | |
702 | | |
703 | | |
704 | | |
705 | | |
706 | | |
707 | | |
708 | | |
709 | | |
831 | if association.nil? || force_reload | |
832 | association = association_proxy_class.new(self, reflection) | |
retval = association.reload | ||
unless retval.nil? | ||
712 | | |
835 | instance_variable_set("@#{reflection.name}", association) | |
else | ||
714 | | |
837 | instance_variable_set("@#{reflection.name}", nil) | |
return nil | ||
end | ||
end | ||
association | ||
end | ||
721 | | |
722 | | |
844 | define_method("#{reflection.name}=") do |new_value| | |
845 | association = instance_variable_get("@#{reflection.name}") | |
if association.nil? | ||
724 | | |
725 | | |
726 | | |
847 | association = association_proxy_class.new(self, reflection) | |
end | ||
849 | ||
association.replace(new_value) | ||
851 | ||
unless new_value.nil? | ||
730 | | |
853 | instance_variable_set("@#{reflection.name}", association) | |
else | ||
732 | | |
855 | instance_variable_set("@#{reflection.name}", nil) | |
return nil | ||
end | ||
858 | ||
association | ||
end | ||
738 | | |
862 | define_method("set_#{reflection.name}_target") do |target| | |
return if target.nil? | ||
740 | | |
741 | | |
742 | | |
864 | association = association_proxy_class.new(self, reflection) | |
association.target = target | ||
744 | | |
866 | instance_variable_set("@#{reflection.name}", association) | |
end | ||
end | ||
748 | | |
749 | | |
870 | def collection_reader_method(reflection, association_proxy_class) | |
871 | define_method(reflection.name) do |*params| | |
force_reload = params.first unless params.empty? | ||
751 | | |
873 | association = instance_variable_get("@#{reflection.name}") | |
874 | ||
unless association.respond_to?(:loaded?) | ||
753 | | |
754 | | |
755 | | |
756 | | |
876 | association = association_proxy_class.new(self, reflection) | |
877 | instance_variable_set("@#{reflection.name}", association) | |
end | ||
879 | ||
association.reload if force_reload | ||
881 | ||
association | ||
end | ||
884 | end | |
762 | | |
763 | | |
886 | def collection_accessor_methods(reflection, association_proxy_class) | |
887 | collection_reader_method(reflection, association_proxy_class) | |
888 | ||
889 | define_method("#{reflection.name}=") do |new_value| | |
890 | association = instance_variable_get("@#{reflection.name}") | |
unless association.respond_to?(:loaded?) | ||
765 | | |
766 | | |
767 | | |
768 | | |
892 | association = association_proxy_class.new(self, reflection) | |
893 | instance_variable_set("@#{reflection.name}", association) | |
end | ||
association.replace(new_value) | ||
association | ||
end | ||
774 | | |
775 | | |
899 | define_method("#{reflection.name.to_s.singularize}_ids=") do |new_value| | |
900 | send("#{reflection.name}=", reflection.class_name.constantize.find(new_value)) | |
end | ||
end | ||
... | ... | |
def add_multiple_associated_save_callbacks(association_name) | ||
method_name = "validate_associated_records_for_#{association_name}".to_sym | ||
define_method(method_name) do | ||
786 | | |
association = instance_variable_get("@#{association_name}") | ||
if association.respond_to?(:loaded?) | ||
if new_record? | ||
... | ... | |
end | ||
validate method_name | ||
924 | before_save("@new_record_before_save = new_record?; true") | |
after_callback = <<-end_eval | ||
association = instance_variable_get("@#{association_name}") | ||
928 | ||
if association.respond_to?(:loaded?) | ||
if @new_record_before_save | ||
records_to_save = association | ||
... | ... | |
records_to_save.each { |record| association.send(:insert_record, record) } | ||
association.send(:construct_sql) # reconstruct the SQL queries now that we know the owner's id | ||
end | ||
812 | ||
813 | | |
814 | | |
end_eval | ||
816 | ||
939 | ||
# Doesn't use after_save as that would save associations added in after_create/after_update twice | ||
after_create(after_callback) | ||
after_update(after_callback) | ||
end | ||
822 | | |
823 | | |
945 | def association_constructor_method(constructor, reflection, association_proxy_class) | |
946 | define_method("#{constructor}_#{reflection.name}") do |*params| | |
attributees = params.first unless params.empty? | ||
replace_existing = params[1].nil? ? true : params[1] | ||
826 | | |
949 | association = instance_variable_get("@#{reflection.name}") | |
if association.nil? | ||
829 | | |
830 | | |
831 | | |
832 | | |
952 | association = association_proxy_class.new(self, reflection) | |
953 | instance_variable_set("@#{reflection.name}", association) | |
end | ||
if association_proxy_class == HasOneAssociation | ||
... | ... | |
end | ||
end | ||
end | ||
963 | ||
964 | def count_with_associations(options = {}) | |
965 | catch :invalid_query do | |
966 | join_dependency = JoinDependency.new(self, merge_includes(scope(:find, :include), options[:include]), options[:joins]) | |
967 | return count_by_sql(construct_counter_sql_with_included_associations(options, join_dependency)) | |
968 | end | |
969 | 0 | |
970 | end | |
def find_with_associations(options = {}) | ||
844 | | |
973 | catch :invalid_query do | |
974 | join_dependency = JoinDependency.new(self, merge_includes(scope(:find, :include), options[:include]), options[:joins]) | |
975 | rows = select_all_rows(options, join_dependency) | |
976 | return join_dependency.instantiate(rows) | |
977 | end | |
978 | [] | |
979 | end | |
846 | | |
847 | | |
848 | | |
849 | | |
981 | def configure_dependency_for_has_many(reflection) | |
982 | if reflection.options[:dependent] && reflection.options[:exclusively_dependent] | |
983 | raise ArgumentError, ':dependent and :exclusively_dependent are mutually exclusive options. You may specify one or the other.' | |
984 | end | |
851 | | |
852 | | |
853 | | |
986 | if reflection.options[:exclusively_dependent] | |
987 | reflection.options[:dependent] = :delete_all | |
988 | #warn "The :exclusively_dependent option is deprecated. Please use :dependent => :delete_all instead.") | |
989 | end | |
990 | ||
991 | # See HasManyAssociation#delete_records. Dependent associations | |
992 | # delete children, otherwise foreign key is set to NULL. | |
993 | ||
994 | # Add polymorphic type if the :as option is present | |
995 | dependent_conditions = %(#{reflection.primary_key_name} = \#{record.quoted_id}) | |
996 | if reflection.options[:as] | |
997 | dependent_conditions += " AND #{reflection.options[:as]}_type = '#{base_class.name}'" | |
998 | end | |
999 | ||
1000 | case reflection.options[:dependent] | |
1001 | when :destroy, true | |
1002 | module_eval "before_destroy '#{reflection.name}.each { |o| o.destroy }'" | |
1003 | when :delete_all | |
1004 | module_eval "before_destroy { |record| #{reflection.class_name}.delete_all(%(#{dependent_conditions})) }" | |
1005 | when :nullify | |
1006 | module_eval "before_destroy { |record| #{reflection.class_name}.update_all(%(#{reflection.primary_key_name} = NULL), %(#{dependent_conditions})) }" | |
1007 | when nil, false | |
1008 | # pass | |
1009 | else | |
1010 | raise ArgumentError, 'The :dependent option expects either :destroy, :delete_all, or :nullify' | |
1011 | end | |
1012 | end | |
1013 | ||
1014 | def configure_dependency_for_has_one(reflection) | |
1015 | case reflection.options[:dependent] | |
1016 | when :destroy, true | |
1017 | module_eval "before_destroy '#{reflection.name}.destroy unless #{reflection.name}.nil?'" | |
1018 | when :nullify | |
1019 | module_eval "before_destroy '#{reflection.name}.update_attribute(\"#{reflection.primary_key_name}\", nil)'" | |
1020 | when nil, false | |
1021 | # pass | |
1022 | else | |
1023 | raise ArgumentError, "The :dependent option expects either :destroy or :nullify." | |
1024 | end | |
1025 | end | |
1026 | ||
1027 | ||
1028 | def add_deprecated_api_for_has_many(association_name) | |
1029 | deprecated_collection_count_method(association_name) | |
1030 | deprecated_add_association_relation(association_name) | |
1031 | deprecated_remove_association_relation(association_name) | |
1032 | deprecated_has_collection_method(association_name) | |
1033 | deprecated_find_in_collection_method(association_name) | |
1034 | deprecated_find_all_in_collection_method(association_name) | |
1035 | deprecated_collection_create_method(association_name) | |
1036 | deprecated_collection_build_method(association_name) | |
1037 | end | |
1038 | ||
1039 | def create_has_many_reflection(association_id, options, &extension) | |
1040 | options.assert_valid_keys( | |
1041 | :class_name, :table_name, :foreign_key, | |
1042 | :exclusively_dependent, :dependent, | |
1043 | :select, :conditions, :include, :order, :group, :limit, :offset, | |
1044 | :as, :through, :source, | |
1045 | :finder_sql, :counter_sql, | |
1046 | :before_add, :after_add, :before_remove, :after_remove, | |
1047 | :extend | |
1048 | ) | |
1049 | ||
1050 | options[:extend] = create_extension_module(association_id, extension) if block_given? | |
1051 | ||
1052 | create_reflection(:has_many, association_id, options, self) | |
1053 | end | |
1054 | ||
1055 | def create_has_one_reflection(association_id, options) | |
1056 | options.assert_valid_keys( | |
1057 | :class_name, :foreign_key, :remote, :conditions, :order, :include, :dependent, :counter_cache, :extend, :as | |
1058 | ) | |
1059 | ||
1060 | create_reflection(:has_one, association_id, options, self) | |
1061 | end | |
1062 | ||
1063 | def create_belongs_to_reflection(association_id, options) | |
1064 | options.assert_valid_keys( | |
1065 | :class_name, :foreign_key, :foreign_type, :remote, :conditions, :order, :include, :dependent, | |
1066 | :counter_cache, :extend, :polymorphic | |
1067 | ) | |
855 | | |
856 | | |
857 | | |
858 | | |
1069 | reflection = create_reflection(:belongs_to, association_id, options, self) | |
860 | | |
861 | | |
862 | | |
863 | | |
864 | | |
1071 | if options[:polymorphic] | |
1072 | reflection.options[:foreign_type] ||= reflection.class_name.underscore + "_type" | |
1073 | end | |
866 | | |
1075 | reflection | |
1076 | end | |
1077 | ||
1078 | def create_has_and_belongs_to_many_reflection(association_id, options, &extension) | |
1079 | options.assert_valid_keys( | |
1080 | :class_name, :table_name, :join_table, :foreign_key, :association_foreign_key, | |
1081 | :select, :conditions, :include, :order, :group, :limit, :offset, | |
1082 | :finder_sql, :delete_sql, :insert_sql, :uniq, | |
1083 | :before_add, :after_add, :before_remove, :after_remove, | |
1084 | :extend | |
1085 | ) | |
868 | | |
869 | | |
870 | | |
871 | | |
1087 | options[:extend] = create_extension_module(association_id, extension) if block_given? | |
873 | | |
874 | | |
875 | | |
876 | | |
877 | | |
878 | | |
879 | | |
1089 | reflection = create_reflection(:has_and_belongs_to_many, association_id, options, self) | |
1090 | ||
1091 | reflection.options[:join_table] ||= join_table_name(undecorated_table_name(self.to_s), undecorated_table_name(reflection.class_name)) | |
881 | | |
1093 | reflection | |
end | ||
884 | ||
def reflect_on_included_associations(associations) | ||
[ associations ].flatten.collect { |association| reflect_on_association(association.to_s.intern) } | ||
end | ||
889 | | |
890 | | |
891 | | |
892 | | |
893 | | |
894 | | |
895 | | |
896 | | |
897 | | |
898 | | |
def guard_against_unlimitable_reflections(reflections, options) | ||
if (options[:offset] || options[:limit]) && !using_limitable_reflections?(reflections) | ||
raise( | ||
... | ... | |
end | ||
end | ||
908 | | |
909 | | |
910 | | |
911 | ||
912 | | |
913 | | |
914 | | |
915 | | |
1109 | def select_all_rows(options, join_dependency) | |
1110 | connection.select_all( | |
1111 | construct_finder_sql_with_included_associations(options, join_dependency), | |
1112 | "#{name} Load Including Associations" | |
1113 | ) | |
1114 | end | |
1115 | ||
1116 | def construct_counter_sql_with_included_associations(options, join_dependency) | |
1117 | scope = scope(:find) | |
1118 | sql = "SELECT COUNT(DISTINCT #{table_name}.#{primary_key})" | |
1119 | ||
1120 | # A (slower) workaround if we're using a backend, like sqlite, that doesn't support COUNT DISTINCT. | |
1121 | if !Base.connection.supports_count_distinct? | |
1122 | sql = "SELECT COUNT(*) FROM (SELECT DISTINCT #{table_name}.#{primary_key}" | |
end | ||
918 | | |
919 | | |
1125 | sql << " FROM #{table_name} " | |
1126 | sql << join_dependency.join_associations.collect{|join| join.association_join }.join | |
1127 | ||
1128 | add_joins!(sql, options, scope) | |
1129 | add_conditions!(sql, options[:conditions], scope) | |
1130 | add_limited_ids_condition!(sql, options, join_dependency) if !using_limitable_reflections?(join_dependency.reflections) && ((scope && scope[:limit]) || options[:limit]) | |
921 | | |
922 | | |
923 | | |
924 | | |
1132 | add_limit!(sql, options, scope) if using_limitable_reflections?(join_dependency.reflections) | |
926 | | |
927 | | |
928 | | |
929 | | |
1134 | if !Base.connection.supports_count_distinct? | |
1135 | sql << ")" | |
end | ||
931 | | |
932 | | |
933 | | |
935 | ||
936 | | |
937 | | |
938 | | |
939 | | |
940 | | |
1138 | return sanitize_sql(sql) | |
end | ||
943 | | |
944 | | |
945 | | |
946 | | |
1141 | def construct_finder_sql_with_included_associations(options, join_dependency) | |
1142 | scope = scope(:find) | |
1143 | sql = "SELECT #{column_aliases(join_dependency)} FROM #{(scope && scope[:from]) || options[:from] || table_name} " | |
1144 | sql << join_dependency.join_associations.collect{|join| join.association_join }.join | |
1145 | ||
1146 | add_joins!(sql, options, scope) | |
1147 | add_conditions!(sql, options[:conditions], scope) | |
1148 | add_limited_ids_condition!(sql, options, join_dependency) if !using_limitable_reflections?(join_dependency.reflections) && options[:limit] | |
948 | | |
949 | | |
950 | | |
951 | ||
sql << "ORDER BY #{options[:order]} " if options[:order] | ||
953 | ||
954 | | |
955 | ||
1151 | ||
1152 | add_limit!(sql, options, scope) if using_limitable_reflections?(join_dependency.reflections) | |
1153 | ||
return sanitize_sql(sql) | ||
end | ||
958 | ||
959 | | |
960 | | |
1156 | ||
1157 | def add_limited_ids_condition!(sql, options, join_dependency) | |
1158 | unless (id_list = select_limited_ids_list(options, join_dependency)).empty? | |
sql << "#{condition_word(sql)} #{table_name}.#{primary_key} IN (#{id_list}) " | ||
1160 | else | |
1161 | throw :invalid_query | |
end | ||
end | ||
964 | ||
965 | | |
1164 | ||
1165 | def select_limited_ids_list(options, join_dependency) | |
connection.select_values( | ||
967 | | |
1167 | construct_finder_sql_for_association_limiting(options, join_dependency), | |
"#{name} Load IDs For Limited Eager Loading" | ||
).collect { |id| connection.quote(id) }.join(", ") | ||
end | ||
971 | ||
972 | | |
973 | | |
1171 | ||
1172 | def construct_finder_sql_for_association_limiting(options, join_dependency) | |
1173 | scope = scope(:find) | |
1174 | #sql = "SELECT DISTINCT #{table_name}.#{primary_key} FROM #{table_name} " | |
1175 | sql = "SELECT " | |
1176 | sql << "DISTINCT #{table_name}." if include_eager_conditions?(options) || include_eager_order?(options) | |
1177 | sql << "#{primary_key} FROM #{table_name} " | |
975 | | |
976 | | |
1179 | if include_eager_conditions?(options) || include_eager_order?(options) | |
1180 | sql << join_dependency.join_associations.collect{|join| join.association_join }.join | |
1181 | add_joins!(sql, options, scope) | |
1182 | end | |
1183 | ||
1184 | add_conditions!(sql, options[:conditions], scope) | |
sql << "ORDER BY #{options[:order]} " if options[:order] | ||
978 | | |
1186 | add_limit!(sql, options, scope) | |
return sanitize_sql(sql) | ||
end | ||
def include_eager_conditions?(options) | ||
983 | | |
1191 | conditions = scope(:find, :conditions) || options[:conditions] | |
return false unless conditions | ||
conditions = conditions.first if conditions.is_a?(Array) | ||
conditions.scan(/(\w+)\.\w+/).flatten.any? do |condition_table_name| | ||
condition_table_name != table_name | ||
end | ||
end | ||
1198 | ||
1199 | def include_eager_order?(options) | |
1200 | order = options[:order] | |
1201 | return false unless order | |
1202 | order.scan(/(\w+)\.\w+/).flatten.any? do |order_table_name| | |
1203 | order_table_name != table_name | |
1204 | end | |
1205 | end | |
def using_limitable_reflections?(reflections) | ||
reflections.reject { |r| [ :belongs_to, :has_one ].include?(r.macro) }.length.zero? | ||
end | ||
995 | | |
996 | | |
997 | | |
998 | | |
999 | | |
1000 | | |
1001 | | |
1002 | | |
1211 | def column_aliases(join_dependency) | |
1212 | join_dependency.joins.collect{|join| join.column_names_with_alias.collect{|column_name, aliased_name| | |
1213 | "#{join.aliased_table_name}.#{connection.quote_column_name column_name} AS #{aliased_name}"}}.flatten.join(", ") | |
end | ||
1005 | | |
1006 | | |
1007 | | |
1008 | ||
1009 | | |
1010 | | |
1011 | | |
1012 | | |
1013 | | |
1014 | | |
1015 | | |
1016 | | |
1017 | | |
1018 | | |
1019 | | |
1020 | | |
1021 | | |
1022 | | |
1023 | | |
1024 | | |
1025 | | |
1026 | | |
1027 | | |
1028 | | |
1029 | | |
1030 | ||
def add_association_callbacks(association_name, options) | ||
callbacks = %w(before_add after_add before_remove after_remove) | ||
callbacks.each do |callback_name| | ||
... | ... | |
end | ||
end | ||
1043 | | |
1044 | | |
1045 | | |
1046 | | |
1047 | | |
1048 | | |
1049 | | |
1050 | | |
1051 | ||
def condition_word(sql) | ||
sql =~ /where/i ? " AND " : "WHERE " | ||
end | ||
... | ... | |
extension_module_name.constantize | ||
end | ||
1241 | ||
1242 | class JoinDependency | |
1243 | attr_reader :joins, :reflections, :table_aliases | |
1244 | ||
1245 | def initialize(base, associations, joins) | |
1246 | @joins = [JoinBase.new(base, joins)] | |
1247 | @associations = associations | |
1248 | @reflections = [] | |
1249 | @base_records_hash = {} | |
1250 | @base_records_in_order = [] | |
1251 | @table_aliases = Hash.new { |aliases, table| aliases[table] = 0 } | |
1252 | @table_aliases[base.table_name] = 1 | |
1253 | build(associations) | |
1254 | end | |
1255 | ||
1256 | def join_associations | |
1257 | @joins[1..-1].to_a | |
1258 | end | |
1259 | ||
1260 | def join_base | |
1261 | @joins[0] | |
1262 | end | |
1263 | ||
1264 | def instantiate(rows) | |
1265 | rows.each_with_index do |row, i| | |
1266 | primary_id = join_base.record_id(row) | |
1267 | unless @base_records_hash[primary_id] | |
1268 | @base_records_in_order << (@base_records_hash[primary_id] = join_base.instantiate(row)) | |
1269 | end | |
1270 | construct(@base_records_hash[primary_id], @associations, join_associations.dup, row) | |
1271 | end | |
1272 | return @base_records_in_order | |
1273 | end | |
1274 | ||
1275 | def aliased_table_names_for(table_name) | |
1276 | joins.select{|join| join.table_name == table_name }.collect{|join| join.aliased_table_name} | |
1277 | end | |
1278 | ||
1279 | protected | |
1280 | def build(associations, parent = nil) | |
1281 | parent ||= @joins.last | |
1282 | case associations | |
1283 | when Symbol, String | |
1284 | reflection = parent.reflections[associations.to_s.intern] or | |
1285 | raise ConfigurationError, "Association named '#{ associations }' was not found; perhaps you misspelled it?" | |
1286 | @reflections << reflection | |
1287 | @joins << JoinAssociation.new(reflection, self, parent) | |
1288 | when Array | |
1289 | associations.each do |association| | |
1290 | build(association, parent) | |
1291 | end | |
1292 | when Hash | |
1293 | associations.keys.sort{|a,b|a.to_s<=>b.to_s}.each do |name| | |
1294 | build(name, parent) | |
1295 | build(associations[name]) | |
1296 | end | |
1297 | else | |
1298 | raise ConfigurationError, associations.inspect | |
1299 | end | |
1300 | end | |
1301 | ||
1302 | def construct(parent, associations, joins, row) | |
1303 | case associations | |
1304 | when Symbol, String | |
1305 | while (join = joins.shift).reflection.name.to_s != associations.to_s | |
1306 | raise ConfigurationError, "Not Enough Associations" if joins.empty? | |
1307 | end | |
1308 | construct_association(parent, join, row) | |
1309 | when Array | |
1310 | associations.each do |association| | |
1311 | construct(parent, association, joins, row) | |
1312 | end | |
1313 | when Hash | |
1314 | associations.keys.sort{|a,b|a.to_s<=>b.to_s}.each do |name| | |
1315 | association = construct_association(parent, joins.shift, row) | |
1316 | construct(association, associations[name], joins, row) if association | |
1317 | end | |
1318 | else | |
1319 | raise ConfigurationError, associations.inspect | |
1320 | end | |
1321 | end | |
1322 | ||
1323 | def construct_association(record, join, row) | |
1324 | case join.reflection.macro | |
1325 | when :has_many, :has_and_belongs_to_many | |
1326 | collection = record.send(join.reflection.name) | |
1327 | collection.loaded | |
1328 | ||
1329 | return nil if record.id.to_s != join.parent.record_id(row).to_s or row[join.aliased_primary_key].nil? | |
1330 | association = join.instantiate(row) | |
1331 | collection.target.push(association) unless collection.target.include?(association) | |
1332 | when :has_one, :belongs_to | |
1333 | return if record.id.to_s != join.parent.record_id(row).to_s or row[join.aliased_primary_key].nil? | |
1334 | association = join.instantiate(row) | |
1335 | record.send("set_#{join.reflection.name}_target", association) | |
1336 | else | |
1337 | raise ConfigurationError, "unknown macro: #{join.reflection.macro}" | |
1338 | end | |
1339 | return association | |
1340 | end | |
1341 | ||
1342 | class JoinBase | |
1343 | attr_reader :active_record, :table_joins | |
1344 | delegate :table_name, :column_names, :primary_key, :reflections, :sanitize_sql, :to => :active_record | |
1345 | ||
1346 | def initialize(active_record, joins = nil) | |
1347 | @active_record = active_record | |
1348 | @cached_record = {} | |
1349 | @table_joins = joins | |
1350 | end | |
1351 | ||
1352 | def aliased_prefix | |
1353 | "t0" | |
1354 | end | |
1355 | ||
1356 | def aliased_primary_key | |
1357 | "#{ aliased_prefix }_r0" | |
1358 | end | |
1359 | ||
1360 | def aliased_table_name | |
1361 | active_record.table_name | |
1362 | end | |
1363 | ||
1364 | def column_names_with_alias | |
1365 | unless @column_names_with_alias | |
1366 | @column_names_with_alias = [] | |
1367 | ([primary_key] + (column_names - [primary_key])).each_with_index do |column_name, i| | |
1368 | @column_names_with_alias << [column_name, "#{ aliased_prefix }_r#{ i }"] | |
1369 | end | |
1370 | end | |
1371 | return @column_names_with_alias | |
1372 | end | |
1373 | ||
1374 | def extract_record(row) | |
1375 | column_names_with_alias.inject({}){|record, (cn, an)| record[cn] = row[an]; record} | |
1376 | end | |
1377 | ||
1378 | def record_id(row) | |
1379 | row[aliased_primary_key] | |
1380 | end | |
1381 | ||
1382 | def instantiate(row) | |
1383 | @cached_record[record_id(row)] ||= active_record.instantiate(extract_record(row)) | |
1384 | end | |
1385 | end | |
1386 | ||
1387 | class JoinAssociation < JoinBase | |
1388 | attr_reader :reflection, :parent, :aliased_table_name, :aliased_prefix, :aliased_join_table_name, :parent_table_name | |
1389 | delegate :options, :klass, :through_reflection, :source_reflection, :to => :reflection | |
1390 | ||
1391 | def initialize(reflection, join_dependency, parent = nil) | |
1392 | reflection.check_validity! | |
1393 | if reflection.options[:polymorphic] | |
1394 | raise EagerLoadPolymorphicError.new(reflection) | |
1395 | end | |
1396 | ||
1397 | super(reflection.klass) | |
1398 | @parent = parent | |
1399 | @reflection = reflection | |
1400 | @aliased_prefix = "t#{ join_dependency.joins.size }" | |
1401 | @aliased_table_name = table_name # start with the table name | |
1402 | @parent_table_name = parent.active_record.table_name | |
1403 | ||
1404 | if !parent.table_joins.blank? && parent.table_joins.to_s.downcase =~ %r{join(\s+\w+)?\s+#{aliased_table_name.downcase}\son} | |
1405 | join_dependency.table_aliases[aliased_table_name] += 1 | |
1406 | end | |
1407 | ||
1408 | unless join_dependency.table_aliases[aliased_table_name].zero? | |
1409 | # if the table name has been used, then use an alias | |
1410 | @aliased_table_name = active_record.connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}" | |
1411 | table_index = join_dependency.table_aliases[aliased_table_name] | |
1412 | @aliased_table_name = @aliased_table_name[0..active_record.connection.table_alias_length-3] + "_#{table_index+1}" if table_index > 0 | |
1413 | end | |
1414 | join_dependency.table_aliases[aliased_table_name] += 1 | |
1415 | ||
1416 | if reflection.macro == :has_and_belongs_to_many || (reflection.macro == :has_many && reflection.options[:through]) | |
1417 | @aliased_join_table_name = reflection.macro == :has_and_belongs_to_many ? reflection.options[:join_table] : reflection.through_reflection.klass.table_name | |
1418 | unless join_dependency.table_aliases[aliased_join_table_name].zero? | |
1419 | @aliased_join_table_name = active_record.connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}_join" | |
1420 | table_index = join_dependency.table_aliases[aliased_join_table_name] | |
1421 | @aliased_join_table_name = @aliased_join_table_name[0..active_record.connection.table_alias_length-3] + "_#{table_index+1}" if table_index > 0 | |
1422 | end | |
1423 | join_dependency.table_aliases[aliased_join_table_name] += 1 | |
1424 | end | |
1425 | end | |
1426 | ||
1427 | def association_join | |
1428 | join = case reflection.macro | |
1429 | when :has_and_belongs_to_many | |
1430 | " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ | |
1431 | table_alias_for(options[:join_table], aliased_join_table_name), | |
1432 | aliased_join_table_name, | |
1433 | options[:foreign_key] || reflection.active_record.to_s.classify.foreign_key, | |
1434 | reflection.active_record.table_name, reflection.active_record.primary_key] + | |
1435 | " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ | |
1436 | table_name_and_alias, aliased_table_name, klass.primary_key, | |
1437 | aliased_join_table_name, options[:association_foreign_key] || klass.table_name.classify.foreign_key | |
1438 | ] | |
1439 | when :has_many, :has_one | |
1440 | case | |
1441 | when reflection.macro == :has_many && reflection.options[:through] | |
1442 | through_conditions = through_reflection.options[:conditions] ? "AND #{interpolate_sql(sanitize_sql(through_reflection.options[:conditions]))}" : '' | |
1443 | if through_reflection.options[:as] # has_many :through against a polymorphic join | |
1444 | polymorphic_foreign_key = through_reflection.options[:as].to_s + '_id' | |
1445 | polymorphic_foreign_type = through_reflection.options[:as].to_s + '_type' | |
1446 | ||
1447 | " LEFT OUTER JOIN %s ON (%s.%s = %s.%s AND %s.%s = %s) " % [ | |
1448 | table_alias_for(through_reflection.klass.table_name, aliased_join_table_name), | |
1449 | aliased_join_table_name, polymorphic_foreign_key, | |
1450 | parent.aliased_table_name, parent.primary_key, | |
1451 | aliased_join_table_name, polymorphic_foreign_type, klass.quote(parent.active_record.base_class.name)] + | |
1452 | " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [table_name_and_alias, | |
1453 | aliased_table_name, primary_key, aliased_join_table_name, options[:foreign_key] || reflection.klass.to_s.classify.foreign_key | |
1454 | ] | |
1455 | else | |
1456 | if source_reflection.macro == :has_many && source_reflection.options[:as] | |
1457 | " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ | |
1458 | table_alias_for(through_reflection.klass.table_name, aliased_join_table_name), aliased_join_table_name, | |
1459 | through_reflection.primary_key_name, | |
1460 | parent.aliased_table_name, parent.primary_key] + | |
1461 | " LEFT OUTER JOIN %s ON %s.%s = %s.%s AND %s.%s = %s " % [ | |
1462 | table_name_and_alias, | |
1463 | aliased_table_name, "#{source_reflection.options[:as]}_id", | |
1464 | aliased_join_table_name, options[:foreign_key] || primary_key, | |
1465 | aliased_table_name, "#{source_reflection.options[:as]}_type", | |
1466 | klass.quote(source_reflection.active_record.base_class.name) | |
1467 | ] | |
1468 | else | |
1469 | case source_reflection.macro | |
1470 | when :belongs_to | |
1471 | first_key = primary_key | |
1472 | second_key = options[:foreign_key] || klass.to_s.classify.foreign_key | |
1473 | when :has_many | |
1474 | first_key = through_reflection.klass.to_s.classify.foreign_key | |
1475 | second_key = options[:foreign_key] || primary_key | |
1476 | end | |
1477 | ||
1478 | " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ | |
1479 | table_alias_for(through_reflection.klass.table_name, aliased_join_table_name), aliased_join_table_name, | |
1480 | through_reflection.primary_key_name, | |
1481 | parent.aliased_table_name, parent.primary_key] + | |
1482 | " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ | |
1483 | table_name_and_alias, | |
1484 | aliased_table_name, first_key, | |
1485 | aliased_join_table_name, second_key | |
1486 | ] | |
1487 | end | |
1488 | end | |
1489 | ||
1490 | when reflection.macro == :has_many && reflection.options[:as] | |
1491 | " LEFT OUTER JOIN %s ON %s.%s = %s.%s AND %s.%s = %s" % [ | |
1492 | table_name_and_alias, | |
1493 | aliased_table_name, "#{reflection.options[:as]}_id", | |
1494 | parent.aliased_table_name, parent.primary_key, | |
1495 | aliased_table_name, "#{reflection.options[:as]}_type", | |
1496 | klass.quote(parent.active_record.base_class.name) | |
1497 | ] | |
1498 | when reflection.macro == :has_one && reflection.options[:as] | |
1499 | " LEFT OUTER JOIN %s ON %s.%s = %s.%s AND %s.%s = %s " % [ | |
1500 | table_name_and_alias, | |
1501 | aliased_table_name, "#{reflection.options[:as]}_id", | |
1502 | parent.aliased_table_name, parent.primary_key, | |
1503 | aliased_table_name, "#{reflection.options[:as]}_type", | |
1504 | klass.quote(reflection.active_record.base_class.name) | |
1505 | ] | |
1506 | else | |
1507 | foreign_key = options[:foreign_key] || reflection.active_record.name.foreign_key | |
1508 | " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ | |
1509 | table_name_and_alias, | |
1510 | aliased_table_name, foreign_key, | |
1511 | parent.aliased_table_name, parent.primary_key | |
1512 | ] | |
1513 | end | |
1514 | when :belongs_to | |
1515 | " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ | |
1516 | table_name_and_alias, aliased_table_name, reflection.klass.primary_key, | |
1517 | parent.aliased_table_name, options[:foreign_key] || klass.to_s.foreign_key | |
1518 | ] | |
1519 | else | |
1520 | "" | |
1521 | end || '' | |
1522 | join << %(AND %s.%s = %s ) % [ | |
1523 | aliased_table_name, | |
1524 | reflection.active_record.connection.quote_column_name(reflection.active_record.inheritance_column), | |
1525 | klass.quote(klass.name)] unless klass.descends_from_active_record? | |
1526 | join << "AND #{interpolate_sql(sanitize_sql(reflection.options[:conditions]))} " if reflection.options[:conditions] | |
1527 | join | |
1528 | end | |
1529 | ||
1530 | protected | |
1531 | def pluralize(table_name) | |
1532 | ActiveRecord::Base.pluralize_table_names ? table_name.to_s.pluralize : table_name | |
1533 | end | |
1534 | ||
1535 | def table_alias_for(table_name, table_alias) | |
1536 | "#{table_name} #{table_alias if table_name != table_alias}".strip | |
1537 | end | |
1538 | ||
1539 | def table_name_and_alias | |
1540 | table_alias_for table_name, @aliased_table_name | |
1541 | end | |
1542 | ||
1543 | def interpolate_sql(sql) | |
1544 | instance_eval("%@#{sql.gsub('@', '\@')}@") | |
1545 | end | |
1546 | end | |
1547 | end | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:
prev. | current | |
def <<(*records) | ||
result = true | ||
load_target | ||
21 | ||
@owner.transaction do | ||
flatten_deeper(records).each do |record| | ||
raise_on_type_mismatch(record) | ||
... | ... | |
end | ||
end | ||
31 | | |
32 | result && self | |
end | ||
alias_method :push, :<< | ||
... | ... | |
# Remove all records from this association | ||
def delete_all | ||
40 | load_target | |
delete(@target) | ||
@target = [] | ||
end | ||
... | ... | |
# Removes all records from this association. Returns +self+ so method calls may be chained. | ||
def clear | ||
return self if length.zero? # forces load_target if hasn't happened already | ||
63 | | |
65 | ||
66 | if @reflection.options[:dependent] && @reflection.options[:dependent] == :delete_all | |
destroy_all | ||
else | ||
delete_all | ||
end | ||
71 | ||
self | ||
end | ||
... | ... | |
end | ||
private | ||
127 | | |
128 | | |
129 | | |
130 | ||
131 | | |
132 | | |
133 | | |
134 | ||
# Array#flatten has problems with recursive arrays. Going one level deeper solves the majority of the problems. | ||
def flatten_deeper(array) | ||
array.collect { |element| element.respond_to?(:flatten) ? element.flatten : element }.flatten | ||
... | ... | |
end | ||
def callbacks_for(callback_name) | ||
158 | | |
159 | | |
154 | full_callback_name = "#{callback_name}_for_#{@reflection.name}" | |
155 | @owner.class.read_inheritable_attribute(full_callback_name.to_sym) || [] | |
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:
prev. | current | |
module ActiveRecord | ||
module Associations | ||
class AssociationProxy #:nodoc: | ||
4 | attr_reader :reflection | |
alias_method :proxy_respond_to?, :respond_to? | ||
alias_method :proxy_extend, :extend | ||
instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?|^proxy_respond_to\?|^proxy_extend|^send)/ } | ||
8 | | |
9 | | |
10 | | |
11 | | |
12 | | |
13 | | |
14 | ||
15 | | |
16 | ||
9 | def initialize(owner, reflection) | |
10 | @owner, @reflection = owner, reflection | |
11 | proxy_extend(reflection.options[:extend]) if reflection.options[:extend] | |
reset | ||
end | ||
15 | def respond_to?(symbol, include_priv = false) | |
16 | proxy_respond_to?(symbol, include_priv) || (load_target && @target.respond_to?(symbol, include_priv)) | |
17 | end | |
18 | ||
19 | # Explicitly proxy === because the instance method removal above | |
20 | # doesn't catch it. | |
21 | def ===(other) | |
22 | load_target | |
23 | other === @target | |
24 | end | |
25 | ||
26 | def aliased_table_name | |
27 | @reflection.klass.table_name | |
28 | end | |
29 | ||
30 | def conditions | |
31 | @conditions ||= eval("%(#{@reflection.active_record.send :sanitize_sql, @reflection.options[:conditions]})") if @reflection.options[:conditions] | |
32 | end | |
33 | alias :sql_conditions :conditions | |
34 | ||
35 | def reset | |
36 | @target = nil | |
37 | @loaded = false | |
38 | end | |
39 | ||
def reload | ||
reset | ||
load_target | ||
end | ||
25 | | |
26 | | |
27 | | |
28 | ||
def loaded? | ||
@loaded | ||
end | ||
... | ... | |
@target | ||
end | ||
41 | | |
42 | | |
43 | | |
57 | def target=(target) | |
58 | @target = target | |
59 | loaded | |
end | ||
protected | ||
def dependent? | ||
48 | | |
64 | @reflection.options[:dependent] || false | |
end | ||
def quoted_record_ids(records) | ||
... | ... | |
end | ||
def sanitize_sql(sql) | ||
64 | | |
80 | @reflection.klass.send(:sanitize_sql, sql) | |
end | ||
def extract_options_from_args!(args) | ||
@owner.send(:extract_options_from_args!, args) | ||
end | ||
86 | ||
87 | def set_belongs_to_association_for(record) | |
88 | if @reflection.options[:as] | |
89 | record["#{@reflection.options[:as]}_id"] = @owner.id unless @owner.new_record? | |
90 | record["#{@reflection.options[:as]}_type"] = @owner.class.base_class.name.to_s | |
91 | else | |
92 | record[@reflection.primary_key_name] = @owner.id unless @owner.new_record? | |
93 | end | |
94 | end | |
95 | ||
96 | def merge_options_from_reflection!(options) | |
97 | options.reverse_merge!( | |
98 | :group => @reflection.options[:group], | |
99 | :limit => @reflection.options[:limit], | |
100 | :offset => @reflection.options[:offset], | |
101 | :joins => @reflection.options[:joins], | |
102 | :include => @reflection.options[:include], | |
103 | :select => @reflection.options[:select] | |
104 | ) | |
105 | end | |
private | ||
72 | | |
def method_missing(method, *args, &block) | ||
load_target | ||
@target.send(method, *args, &block) | ||
... | ... | |
def load_target | ||
if !@owner.new_record? || foreign_key_present | ||
begin | ||
81 | | |
116 | @target = find_target if !loaded? | |
rescue ActiveRecord::RecordNotFound | ||
reset | ||
end | ||
end | ||
86 | | |
87 | | |
121 | ||
122 | loaded if target | |
123 | target | |
end | ||
# Can be overwritten by associations that might have the foreign key available for an association without | ||
... | ... | |
end | ||
def raise_on_type_mismatch(record) | ||
97 | | |
133 | unless record.is_a?(@reflection.klass) | |
134 | raise ActiveRecord::AssociationTypeMismatch, "#{@reflection.class_name} expected, got #{record.class}" | |
135 | end | |
end | ||
end | ||
end | ||
101 | ||
140 | end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/associations/belongs_to_association.rb:
prev. | current | |
module ActiveRecord | ||
module Associations | ||
class BelongsToAssociation < AssociationProxy #:nodoc: | ||
4 | | |
5 | | |
6 | | |
7 | | |
8 | | |
9 | | |
10 | | |
11 | | |
12 | | |
13 | | |
14 | ||
def create(attributes = {}) | ||
16 | | |
17 | | |
18 | | |
5 | replace(@reflection.klass.create(attributes)) | |
end | ||
def build(attributes = {}) | ||
22 | | |
23 | | |
24 | | |
9 | replace(@reflection.klass.new(attributes)) | |
end | ||
27 | | |
28 | | |
29 | | |
12 | def replace(record) | |
13 | counter_cache_name = @reflection.counter_cache_column | |
14 | ||
15 | if record.nil? | |
16 | if counter_cache_name && @owner[counter_cache_name] && !@owner.new_record? | |
17 | @reflection.klass.decrement_counter(counter_cache_name, @owner[@reflection.primary_key_name]) if @owner[@reflection.primary_key_name] | |
18 | end | |
19 | ||
20 | @target = @owner[@reflection.primary_key_name] = nil | |
else | ||
31 | | |
22 | raise_on_type_mismatch(record) | |
33 | | |
34 | | |
24 | if counter_cache_name && !@owner.new_record? | |
25 | @reflection.klass.increment_counter(counter_cache_name, record.id) | |
26 | @reflection.klass.decrement_counter(counter_cache_name, @owner[@reflection.primary_key_name]) if @owner[@reflection.primary_key_name] | |
27 | end | |
28 | ||
29 | @target = (AssociationProxy === record ? record.target : record) | |
30 | @owner[@reflection.primary_key_name] = record.id unless record.new_record? | |
@updated = true | ||
end | ||
37 | | |
39 | | |
34 | loaded | |
35 | record | |
end | ||
def updated? | ||
@updated | ||
end | ||
46 | | |
47 | ||
48 | ||
private | ||
def find_target | ||
51 | | |
52 | | |
53 | | |
54 | | |
55 | | |
56 | | |
57 | | |
58 | | |
59 | | |
44 | @reflection.klass.find( | |
45 | @owner[@reflection.primary_key_name], | |
46 | :conditions => conditions, | |
47 | :include => @reflection.options[:include] | |
48 | ) | |
end | ||
def foreign_key_present | ||
63 | | |
52 | !@owner[@reflection.primary_key_name].nil? | |
end | ||
65 | ||
66 | | |
67 | | |
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb:
prev. | current | |
module ActiveRecord | ||
module Associations | ||
class HasAndBelongsToManyAssociation < AssociationCollection #:nodoc: | ||
4 | | |
4 | def initialize(owner, reflection) | |
super | ||
6 | ||
7 | | |
8 | | |
9 | | |
10 | | |
11 | ||
construct_sql | ||
end | ||
def build(attributes = {}) | ||
load_target | ||
17 | | |
11 | record = @reflection.klass.new(attributes) | |
@target << record | ||
record | ||
end | ||
... | ... | |
options = Base.send(:extract_options_from_args!, args) | ||
# If using a custom finder_sql, scan the entire collection. | ||
30 | | |
24 | if @reflection.options[:finder_sql] | |
expects_array = args.first.kind_of?(Array) | ||
ids = args.flatten.compact.uniq | ||
... | ... | |
end | ||
else | ||
conditions = "#{@finder_sql}" | ||
37 | ||
if sanitized_conditions = sanitize_sql(options[:conditions]) | ||
conditions << " AND (#{sanitized_conditions})" | ||
end | ||
41 | ||
options[:conditions] = conditions | ||
47 | | |
48 | | |
43 | options[:joins] = @join_sql | |
44 | options[:readonly] = finding_with_ambigious_select?(options[:select]) | |
50 | | |
51 | | |
52 | | |
53 | | |
46 | if options[:order] && @reflection.options[:order] | |
47 | options[:order] = "#{options[:order]}, #{@reflection.options[:order]}" | |
48 | elsif @reflection.options[:order] | |
49 | options[:order] = @reflection.options[:order] | |
end | ||
52 | merge_options_from_reflection!(options) | |
53 | ||
# Pass through args exactly as we received them. | ||
args << options | ||
58 | | |
56 | @reflection.klass.find(*args) | |
end | ||
end | ||
def push_with_attributes(record, join_attributes = {}) | ||
raise_on_type_mismatch(record) | ||
join_attributes.each { |key, value| record[key.to_s] = value } | ||
63 | ||
callback(:before_add, record) | ||
insert_record(record) unless @owner.new_record? | ||
@target << record | ||
callback(:after_add, record) | ||
68 | ||
self | ||
end | ||
alias :concat_with_attributes :push_with_attributes | ||
def size | ||
75 | | |
75 | @reflection.options[:uniq] ? count_records : super | |
end | ||
protected | ||
def method_missing(method, *args, &block) | ||
80 | | |
80 | if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method)) | |
super | ||
else | ||
83 | | |
84 | | |
83 | @reflection.klass.with_scope(:find => { :conditions => @finder_sql, :joins => @join_sql, :readonly => false }) do | |
84 | @reflection.klass.send(method, *args, &block) | |
end | ||
end | ||
end | ||
def find_target | ||
90 | | |
91 | | |
90 | if @reflection.options[:finder_sql] | |
91 | records = @reflection.klass.find_by_sql(@finder_sql) | |
else | ||
93 | | |
93 | records = find(:all) | |
end | ||
96 | | |
96 | @reflection.options[:uniq] ? uniq(records) : records | |
end | ||
def count_records | ||
... | ... | |
return false unless record.save | ||
end | ||
108 | | |
109 | | |
108 | if @reflection.options[:insert_sql] | |
109 | @owner.connection.execute(interpolate_sql(@reflection.options[:insert_sql], record)) | |
else | ||
111 | | |
111 | columns = @owner.connection.columns(@reflection.options[:join_table], "#{@reflection.options[:join_table]} Columns") | |
attributes = columns.inject({}) do |attributes, column| | ||
case column.name | ||
115 | | |
115 | when @reflection.primary_key_name | |
attributes[column.name] = @owner.quoted_id | ||
117 | | |
117 | when @reflection.association_foreign_key | |
attributes[column.name] = record.quoted_id | ||
else | ||
if record.attributes.has_key?(column.name) | ||
... | ... | |
end | ||
sql = | ||
129 | | |
129 | "INSERT INTO #{@reflection.options[:join_table]} (#{@owner.send(:quoted_column_names, attributes).join(', ')}) " + | |
"VALUES (#{attributes.values.join(', ')})" | ||
@owner.connection.execute(sql) | ||
... | ... | |
end | ||
def delete_records(records) | ||
139 | | |
139 | if sql = @reflection.options[:delete_sql] | |
records.each { |record| @owner.connection.execute(interpolate_sql(sql, record)) } | ||
else | ||
ids = quoted_record_ids(records) | ||
143 | | |
143 | sql = "DELETE FROM #{@reflection.options[:join_table]} WHERE #{@reflection.primary_key_name} = #{@owner.quoted_id} AND #{@reflection.association_foreign_key} IN (#{ids})" | |
@owner.connection.execute(sql) | ||
end | ||
end | ||
147 | ||
147 | ||
def construct_sql | ||
149 | | |
149 | interpolate_sql_options!(@reflection.options, :finder_sql) | |
151 | | |
152 | | |
151 | if @reflection.options[:finder_sql] | |
152 | @finder_sql = @reflection.options[:finder_sql] | |
else | ||
154 | | |
155 | | |
154 | @finder_sql = "#{@reflection.options[:join_table]}.#{@reflection.primary_key_name} = #{@owner.quoted_id} " | |
155 | @finder_sql << " AND (#{conditions})" if conditions | |
end | ||
157 | | |
158 | | |
157 | ||
158 | @join_sql = "INNER JOIN #{@reflection.options[:join_table]} ON #{@reflection.klass.table_name}.#{@reflection.klass.primary_key} = #{@reflection.options[:join_table]}.#{@reflection.association_foreign_key}" | |
end | ||
160 | | |
160 | ||
161 | # Join tables with additional columns on top of the two foreign keys must be considered ambigious unless a select | |
162 | # clause has been explicitly defined. Otherwise you can get broken records back, if, say, the join column also has | |
163 | # and id column, which will then overwrite the id column of the records coming back. | |
164 | def finding_with_ambigious_select?(select_clause) | |
165 | !select_clause && @owner.connection.columns(@reflection.options[:join_table], "Join Table Columns").size != 2 | |
166 | end | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/associations/has_many_association.rb:
prev. | current | |
module ActiveRecord | ||
module Associations | ||
class HasManyAssociation < AssociationCollection #:nodoc: | ||
4 | | |
4 | def initialize(owner, reflection) | |
super | ||
6 | | |
7 | ||
construct_sql | ||
end | ||
def build(attributes = {}) | ||
if attributes.is_a?(Array) | ||
13 | | |
11 | attributes.collect { |attr| build(attr) } | |
else | ||
load_target | ||
16 | | |
17 | | |
14 | record = @reflection.klass.new(attributes) | |
15 | set_belongs_to_association_for(record) | |
@target << record | ||
record | ||
end | ||
... | ... | |
# DEPRECATED. | ||
def find_all(runtime_conditions = nil, orderings = nil, limit = nil, joins = nil) | ||
25 | | |
26 | | |
23 | if @reflection.options[:finder_sql] | |
24 | @reflection.klass.find_by_sql(@finder_sql) | |
else | ||
conditions = @finder_sql | ||
conditions += " AND (#{sanitize_sql(runtime_conditions)})" if runtime_conditions | ||
30 | | |
31 | | |
28 | orderings ||= @reflection.options[:order] | |
29 | @reflection.klass.find_all(conditions, orderings, limit, joins) | |
end | ||
end | ||
... | ... | |
# Count the number of associated records. All arguments are optional. | ||
def count(runtime_conditions = nil) | ||
42 | | |
43 | | |
44 | | |
45 | | |
40 | if @reflection.options[:counter_sql] | |
41 | @reflection.klass.count_by_sql(@counter_sql) | |
42 | elsif @reflection.options[:finder_sql] | |
43 | @reflection.klass.count_by_sql(@finder_sql) | |
else | ||
sql = @finder_sql | ||
sql += " AND (#{sanitize_sql(runtime_conditions)})" if runtime_conditions | ||
49 | | |
47 | @reflection.klass.count(sql) | |
end | ||
end | ||
... | ... | |
options = Base.send(:extract_options_from_args!, args) | ||
# If using a custom finder_sql, scan the entire collection. | ||
57 | | |
55 | if @reflection.options[:finder_sql] | |
expects_array = args.first.kind_of?(Array) | ||
ids = args.flatten.compact.uniq | ||
if ids.size == 1 | ||
id = ids.first | ||
record = load_target.detect { |record| id == record.id } | ||
64 | | |
62 | expects_array ? [ record ] : record | |
else | ||
load_target.select { |record| ids.include?(record.id) } | ||
end | ||
... | ... | |
end | ||
options[:conditions] = conditions | ||
75 | | |
76 | | |
77 | | |
78 | | |
73 | if options[:order] && @reflection.options[:order] | |
74 | options[:order] = "#{options[:order]}, #{@reflection.options[:order]}" | |
75 | elsif @reflection.options[:order] | |
76 | options[:order] = @reflection.options[:order] | |
end | ||
79 | merge_options_from_reflection!(options) | |
80 | ||
# Pass through args exactly as we received them. | ||
args << options | ||
83 | | |
83 | @reflection.klass.find(*args) | |
end | ||
end | ||
protected | ||
def method_missing(method, *args, &block) | ||
89 | | |
89 | if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method)) | |
super | ||
else | ||
92 | | |
92 | @reflection.klass.with_scope( | |
:find => { | ||
:conditions => @finder_sql, | ||
:joins => @join_sql, | ||
:readonly => false | ||
}, | ||
:create => { | ||
99 | | |
99 | @reflection.primary_key_name => @owner.id | |
} | ||
) do | ||
102 | | |
102 | @reflection.klass.send(method, *args, &block) | |
end | ||
end | ||
end | ||
def find_target | ||
108 | | |
109 | | |
108 | if @reflection.options[:finder_sql] | |
109 | @reflection.klass.find_by_sql(@finder_sql) | |
else | ||
111 | | |
112 | | |
113 | | |
114 | | |
115 | | |
116 | | |
117 | | |
118 | | |
111 | find(:all) | |
end | ||
end | ||
def count_records | ||
count = if has_cached_counter? | ||
@owner.send(:read_attribute, cached_counter_attribute_name) | ||
125 | | |
126 | | |
118 | elsif @reflection.options[:counter_sql] | |
119 | @reflection.klass.count_by_sql(@counter_sql) | |
else | ||
128 | | |
121 | @reflection.klass.count(@counter_sql) | |
end | ||
@target = [] and loaded if count == 0 | ||
126 | if @reflection.options[:limit] | |
127 | count = [ @reflection.options[:limit], count ].min | |
128 | end | |
129 | ||
return count | ||
end | ||
... | ... | |
end | ||
def cached_counter_attribute_name | ||
141 | | |
138 | "#{@reflection.name}_count" | |
end | ||
def insert_record(record) | ||
145 | | |
142 | set_belongs_to_association_for(record) | |
record.save | ||
end | ||
def delete_records(records) | ||
150 | | |
147 | if @reflection.options[:dependent] | |
records.each { |r| r.destroy } | ||
else | ||
ids = quoted_record_ids(records) | ||
154 | | |
155 | | |
156 | | |
151 | @reflection.klass.update_all( | |
152 | "#{@reflection.primary_key_name} = NULL", | |
153 | "#{@reflection.primary_key_name} = #{@owner.quoted_id} AND #{@reflection.klass.primary_key} IN (#{ids})" | |
) | ||
end | ||
end | ||
... | ... | |
end | ||
def construct_sql | ||
166 | | |
167 | | |
168 | | |
169 | | |
170 | | |
163 | case | |
164 | when @reflection.options[:finder_sql] | |
165 | @finder_sql = interpolate_sql(@reflection.options[:finder_sql]) | |
166 | ||
167 | when @reflection.options[:as] | |
168 | @finder_sql = | |
169 | "#{@reflection.klass.table_name}.#{@reflection.options[:as]}_id = #{@owner.quoted_id} AND " + | |
170 | "#{@reflection.klass.table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote @owner.class.base_class.name.to_s}" | |
171 | @finder_sql << " AND (#{conditions})" if conditions | |
172 | ||
173 | else | |
174 | @finder_sql = "#{@reflection.klass.table_name}.#{@reflection.primary_key_name} = #{@owner.quoted_id}" | |
175 | @finder_sql << " AND (#{conditions})" if conditions | |
end | ||
173 | | |
174 | | |
175 | | |
176 | | |
177 | | |
178 | if @reflection.options[:counter_sql] | |
179 | @counter_sql = interpolate_sql(@reflection.options[:counter_sql]) | |
180 | elsif @reflection.options[:finder_sql] | |
181 | # replace the SELECT clause with COUNT(*), preserving any hints within /* ... */ | |
182 | @reflection.options[:counter_sql] = @reflection.options[:finder_sql].sub(/SELECT (\/\*.*?\*\/ )?(.*)\bFROM\b/im) { "SELECT #{$1}COUNT(*) FROM" } | |
183 | @counter_sql = interpolate_sql(@reflection.options[:counter_sql]) | |
else | ||
179 | | |
180 | | |
185 | @counter_sql = @finder_sql | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/associations/has_one_association.rb:
prev. | current | |
module ActiveRecord | ||
module Associations | ||
class HasOneAssociation < BelongsToAssociation #:nodoc: | ||
4 | | |
4 | def initialize(owner, reflection) | |
super | ||
6 | ||
construct_sql | ||
end | ||
... | ... | |
end | ||
def build(attributes = {}, replace_existing = true) | ||
17 | | |
16 | record = @reflection.klass.new(attributes) | |
if replace_existing | ||
replace(record, true) | ||
else | ||
22 | | |
21 | record[@reflection.primary_key_name] = @owner.id unless @owner.new_record? | |
self.target = record | ||
end | ||
... | ... | |
def replace(obj, dont_save = false) | ||
load_target | ||
30 | ||
unless @target.nil? | ||
if dependent? && !dont_save && @target != obj | ||
@target.destroy unless @target.new_record? | ||
@owner.clear_association_cache | ||
else | ||
36 | | |
37 | | |
36 | @target[@reflection.primary_key_name] = nil | |
37 | @target.save unless @owner.new_record? || @target.new_record? | |
end | ||
end | ||
... | ... | |
@target = nil | ||
else | ||
raise_on_type_mismatch(obj) | ||
45 | | |
46 | | |
45 | set_belongs_to_association_for(obj) | |
@target = (AssociationProxy === obj ? obj.target : obj) | ||
end | ||
@loaded = true | ||
50 | ||
unless @owner.new_record? or obj.nil? or dont_save | ||
return (obj.save ? self : false) | ||
else | ||
... | ... | |
private | ||
def find_target | ||
60 | | |
60 | @reflection.klass.find(:first, | |
61 | :conditions => @finder_sql, | |
62 | :order => @reflection.options[:order], | |
63 | :include => @reflection.options[:include] | |
64 | ) | |
end | ||
63 | | |
64 | | |
65 | | |
66 | ||
def construct_sql | ||
68 | | |
69 | | |
70 | | |
68 | case | |
69 | when @reflection.options[:as] | |
70 | @finder_sql = | |
71 | "#{@reflection.klass.table_name}.#{@reflection.options[:as]}_id = #{@owner.quoted_id} AND " + | |
72 | "#{@reflection.klass.table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote @owner.class.base_class.name.to_s}" | |
73 | else | |
74 | @finder_sql = "#{@reflection.table_name}.#{@reflection.primary_key_name} = #{@owner.quoted_id}" | |
75 | end | |
76 | @finder_sql << " AND (#{conditions})" if conditions | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/base.rb:
prev. | current | |
end | ||
class RecordNotFound < ActiveRecordError #:nodoc: | ||
end | ||
24 | class RecordNotSaved < ActiveRecordError #:nodoc: | |
25 | end | |
class StatementInvalid < ActiveRecordError #:nodoc: | ||
end | ||
class PreparedStatementInvalid < ActiveRecordError #:nodoc: | ||
... | ... | |
# Accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then passed | ||
# on to any new database connections made and which can be retrieved on both a class and instance level by calling +logger+. | ||
cattr_accessor :logger | ||
245 | ||
247 | ||
248 | include Reloadable::Subclasses | |
249 | ||
def self.inherited(child) #:nodoc: | ||
@@subclasses[self] ||= [] | ||
@@subclasses[self] << child | ||
super | ||
end | ||
252 | | |
253 | | |
254 | | |
255 | | |
256 | | |
257 | | |
258 | | |
259 | ||
260 | | |
256 | def self.reset_subclasses #:nodoc: | |
nonreloadables = [] | ||
subclasses.each do |klass| | ||
unless klass.reloadable? | ||
... | ... | |
# This is set to :local by default. | ||
cattr_accessor :default_timezone | ||
@@default_timezone = :local | ||
313 | | |
309 | ||
# Determines whether or not to use a connection for each thread, or a single shared connection for all threads. | ||
315 | | |
311 | # Defaults to false. Set to true if you're writing a threaded application. | |
cattr_accessor :allow_concurrency | ||
317 | | |
318 | | |
313 | @@allow_concurrency = false | |
314 | ||
# Determines whether to speed up access by generating optimized reader | ||
# methods to avoid expensive calls to method_missing when accessing | ||
# attributes by name. You might want to set this to false in development | ||
... | ... | |
# supports migrations. Use :ruby if you want to have different database | ||
# adapters for, e.g., your development and test environments. | ||
cattr_accessor :schema_format | ||
333 | | |
329 | @@schema_format = :ruby | |
class << self # Class methods | ||
# Find operates with three different retrieval approaches: | ||
... | ... | |
# Person.find(:all, :group => "category") | ||
def find(*args) | ||
options = extract_options_from_args!(args) | ||
376 | validate_find_options(options) | |
377 | set_readonly_option!(options) | |
381 | | |
382 | | |
383 | | |
384 | | |
385 | | |
386 | | |
387 | | |
388 | | |
389 | | |
390 | ||
case args.first | ||
392 | | |
393 | | |
394 | | |
395 | | |
396 | | |
397 | | |
398 | | |
399 | | |
400 | | |
401 | | |
402 | | |
403 | ||
404 | | |
405 | | |
406 | | |
407 | | |
408 | | |
409 | | |
410 | | |
411 | | |
412 | | |
413 | | |
414 | | |
415 | | |
416 | | |
417 | | |
418 | | |
419 | | |
420 | | |
421 | | |
422 | | |
423 | | |
380 | when :first then find_initial(options) | |
381 | when :all then find_every(options) | |
382 | else find_from_ids(args, options) | |
end | ||
end | ||
426 | ||
385 | ||
# Works like find(:all), but requires a complete SQL string. Examples: | ||
# Post.find_by_sql "SELECT p.*, c.author FROM posts p, comments c WHERE p.id = c.post_id" | ||
# Post.find_by_sql ["SELECT * FROM posts WHERE author = ? AND created > ?", author_id, start_date] | ||
... | ... | |
if attributes.is_a?(Array) | ||
attributes.collect { |attr| create(attr) } | ||
else | ||
447 | | |
448 | ||
object = new(attributes) | ||
407 | scope(:create).each { |att,value| object.send("#{att}=", value) } if scoped?(:create) | |
object.save | ||
object | ||
end | ||
... | ... | |
# Finds the record from the passed +id+, instantly saves it with the passed +attributes+ (if the validation permits it), | ||
# and returns it. If the save fails under validations, the unsaved object is still returned. | ||
415 | # | |
416 | # The arguments may also be given as arrays in which case the update method is called for each pair of +id+ and | |
417 | # +attributes+ and an array of objects is returned. | |
418 | # | |
419 | # Example of updating one record: | |
420 | # Person.update(15, {:user_name => 'Samuel', :group => 'expert'}) | |
421 | # | |
422 | # Example of updating multiple records: | |
423 | # people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy"} } | |
424 | # Person.update(people.keys, people.values) | |
def update(id, attributes) | ||
if id.is_a?(Array) | ||
idx = -1 | ||
... | ... | |
# Billing.update_all "category = 'authorized', approved = 1", "author = 'David'" | ||
def update_all(updates, conditions = nil) | ||
sql = "UPDATE #{table_name} SET #{sanitize_sql(updates)} " | ||
485 | | |
453 | add_conditions!(sql, conditions, scope(:find)) | |
connection.update(sql, "#{name} Update") | ||
end | ||
... | ... | |
# Post.delete_all "person_id = 5 AND (category = 'Something' OR category = 'Else')" | ||
def delete_all(conditions = nil) | ||
sql = "DELETE FROM #{table_name} " | ||
501 | | |
469 | add_conditions!(sql, conditions, scope(:find)) | |
connection.delete(sql, "#{name} Delete all") | ||
end | ||
505 | | |
506 | | |
507 | | |
508 | | |
509 | | |
510 | | |
511 | | |
512 | | |
513 | ||
# Returns the result of an SQL statement that should only include a COUNT(*) in the SELECT part. | ||
# Product.count_by_sql "SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id" | ||
def count_by_sql(sql) | ||
... | ... | |
update_all "#{counter_name} = #{counter_name} - 1", "#{primary_key} = #{quote(id)}" | ||
end | ||
494 | ||
# Attributes named in this macro are protected from mass-assignment, such as <tt>new(attributes)</tt> and | ||
# <tt>attributes=(attributes)</tt>. Their assignment will simply be ignored. Instead, you can use the direct writer | ||
# methods to do assignment. This is meant to protect sensitive attributes from being overwritten by URL/form hackers. Example: | ||
... | ... | |
read_inheritable_attribute("attr_accessible") | ||
end | ||
532 | ||
# Specifies that the attribute by the name of +attr_name+ should be serialized before saving to the database and unserialized | ||
# after loading from the database. The serialization is done through YAML. If +class_name+ is specified, the serialized | ||
# object must be of that class on retrieval or +SerializationTypeMismatch+ will be raised. | ||
... | ... | |
read_inheritable_attribute("attr_serialized") or write_inheritable_attribute("attr_serialized", {}) | ||
end | ||
545 | ||
# Guesses the table name (in forced lower-case) based on the name of the class in the inheritance hierarchy descending | ||
# directly from ActiveRecord. So if the hierarchy looks like: Reply < Message < ActiveRecord, then Message is used | ||
# to guess the table name from even when called on Reply. The rules used to do the guess are handled by the Inflector class | ||
... | ... | |
reset_table_name | ||
end | ||
602 | | |
603 | | |
604 | | |
564 | def reset_table_name #:nodoc: | |
565 | name = "#{table_name_prefix}#{undecorated_table_name(base_class.name)}#{table_name_suffix}" | |
566 | set_table_name(name) | |
name | ||
end | ||
... | ... | |
reset_primary_key | ||
end | ||
614 | | |
576 | def reset_primary_key #:nodoc: | |
key = 'id' | ||
case primary_key_prefix_type | ||
when :table_name | ||
618 | | |
580 | key = Inflector.foreign_key(base_class.name, false) | |
when :table_name_with_underscore | ||
620 | | |
582 | key = Inflector.foreign_key(base_class.name) | |
end | ||
set_primary_key(key) | ||
key | ||
... | ... | |
# Lazy-set the sequence name to the connection's default. This method | ||
# is only ever called once since set_sequence_name overrides it. | ||
633 | | |
595 | def sequence_name #:nodoc: | |
reset_sequence_name | ||
end | ||
637 | | |
599 | def reset_sequence_name #:nodoc: | |
default = connection.default_sequence_name(table_name, primary_key) | ||
set_sequence_name(default) | ||
default | ||
... | ... | |
# class Project < ActiveRecord::Base | ||
# set_table_name "project" | ||
# end | ||
651 | | |
613 | def set_table_name(value = nil, &block) | |
define_attr_method :table_name, value, &block | ||
end | ||
alias :table_name= :set_table_name | ||
... | ... | |
# class Project < ActiveRecord::Base | ||
# set_primary_key "sysid" | ||
# end | ||
665 | | |
627 | def set_primary_key(value = nil, &block) | |
define_attr_method :primary_key, value, &block | ||
end | ||
alias :primary_key= :set_primary_key | ||
... | ... | |
# original_inheritance_column + "_id" | ||
# end | ||
# end | ||
681 | | |
643 | def set_inheritance_column(value = nil, &block) | |
define_attr_method :inheritance_column, value, &block | ||
end | ||
alias :inheritance_column= :set_inheritance_column | ||
... | ... | |
# class Project < ActiveRecord::Base | ||
# set_sequence_name "projectseq" # default would have been "project_seq" | ||
# end | ||
702 | | |
664 | def set_sequence_name(value = nil, &block) | |
define_attr_method :sequence_name, value, &block | ||
end | ||
alias :sequence_name= :set_sequence_name | ||
... | ... | |
@columns_hash ||= columns.inject({}) { |hash, column| hash[column.name] = column; hash } | ||
end | ||
707 | # Returns an array of column names as strings. | |
def column_names | ||
@column_names ||= columns.map { |column| column.name } | ||
end | ||
... | ... | |
# Returns a hash of all the methods added to query each of the columns in the table with the name of the method as the key | ||
# and true as the value. This makes it possible to do O(1) lookups in respond_to? to check if a given method for attribute | ||
# is available. | ||
758 | | |
721 | def column_methods_hash #:nodoc: | |
@dynamic_methods_hash ||= column_names.inject(Hash.new(false)) do |methods, attr| | ||
attr_name = attr.to_s | ||
methods[attr.to_sym] = attr_name | ||
... | ... | |
end | ||
# Contains the names of the generated reader methods. | ||
770 | | |
733 | def read_methods #:nodoc: | |
@read_methods ||= Set.new | ||
end | ||
... | ... | |
end | ||
# Scope parameters to method calls within the block. Takes a hash of method_name => parameters hash. | ||
837 | | |
838 | | |
839 | | |
840 | | |
800 | # method_name may be :find or :create. :find parameters may include the <tt>:conditions</tt>, <tt>:joins</tt>, | |
801 | # <tt>:include</tt>, <tt>:offset</tt>, <tt>:limit</tt>, and <tt>:readonly</tt> options. :create parameters are an attributes hash. | |
# | ||
# Article.with_scope(:find => { :conditions => "blog_id = 1" }, :create => { :blog_id => 1 }) do | ||
# Article.find(1) # => SELECT * from articles WHERE blog_id = 1 AND id = 1 | ||
# a = Article.create(1) | ||
845 | | |
806 | # a.blog_id # => 1 | |
# end | ||
847 | | |
808 | # | |
809 | # In nested scopings, all previous parameters are overwritten by inner rule | |
810 | # except :conditions in :find, that are merged as hash. | |
811 | # | |
812 | # Article.with_scope(:find => { :conditions => "blog_id = 1", :limit => 1 }, :create => { :blog_id => 1 }) do | |
813 | # Article.with_scope(:find => { :limit => 10}) | |
814 | # Article.find(:all) # => SELECT * from articles WHERE blog_id = 1 LIMIT 10 | |
815 | # end | |
816 | # Article.with_scope(:find => { :conditions => "author_id = 3" }) | |
817 | # Article.find(:all) # => SELECT * from articles WHERE blog_id = 1 AND author_id = 3 LIMIT 1 | |
818 | # end | |
819 | # end | |
820 | # | |
821 | # You can ignore any previous scopings by using <tt>with_exclusive_scope</tt> method. | |
822 | # | |
823 | # Article.with_scope(:find => { :conditions => "blog_id = 1", :limit => 1 }) do | |
824 | # Article.with_exclusive_scope(:find => { :limit => 10 }) | |
825 | # Article.find(:all) # => SELECT * from articles LIMIT 10 | |
826 | # end | |
827 | # end | |
828 | def with_scope(method_scoping = {}, action = :merge, &block) | |
829 | method_scoping = method_scoping.method_scoping if method_scoping.respond_to?(:method_scoping) | |
830 | ||
# Dup first and second level of hash (method and params). | ||
method_scoping = method_scoping.inject({}) do |hash, (method, params)| | ||
850 | | |
833 | hash[method] = (params == true) ? params : params.dup | |
hash | ||
end | ||
854 | | |
837 | method_scoping.assert_valid_keys([ :find, :create ]) | |
838 | ||
if f = method_scoping[:find] | ||
856 | | |
840 | f.assert_valid_keys([ :conditions, :joins, :select, :include, :from, :offset, :limit, :readonly ]) | |
f[:readonly] = true if !f[:joins].blank? && !f.has_key?(:readonly) | ||
end | ||
860 | | |
844 | # Merge scopings | |
845 | if action == :merge && current_scoped_methods | |
846 | method_scoping = current_scoped_methods.inject(method_scoping) do |hash, (method, params)| | |
847 | case hash[method] | |
848 | when Hash | |
849 | if method == :find | |
850 | (hash[method].keys + params.keys).uniq.each do |key| | |
851 | merge = hash[method][key] && params[key] # merge if both scopes have the same key | |
852 | if key == :conditions && merge | |
853 | hash[method][key] = [params[key], hash[method][key]].collect{ |sql| "( %s )" % sanitize_sql(sql) }.join(" AND ") | |
854 | elsif key == :include && merge | |
855 | hash[method][key] = merge_includes(hash[method][key], params[key]).uniq | |
856 | else | |
857 | hash[method][key] = hash[method][key] || params[key] | |
858 | end | |
859 | end | |
860 | else | |
861 | hash[method] = params.merge(hash[method]) | |
862 | end | |
863 | else | |
864 | hash[method] = params | |
865 | end | |
866 | hash | |
867 | end | |
868 | end | |
862 | | |
863 | | |
864 | | |
865 | | |
870 | self.scoped_methods << method_scoping | |
871 | ||
872 | begin | |
873 | yield | |
874 | ensure | |
875 | self.scoped_methods.pop | |
876 | end | |
end | ||
879 | # Works like with_scope, but discards any nested properties. | |
880 | def with_exclusive_scope(method_scoping = {}, &block) | |
881 | with_scope(method_scoping, :overwrite, &block) | |
882 | end | |
883 | ||
# Overwrite the default class equality method to provide support for association proxies. | ||
def ===(object) | ||
object.is_a?(self) | ||
end | ||
# Deprecated | ||
874 | | |
890 | def threaded_connections #:nodoc: | |
allow_concurrency | ||
end | ||
# Deprecated | ||
879 | | |
895 | def threaded_connections=(value) #:nodoc: | |
self.allow_concurrency = value | ||
end | ||
899 | # Returns the base AR subclass that this class descends from. If A | |
900 | # extends AR::Base, A.base_class will return A. If B descends from A | |
901 | # through some arbitrarily deep hierarchy, B.base_class will return A. | |
902 | def base_class | |
903 | class_of_active_record_descendant(self) | |
904 | end | |
905 | ||
906 | # Set this to true if this is an abstract class (see #abstract_class?). | |
907 | attr_accessor :abstract_class | |
908 | ||
909 | # Returns whether this class is a base AR class. If A is a base class and | |
910 | # B descends from A, then B.base_class will return B. | |
911 | def abstract_class? | |
912 | abstract_class == true | |
913 | end | |
914 | ||
915 | private | |
916 | def find_initial(options) | |
917 | options.update(:limit => 1) unless options[:include] | |
918 | find_every(options).first | |
919 | end | |
920 | ||
921 | def find_every(options) | |
922 | records = scoped?(:find, :include) || options[:include] ? | |
923 | find_with_associations(options) : | |
924 | find_by_sql(construct_finder_sql(options)) | |
925 | ||
926 | records.each { |record| record.readonly! } if options[:readonly] | |
927 | ||
928 | records | |
929 | end | |
930 | ||
931 | def find_from_ids(ids, options) | |
932 | expects_array = ids.first.kind_of?(Array) | |
933 | return ids.first if expects_array && ids.first.empty? | |
934 | ||
935 | ids = ids.flatten.compact.uniq | |
936 | ||
937 | case ids.size | |
938 | when 0 | |
939 | raise RecordNotFound, "Couldn't find #{name} without an ID" | |
940 | when 1 | |
941 | result = find_one(ids.first, options) | |
942 | expects_array ? [ result ] : result | |
943 | else | |
944 | find_some(ids, options) | |
945 | end | |
946 | end | |
884 | | |
948 | def find_one(id, options) | |
949 | conditions = " AND (#{sanitize_sql(options[:conditions])})" if options[:conditions] | |
950 | options.update :conditions => "#{table_name}.#{primary_key} = #{sanitize(id)}#{conditions}" | |
951 | ||
952 | if result = find_initial(options) | |
953 | result | |
954 | else | |
955 | raise RecordNotFound, "Couldn't find #{name} with ID=#{id}#{conditions}" | |
956 | end | |
957 | end | |
958 | ||
959 | def find_some(ids, options) | |
960 | conditions = " AND (#{sanitize_sql(options[:conditions])})" if options[:conditions] | |
961 | ids_list = ids.map { |id| sanitize(id) }.join(',') | |
962 | options.update :conditions => "#{table_name}.#{primary_key} IN (#{ids_list})#{conditions}" | |
963 | ||
964 | result = find_every(options) | |
965 | ||
966 | if result.size == ids.size | |
967 | result | |
968 | else | |
969 | raise RecordNotFound, "Couldn't find all #{name.pluralize} with IDs (#{ids_list})#{conditions}" | |
970 | end | |
971 | end | |
972 | ||
# Finder methods must instantiate through this method to work with the single-table inheritance model | ||
# that makes it possible to create objects of different types from the same table. | ||
def instantiate(record) | ||
... | ... | |
object | ||
end | ||
912 | | |
913 | | |
1000 | # Nest the type name in the same module as this class. | |
1001 | # Bar is "MyApp::Business::Bar" relative to MyApp::Business::Foo | |
def type_name_with_module(type_name) | ||
915 | | |
1003 | (/^::/ =~ type_name) ? type_name : "#{parent.name}::#{type_name}" | |
end | ||
def construct_finder_sql(options) | ||
919 | | |
920 | | |
921 | | |
1007 | scope = scope(:find) | |
1008 | sql = "SELECT #{(scope && scope[:select]) || options[:select] || '*'} " | |
1009 | sql << "FROM #{(scope && scope[:from]) || options[:from] || table_name} " | |
1010 | ||
1011 | add_joins!(sql, options, scope) | |
1012 | add_conditions!(sql, options[:conditions], scope) | |
1013 | ||
sql << " GROUP BY #{options[:group]} " if options[:group] | ||
sql << " ORDER BY #{options[:order]} " if options[:order] | ||
924 | | |
1016 | ||
1017 | add_limit!(sql, options, scope) | |
1018 | ||
sql | ||
end | ||
928 | | |
929 | | |
930 | | |
1022 | # Merges includes so that the result is a valid +include+ | |
1023 | def merge_includes(first, second) | |
1024 | safe_to_array(first) + safe_to_array(second) | |
1025 | end | |
1026 | ||
1027 | # Object#to_a is deprecated, though it does have the desired behaviour | |
1028 | def safe_to_array(o) | |
1029 | case o | |
1030 | when NilClass | |
1031 | [] | |
1032 | when Array | |
1033 | o | |
1034 | else | |
1035 | [o] | |
1036 | end | |
1037 | end | |
1038 | ||
1039 | # The optional scope argument is for the current :find scope. | |
1040 | def add_limit!(sql, options, scope = :auto) | |
1041 | scope = scope(:find) if :auto == scope | |
1042 | if scope | |
1043 | options[:limit] ||= scope[:limit] | |
1044 | options[:offset] ||= scope[:offset] | |
1045 | end | |
connection.add_limit_offset!(sql, options) | ||
end | ||
934 | | |
935 | | |
1049 | # The optional scope argument is for the current :find scope. | |
1050 | def add_joins!(sql, options, scope = :auto) | |
1051 | scope = scope(:find) if :auto == scope | |
1052 | join = (scope && scope[:joins]) || options[:joins] | |
sql << " #{join} " if join | ||
end | ||
# Adds a sanitized version of +conditions+ to the +sql+ string. Note that the passed-in +sql+ string is changed. | ||
940 | | |
941 | | |
1057 | # The optional scope argument is for the current :find scope. | |
1058 | def add_conditions!(sql, conditions, scope = :auto) | |
1059 | scope = scope(:find) if :auto == scope | |
1060 | segments = [] | |
1061 | segments << sanitize_sql(scope[:conditions]) if scope && scope[:conditions] | |
segments << sanitize_sql(conditions) unless conditions.nil? | ||
segments << type_condition unless descends_from_active_record? | ||
segments.compact! | ||
... | ... | |
end | ||
# Guesses the table name, but does not decorate it with prefix and suffix information. | ||
958 | | |
1078 | def undecorated_table_name(class_name = base_class.name) | |
table_name = Inflector.underscore(Inflector.demodulize(class_name)) | ||
table_name = Inflector.pluralize(table_name) if pluralize_table_names | ||
table_name | ||
... | ... | |
# is actually find_all_by_amount(amount, options). | ||
def method_missing(method_id, *arguments) | ||
if match = /find_(all_by|by)_([_a-zA-Z]\w*)/.match(method_id.to_s) | ||
972 | | |
1092 | finder, deprecated_finder = determine_finder(match), determine_deprecated_finder(match) | |
attribute_names = extract_attribute_names_from_match(match) | ||
super unless all_attributes_exists?(attribute_names) | ||
conditions = construct_conditions_from_arguments(attribute_names, arguments) | ||
979 | | |
980 | | |
981 | | |
982 | | |
1099 | case extra_options = arguments[attribute_names.size] | |
1100 | when nil | |
1101 | options = { :conditions => conditions } | |
1102 | set_readonly_option!(options) | |
1103 | send(finder, options) | |
1104 | ||
1105 | when Hash | |
1106 | finder_options = extra_options.merge(:conditions => conditions) | |
1107 | validate_find_options(finder_options) | |
1108 | set_readonly_option!(finder_options) | |
1109 | ||
1110 | if extra_options[:conditions] | |
1111 | with_scope(:find => { :conditions => extra_options[:conditions] }) do | |
1112 | send(finder, finder_options) | |
1113 | end | |
1114 | else | |
1115 | send(finder, finder_options) | |
1116 | end | |
1117 | ||
1118 | else | |
1119 | send(deprecated_finder, conditions, *arguments[attribute_names.length..-1]) # deprecated API | |
end | ||
elsif match = /find_or_create_by_([_a-zA-Z]\w*)/.match(method_id.to_s) | ||
attribute_names = extract_attribute_names_from_match(match) | ||
super unless all_attributes_exists?(attribute_names) | ||
988 | | |
989 | | |
1125 | options = { :conditions => construct_conditions_from_arguments(attribute_names, arguments) } | |
1126 | set_readonly_option!(options) | |
1127 | find_initial(options) || create(construct_attributes_from_arguments(attribute_names, arguments)) | |
else | ||
super | ||
end | ||
end | ||
def determine_finder(match) | ||
996 | | |
1134 | match.captures.first == 'all_by' ? :find_every : :find_initial | |
end | ||
1137 | def determine_deprecated_finder(match) | |
1138 | match.captures.first == 'all_by' ? :find_all : :find_first | |
1139 | end | |
1140 | ||
def extract_attribute_names_from_match(match) | ||
match.captures.last.split('_and_') | ||
end | ||
... | ... | |
end | ||
protected | ||
1058 | | |
1200 | def subclasses #:nodoc: | |
@@subclasses[self] ||= [] | ||
@@subclasses[self] + extra = @@subclasses[self].inject([]) {|list, subclass| list + subclass.subclasses } | ||
end | ||
# Test whether the given method and optional key are scoped. | ||
1064 | | |
1065 | | |
1206 | def scoped?(method, key = nil) #:nodoc: | |
1207 | if current_scoped_methods && (scope = current_scoped_methods[method]) | |
1208 | !key || scope.has_key?(key) | |
1209 | end | |
end | ||
# Retrieve the scope for the given method and optional key. | ||
1069 | | |
1070 | | |
1213 | def scope(method, key = nil) #:nodoc: | |
1214 | if current_scoped_methods && (scope = current_scoped_methods[method]) | |
key ? scope[key] : scope | ||
end | ||
end | ||
1075 | | |
1076 | | |
1077 | | |
1078 | | |
1079 | | |
1080 | | |
1081 | | |
1219 | def thread_safe_scoped_methods #:nodoc: | |
1220 | scoped_methods = (Thread.current[:scoped_methods] ||= {}) | |
1221 | scoped_methods[self] ||= [] | |
end | ||
1083 | ||
1084 | | |
1085 | | |
1086 | | |
1087 | | |
1088 | | |
1089 | | |
1090 | | |
1223 | ||
1224 | def single_threaded_scoped_methods #:nodoc: | |
1225 | @scoped_methods ||= [] | |
end | ||
1227 | ||
1228 | # pick up the correct scoped_methods version from @@allow_concurrency | |
1229 | if @@allow_concurrency | |
1230 | alias_method :scoped_methods, :thread_safe_scoped_methods | |
1231 | else | |
1232 | alias_method :scoped_methods, :single_threaded_scoped_methods | |
1233 | end | |
1234 | ||
1235 | def current_scoped_methods #:nodoc: | |
1236 | scoped_methods.last | |
1237 | end | |
# Returns the class type of the record using the current module as a prefix. So descendents of | ||
# MyApp::Business::Account would appear as MyApp::Business::AccountSubclass. | ||
def compute_type(type_name) | ||
1096 | | |
1097 | | |
1242 | modularized_name = type_name_with_module(type_name) | |
1243 | begin | |
1244 | instance_eval(modularized_name) | |
1245 | rescue NameError => e | |
1246 | instance_eval(type_name) | |
end | ||
end | ||
1101 | | |
1102 | | |
1103 | | |
1104 | | |
1250 | # Returns the class descending directly from ActiveRecord in the inheritance hierarchy. | |
1251 | def class_of_active_record_descendant(klass) | |
1252 | if klass.superclass == Base || klass.superclass.abstract_class? | |
1253 | klass | |
elsif klass.superclass.nil? | ||
raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord" | ||
else | ||
1108 | | |
1257 | class_of_active_record_descendant(klass.superclass) | |
end | ||
end | ||
1261 | # Returns the name of the class descending directly from ActiveRecord in the inheritance hierarchy. | |
1262 | def class_name_of_active_record_descendant(klass) #:nodoc: | |
1263 | klass.base_class.name | |
1264 | end | |
1265 | ||
# Accepts an array or string. The string is returned untouched, but the array has each value | ||
# sanitized and interpolated into the sql statement. | ||
# ["name='%s' and group_id='%s'", "foo'bar", 4] returns "name='foo''bar' and group_id='4'" | ||
... | ... | |
alias_method :sanitize_conditions, :sanitize_sql | ||
1130 | | |
1284 | def replace_bind_variables(statement, values) #:nodoc: | |
raise_if_bind_arity_mismatch(statement, statement.count('?'), values.size) | ||
bound = values.dup | ||
statement.gsub('?') { quote_bound_value(bound.shift) } | ||
end | ||
1136 | | |
1137 | | |
1290 | def replace_named_bind_variables(statement, bind_vars) #:nodoc: | |
statement.gsub(/:(\w+)/) do | ||
match = $1.to_sym | ||
if bind_vars.include?(match) | ||
... | ... | |
end | ||
end | ||
1148 | | |
1301 | def quote_bound_value(value) #:nodoc: | |
if (value.respond_to?(:map) && !value.is_a?(String)) | ||
value.map { |v| connection.quote(v) }.join(',') | ||
else | ||
... | ... | |
end | ||
end | ||
1156 | | |
1309 | def raise_if_bind_arity_mismatch(statement, expected, provided) #:nodoc: | |
unless expected == provided | ||
raise PreparedStatementInvalid, "wrong number of bind variables (#{provided} for #{expected}) in: #{statement}" | ||
end | ||
end | ||
1162 | | |
1163 | | |
1164 | | |
1165 | | |
1315 | def extract_options_from_args!(args) #:nodoc: | |
1316 | args.last.is_a?(Hash) ? args.pop : {} | |
end | ||
1168 | | |
1169 | | |
1319 | VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, | |
1320 | :order, :select, :readonly, :group, :from ] | |
1321 | ||
1322 | def validate_find_options(options) #:nodoc: | |
1323 | options.assert_valid_keys(VALID_FIND_OPTIONS) | |
end | ||
1325 | ||
1326 | def set_readonly_option!(options) #:nodoc: | |
1327 | # Inherit :readonly from finder scope if set. Otherwise, | |
1328 | # if :joins is not blank then :readonly defaults to true. | |
1329 | unless options.has_key?(:readonly) | |
1330 | if scoped?(:find, :readonly) | |
1331 | options[:readonly] = scope(:find, :readonly) | |
1332 | elsif !options[:joins].blank? && !options[:select] | |
1333 | options[:readonly] = true | |
1334 | end | |
1335 | end | |
1336 | end | |
1172 | | |
1338 | def encode_quoted_value(value) #:nodoc: | |
quoted_value = connection.quote(value) | ||
quoted_value = "'#{quoted_value[1..-2].gsub(/\'/, "\\\\'")}'" if quoted_value.include?("\\\'") # (for ruby mode) " | ||
quoted_value | ||
... | ... | |
# * No record exists: Creates a new record with values matching those of the object attributes. | ||
# * A record does exist: Updates the record with values matching those of the object attributes. | ||
def save | ||
1225 | | |
1391 | raise ReadOnlyRecord if readonly? | |
create_or_update | ||
end | ||
1394 | ||
1395 | # Attempts to save the record, but instead of just returning false if it couldn't happen, it raises a | |
1396 | # RecordNotSaved exception | |
1397 | def save! | |
1398 | save || raise(RecordNotSaved) | |
1399 | end | |
# Deletes the record in the database and freezes this instance to reflect that no changes should | ||
# be made (since they can't be persisted). | ||
... | ... | |
# from this form of mass-assignment by using the +attr_protected+ macro. Or you can alternatively | ||
# specify which attributes *can* be accessed in with the +attr_accessible+ macro. Then all the | ||
# attributes not included in that won't be allowed to be mass-assigned. | ||
1331 | | |
1332 | | |
1503 | def attributes=(new_attributes) | |
1504 | return if new_attributes.nil? | |
1505 | attributes = new_attributes.dup | |
attributes.stringify_keys! | ||
multi_parameter_attributes = [] | ||
remove_attributes_protected_from_mass_assignment(attributes).each do |k, v| | ||
k.include?("(") ? multi_parameter_attributes << [ k, v ] : send(k + "=", v) | ||
end | ||
1512 | ||
assign_multiparameter_attributes(multi_parameter_attributes) | ||
end | ||
1516 | ||
# Returns a hash of all the attributes with their names as keys and clones of their objects as values. | ||
1343 | | |
1344 | | |
1518 | def attributes(options = nil) | |
1519 | attributes = clone_attributes :read_attribute | |
1520 | ||
1521 | if options.nil? | |
1522 | attributes | |
1523 | else | |
1524 | if except = options[:except] | |
1525 | except = Array(except).collect { |attribute| attribute.to_s } | |
1526 | except.each { |attribute_name| attributes.delete(attribute_name) } | |
1527 | attributes | |
1528 | elsif only = options[:only] | |
1529 | only = Array(only).collect { |attribute| attribute.to_s } | |
1530 | attributes.delete_if { |key, value| !only.include?(key) } | |
1531 | attributes | |
1532 | else | |
1533 | raise ArgumentError, "Options does not specify :except or :only (#{options.keys.inspect})" | |
1534 | end | |
1535 | end | |
end | ||
# Returns a hash of cloned attributes before typecasting and deserialization. | ||
... | ... | |
# A Person object with a name attribute can ask person.respond_to?("name"), person.respond_to?("name="), and | ||
# person.respond_to?("name?") which will all return true. | ||
def respond_to?(method, include_priv = false) | ||
1399 | | |
1590 | if @attributes.nil? | |
1591 | return super | |
1592 | elsif attr_name = self.class.column_methods_hash[method.to_sym] | |
return true if @attributes.include?(attr_name) || attr_name == self.class.primary_key | ||
return false if self.class.read_methods.include?(attr_name) | ||
elsif @attributes.include?(method_name = method.to_s) | ||
... | ... | |
@attributes.frozen? | ||
end | ||
1614 | # Records loaded through joins with piggy-back attributes will be marked as read only as they cannot be saved and return true to this query. | |
def readonly? | ||
@readonly == true | ||
end | ||
1425 | | |
1619 | def readonly! #:nodoc: | |
@readonly = true | ||
end | ||
1623 | # Builds an XML document to represent the model. Some configuration is | |
1624 | # availble through +options+, however more complicated cases should use | |
1625 | # Builder. | |
1626 | # | |
1627 | # By default the generated XML document will include the processing | |
1628 | # instruction and all object's attributes. For example: | |
1629 | # | |
1630 | # <?xml version="1.0" encoding="UTF-8"?> | |
1631 | # <topic> | |
1632 | # <title>The First Topic</title> | |
1633 | # <author-name>David</author-name> | |
1634 | # <id type="integer">1</id> | |
1635 | # <approved type="boolean">false</approved> | |
1636 | # <replies-count type="integer">0</replies-count> | |
1637 | # <bonus-time type="datetime">2000-01-01T08:28:00+12:00</bonus-time> | |
1638 | # <written-on type="datetime">2003-07-16T09:28:00+1200</written-on> | |
1639 | # <content>Have a nice day</content> | |
1640 | # <author-email-address>david@loudthinking.com</author-email-address> | |
1641 | # <parent-id></parent-id> | |
1642 | # <last-read type="date">2004-04-15</last-read> | |
1643 | # </topic> | |
1644 | # | |
1645 | # This behaviour can be controlled with :only, :except, and :skip_instruct | |
1646 | # for instance: | |
1647 | # | |
1648 | # topic.to_xml(:skip_instruct => true, :except => [ :id, bonus_time, :written_on, replies_count ]) | |
1649 | # | |
1650 | # <topic> | |
1651 | # <title>The First Topic</title> | |
1652 | # <author-name>David</author-name> | |
1653 | # <approved type="boolean">false</approved> | |
1654 | # <content>Have a nice day</content> | |
1655 | # <author-email-address>david@loudthinking.com</author-email-address> | |
1656 | # <parent-id></parent-id> | |
1657 | # <last-read type="date">2004-04-15</last-read> | |
1658 | # </topic> | |
1659 | # | |
1660 | # To include first level associations use :include | |
1661 | # | |
1662 | # firm.to_xml :include => [ :account, :clients ] | |
1663 | # | |
1664 | # <?xml version="1.0" encoding="UTF-8"?> | |
1665 | # <firm> | |
1666 | # <id type="integer">1</id> | |
1667 | # <rating type="integer">1</rating> | |
1668 | # <name>37signals</name> | |
1669 | # <clients> | |
1670 | # <client> | |
1671 | # <rating type="integer">1</rating> | |
1672 | # <name>Summit</name> | |
1673 | # </client> | |
1674 | # <client> | |
1675 | # <rating type="integer">1</rating> | |
1676 | # <name>Microsoft</name> | |
1677 | # </client> | |
1678 | # </clients> | |
1679 | # <account> | |
1680 | # <id type="integer">1</id> | |
1681 | # <credit-limit type="integer">50</credit-limit> | |
1682 | # </account> | |
1683 | # </firm> | |
1684 | def to_xml(options = {}) | |
1685 | options[:root] ||= self.class.to_s.underscore | |
1686 | options[:except] = Array(options[:except]) << self.class.inheritance_column unless options[:only] # skip type column | |
1687 | root_only_or_except = { :only => options[:only], :except => options[:except] } | |
1688 | ||
1689 | attributes_for_xml = attributes(root_only_or_except) | |
1690 | ||
1691 | if include_associations = options.delete(:include) | |
1692 | include_has_options = include_associations.is_a?(Hash) | |
1693 | ||
1694 | for association in include_has_options ? include_associations.keys : Array(include_associations) | |
1695 | association_options = include_has_options ? include_associations[association] : root_only_or_except | |
1696 | ||
1697 | case self.class.reflect_on_association(association).macro | |
1698 | when :has_many, :has_and_belongs_to_many | |
1699 | records = send(association).to_a | |
1700 | unless records.empty? | |
1701 | attributes_for_xml[association] = records.collect do |record| | |
1702 | record.attributes(association_options) | |
1703 | end | |
1704 | end | |
1705 | when :has_one, :belongs_to | |
1706 | if record = send(association) | |
1707 | attributes_for_xml[association] = record.attributes(association_options) | |
1708 | end | |
1709 | end | |
1710 | end | |
1711 | end | |
1712 | ||
1713 | attributes_for_xml.to_xml(options) | |
1714 | end | |
1715 | ||
private | ||
def create_or_update | ||
if new_record? then create else update end | ||
... | ... | |
"WHERE #{self.class.primary_key} = #{quote(id)}", | ||
"#{self.class.name} Update" | ||
) | ||
1729 | ||
1730 | return true | |
end | ||
# Creates a new record with values matching those of the instance attributes. | ||
def create | ||
1446 | | |
1735 | if self.id.nil? && connection.prefetch_primary_key?(self.class.table_name) | |
self.id = connection.next_sequence_value(self.class.sequence_name) | ||
end | ||
... | ... | |
) | ||
@new_record = false | ||
1748 | ||
1749 | return true | |
end | ||
# Sets the attribute used for single table inheritance to this class name if this is not the ActiveRecord descendent. | ||
... | ... | |
# table with a master_id foreign key can instantiate master through Client#master. | ||
def method_missing(method_id, *args, &block) | ||
method_name = method_id.to_s | ||
1481 | | |
1772 | if @attributes.include?(method_name) or | |
1773 | (md = /\?$/.match(method_name) and | |
1774 | @attributes.include?(method_name = md.pre_match)) | |
define_read_methods if self.class.read_methods.empty? && self.class.generate_read_methods | ||
1483 | | |
1776 | md ? query_attribute(method_name) : read_attribute(method_name) | |
elsif self.class.primary_key.to_s == method_name | ||
id | ||
1486 | | |
1779 | elsif md = /(=|_before_type_cast)$/.match(method_name) | |
attribute_name, method_type = md.pre_match, md.to_s | ||
if @attributes.include?(attribute_name) | ||
case method_type | ||
when '=' | ||
write_attribute(attribute_name, args.first) | ||
1492 | | |
1493 | | |
when '_before_type_cast' | ||
read_attribute_before_type_cast(attribute_name) | ||
end | ||
... | ... | |
# ActiveRecord::Base.generate_read_methods is set to true. | ||
def define_read_methods | ||
self.class.columns_hash.each do |name, column| | ||
1533 | | |
1534 | | |
1824 | unless self.class.serialized_attributes[name] | |
1825 | define_read_method(name.to_sym, name, column) unless respond_to_without_attributes?(name) | |
1826 | define_question_method(name) unless respond_to_without_attributes?("#{name}?") | |
end | ||
end | ||
end | ||
... | ... | |
def define_read_method(symbol, attr_name, column) | ||
cast_code = column.type_cast_code('v') if column | ||
access_code = cast_code ? "(v=@attributes['#{attr_name}']) && #{cast_code}" : "@attributes['#{attr_name}']" | ||
1543 | ||
1835 | ||
unless attr_name.to_s == self.class.primary_key.to_s | ||
access_code = access_code.insert(0, "raise NoMethodError, 'missing attribute: #{attr_name}', caller unless @attributes.has_key?('#{attr_name}'); ") | ||
self.class.read_methods << attr_name | ||
end | ||
1548 | ||
1840 | ||
1841 | evaluate_read_method attr_name, "def #{symbol}; #{access_code}; end" | |
1842 | end | |
1843 | ||
1844 | # Define an attribute ? method. | |
1845 | def define_question_method(attr_name) | |
1846 | unless attr_name.to_s == self.class.primary_key.to_s | |
1847 | self.class.read_methods << "#{attr_name}?" | |
1848 | end | |
1849 | ||
1850 | evaluate_read_method attr_name, "def #{attr_name}?; query_attribute('#{attr_name}'); end" | |
1851 | end | |
1852 | ||
1853 | # Evaluate the definition for an attribute reader or ? method | |
1854 | def evaluate_read_method(attr_name, method_definition) | |
begin | ||
1550 | | |
1856 | self.class.class_eval(method_definition) | |
rescue SyntaxError => err | ||
self.class.read_methods.delete(attr_name) | ||
if logger | ||
... | ... | |
def execute_callstack_for_multiparameter_attributes(callstack) | ||
errors = [] | ||
callstack.each do |name, values| | ||
1685 | | |
1991 | klass = (self.class.reflect_on_aggregation(name.to_sym) || column_for_attribute(name)).klass | |
if values.empty? | ||
send(name + "=", nil) | ||
else |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/callbacks.rb:
prev. | current | |
# * (2) before_validation_on_create | ||
# * (-) validate | ||
# * (-) validate_on_create | ||
16 | | |
17 | | |
18 | | |
19 | | |
16 | # * (3) after_validation | |
17 | # * (4) after_validation_on_create | |
18 | # * (5) before_save | |
19 | # * (6) before_create | |
# * (-) create | ||
21 | | |
22 | | |
21 | # * (7) after_create | |
22 | # * (8) after_save | |
# | ||
24 | | |
24 | # That's a total of eight callbacks, which gives you immense power to react and prepare for each state in the | |
# Active Record lifecycle. | ||
# | ||
# Examples: |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb:
prev. | current | |
1 | require 'set' | |
2 | ||
module ActiveRecord | ||
class Base | ||
class ConnectionSpecification #:nodoc: | ||
... | ... | |
end | ||
end | ||
12 | # Check for activity after at least +verification_timeout+ seconds. | |
13 | # Defaults to 0 (always check.) | |
14 | cattr_accessor :verification_timeout | |
15 | @@verification_timeout = 0 | |
16 | ||
# The class -> [adapter_method, config] map | ||
@@defined_connections = {} | ||
13 | | |
14 | | |
20 | # The class -> thread id -> adapter cache. (class -> adapter if not allow_concurrency) | |
21 | @@active_connections = {} | |
16 | | |
17 | | |
18 | | |
19 | | |
20 | | |
21 | | |
23 | class << self | |
24 | # Retrieve the connection cache. | |
25 | def thread_safe_active_connections #:nodoc: | |
26 | @@active_connections[Thread.current.object_id] ||= {} | |
27 | end | |
28 | ||
29 | def single_threaded_active_connections #:nodoc: | |
30 | @@active_connections | |
31 | end | |
32 | ||
33 | # pick up the right active_connection method from @@allow_concurrency | |
34 | if @@allow_concurrency | |
35 | alias_method :active_connections, :thread_safe_active_connections | |
36 | else | |
37 | alias_method :active_connections, :single_threaded_active_connections | |
38 | end | |
39 | ||
40 | # set concurrency support flag (not thread safe, like most of the methods in this file) | |
41 | def allow_concurrency=(threaded) #:nodoc: | |
42 | logger.debug "allow_concurrency=#{threaded}" if logger | |
43 | return if @@allow_concurrency == threaded | |
44 | clear_all_cached_connections! | |
45 | @@allow_concurrency = threaded | |
46 | method_prefix = threaded ? "thread_safe" : "single_threaded" | |
47 | sing = (class << self; self; end) | |
48 | [:active_connections, :scoped_methods].each do |method| | |
49 | sing.send(:alias_method, method, "#{method_prefix}_#{method}") | |
50 | end | |
51 | log_connections if logger | |
52 | end | |
53 | ||
54 | def active_connection_name #:nodoc: | |
55 | @active_connection_name ||= | |
56 | if active_connections[name] || @@defined_connections[name] | |
57 | name | |
58 | elsif self == ActiveRecord::Base | |
59 | nil | |
60 | else | |
61 | superclass.active_connection_name | |
62 | end | |
63 | end | |
23 | | |
24 | | |
25 | | |
65 | def clear_active_connection_name #:nodoc: | |
66 | @active_connection_name = nil | |
67 | subclasses.each { |klass| klass.clear_active_connection_name } | |
68 | end | |
69 | ||
70 | # Returns the connection currently associated with the class. This can | |
71 | # also be used to "borrow" the connection to do database work unrelated | |
72 | # to any of the specific Active Records. | |
73 | def connection | |
74 | if @active_connection_name && (conn = active_connections[@active_connection_name]) | |
75 | conn | |
76 | else | |
77 | # retrieve_connection sets the cache key. | |
78 | conn = retrieve_connection | |
79 | active_connections[@active_connection_name] = conn | |
80 | end | |
81 | end | |
82 | ||
83 | # Clears the cache which maps classes to connections. | |
84 | def clear_active_connections! | |
85 | clear_cache!(@@active_connections) do |name, conn| | |
86 | conn.disconnect! | |
87 | end | |
88 | end | |
89 | ||
90 | # Verify active connections. | |
91 | def verify_active_connections! #:nodoc: | |
92 | if @@allow_concurrency | |
93 | remove_stale_cached_threads!(@@active_connections) do |name, conn| | |
94 | conn.disconnect! | |
95 | end | |
96 | end | |
97 | ||
98 | active_connections.each_value do |connection| | |
99 | connection.verify!(@@verification_timeout) | |
100 | end | |
101 | end | |
102 | ||
103 | private | |
104 | def clear_cache!(cache, thread_id = nil, &block) | |
105 | if cache | |
106 | if @@allow_concurrency | |
107 | thread_id ||= Thread.current.object_id | |
108 | thread_cache, cache = cache, cache[thread_id] | |
109 | return unless cache | |
110 | end | |
111 | ||
112 | cache.each(&block) if block_given? | |
113 | cache.clear | |
114 | end | |
115 | ensure | |
116 | if thread_cache && @@allow_concurrency | |
117 | thread_cache.delete(thread_id) | |
118 | end | |
119 | end | |
120 | ||
121 | # Remove stale threads from the cache. | |
122 | def remove_stale_cached_threads!(cache, &block) | |
123 | stale = Set.new(cache.keys) | |
124 | ||
125 | Thread.list.each do |thread| | |
126 | stale.delete(thread.object_id) if thread.alive? | |
127 | end | |
128 | ||
129 | stale.each do |thread_id| | |
130 | clear_cache!(cache, thread_id, &block) | |
131 | end | |
132 | end | |
133 | ||
134 | def clear_all_cached_connections! | |
135 | if @@allow_concurrency | |
136 | @@active_connections.each_value do |connection_hash_for_thread| | |
137 | connection_hash_for_thread.each_value {|conn| conn.disconnect! } | |
138 | connection_hash_for_thread.clear | |
139 | end | |
140 | else | |
141 | @@active_connections.each_value {|conn| conn.disconnect! } | |
142 | end | |
143 | @@active_connections.clear | |
144 | end | |
end | ||
# Returns the connection currently associated with the class. This can | ||
... | ... | |
raise AdapterNotSpecified unless defined? RAILS_ENV | ||
establish_connection(RAILS_ENV) | ||
when ConnectionSpecification | ||
187 | clear_active_connection_name | |
188 | @active_connection_name = name | |
@@defined_connections[name] = spec | ||
when Symbol, String | ||
if configuration = configurations[spec.to_s] | ||
... | ... | |
end | ||
end | ||
85 | | |
86 | | |
87 | | |
88 | | |
89 | | |
90 | | |
91 | | |
92 | ||
# Locate the connection of the nearest super class. This can be an | ||
# active or defined connections: if it is the latter, it will be | ||
# opened and set as the active connection for the class it was defined | ||
# for (not necessarily the current class). | ||
def self.retrieve_connection #:nodoc: | ||
98 | | |
99 | | |
100 | | |
101 | | |
102 | | |
103 | | |
104 | | |
105 | | |
106 | | |
107 | | |
211 | # Name is nil if establish_connection hasn't been called for | |
212 | # some class along the inheritance chain up to AR::Base yet. | |
213 | if name = active_connection_name | |
214 | if conn = active_connections[name] | |
215 | # Verify the connection. | |
216 | conn.verify!(@@verification_timeout) | |
217 | elsif spec = @@defined_connections[name] | |
218 | # Activate this connection specification. | |
219 | klass = name.constantize | |
220 | klass.connection = spec | |
221 | conn = active_connections[name] | |
end | ||
109 | | |
end | ||
111 | | |
224 | ||
225 | conn or raise ConnectionNotEstablished | |
end | ||
# Returns true if a connection that's accessible to this class have already been opened. | ||
def self.connected? | ||
116 | | |
117 | | |
118 | | |
119 | | |
120 | | |
121 | | |
122 | | |
123 | | |
124 | | |
230 | active_connections[active_connection_name] ? true : false | |
end | ||
# Remove the connection for this class. This will close the active | ||
... | ... | |
# can be used as argument for establish_connection, for easy | ||
# re-establishing of the connection. | ||
def self.remove_connection(klass=self) | ||
132 | | |
133 | | |
134 | | |
135 | | |
136 | | |
137 | | |
238 | spec = @@defined_connections[klass.name] | |
239 | konn = active_connections[klass.name] | |
240 | @@defined_connections.delete_if { |key, value| value == spec } | |
241 | active_connections.delete_if { |key, value| value == konn } | |
242 | konn.disconnect! if konn | |
243 | spec.config if spec | |
end | ||
# Set the connection for the class. | ||
141 | | |
247 | def self.connection=(spec) #:nodoc: | |
if spec.kind_of?(ActiveRecord::ConnectionAdapters::AbstractAdapter) | ||
active_connections[name] = spec | ||
elsif spec.kind_of?(ConnectionSpecification) | ||
... | ... | |
establish_connection spec | ||
end | ||
end | ||
258 | ||
259 | # connection state logging | |
260 | def self.log_connections #:nodoc: | |
261 | if logger | |
262 | logger.info "Defined connections: #{@@defined_connections.inspect}" | |
263 | logger.info "Active connections: #{active_connections.inspect}" | |
264 | logger.info "Active connection name: #{@active_connection_name}" | |
265 | end | |
266 | end | |
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb:
prev. | current | |
def quote(value, column = nil) | ||
case value | ||
when String | ||
9 | | |
9 | if column && column.type == :binary && column.class.respond_to?(:string_to_binary) | |
"'#{quote_string(column.class.string_to_binary(value))}'" # ' (for ruby-mode) | ||
elsif column && [:integer, :float].include?(column.type) | ||
value.to_s |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb:
prev. | current | |
module ConnectionAdapters #:nodoc: | ||
# An abstract definition of a column in a table. | ||
class Column | ||
7 | | |
7 | attr_reader :name, :default, :type, :limit, :null, :sql_type | |
attr_accessor :primary | ||
# Instantiates a new column in the table. | ||
... | ... | |
# +null+ determines if this column allows +NULL+ values. | ||
def initialize(name, default, sql_type = nil, null = true) | ||
@name, @type, @null = name, simplified_type(sql_type), null | ||
18 | @sql_type = sql_type | |
# have to do this one separately because type_cast depends on #type | ||
@default = type_cast(default) | ||
@limit = extract_limit(sql_type) unless sql_type.nil? |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb:
prev. | current | |
{} | ||
end | ||
11 | # This is the maximum length a table alias can be | |
12 | def table_alias_length | |
13 | 255 | |
14 | end | |
15 | ||
16 | # Truncates a table alias according to the limits of the current adapter. | |
17 | def table_alias_for(table_name) | |
18 | table_name[0..table_alias_length-1].gsub(/\./, '_') | |
19 | end | |
20 | ||
# def tables(name = nil) end | ||
# Returns an array of indexes for the given table. | ||
... | ... | |
# The index will be named after the table and the first column names, | ||
# unless you pass +:name+ as an option. | ||
# | ||
166 | # When creating an index on multiple columns, the first column is used as a name | |
167 | # for the index. For example, when you specify an index on two columns | |
168 | # [+:first+, +:last+], the DBMS creates an index for both columns as well as an | |
169 | # index for the first colum +:first+. Using just the first name for this index | |
170 | # makes sense, because you will never have to create a singular index with this | |
171 | # name. | |
172 | # | |
# ===== Examples | ||
# ====== Creating a simple index | ||
# add_index(:suppliers, :name) | ||
... | ... | |
# remove_index :accounts, :column => :branch_id | ||
# Remove the index named by_branch_party in the accounts table. | ||
# remove_index :accounts, :name => :by_branch_party | ||
190 | | |
207 | # | |
208 | # You can remove an index on multiple columns by specifying the first column. | |
209 | # add_index :accounts, [:username, :password] | |
210 | # remove_index :accounts, :username | |
def remove_index(table_name, options = {}) | ||
execute "DROP INDEX #{index_name(table_name, options)} ON #{table_name}" | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:
prev. | current | |
class AbstractAdapter | ||
include Quoting, DatabaseStatements, SchemaStatements | ||
@@row_even = true | ||
24 | ||
24 | ||
def initialize(connection, logger = nil) #:nodoc: | ||
@connection, @logger = connection, logger | ||
@runtime = 0 | ||
28 | @last_verification = 0 | |
end | ||
# Returns the human-readable name of the adapter. Use mixed case - one | ||
... | ... | |
def supports_migrations? | ||
false | ||
end | ||
42 | ||
43 | # Does this adapter support using DISTINCT within COUNT? This is +true+ | |
44 | # for all adapters except sqlite. | |
45 | def supports_count_distinct? | |
46 | true | |
47 | end | |
# Should primary key values be selected from their corresponding | ||
# sequence before the insert statement? If true, next_sequence_value | ||
... | ... | |
# Is this connection active and ready to perform queries? | ||
def active? | ||
60 | | |
67 | @active != false | |
end | ||
# Close this connection and open a new one in its place. | ||
def reconnect! | ||
72 | @active = true | |
end | ||
75 | # Close this connection | |
76 | def disconnect! | |
77 | @active = false | |
78 | end | |
80 | # Lazily verify this connection, calling +active?+ only if it hasn't | |
81 | # been called for +timeout+ seconds. | |
82 | def verify!(timeout) | |
83 | now = Time.now.to_i | |
84 | if (now - @last_verification) > timeout | |
85 | reconnect! unless active? | |
86 | @last_verification = now | |
87 | end | |
88 | end | |
89 | ||
90 | # Provides access to the underlying database connection. Useful for | |
91 | # when you need to call a proprietary method such as postgresql's lo_* | |
92 | # methods | |
93 | def raw_connection | |
94 | @connection | |
95 | end | |
96 | ||
protected | ||
def log(sql, name) | ||
if block_given? | ||
... | ... | |
end | ||
rescue Exception => e | ||
# Log message and raise exception. | ||
115 | # Set last_verfication to 0, so that connection gets verified | |
116 | # upon reentering the request loop | |
117 | @last_verification = 0 | |
message = "#{e.class.name}: #{e.message}: #{sql}" | ||
log_info(message, name, 0) | ||
raise ActiveRecord::StatementInvalid, message |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/db2_adapter.rb:
prev. | current | |
config = config.symbolize_keys | ||
usr = config[:username] | ||
pwd = config[:password] | ||
17 | schema = config[:schema] | |
if config.has_key?(:database) | ||
database = config[:database] | ||
else | ||
21 | | |
22 | raise ArgumentError, 'No database specified. Missing argument: database.' | |
end | ||
connection = DB2::Connection.new(DB2::Environment.new) | ||
connection.connect(database, usr, pwd) | ||
26 | | |
27 | ConnectionAdapters::DB2Adapter.new(connection, logger, :schema => schema) | |
end | ||
end | ||
... | ... | |
# * <tt>:username</tt> -- Defaults to nothing | ||
# * <tt>:password</tt> -- Defaults to nothing | ||
# * <tt>:database</tt> -- The name of the database. No default, must be provided. | ||
39 | # * <tt>:schema</tt> -- Database schema to be set initially. | |
class DB2Adapter < AbstractAdapter | ||
41 | def initialize(connection, logger, connection_options) | |
42 | super(connection, logger) | |
43 | @connection_options = connection_options | |
44 | if schema = @connection_options[:schema] | |
45 | with_statement do |stmt| | |
46 | stmt.exec_direct("SET SCHEMA=#{schema}") | |
47 | end | |
48 | end | |
49 | end | |
50 | ||
def select_all(sql, name = nil) | ||
select(sql, name) | ||
end | ||
... | ... | |
def execute(sql, name = nil) | ||
rows_affected = 0 | ||
54 | ||
55 | | |
56 | | |
57 | | |
58 | | |
59 | | |
66 | with_statement do |stmt| | |
67 | log(sql, name) do | |
68 | stmt.exec_direct(sql) | |
69 | rows_affected = stmt.row_count | |
70 | end | |
end | ||
61 | ||
rows_affected | ||
end | ||
... | ... | |
end | ||
def add_limit_offset!(sql, options) | ||
95 | | |
96 | | |
97 | | |
98 | | |
99 | | |
100 | | |
101 | | |
102 | | |
103 | | |
104 | | |
105 | | |
106 | | |
107 | | |
108 | | |
109 | | |
105 | if limit = options[:limit] | |
106 | offset = options[:offset] || 0 | |
107 | # The following trick was added by andrea+rails@webcom.it. | |
108 | sql.gsub!(/SELECT/i, 'SELECT B.* FROM (SELECT A.*, row_number() over () AS internal$rownum FROM (SELECT') | |
109 | sql << ") A ) B WHERE B.internal$rownum > #{offset} AND B.internal$rownum <= #{limit + offset}" | |
end | ||
111 | | |
112 | | |
113 | | |
end | ||
def tables(name = nil) | ||
117 | | |
result = [] | ||
119 | | |
120 | | |
115 | schema = @connection_options[:schema] || '%' | |
116 | with_statement do |stmt| | |
117 | stmt.tables(schema).each { |t| result << t[2].downcase } | |
118 | end | |
result | ||
end | ||
122 | def indexes(table_name, name = nil) | |
123 | tmp = {} | |
124 | schema = @connection_options[:schema] || '' | |
125 | with_statement do |stmt| | |
126 | stmt.indexes(table_name, schema).each do |t| | |
127 | next unless t[5] | |
128 | next if t[4] == 'SYSIBM' # Skip system indexes. | |
129 | idx_name = t[5].downcase | |
130 | col_name = t[8].downcase | |
131 | if tmp.has_key?(idx_name) | |
132 | tmp[idx_name].columns << col_name | |
133 | else | |
134 | is_unique = t[3] == 0 | |
135 | tmp[idx_name] = IndexDefinition.new(table_name, idx_name, is_unique, [col_name]) | |
136 | end | |
137 | end | |
138 | end | |
139 | tmp.values | |
140 | end | |
141 | ||
def columns(table_name, name = nil) | ||
125 | | |
result = [] | ||
127 | ||
128 | | |
129 | | |
130 | | |
131 | | |
132 | | |
133 | | |
134 | | |
135 | ||
136 | | |
144 | schema = @connection_options[:schema] || '%' | |
145 | with_statement do |stmt| | |
146 | stmt.columns(table_name, schema).each do |c| | |
147 | c_name = c[3].downcase | |
148 | c_default = c[12] == 'NULL' ? nil : c[12] | |
149 | c_default.gsub!(/^'(.*)'$/, '\1') if !c_default.nil? | |
150 | c_type = c[5].downcase | |
151 | c_type += "(#{c[6]})" if !c[6].nil? && c[6] != '' | |
152 | result << Column.new(c_name, c_default, c_type, c[17] == 'YES') | |
153 | end | |
154 | end | |
result | ||
end | ||
def native_database_types | ||
{ | ||
142 | | |
143 | | |
144 | | |
145 | | |
146 | | |
147 | | |
148 | | |
149 | | |
150 | | |
151 | | |
152 | | |
160 | :primary_key => 'int generated by default as identity (start with 42) primary key', | |
161 | :string => { :name => 'varchar', :limit => 255 }, | |
162 | :text => { :name => 'clob', :limit => 32768 }, | |
163 | :integer => { :name => 'int' }, | |
164 | :float => { :name => 'float' }, | |
165 | :datetime => { :name => 'timestamp' }, | |
166 | :timestamp => { :name => 'timestamp' }, | |
167 | :time => { :name => 'time' }, | |
168 | :date => { :name => 'date' }, | |
169 | :binary => { :name => 'blob', :limit => 32768 }, | |
170 | :boolean => { :name => 'decimal', :limit => 1 } | |
} | ||
end | ||
... | ... | |
'0' | ||
end | ||
182 | def active? | |
183 | @connection.select_one 'select 1 from ibm.sysdummy1' | |
184 | true | |
185 | rescue Exception | |
186 | false | |
187 | end | |
188 | ||
189 | def reconnect! | |
190 | end | |
191 | ||
192 | def table_alias_length | |
193 | 128 | |
194 | end | |
195 | ||
private | ||
198 | def with_statement | |
199 | stmt = DB2::Statement.new(@connection) | |
200 | yield stmt | |
201 | stmt.free | |
202 | end | |
203 | ||
def last_insert_id | ||
row = select_one(<<-GETID.strip) | ||
with temp(id) as (values (identity_val_local())) select * from temp | ||
... | ... | |
end | ||
def select(sql, name = nil) | ||
174 | | |
175 | | |
176 | | |
177 | | |
178 | | |
212 | rows = [] | |
213 | with_statement do |stmt| | |
214 | log(sql, name) do | |
215 | stmt.exec_direct("#{sql.gsub(/=\s*null/i, 'IS NULL')} with ur") | |
216 | end | |
180 | | |
181 | | |
182 | | |
218 | while row = stmt.fetch_as_hash | |
219 | row.delete('internal$rownum') | |
220 | rows << row | |
221 | end | |
end | ||
184 | | |
rows | ||
end | ||
end | ||
... | ... | |
end | ||
rescue LoadError | ||
# DB2 driver is unavailable. | ||
230 | module ActiveRecord # :nodoc: | |
231 | class Base | |
232 | def self.db2_connection(config) # :nodoc: | |
233 | # Set up a reasonable error message | |
234 | raise LoadError, "DB2 Libraries could not be loaded." | |
235 | end | |
236 | end | |
237 | end | |
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb:
prev. | current | |
class MysqlColumn < Column #:nodoc: | ||
private | ||
def simplified_type(field_type) | ||
45 | | |
45 | return :boolean if MysqlAdapter.emulate_booleans && field_type.downcase.index("tinyint(1)") | |
46 | return :string if field_type =~ /enum/i | |
super | ||
end | ||
end | ||
... | ... | |
# QUOTING ================================================== | ||
def quote(value, column = nil) | ||
118 | | |
119 | if value.kind_of?(String) && column && column.type == :binary && column.class.respond_to?(:string_to_binary) | |
s = column.class.string_to_binary(value).unpack("H*")[0] | ||
"x'#{s}'" | ||
else | ||
... | ... | |
end | ||
def reconnect! | ||
163 | | |
164 | disconnect! | |
connect | ||
end | ||
167 | ||
168 | def disconnect! | |
169 | @connection.close rescue nil | |
170 | end | |
# DATABASE STATEMENTS ====================================== | ||
... | ... | |
# SCHEMA STATEMENTS ======================================== | ||
def structure_dump #:nodoc: | ||
235 | | |
240 | if supports_views? | |
241 | sql = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'" | |
242 | else | |
243 | sql = "SHOW TABLES" | |
244 | end | |
245 | ||
246 | select_all(sql).inject("") do |structure, table| | |
247 | table.delete('Table_type') | |
structure += select_one("SHOW CREATE TABLE #{table.to_a.first.last}")["Create Table"] + ";\n\n" | ||
end | ||
end | ||
... | ... | |
end | ||
def create_database(name) #:nodoc: | ||
246 | | |
258 | execute "CREATE DATABASE `#{name}`" | |
end | ||
def drop_database(name) #:nodoc: | ||
250 | | |
262 | execute "DROP DATABASE IF EXISTS `#{name}`" | |
end | ||
265 | def current_database | |
266 | select_one("SELECT DATABASE() as db")["db"] | |
267 | end | |
def tables(name = nil) #:nodoc: | ||
tables = [] | ||
... | ... | |
result.free | ||
rows | ||
end | ||
348 | ||
349 | def supports_views? | |
350 | version[0] >= 5 | |
351 | end | |
352 | ||
353 | def version | |
354 | @version ||= @connection.server_info.scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i } | |
355 | end | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:
prev. | current | |
PGconn.connect(host, port, "", "", database, username, password), logger, config | ||
) | ||
27 | PGconn.translate_results = false if PGconn.respond_to? :translate_results= | |
28 | ||
pga.schema_search_path = config[:schema_search_path] || config[:schema_order] | ||
pga | ||
... | ... | |
@connection.query 'SELECT 1' | ||
true | ||
end | ||
66 | | |
67 | | |
68 | # postgres-pr raises a NoMethodError when querying if no conn is available | |
69 | rescue PGError, NoMethodError | |
70 | false | |
end | ||
# Close then reopen the connection. | ||
... | ... | |
configure_connection | ||
end | ||
end | ||
81 | ||
82 | def disconnect! | |
83 | # Both postgres and postgres-pr respond to :close | |
84 | @connection.close rescue nil | |
85 | end | |
def native_database_types | ||
{ | ||
... | ... | |
true | ||
end | ||
107 | def table_alias_length | |
108 | 63 | |
109 | end | |
# QUOTING ================================================== | ||
... | ... | |
end | ||
def add_column(table_name, column_name, type, options = {}) | ||
299 | | |
300 | | |
301 | | |
302 | | |
303 | | |
304 | | |
305 | | |
306 | | |
307 | | |
310 | execute("ALTER TABLE #{table_name} ADD #{column_name} #{type_to_sql(type, options[:limit])}") | |
311 | execute("ALTER TABLE #{table_name} ALTER #{column_name} SET NOT NULL") if options[:null] == false | |
312 | change_column_default(table_name, column_name, options[:default]) unless options[:default].nil? | |
end | ||
def change_column(table_name, column_name, type, options = {}) #:nodoc: | ||
311 | | |
316 | begin | |
317 | execute "ALTER TABLE #{table_name} ALTER #{column_name} TYPE #{type_to_sql(type, options[:limit])}" | |
318 | rescue ActiveRecord::StatementInvalid | |
319 | # This is PG7, so we use a more arcane way of doing it. | |
320 | begin_db_transaction | |
321 | add_column(table_name, "#{column_name}_ar_tmp", type, options) | |
322 | execute "UPDATE #{table_name} SET #{column_name}_ar_tmp = CAST(#{column_name} AS #{type_to_sql(type, options[:limit])})" | |
323 | remove_column(table_name, column_name) | |
324 | rename_column(table_name, "#{column_name}_ar_tmp", column_name) | |
325 | commit_db_transaction | |
326 | end | |
change_column_default(table_name, column_name, options[:default]) unless options[:default].nil? | ||
end | ||
... | ... | |
end | ||
def remove_index(table_name, options) #:nodoc: | ||
324 | | |
325 | | |
326 | | |
327 | | |
328 | | |
329 | ||
330 | | |
339 | execute "DROP INDEX #{index_name(table_name, options)}" | |
end | ||
private | ||
BYTEA_COLUMN_TYPE_OID = 17 | ||
345 | TIMESTAMPOID = 1114 | |
346 | TIMESTAMPTZOID = 1184 | |
def configure_connection | ||
if @config[:encoding] | ||
... | ... | |
def select(sql, name = nil) | ||
res = execute(sql, name) | ||
352 | | |
363 | results = res.result | |
rows = [] | ||
if results.length > 0 | ||
fields = res.fields | ||
... | ... | |
hashed_row = {} | ||
row.each_index do |cel_index| | ||
column = row[cel_index] | ||
360 | | |
361 | | |
371 | ||
372 | case res.type(cel_index) | |
373 | when BYTEA_COLUMN_TYPE_OID | |
374 | column = unescape_bytea(column) | |
375 | when TIMESTAMPTZOID, TIMESTAMPOID | |
376 | column = cast_to_time(column) | |
end | ||
378 | ||
hashed_row[fields[cel_index]] = column | ||
end | ||
rows << hashed_row | ||
... | ... | |
return "t" if value =~ /true/i | ||
return "f" if value =~ /false/i | ||
469 | | |
470 | | |
485 | # Char/String/Bytea type values | |
486 | return $1 if value =~ /^'(.*)'::(bpchar|text|character varying|bytea)$/ | |
# Numeric values | ||
473 | | |
489 | return value if value =~ /^-?[0-9]+(\.[0-9]*)?/ | |
475 | | |
476 | | |
477 | ||
# Fixed dates / times | ||
return $1 if value =~ /^'(.+)'::(date|timestamp)/ | ||
... | ... | |
# and we can't know the value of that, so return nil. | ||
return nil | ||
end | ||
498 | ||
499 | # Only needed for DateTime instances | |
500 | def cast_to_time(value) | |
501 | return value unless value.class == DateTime | |
502 | v = value | |
503 | time_array = [v.year, v.month, v.day, v.hour, v.min, v.sec] | |
504 | Time.send(Base.default_timezone, *time_array) rescue nil | |
505 | end | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb:
prev. | current | |
# "Downgrade" deprecated sqlite API | ||
if SQLite.const_defined?(:Version) | ||
39 | | |
39 | ConnectionAdapters::SQLite2Adapter.new(db, logger) | |
else | ||
ConnectionAdapters::DeprecatedSQLiteAdapter.new(db, logger) | ||
end | ||
... | ... | |
def supports_migrations? #:nodoc: | ||
true | ||
end | ||
101 | ||
102 | def supports_count_distinct? #:nodoc: | |
103 | false | |
104 | end | |
def native_database_types #:nodoc: | ||
{ | ||
... | ... | |
# DATABASE STATEMENTS ====================================== | ||
def execute(sql, name = nil) #:nodoc: | ||
133 | | |
137 | catch_schema_changes { log(sql, name) { @connection.execute(sql) } } | |
end | ||
def update(sql, name = nil) #:nodoc: | ||
... | ... | |
def begin_db_transaction #:nodoc: | ||
171 | | |
175 | catch_schema_changes { @connection.transaction } | |
end | ||
def commit_db_transaction #:nodoc: | ||
175 | | |
179 | catch_schema_changes { @connection.commit } | |
end | ||
def rollback_db_transaction #:nodoc: | ||
179 | | |
183 | catch_schema_changes { @connection.rollback } | |
end | ||
... | ... | |
end | ||
def columns(table_name, name = nil) #:nodoc: | ||
192 | | |
196 | table_structure(table_name).map do |field| | |
SQLiteColumn.new(field['name'], field['dflt_value'], field['type'], field['notnull'] == "0") | ||
194 | | |
198 | end | |
end | ||
def indexes(table_name, name = nil) #:nodoc: | ||
... | ... | |
@connection.execute sql | ||
end | ||
end | ||
333 | ||
334 | def catch_schema_changes | |
335 | return yield | |
336 | rescue ActiveRecord::StatementInvalid => exception | |
337 | if exception.message =~ /database schema has changed/ | |
338 | reconnect! | |
339 | retry | |
340 | else | |
341 | raise | |
342 | end | |
343 | end | |
end | ||
345 | ||
346 | class SQLite2Adapter < SQLiteAdapter # :nodoc: | |
347 | # SQLite 2 does not support COUNT(DISTINCT) queries: | |
348 | # | |
349 | # select COUNT(DISTINCT ArtistID) from CDs; | |
350 | # | |
351 | # In order to get the number of artists we execute the following statement | |
352 | # | |
353 | # SELECT COUNT(ArtistID) FROM (SELECT DISTINCT ArtistID FROM CDs); | |
354 | def execute(sql, name = nil) #:nodoc: | |
355 | super(rewrite_count_distinct_queries(sql), name) | |
356 | end | |
357 | ||
358 | def rewrite_count_distinct_queries(sql) | |
359 | if sql =~ /count\(distinct ([^\)]+)\)( AS \w+)? (.*)/i | |
360 | distinct_column = $1 | |
361 | distinct_query = $3 | |
362 | column_name = distinct_column.split('.').last | |
363 | "SELECT COUNT(#{column_name}) FROM (SELECT DISTINCT #{distinct_column} #{distinct_query})" | |
364 | else | |
365 | sql | |
366 | end | |
367 | end | |
368 | end | |
331 | | |
370 | class DeprecatedSQLiteAdapter < SQLite2Adapter # :nodoc: | |
def insert(sql, name = nil, pk = nil, id_value = nil) | ||
execute(sql, name = nil) | ||
id_value || @connection.last_insert_rowid |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/connection_adapters/sqlserver_adapter.rb:
prev. | current | |
mode = config[:mode] ? config[:mode].to_s.upcase : 'ADO' | ||
username = config[:username] ? config[:username].to_s : 'sa' | ||
password = config[:password] ? config[:password].to_s : '' | ||
30 | autocommit = config.key?(:autocommit) ? config[:autocommit] : true | |
if mode == "ODBC" | ||
raise ArgumentError, "Missing DSN. Argument ':dsn' must be set in order for this adapter to work." unless config.has_key?(:dsn) | ||
dsn = config[:dsn] | ||
... | ... | |
driver_url = "DBI:ADO:Provider=SQLOLEDB;Data Source=#{host};Initial Catalog=#{database};User Id=#{username};Password=#{password};" | ||
end | ||
conn = DBI.connect(driver_url, username, password) | ||
41 | ||
42 | | |
42 | conn["AutoCommit"] = autocommit | |
ConnectionAdapters::SQLServerAdapter.new(conn, logger, [driver_url, username, password]) | ||
end | ||
end # class Base | ||
... | ... | |
class ColumnWithIdentity < Column# :nodoc: | ||
attr_reader :identity, :is_special, :scale | ||
51 | | |
52 | | |
51 | def initialize(name, default, sql_type = nil, is_identity = false, null = true, scale_value = 0) | |
52 | super(name, default, sql_type, null) | |
@identity = is_identity | ||
@is_special = sql_type =~ /text|ntext|image/i ? true : false | ||
@scale = scale_value | ||
... | ... | |
# Reconnects to the database, returns false if no connection could be made. | ||
def reconnect! | ||
219 | | |
219 | disconnect! | |
@connection = DBI.connect(*@connection_options) | ||
rescue DBI::DatabaseError => e | ||
@logger.warn "#{adapter_name} reconnection failed: #{e.message}" if @logger | ||
false | ||
end | ||
225 | ||
226 | # Disconnects from the database | |
227 | ||
228 | def disconnect! | |
229 | @connection.disconnect rescue nil | |
230 | end | |
def select_all(sql, name = nil) | ||
select(sql, name) | ||
... | ... | |
return [] if table_name.blank? | ||
table_name = table_name.to_s if table_name.is_a?(Symbol) | ||
table_name = table_name.split('.')[-1] unless table_name.nil? | ||
240 | | |
246 | sql = "SELECT COLUMN_NAME as ColName, COLUMN_DEFAULT as DefaultValue, DATA_TYPE as ColType, IS_NULLABLE As IsNullable, COL_LENGTH('#{table_name}', COLUMN_NAME) as Length, COLUMNPROPERTY(OBJECT_ID('#{table_name}'), COLUMN_NAME, 'IsIdentity') as IsIdentity, NUMERIC_SCALE as Scale FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '#{table_name}'" | |
# Comment out if you want to have the Columns select statment logged. | ||
242 | | |
248 | # Personally, I think it adds unnecessary bloat to the log. | |
# If you do comment it out, make sure to un-comment the "result" line that follows | ||
result = log(sql, name) { @connection.select_all(sql) } | ||
#result = @connection.select_all(sql) | ||
columns = [] | ||
247 | | |
253 | result.each do |field| | |
254 | default = field[:DefaultValue].to_s.gsub!(/[()\']/,"") =~ /null/ ? nil : field[:DefaultValue] | |
255 | type = "#{field[:ColType]}(#{field[:Length]})" | |
256 | is_identity = field[:IsIdentity] == 1 | |
257 | is_nullable = field[:IsNullable] == 'YES' | |
258 | columns << ColumnWithIdentity.new(field[:ColName], default, type, is_identity, is_nullable, field[:Scale]) | |
259 | end | |
columns | ||
end | ||
... | ... | |
def quote(value, column = nil) | ||
case value | ||
when String | ||
321 | | |
333 | if column && column.type == :binary && column.class.respond_to?(:string_to_binary) | |
"'#{quote_string(column.class.string_to_binary(value))}'" | ||
else | ||
"'#{quote_string(value)}'" | ||
... | ... | |
sql << " ) AS tmp2" | ||
end | ||
elsif sql !~ /^\s*SELECT (@@|COUNT\()/i | ||
378 | | |
390 | sql.sub!(/^\s*SELECT([\s]*distinct)?/i) do | |
391 | "SELECT#{$1} TOP #{options[:limit]}" | |
392 | end unless options[:limit].nil? | |
end | ||
end | ||
... | ... | |
def create_database(name) | ||
execute "CREATE DATABASE #{name}" | ||
end | ||
408 | ||
409 | def current_database | |
410 | @connection.select_one("select DB_NAME()")[0] | |
411 | end | |
def tables(name = nil) | ||
execute("SELECT table_name from information_schema.tables WHERE table_type = 'BASE TABLE'", name).inject([]) do |tables, field| | ||
... | ... | |
def type_to_sql(type, limit = nil) #:nodoc: | ||
native = native_database_types[type] | ||
# if there's no :limit in the default type definition, assume that type doesn't support limits | ||
457 | | |
475 | limit = limit || native[:limit] | |
column_type_sql = native[:name] | ||
column_type_sql << "(#{limit})" if limit | ||
column_type_sql | ||
... | ... | |
end | ||
def change_order_direction(order) | ||
515 | | |
516 | | |
517 | | |
518 | | |
519 | | |
533 | order.split(",").collect {|fragment| | |
534 | case fragment | |
535 | when /\bDESC\b/i then fragment.gsub(/\bDESC\b/i, "ASC") | |
536 | when /\bASC\b/i then fragment.gsub(/\bASC\b/i, "DESC") | |
537 | else String.new(fragment).split(',').join(' DESC,') + ' DESC' | |
538 | end | |
539 | }.join(",") | |
end | ||
def get_special_columns(table_name) |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/fixtures.rb:
prev. | current | |
end | ||
end | ||
12 | class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc: | |
13 | end | |
14 | ||
# Fixtures are a way of organizing data that you want to test against; in short, sample data. They come in 3 flavours: | ||
# | ||
# 1. YAML fixtures | ||
... | ... | |
if load_instances | ||
ActiveRecord::Base.silence do | ||
fixtures.each do |name, fixture| | ||
223 | | |
224 | | |
226 | begin | |
227 | object.instance_variable_set "@#{name}", fixture.find | |
228 | rescue FixtureClassNotFound | |
229 | nil | |
end | ||
end | ||
end | ||
... | ... | |
cattr_accessor :all_loaded_fixtures | ||
self.all_loaded_fixtures = {} | ||
240 | | |
241 | | |
245 | def self.create_fixtures(fixtures_directory, table_names, class_names = {}) | |
246 | table_names = [table_names].flatten.map { |n| n.to_s } | |
connection = block_given? ? yield : ActiveRecord::Base.connection | ||
243 | ||
ActiveRecord::Base.silence do | ||
fixtures_map = {} | ||
fixtures = table_names.map do |table_name| | ||
247 | | |
251 | fixtures_map[table_name] = Fixtures.new(connection, File.split(table_name.to_s).last, class_names[table_name.to_sym], File.join(fixtures_directory, table_name.to_s)) | |
end | ||
all_loaded_fixtures.merge! fixtures_map | ||
... | ... | |
attr_reader :table_name | ||
270 | | |
274 | def initialize(connection, table_name, class_name, fixture_path, file_filter = DEFAULT_FILTER_RE) | |
@connection, @table_name, @fixture_path, @file_filter = connection, table_name, fixture_path, file_filter | ||
272 | ||
273 | | |
276 | @class_name = class_name || | |
277 | (ActiveRecord::Base.pluralize_table_names ? @table_name.singularize.camelize : @table_name.camelize) | |
@table_name = ActiveRecord::Base.table_name_prefix + @table_name + ActiveRecord::Base.table_name_suffix | ||
read_fixture_files | ||
end | ||
... | ... | |
end | ||
private | ||
293 | ||
def read_fixture_files | ||
if File.file?(yaml_file_path) | ||
# YAML fixtures | ||
begin | ||
293 | | |
298 | yaml_string = "" | |
299 | Dir["#{@fixture_path}/**/*.yml"].select {|f| test(?f,f) }.each do |subfixture_path| | |
300 | yaml_string << IO.read(subfixture_path) | |
301 | end | |
302 | yaml_string << IO.read(yaml_file_path) | |
303 | ||
304 | if yaml = YAML::load(erb_render(yaml_string)) | |
yaml = yaml.value if yaml.respond_to?(:type_id) and yaml.respond_to?(:value) | ||
yaml.each do |name, data| | ||
self[name] = Fixture.new(data, @class_name) | ||
... | ... | |
end | ||
def find | ||
388 | | |
389 | | |
399 | klass = @class_name.is_a?(Class) ? @class_name : Object.const_get(@class_name) rescue nil | |
400 | if klass | |
klass.find(self[klass.primary_key]) | ||
402 | else | |
403 | raise FixtureClassNotFound, "The class #{@class_name.inspect} was not found." | |
end | ||
end | ||
... | ... | |
class TestCase #:nodoc: | ||
cattr_accessor :fixture_path | ||
class_inheritable_accessor :fixture_table_names | ||
432 | class_inheritable_accessor :fixture_class_names | |
class_inheritable_accessor :use_transactional_fixtures | ||
class_inheritable_accessor :use_instantiated_fixtures # true, false, or :no_instances | ||
class_inheritable_accessor :pre_loaded_fixtures | ||
... | ... | |
self.use_transactional_fixtures = false | ||
self.use_instantiated_fixtures = true | ||
self.pre_loaded_fixtures = false | ||
427 | ||
441 | ||
442 | self.fixture_class_names = {} | |
443 | ||
@@already_loaded_fixtures = {} | ||
429 | ||
445 | self.fixture_class_names = {} | |
446 | ||
447 | def self.set_fixture_class(class_names = {}) | |
448 | self.fixture_class_names = self.fixture_class_names.merge(class_names) | |
449 | end | |
450 | ||
def self.fixtures(*table_names) | ||
table_names = table_names.flatten.map { |n| n.to_s } | ||
self.fixture_table_names |= table_names | ||
... | ... | |
force_reload = optionals.shift | ||
@fixture_cache[table_name] ||= Hash.new | ||
@fixture_cache[table_name][fixture] = nil if force_reload | ||
456 | | |
477 | if @loaded_fixtures[table_name][fixture.to_s] | |
478 | @fixture_cache[table_name][fixture] ||= @loaded_fixtures[table_name][fixture.to_s].find | |
479 | else | |
480 | raise StandardError, "No fixture with name '#{fixture}' found for table '#{table_name}'" | |
481 | end | |
end | ||
end | ||
end | ||
... | ... | |
ActiveRecord::Base.connection.rollback_db_transaction | ||
ActiveRecord::Base.unlock_mutex | ||
end | ||
511 | | |
536 | ActiveRecord::Base.verify_active_connections! | |
end | ||
alias_method :teardown, :teardown_with_fixtures | ||
... | ... | |
private | ||
def load_fixtures | ||
@loaded_fixtures = {} | ||
540 | | |
565 | fixtures = Fixtures.create_fixtures(fixture_path, fixture_table_names, fixture_class_names) | |
unless fixtures.nil? | ||
if fixtures.instance_of?(Fixtures) | ||
@loaded_fixtures[fixtures.table_name] = fixtures |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/locking.rb:
prev. | current | |
# You must ensure that your database schema defaults the lock_version column to 0. | ||
# | ||
# This behavior can be turned off by setting <tt>ActiveRecord::Base.lock_optimistically = false</tt>. | ||
21 | # To override the name of the lock_version column, invoke the <tt>set_locking_column</tt> method. | |
22 | # This method uses the same syntax as <tt>set_table_name</tt> | |
module Locking | ||
def self.append_features(base) #:nodoc: | ||
super | ||
... | ... | |
end | ||
def update_with_lock #:nodoc: | ||
31 | | |
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | | |
38 | | |
39 | | |
33 | return update_without_lock unless locking_enabled? | |
41 | | |
42 | | |
43 | | |
44 | | |
45 | | |
35 | lock_col = self.class.locking_column | |
36 | previous_value = send(lock_col) | |
37 | send(lock_col + '=', previous_value + 1) | |
38 | ||
39 | affected_rows = connection.update(<<-end_sql, "#{self.class.name} Update with optimistic locking") | |
40 | UPDATE #{self.class.table_name} | |
41 | SET #{quoted_comma_pair_list(connection, attributes_with_quotes(false))} | |
42 | WHERE #{self.class.primary_key} = #{quote(id)} | |
43 | AND #{lock_col} = #{quote(previous_value)} | |
44 | end_sql | |
45 | ||
46 | unless affected_rows == 1 | |
47 | raise ActiveRecord::StaleObjectError, "Attempted to update a stale object" | |
end | ||
49 | ||
50 | return true | |
end | ||
end | ||
... | ... | |
cattr_accessor :lock_optimistically | ||
def locking_enabled? #:nodoc: | ||
55 | | |
59 | lock_optimistically && respond_to?(self.class.locking_column) | |
end | ||
61 | ||
62 | class << self | |
63 | def set_locking_column(value = nil, &block) | |
64 | define_attr_method :locking_column, value, &block | |
65 | end | |
66 | ||
67 | def locking_column #:nodoc: | |
68 | reset_locking_column | |
69 | end | |
70 | ||
71 | def reset_locking_column #:nodoc: | |
72 | default = 'lock_version' | |
73 | set_locking_column(default) | |
74 | default | |
75 | end | |
76 | end | |
77 | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/migration.rb:
prev. | current | |
# that can then add columns to it, following the same format as add_column. See example above. The options hash is for | ||
# fragments like "DEFAULT CHARSET=UTF-8" that are appended to the create table definition. | ||
# * <tt>drop_table(name)</tt>: Drops the table called +name+. | ||
64 | # * <tt>rename_table(old_name, new_name)</tt>: Renames the table called +old_name+ to +new_name+. | |
# * <tt>add_column(table_name, column_name, type, options)</tt>: Adds a new column to the table called +table_name+ | ||
# named +column_name+ specified to be one of the following types: | ||
# :string, :text, :integer, :float, :datetime, :timestamp, :time, :date, :binary, :boolean. A default value can be specified | ||
... | ... | |
# pending migrations, creating the <tt>schema_info</tt> table if missing. | ||
# | ||
# To roll the database back to a previous migration version, use | ||
96 | | |
97 | # <tt>rake migrate VERSION=X</tt> where <tt>X</tt> is the version to which | |
# you wish to downgrade. If any of the migrations throw an | ||
# <tt>IrreversibleMigration</tt> exception, that step will fail and you'll | ||
# have some manual work to do. | ||
... | ... | |
# == Database support | ||
# | ||
# Migrations are currently supported in MySQL, PostgreSQL, SQLite, | ||
104 | | |
105 | # SQL Server, Sybase, and Oracle (all supported databases except DB2). | |
# | ||
# == More examples | ||
# | ||
... | ... | |
# end | ||
# end | ||
# end | ||
163 | # | |
164 | # == Controlling verbosity | |
165 | # | |
166 | # By default, migrations will describe the actions they are taking, writing | |
167 | # them to the console as they happen, along with benchmarks describing how | |
168 | # long each step took. | |
169 | # | |
170 | # You can quiet them down by setting ActiveRecord::Migration.verbose = false. | |
171 | # | |
172 | # You can also insert your own messages and benchmarks by using the #say_with_time | |
173 | # method: | |
174 | # | |
175 | # def self.up | |
176 | # ... | |
177 | # say_with_time "Updating salaries..." do | |
178 | # Person.find(:all).each do |p| | |
179 | # p.salary = SalaryCalculator.compute(p) | |
180 | # end | |
181 | # end | |
182 | # ... | |
183 | # end | |
184 | # | |
185 | # The phrase "Updating salaries..." would then be printed, along with the | |
186 | # benchmark for the block when the block completes. | |
class Migration | ||
188 | @@verbose = true | |
189 | cattr_accessor :verbose | |
190 | ||
class << self | ||
164 | | |
165 | | |
192 | def up_using_benchmarks #:nodoc: | |
193 | migrate(:up) | |
194 | end | |
167 | | |
168 | | |
169 | | |
196 | def down_using_benchmarks #:nodoc: | |
197 | migrate(:down) | |
198 | end | |
199 | ||
200 | # Execute this migration in the named direction | |
201 | def migrate(direction) | |
202 | return unless respond_to?(direction) | |
203 | ||
204 | case direction | |
205 | when :up then announce "migrating" | |
206 | when :down then announce "reverting" | |
207 | end | |
208 | ||
209 | result = nil | |
210 | time = Benchmark.measure { result = send("real_#{direction}") } | |
211 | ||
212 | case direction | |
213 | when :up then announce "migrated (%.4fs)" % time.real; write | |
214 | when :down then announce "reverted (%.4fs)" % time.real; write | |
215 | end | |
216 | ||
217 | result | |
218 | end | |
219 | ||
220 | # Because the method added may do an alias_method, it can be invoked | |
221 | # recursively. We use @ignore_new_methods as a guard to indicate whether | |
222 | # it is safe for the call to proceed. | |
223 | def singleton_method_added(sym) #:nodoc: | |
224 | return if @ignore_new_methods | |
225 | ||
226 | begin | |
227 | @ignore_new_methods = true | |
228 | ||
229 | case sym | |
230 | when :up, :down | |
231 | klass = (class << self; self; end) | |
232 | klass.send(:alias_method, "real_#{sym}", sym) | |
233 | klass.send(:alias_method, sym, "#{sym}_using_benchmarks") | |
234 | end | |
235 | ensure | |
236 | @ignore_new_methods = false | |
237 | end | |
238 | end | |
239 | ||
240 | def write(text="") | |
241 | puts(text) if verbose | |
242 | end | |
243 | ||
244 | def announce(message) | |
245 | text = "#{name}: #{message}" | |
246 | write "== %s %s" % [ text, "=" * (75 - text.length) ] | |
247 | end | |
248 | ||
249 | def say(message, subitem=false) | |
250 | write "#{subitem ? " ->" : "--"} #{message}" | |
251 | end | |
252 | ||
253 | def say_with_time(message) | |
254 | say(message) | |
255 | result = nil | |
256 | time = Benchmark.measure { result = yield } | |
257 | say "%.4fs" % time.real, :subitem | |
258 | result | |
259 | end | |
260 | ||
261 | def suppress_messages | |
262 | save = verbose | |
263 | self.verbose = false | |
264 | yield | |
265 | ensure | |
266 | self.verbose = save | |
267 | end | |
268 | ||
269 | def method_missing(method, *arguments, &block) | |
270 | say_with_time "#{method}(#{arguments.map { |a| a.inspect }.join(", ")})" do | |
271 | arguments[0] = Migrator.proper_table_name(arguments.first) unless arguments.empty? || method == :execute | |
ActiveRecord::Base.connection.send(method, *arguments, &block) | ||
end | ||
274 | end | |
end | ||
end | ||
... | ... | |
class << self | ||
def migrate(migrations_path, target_version = nil) | ||
Base.connection.initialize_schema_information | ||
282 | ||
case | ||
when target_version.nil?, current_version < target_version | ||
up(migrations_path, target_version) | ||
... | ... | |
next if irrelevant_migration?(version) | ||
Base.logger.info "Migrating to #{migration_class} (#{version})" | ||
228 | | |
332 | migration_class.migrate(@direction) | |
set_schema_version(version) | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/observer.rb:
prev. | current | |
# | ||
# This Observer sends an email when a Comment#save is finished. | ||
# | ||
45 | # class ContactObserver < ActiveRecord::Observer | |
46 | # def after_create(contact) | |
47 | # contact.logger.info('New contact added!') | |
48 | # end | |
49 | # | |
50 | # def after_destroy(contact) | |
51 | # contact.logger.warn("Contact with an id of #{contact.id} was destroyed!") | |
52 | # end | |
53 | # end | |
54 | # | |
55 | # This Observer uses logger to log when specific callbacks are triggered. | |
56 | # | |
# == Observing a class that can't be inferred | ||
# | ||
# Observers will by default be mapped to the class with which they share a name. So CommentObserver will | ||
... | ... | |
# | ||
# The observer can implement callback methods for each of the methods described in the Callbacks module. | ||
# | ||
75 | | |
87 | # == Storing Observers in Rails | |
# | ||
89 | # If you're using Active Record within Rails, observer classes are usually stored in app/models with the | |
90 | # naming convention of app/models/audit_observer.rb. | |
91 | # | |
92 | # == Configuration | |
93 | # | |
# In order to activate an observer, list it in the <tt>config.active_record.observers</tt> configuration setting in your | ||
# <tt>config/environment.rb</tt> file. | ||
# | ||
# config.active_record.observers = :comment_observer, :signup_observer | ||
98 | # | |
99 | # Observers will not be invoked unless you define these in your application configuration. | |
100 | # | |
class Observer | ||
include Singleton | ||
104 | # Observer subclasses should be reloaded by the dispatcher in Rails | |
105 | # when Dependencies.mechanism = :load. | |
106 | include Reloadable::Subclasses | |
107 | ||
# Attaches the observer to the supplied model classes. | ||
def self.observe(*models) | ||
define_method(:observed_class) { models } |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/reflection.rb:
prev. | current | |
module ActiveRecord | ||
module Reflection # :nodoc: | ||
3 | | |
4 | | |
3 | def self.included(base) | |
base.extend(ClassMethods) | ||
6 | ||
7 | | |
8 | | |
9 | | |
10 | ||
11 | | |
12 | | |
13 | | |
14 | | |
15 | ||
16 | | |
17 | | |
18 | | |
19 | ||
20 | | |
21 | | |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
30 | | |
31 | | |
32 | | |
33 | | |
end | ||
# Reflection allows you to interrogate Active Record classes and objects about their associations and aggregations. | ||
... | ... | |
# | ||
# You can find the interface for the AggregateReflection and AssociationReflection classes in the abstract MacroReflection class. | ||
module ClassMethods | ||
13 | def create_reflection(macro, name, options, active_record) | |
14 | case macro | |
15 | when :has_many, :belongs_to, :has_one, :has_and_belongs_to_many | |
16 | reflection = AssociationReflection.new(macro, name, options, active_record) | |
17 | when :composed_of | |
18 | reflection = AggregateReflection.new(macro, name, options, active_record) | |
19 | end | |
20 | write_inheritable_hash :reflections, name => reflection | |
21 | reflection | |
22 | end | |
23 | ||
24 | def reflections | |
25 | read_inheritable_attribute(:reflections) or write_inheritable_attribute(:reflections, {}) | |
26 | end | |
27 | ||
# Returns an array of AggregateReflection objects for all the aggregations in the class. | ||
def reflect_on_all_aggregations | ||
44 | | |
30 | reflections.values.select { |reflection| reflection.is_a?(AggregateReflection) } | |
end | ||
# Returns the AggregateReflection object for the named +aggregation+ (use the symbol). Example: | ||
# Account.reflect_on_aggregation(:balance) # returns the balance AggregateReflection | ||
def reflect_on_aggregation(aggregation) | ||
50 | | |
36 | reflections[aggregation].is_a?(AggregateReflection) ? reflections[aggregation] : nil | |
end | ||
53 | | |
54 | | |
55 | | |
39 | # Returns an array of AssociationReflection objects for all the aggregations in the class. If you only want to reflect on a | |
40 | # certain association type, pass in the symbol (:has_many, :has_one, :belongs_to) for that as the first parameter. Example: | |
41 | # Account.reflect_on_all_associations # returns an array of all associations | |
42 | # Account.reflect_on_all_associations(:has_many) # returns an array of all has_many associations | |
43 | def reflect_on_all_associations(macro = nil) | |
44 | association_reflections = reflections.values.select { |reflection| reflection.is_a?(AssociationReflection) } | |
45 | macro ? association_reflections.select { |reflection| reflection.macro == macro } : association_reflections | |
end | ||
# Returns the AssociationReflection object for the named +aggregation+ (use the symbol). Example: | ||
# Account.reflect_on_association(:owner) # returns the owner AssociationReflection | ||
50 | # Invoice.reflect_on_association(:line_items).macro # returns :has_many | |
def reflect_on_association(association) | ||
61 | | |
52 | reflections[association].is_a?(AssociationReflection) ? reflections[association] : nil | |
end | ||
end | ||
... | ... | |
# Returns the class for the macro, so "composed_of :balance, :class_name => 'Money'" would return the Money class and | ||
# "has_many :clients" would return the Client class. | ||
def klass() end | ||
86 | ||
87 | def class_name | |
88 | @class_name ||= name_to_class_name(name.id2name) | |
89 | end | |
def ==(other_aggregation) | ||
name == other_aggregation.name && other_aggregation.options && active_record == other_aggregation.active_record | ||
... | ... | |
# Holds all the meta-data about an aggregation as it was specified in the Active Record class. | ||
class AggregateReflection < MacroReflection #:nodoc: | ||
def klass | ||
105 | | |
100 | @klass ||= Object.const_get(options[:class_name] || class_name) | |
end | ||
private | ||
... | ... | |
# Holds all the meta-data about an association as it was specified in the Active Record class. | ||
class AssociationReflection < MacroReflection #:nodoc: | ||
def klass | ||
117 | | |
112 | @klass ||= active_record.send(:compute_type, class_name) | |
end | ||
def table_name | ||
@table_name ||= klass.table_name | ||
end | ||
119 | def primary_key_name | |
120 | return @primary_key_name if @primary_key_name | |
121 | case | |
122 | when macro == :belongs_to | |
123 | @primary_key_name = options[:foreign_key] || class_name.foreign_key | |
124 | when options[:as] | |
125 | @primary_key_name = options[:foreign_key] || "#{options[:as]}_id" | |
126 | else | |
127 | @primary_key_name = options[:foreign_key] || active_record.name.foreign_key | |
128 | end | |
129 | end | |
130 | ||
131 | def association_foreign_key | |
132 | @association_foreign_key ||= @options[:association_foreign_key] || class_name.foreign_key | |
133 | end | |
134 | ||
135 | def counter_cache_column | |
136 | if options[:counter_cache] == true | |
137 | "#{active_record.name.underscore.pluralize}_count" | |
138 | elsif options[:counter_cache] | |
139 | options[:counter_cache] | |
140 | end | |
141 | end | |
142 | ||
143 | def through_reflection | |
144 | @through_reflection ||= options[:through] ? active_record.reflect_on_association(options[:through]) : false | |
145 | end | |
146 | ||
147 | # Gets an array of possible :through source reflection names | |
148 | # | |
149 | # [singularized, pluralized] | |
150 | def source_reflection_names | |
151 | @source_reflection_names ||= (options[:source] ? [options[:source]] : [name.to_s.singularize, name]).collect { |n| n.to_sym } | |
152 | end | |
153 | ||
154 | # Gets the source of the through reflection. It checks both a singularized and pluralized form for :belongs_to or :has_many. | |
155 | # (The :tags association on Tagging below) | |
156 | # | |
157 | # class Post | |
158 | # has_many :tags, :through => :taggings | |
159 | # end | |
160 | # | |
161 | def source_reflection | |
162 | return nil unless through_reflection | |
163 | @source_reflection ||= source_reflection_names.collect { |name| through_reflection.klass.reflect_on_association(name) }.compact.first | |
164 | end | |
165 | ||
166 | def check_validity! | |
167 | if options[:through] | |
168 | if through_reflection.nil? | |
169 | raise HasManyThroughAssociationNotFoundError.new(self) | |
170 | end | |
171 | ||
172 | if source_reflection.nil? | |
173 | raise HasManyThroughSourceAssociationNotFoundError.new(self) | |
174 | end | |
175 | ||
176 | if source_reflection.options[:polymorphic] | |
177 | raise HasManyThroughAssociationPolymorphicError.new(class_name, self, source_reflection) | |
178 | end | |
179 | ||
180 | unless [:belongs_to, :has_many].include?(source_reflection.macro) && source_reflection.options[:through].nil? | |
181 | raise HasManyThroughSourceAssociationMacroError.new(self) | |
182 | end | |
183 | end | |
184 | end | |
185 | ||
private | ||
def name_to_class_name(name) | ||
if name =~ /::/ | ||
name | ||
else | ||
129 | | |
191 | if options[:class_name] | |
192 | options[:class_name] | |
193 | elsif through_reflection # get the class_name of the belongs_to association of the through reflection | |
194 | source_reflection.class_name | |
195 | else | |
class_name = name.to_s.camelize | ||
131 | | |
197 | class_name = class_name.singularize if [ :has_many, :has_and_belongs_to_many ].include?(macro) | |
198 | class_name | |
end | ||
133 | | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/schema.rb:
prev. | current | |
cols = columns('schema_info') | ||
info = info.map do |k,v| | ||
50 | | |
50 | v = Base.connection.quote(v, cols.detect { |c| c.name == k.to_s }) | |
"#{k} = #{v}" | ||
end | ||
54 | | |
54 | Base.connection.update "UPDATE #{Migrator.schema_info_table_name} SET #{info.join(", ")}" | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/schema_dumper.rb:
prev. | current | |
# output format (i.e., ActiveRecord::Schema). | ||
class SchemaDumper #:nodoc: | ||
private_class_method :new | ||
6 | ||
7 | # A list of tables which should not be dumped to the schema. | |
8 | # Acceptable values are strings as well as regexp. | |
9 | # This setting is only used if ActiveRecord::Base.schema_format == :ruby | |
10 | cattr_accessor :ignore_tables | |
11 | @@ignore_tables = [] | |
def self.dump(connection=ActiveRecord::Base.connection, stream=STDOUT) | ||
new(connection).dump(stream) | ||
... | ... | |
def tables(stream) | ||
@connection.tables.sort.each do |tbl| | ||
46 | | |
52 | next if ["schema_info", ignore_tables].flatten.any? do |ignored| | |
53 | case ignored | |
54 | when String: tbl == ignored | |
55 | when Regexp: tbl =~ ignored | |
56 | else | |
57 | raise StandardError, 'ActiveRecord::SchemaDumper.ignore_tables accepts an array of String and / or Regexp values.' | |
58 | end | |
59 | end | |
table(tbl, stream) | ||
end | ||
end | ||
def table(table, stream) | ||
columns = @connection.columns(table) | ||
66 | begin | |
67 | tbl = StringIO.new | |
54 | | |
55 | | |
56 | | |
57 | | |
69 | if @connection.respond_to?(:pk_and_sequence_for) | |
70 | pk, pk_seq = @connection.pk_and_sequence_for(table) | |
71 | end | |
72 | pk ||= 'id' | |
59 | | |
60 | | |
61 | | |
62 | | |
63 | | |
64 | | |
74 | tbl.print " create_table #{table.inspect}" | |
75 | if columns.detect { |c| c.name == pk } | |
76 | if pk != 'id' | |
77 | tbl.print %Q(, :primary_key => "#{pk}") | |
78 | end | |
79 | else | |
80 | tbl.print ", :id => false" | |
81 | end | |
82 | tbl.print ", :force => true" | |
83 | tbl.puts " do |t|" | |
84 | ||
85 | columns.each do |column| | |
86 | raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" if @types[column.type].nil? | |
87 | next if column.name == pk | |
88 | tbl.print " t.column #{column.name.inspect}, #{column.type.inspect}" | |
89 | tbl.print ", :limit => #{column.limit.inspect}" if column.limit != @types[column.type][:limit] | |
90 | tbl.print ", :default => #{column.default.inspect}" if !column.default.nil? | |
91 | tbl.print ", :null => false" if !column.null | |
92 | tbl.puts | |
93 | end | |
94 | ||
95 | tbl.puts " end" | |
96 | tbl.puts | |
97 | ||
98 | indexes(table, tbl) | |
99 | ||
100 | tbl.rewind | |
101 | stream.print tbl.read | |
102 | rescue => e | |
103 | stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}" | |
104 | stream.puts "# #{e.message}" | |
stream.puts | ||
end | ||
67 | ||
68 | | |
69 | | |
70 | ||
71 | | |
107 | ||
108 | stream | |
end | ||
def indexes(table, stream) |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/timestamp.rb:
prev. | current | |
# automatically included, so you don't need to do that manually. | ||
# | ||
# This behavior can be turned off by setting <tt>ActiveRecord::Base.record_timestamps = false</tt>. | ||
7 | | |
8 | | |
7 | # This behavior by default uses local time, but can use UTC by setting <tt>ActiveRecord::Base.default_timezone = :utc</tt> | |
8 | module Timestamp | |
def self.append_features(base) # :nodoc: | ||
super | ||
... | ... | |
alias_method :update_without_timestamps, :update | ||
alias_method :update, :update_with_timestamps | ||
end | ||
19 | | |
20 | | |
19 | end | |
20 | ||
def create_with_timestamps #:nodoc: | ||
if record_timestamps | ||
t = ( self.class.default_timezone == :utc ? Time.now.utc : Time.now ) | ||
write_attribute('created_at', t) if respond_to?(:created_at) && created_at.nil? | ||
write_attribute('created_on', t) if respond_to?(:created_on) && created_on.nil? | ||
26 | | |
26 | ||
write_attribute('updated_at', t) if respond_to?(:updated_at) | ||
write_attribute('updated_on', t) if respond_to?(:updated_on) | ||
end | ||
... | ... | |
end | ||
update_without_timestamps | ||
end | ||
41 | | |
41 | end | |
class Base | ||
# Records the creation date and possibly time in created_on (date only) or created_at (date and time) and the update date and possibly |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/validations.rb:
prev. | current | |
# rescue ActiveRecord::RecordInvalid => invalid | ||
# puts invalid.record.errors | ||
# end | ||
9 | | |
9 | class RecordInvalid < ActiveRecordError #:nodoc: | |
attr_reader :record | ||
11 | | |
11 | def initialize(record) | |
@record = record | ||
13 | | |
13 | super("Validation failed: #{@record.errors.full_messages.join(", ")}") | |
end | ||
end | ||
... | ... | |
:accepted => "must be accepted", | ||
:empty => "can't be empty", | ||
:blank => "can't be blank", | ||
34 | | |
35 | | |
34 | :too_long => "is too long (maximum is %d characters)", | |
35 | :too_short => "is too short (minimum is %d characters)", | |
:wrong_length => "is the wrong length (should be %d characters)", | ||
:taken => "has already been taken", | ||
:not_a_number => "is not a number" | ||
... | ... | |
def empty? | ||
return @errors.empty? | ||
end | ||
150 | ||
150 | ||
# Removes all the errors that have been added. | ||
def clear | ||
@errors = {} | ||
... | ... | |
# Returns the total number of errors added. Two errors added to the same attribute will be counted as such | ||
# with this as well. | ||
158 | | |
158 | def size | |
error_count = 0 | ||
@errors.each_value { |attribute| error_count += attribute.length } | ||
error_count | ||
end | ||
163 | ||
164 | alias_method :count, :size | |
165 | alias_method :length, :size | |
end | ||
... | ... | |
alias_method :save_without_validation, :save | ||
alias_method :save, :save_with_validation | ||
219 | alias_method :save_without_validation!, :save! | |
220 | alias_method :save!, :save_with_validation! | |
221 | ||
alias_method :update_attribute_without_validation_skipping, :update_attribute | ||
alias_method :update_attribute, :update_attribute_with_validation_skipping | ||
end | ||
... | ... | |
# Validates each attribute against a block. | ||
# | ||
# class Person < ActiveRecord::Base | ||
274 | | |
275 | | |
280 | # validates_each :first_name, :last_name do |record, attr, value| | |
281 | # record.errors.add attr, 'starts with z.' if value[0] == ?z | |
# end | ||
# end | ||
# | ||
... | ... | |
end | ||
end | ||
364 | | |
370 | # Validates that the specified attributes are not blank (as defined by Object#blank?). Happens by default on save. Example: | |
# | ||
372 | # class Person < ActiveRecord::Base | |
373 | # validates_presence_of :first_name | |
374 | # end | |
375 | # | |
376 | # The first_name attribute must be in the object and it cannot be blank. | |
377 | # | |
# Configuration options: | ||
# * <tt>message</tt> - A custom error message (default is: "can't be blank") | ||
# * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update) | ||
... | ... | |
# * <tt>in</tt> - A synonym(or alias) for :within | ||
# * <tt>allow_nil</tt> - Attribute may be nil; skip validation. | ||
# | ||
406 | | |
418 | # * <tt>too_long</tt> - The error message if the attribute goes over the maximum (default is: "is too long (maximum is %d characters)") | |
# * <tt>too_short</tt> - The error message if the attribute goes under the minimum (default is: "is too short (min is %d characters)") | ||
# * <tt>wrong_length</tt> - The error message if using the :is method and the attribute is the wrong size (default is: "is the wrong length (should be %d characters)") | ||
# * <tt>message</tt> - The error message to use for a :minimum, :maximum, or :is violation. An alias of the appropriate too_long/too_short/wrong_length message | ||
... | ... | |
option_value = options[range_options.first] | ||
case option | ||
439 | | |
440 | | |
451 | when :within, :in | |
452 | raise ArgumentError, ":#{option} must be a Range" unless option_value.is_a?(Range) | |
442 | | |
443 | | |
454 | too_short = options[:too_short] % option_value.begin | |
455 | too_long = options[:too_long] % option_value.end | |
445 | | |
446 | | |
447 | | |
448 | | |
449 | | |
457 | validates_each(attrs, options) do |record, attr, value| | |
458 | if value.nil? or value.split(//).size < option_value.begin | |
459 | record.errors.add(attr, too_short) | |
460 | elsif value.split(//).size > option_value.end | |
461 | record.errors.add(attr, too_long) | |
462 | end | |
end | ||
451 | | |
452 | | |
453 | | |
464 | when :is, :minimum, :maximum | |
465 | raise ArgumentError, ":#{option} must be a nonnegative Integer" unless option_value.is_a?(Integer) and option_value >= 0 | |
455 | | |
456 | | |
457 | | |
467 | # Declare different validations per option. | |
468 | validity_checks = { :is => "==", :minimum => ">=", :maximum => "<=" } | |
469 | message_options = { :is => :wrong_length, :minimum => :too_short, :maximum => :too_long } | |
459 | | |
471 | message = (options[:message] || options[message_options[option]]) % option_value | |
461 | | |
462 | | |
463 | | |
473 | validates_each(attrs, options) do |record, attr, value| | |
474 | if value.kind_of?(String) | |
475 | record.errors.add(attr, message) unless !value.nil? and value.split(//).size.method(validity_checks[option])[option_value] | |
476 | else | |
477 | record.errors.add(attr, message) unless !value.nil? and value.size.method(validity_checks[option])[option_value] | |
478 | end | |
479 | end | |
end | ||
end | ||
... | ... | |
# can be named "davidhh". | ||
# | ||
# class Person < ActiveRecord::Base | ||
474 | | |
490 | # validates_uniqueness_of :user_name, :scope => :account_id | |
# end | ||
# | ||
493 | # It can also validate whether the value of the specified attributes are unique based on multiple scope parameters. For example, | |
494 | # making sure that a teacher can only be on the schedule once per semester for a particular class. | |
495 | # | |
496 | # class TeacherSchedule < ActiveRecord::Base | |
497 | # validates_uniqueness_of :teacher_id, :scope => [:semester_id, :class_id] | |
498 | # end | |
499 | # | |
# When the record is created, a check is performed to make sure that no record exists in the database with the given value for the specified | ||
# attribute (that maps to a column). When the record is updated, the same check is made but disregarding the record itself. | ||
# | ||
# Configuration options: | ||
# * <tt>message</tt> - Specifies a custom error message (default is: "has already been taken") | ||
482 | | |
505 | # * <tt>scope</tt> - One or more columns by which to limit the scope of the uniquness constraint. | |
# * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should | ||
# occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The | ||
# method, proc or string should return or evaluate to a true or false value. | ||
509 | ||
def validates_uniqueness_of(*attr_names) | ||
configuration = { :message => ActiveRecord::Errors.default_error_messages[:taken] } | ||
configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash) | ||
validates_each(attr_names,configuration) do |record, attr_name, value| | ||
491 | | |
515 | condition_sql = "#{record.class.table_name}.#{attr_name} #{attribute_condition(value)}" | |
condition_params = [value] | ||
if scope = configuration[:scope] | ||
494 | | |
495 | | |
496 | | |
518 | Array(scope).map do |scope_item| | |
519 | scope_value = record.send(scope_item) | |
520 | condition_sql << " AND #{record.class.table_name}.#{scope_item} #{attribute_condition(scope_value)}" | |
521 | condition_params << scope_value | |
522 | end | |
end | ||
unless record.new_record? | ||
499 | | |
525 | condition_sql << " AND #{record.class.table_name}.#{record.class.primary_key} <> ?" | |
condition_params << record.send(:id) | ||
end | ||
if record.class.find(:first, :conditions => [condition_sql, *condition_params]) | ||
... | ... | |
def save_with_validation(perform_validation = true) | ||
if perform_validation && valid? || !perform_validation | ||
save_without_validation | ||
699 | | |
else | ||
false | ||
end | ||
... | ... | |
# Attempts to save the record just like Base#save but will raise a RecordInvalid exception instead of returning false | ||
# if the record is not valid. | ||
707 | | |
732 | def save_with_validation! | |
if valid? | ||
709 | | |
734 | save_without_validation! | |
else | ||
raise RecordInvalid.new(self) | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/vendor/db2.rb:
prev. | current | |
end | ||
def connect(server_name, user_name = '', auth = '') | ||
69 | | |
69 | check_rc(SQLConnect(@handle, server_name, user_name.to_s, auth.to_s)) | |
end | ||
def set_connect_attr(attr, value) | ||
... | ... | |
check_rc(rc) | ||
end | ||
113 | | |
114 | | |
113 | def columns(table_name, schema_name = '%') | |
114 | check_rc(SQLColumns(@handle, '', schema_name.upcase, table_name.upcase, '%')) | |
fetch_all | ||
end | ||
118 | | |
119 | | |
118 | def tables(schema_name = '%') | |
119 | check_rc(SQLTables(@handle, '', schema_name.upcase, '%', 'TABLE')) | |
fetch_all | ||
end | ||
123 | def indexes(table_name, schema_name = '') | |
124 | check_rc(SQLStatistics(@handle, '', schema_name.upcase, table_name.upcase, SQL_INDEX_ALL, SQL_ENSURE)) | |
125 | fetch_all | |
126 | end | |
127 | ||
def prepare(sql) | ||
@sql = sql | ||
check_rc(SQLPrepare(@handle, sql)) |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/vendor/simple.rb:
prev. | current | |
1 | ||
2 | ||
3 | ||
4 | ||
5 | ||
6 | ||
7 | ||
8 | ||
9 | ||
10 | ||
11 | ||
12 | ||
13 | ||
14 | ||
15 | ||
16 | ||
17 | ||
18 | ||
19 | ||
20 | ||
21 | ||
22 | ||
23 | ||
24 | ||
25 | ||
26 | ||
27 | ||
28 | ||
29 | ||
30 | ||
31 | ||
32 | ||
33 | ||
34 | ||
35 | ||
36 | ||
37 | ||
38 | ||
39 | ||
40 | ||
41 | ||
42 | ||
43 | ||
44 |
| |
45 | | |
46 | | |
47 | ||
48 |
| |
49 | | |
50 | | |
51 | | |
52 | | |
53 | | |
54 |
| |
55 | | |
56 | | |
57 | | |
58 | | |
59 | | |
60 | | |
61 | | |
62 | | |
63 | | |
64 | | |
65 | | |
66 | | |
67 | | |
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
73 | | |
74 | | |
75 | | |
76 | | |
77 | | |
78 | | |
79 | | |
80 | | |
81 | | |
82 | | |
83 | | |
84 | | |
85 | | |
86 | | |
87 | | |
88 | | |
89 | | |
90 | | |
91 | | |
92 | | |
93 | | |
94 | | |
95 | | |
96 | | |
97 | | |
98 | | |
99 | | |
100 | | |
101 | | |
102 | | |
103 | | |
104 | | |
105 | | |
106 | | |
107 | | |
108 | | |
109 | | |
110 | | |
111 | | |
112 | | |
113 | | |
114 | | |
115 | | |
116 | | |
117 | | |
118 | | |
119 | | |
120 | | |
121 | | |
122 | | |
123 | | |
124 | | |
125 | | |
126 | | |
127 | | |
128 | | |
129 | | |
130 | | |
131 | | |
132 | | |
133 | | |
134 | | |
135 | | |
136 | | |
137 | | |
138 | | |
139 | | |
140 | | |
141 | | |
142 | | |
143 | | |
144 | | |
145 | | |
146 | | |
147 | | |
148 | | |
149 | | |
150 | | |
151 | | |
152 | | |
153 | | |
154 | | |
155 | | |
156 | | |
157 | | |
158 | | |
159 | | |
160 | | |
161 | | |
162 | | |
163 | | |
164 | | |
165 | | |
166 | | |
167 | | |
168 | | |
169 | | |
170 | | |
171 | | |
172 | | |
173 | | |
174 | | |
175 | | |
176 | | |
177 |
| |
178 | | |
179 | | |
180 | | |
181 | | |
182 | | |
183 | | |
184 | | |
185 | | |
186 |
| |
187 | | |
188 | | |
189 | | |
190 | | |
191 |
| |
192 | | |
193 | | |
194 | | |
195 | | |
196 | | |
197 | | |
198 | | |
199 | | |
200 | | |
201 | | |
202 | | |
203 | | |
204 | | |
205 | | |
206 |
| |
207 | | |
208 | | |
209 | | |
210 | | |
211 | | |
212 | | |
213 | | |
214 |
| |
215 | | |
216 | | |
217 | | |
218 | | |
219 | | |
220 | | |
221 | | |
222 |
| |
223 | | |
224 | | |
225 | | |
226 | | |
227 | | |
228 | | |
229 | | |
230 | | |
231 |
| |
232 | | |
233 |
| |
234 | | |
235 |
| |
236 | | |
237 | | |
238 |
| |
239 | | |
240 | | |
241 | | |
242 | | |
243 | | |
244 | | |
245 | | |
246 | | |
247 | | |
248 | | |
249 | | |
250 |
| |
251 | | |
252 | | |
253 | | |
254 | | |
255 | | |
256 | | |
257 | | |
258 | | |
259 | | |
260 | | |
261 | | |
262 |
| |
263 | | |
264 | | |
265 | | |
266 | | |
267 | | |
268 | | |
269 | | |
270 | | |
271 | | |
272 | | |
273 |
| |
274 | | |
275 | | |
276 | | |
277 | | |
278 |
| |
279 | | |
280 | | |
281 | | |
282 | | |
283 | | |
284 | | |
285 | | |
286 | | |
287 |
| |
288 | | |
289 | | |
290 | | |
291 | | |
292 | | |
293 | | |
294 | | |
295 |
| |
296 | | |
297 | | |
298 | | |
299 | | |
300 | | |
301 | | |
302 | | |
303 | | |
304 | | |
305 |
| |
306 | | |
307 | | |
308 | | |
309 | | |
310 | | |
311 | | |
312 | | |
313 | | |
314 | | |
315 | | |
316 | | |
317 | | |
318 | | |
319 | | |
320 | | |
321 | | |
322 | | |
323 | | |
324 | | |
325 | | |
326 | | |
327 | | |
328 | | |
329 | | |
330 | | |
331 |
| |
332 | | |
333 | | |
334 |
| |
335 | | |
336 | | |
337 | | |
338 | | |
339 | | |
340 |
| |
341 | | |
342 | | |
343 | | |
344 | | |
345 | | |
346 | | |
347 | | |
348 | | |
349 |
| |
350 | | |
351 | | |
352 |
| |
353 | | |
354 | | |
355 |
| |
356 | | |
357 | | |
358 | | |
359 | | |
360 | | |
361 |
| |
362 | | |
363 | | |
364 | | |
365 | | |
366 | | |
367 | | |
368 | | |
369 | | |
370 |
| |
371 | | |
372 | | |
373 | | |
374 | | |
375 | | |
376 | | |
377 |
| |
378 | | |
379 | | |
380 | | |
381 | | |
382 | | |
383 | | |
384 |
| |
385 | | |
386 | | |
387 | | |
388 | | |
389 | | |
390 | | |
391 | | |
392 |
| |
393 | | |
394 |
| |
395 | | |
396 | | |
397 | | |
398 | | |
399 | | |
400 | | |
401 | | |
402 | | |
403 | | |
404 | | |
405 | | |
406 | | |
407 | | |
408 | | |
409 |
| |
410 | | |
411 |
| |
412 | | |
413 | | |
414 |
| |
415 | | |
416 | | |
417 | | |
418 | | |
419 | | |
420 | | |
421 | | |
422 | | |
423 | | |
424 | | |
425 | | |
426 | | |
427 | | |
428 | | |
429 | | |
430 | | |
431 | | |
432 | | |
433 | | |
434 | ||
435 |
| |
436 | ||
437 | | |
438 |
| |
439 | | |
440 | | |
441 |
| |
442 | | |
443 | | |
444 | | |
445 | | |
446 |
| |
447 | | |
448 | | |
449 | | |
450 |
| |
451 | | |
452 | | |
453 | | |
454 | | |
455 | | |
456 |
| |
457 | | |
458 | | |
459 | | |
460 | | |
461 | | |
462 | | |
463 | | |
464 | | |
465 | | |
466 | | |
467 | | |
468 |
| |
469 | | |
470 | | |
471 | | |
472 | | |
473 | | |
474 | | |
475 | | |
476 | | |
477 | | |
478 | | |
479 | | |
480 |
| |
481 | | |
482 | | |
483 | | |
484 | | |
485 | | |
486 | | |
487 | | |
488 | | |
489 | | |
490 | | |
491 | | |
492 | | |
493 |
| |
494 | | |
495 | | |
496 | | |
497 | | |
498 | | |
499 | | |
500 | | |
501 | | |
502 | | |
503 | | |
504 | | |
505 | | |
506 | | |
507 | | |
508 | | |
509 |
| |
510 | | |
511 | | |
512 | | |
513 | | |
514 | | |
515 | | |
516 | | |
517 | | |
518 | | |
519 | | |
520 | | |
521 | | |
522 | | |
523 | | |
524 | | |
525 | | |
526 | | |
527 | | |
528 | | |
529 | | |
530 | | |
531 | | |
532 | | |
533 | | |
534 | | |
535 | | |
536 | | |
537 | | |
538 | | |
539 | | |
540 | | |
541 | | |
542 | | |
543 | | |
544 | | |
545 | | |
546 | | |
547 | | |
548 | | |
549 | | |
550 | | |
551 | | |
552 | | |
553 | | |
554 |
| |
555 | | |
556 | | |
557 | | |
558 | | |
559 | | |
560 | | |
561 | | |
562 | | |
563 | | |
564 | | |
565 | | |
566 | | |
567 | | |
568 | | |
569 | | |
570 |
| |
571 | | |
572 | | |
573 |
| |
574 | | |
575 | | |
576 | | |
577 | | |
578 |
| |
579 | | |
580 | | |
581 | | |
582 |
| |
583 | | |
584 | | |
585 | | |
586 | | |
587 | | |
588 |
| |
589 | | |
590 | | |
591 | | |
592 | | |
593 | | |
594 | | |
595 | | |
596 | | |
597 | | |
598 | | |
599 | | |
600 |
| |
601 | | |
602 | | |
603 | | |
604 | | |
605 | | |
606 | | |
607 | | |
608 | | |
609 | | |
610 | | |
611 | | |
612 |
| |
613 | | |
614 | | |
615 | | |
616 | | |
617 | | |
618 | | |
619 | | |
620 | | |
621 | | |
622 | | |
623 | | |
624 | | |
625 |
| |
626 | | |
627 | | |
628 | | |
629 | | |
630 | | |
631 | | |
632 | | |
633 | | |
634 | | |
635 | | |
636 | | |
637 | | |
638 | | |
639 | | |
640 | | |
641 |
| |
642 | | |
643 | | |
644 | | |
645 | | |
646 | | |
647 | | |
648 | | |
649 | | |
650 | | |
651 | | |
652 | | |
653 | | |
654 | | |
655 | | |
656 | | |
657 | | |
658 | | |
659 | | |
660 | | |
661 | | |
662 | | |
663 | | |
664 | | |
665 | | |
666 | | |
667 | | |
668 | | |
669 | | |
670 | | |
671 | | |
672 | | |
673 | | |
674 | | |
675 | | |
676 | | |
677 | | |
678 | | |
679 | | |
680 | | |
681 | | |
682 | | |
683 | | |
684 | | |
685 | | |
686 |
| |
687 | | |
688 | | |
689 | | |
690 | | |
691 | | |
692 | | |
693 | | |
694 | | |
695 | | |
696 | | |
697 | | |
698 | | |
699 | | |
700 | | |
701 | | |
702 | ||
1 | # :title: Transaction::Simple -- Active Object Transaction Support for Ruby | |
2 | # :main: Transaction::Simple | |
3 | # | |
4 | # == Licence | |
5 | # | |
6 | # Permission is hereby granted, free of charge, to any person obtaining a | |
7 | # copy of this software and associated documentation files (the "Software"), | |
8 | # to deal in the Software without restriction, including without limitation | |
9 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
10 | # and/or sell copies of the Software, and to permit persons to whom the | |
11 | # Software is furnished to do so, subject to the following conditions: | |
12 | # | |
13 | # The above copyright notice and this permission notice shall be included in | |
14 | # all copies or substantial portions of the Software. | |
15 | # | |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
19 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
22 | # DEALINGS IN THE SOFTWARE. | |
23 | #-- | |
24 | # Transaction::Simple | |
25 | # Simple object transaction support for Ruby | |
26 | # Version 1.3.0 | |
27 | # | |
28 | # Copyright (c) 2003 - 2005 Austin Ziegler | |
29 | # | |
30 | # $Id: simple.rb,v 1.5 2005/05/05 16:16:49 austin Exp $ | |
31 | #++ | |
32 | # The "Transaction" namespace can be used for additional transaction | |
33 | # support objects and modules. | |
34 | module Transaction | |
35 | # A standard exception for transaction errors. | |
36 | class TransactionError < StandardError; end | |
37 | # The TransactionAborted exception is used to indicate when a | |
38 | # transaction has been aborted in the block form. | |
39 | class TransactionAborted < Exception; end | |
40 | # The TransactionCommitted exception is used to indicate when a | |
41 | # transaction has been committed in the block form. | |
42 | class TransactionCommitted < Exception; end | |
43 | ||
44 | te = "Transaction Error: %s" | |
45 | ||
46 | Messages = { | |
47 | :bad_debug_object => | |
48 | te % "the transaction debug object must respond to #<<.", | |
49 | :unique_names => | |
50 | te % "named transactions must be unique.", | |
51 | :no_transaction_open => | |
52 | te % "no transaction open.", | |
53 | :cannot_rewind_no_transaction => | |
54 | te % "cannot rewind; there is no current transaction.", | |
55 | :cannot_rewind_named_transaction => | |
56 | te % "cannot rewind to transaction %s because it does not exist.", | |
57 | :cannot_rewind_transaction_before_block => | |
58 | te % "cannot rewind a transaction started before the execution block.", | |
59 | :cannot_abort_no_transaction => | |
60 | te % "cannot abort; there is no current transaction.", | |
61 | :cannot_abort_transaction_before_block => | |
62 | te % "cannot abort a transaction started before the execution block.", | |
63 | :cannot_abort_named_transaction => | |
64 | te % "cannot abort nonexistant transaction %s.", | |
65 | :cannot_commit_no_transaction => | |
66 | te % "cannot commit; there is no current transaction.", | |
67 | :cannot_commit_transaction_before_block => | |
68 | te % "cannot commit a transaction started before the execution block.", | |
69 | :cannot_commit_named_transaction => | |
70 | te % "cannot commit nonexistant transaction %s.", | |
71 | :cannot_start_empty_block_transaction => | |
72 | te % "cannot start a block transaction with no objects.", | |
73 | :cannot_obtain_transaction_lock => | |
74 | te % "cannot obtain transaction lock for #%s.", | |
75 | } | |
76 | ||
77 | # = Transaction::Simple for Ruby | |
78 | # Simple object transaction support for Ruby | |
79 | # | |
80 | # == Introduction | |
81 | # Transaction::Simple provides a generic way to add active transaction | |
82 | # support to objects. The transaction methods added by this module will | |
83 | # work with most objects, excluding those that cannot be | |
84 | # <i>Marshal</i>ed (bindings, procedure objects, IO instances, or | |
85 | # singleton objects). | |
86 | # | |
87 | # The transactions supported by Transaction::Simple are not backed | |
88 | # transactions; they are not associated with any sort of data store. | |
89 | # They are "live" transactions occurring in memory and in the object | |
90 | # itself. This is to allow "test" changes to be made to an object | |
91 | # before making the changes permanent. | |
92 | # | |
93 | # Transaction::Simple can handle an "infinite" number of transaction | |
94 | # levels (limited only by memory). If I open two transactions, commit | |
95 | # the second, but abort the first, the object will revert to the | |
96 | # original version. | |
97 | # | |
98 | # Transaction::Simple supports "named" transactions, so that multiple | |
99 | # levels of transactions can be committed, aborted, or rewound by | |
100 | # referring to the appropriate name of the transaction. Names may be any | |
101 | # object *except* +nil+. As with Hash keys, String names will be | |
102 | # duplicated and frozen before using. | |
103 | # | |
104 | # Copyright:: Copyright © 2003 - 2005 by Austin Ziegler | |
105 | # Version:: 1.3.0 | |
106 | # Licence:: MIT-Style | |
107 | # | |
108 | # Thanks to David Black for help with the initial concept that led to | |
109 | # this library. | |
110 | # | |
111 | # == Usage | |
112 | # include 'transaction/simple' | |
113 | # | |
114 | # v = "Hello, you." # -> "Hello, you." | |
115 | # v.extend(Transaction::Simple) # -> "Hello, you." | |
116 | # | |
117 | # v.start_transaction # -> ... (a Marshal string) | |
118 | # v.transaction_open? # -> true | |
119 | # v.gsub!(/you/, "world") # -> "Hello, world." | |
120 | # | |
121 | # v.rewind_transaction # -> "Hello, you." | |
122 | # v.transaction_open? # -> true | |
123 | # | |
124 | # v.gsub!(/you/, "HAL") # -> "Hello, HAL." | |
125 | # v.abort_transaction # -> "Hello, you." | |
126 | # v.transaction_open? # -> false | |
127 | # | |
128 | # v.start_transaction # -> ... (a Marshal string) | |
129 | # v.start_transaction # -> ... (a Marshal string) | |
130 | # | |
131 | # v.transaction_open? # -> true | |
132 | # v.gsub!(/you/, "HAL") # -> "Hello, HAL." | |
133 | # | |
134 | # v.commit_transaction # -> "Hello, HAL." | |
135 | # v.transaction_open? # -> true | |
136 | # v.abort_transaction # -> "Hello, you." | |
137 | # v.transaction_open? # -> false | |
138 | # | |
139 | # == Named Transaction Usage | |
140 | # v = "Hello, you." # -> "Hello, you." | |
141 | # v.extend(Transaction::Simple) # -> "Hello, you." | |
142 | # | |
143 | # v.start_transaction(:first) # -> ... (a Marshal string) | |
144 | # v.transaction_open? # -> true | |
145 | # v.transaction_open?(:first) # -> true | |
146 | # v.transaction_open?(:second) # -> false | |
147 | # v.gsub!(/you/, "world") # -> "Hello, world." | |
148 | # | |
149 | # v.start_transaction(:second) # -> ... (a Marshal string) | |
150 | # v.gsub!(/world/, "HAL") # -> "Hello, HAL." | |
151 | # v.rewind_transaction(:first) # -> "Hello, you." | |
152 | # v.transaction_open? # -> true | |
153 | # v.transaction_open?(:first) # -> true | |
154 | # v.transaction_open?(:second) # -> false | |
155 | # | |
156 | # v.gsub!(/you/, "world") # -> "Hello, world." | |
157 | # v.start_transaction(:second) # -> ... (a Marshal string) | |
158 | # v.gsub!(/world/, "HAL") # -> "Hello, HAL." | |
159 | # v.transaction_name # -> :second | |
160 | # v.abort_transaction(:first) # -> "Hello, you." | |
161 | # v.transaction_open? # -> false | |
162 | # | |
163 | # v.start_transaction(:first) # -> ... (a Marshal string) | |
164 | # v.gsub!(/you/, "world") # -> "Hello, world." | |
165 | # v.start_transaction(:second) # -> ... (a Marshal string) | |
166 | # v.gsub!(/world/, "HAL") # -> "Hello, HAL." | |
167 | # | |
168 | # v.commit_transaction(:first) # -> "Hello, HAL." | |
169 | # v.transaction_open? # -> false | |
170 | # | |
171 | # == Block Usage | |
172 | # v = "Hello, you." # -> "Hello, you." | |
173 | # Transaction::Simple.start(v) do |tv| | |
174 | # # v has been extended with Transaction::Simple and an unnamed | |
175 | # # transaction has been started. | |
176 | # tv.transaction_open? # -> true | |
177 | # tv.gsub!(/you/, "world") # -> "Hello, world." | |
178 | # | |
179 | # tv.rewind_transaction # -> "Hello, you." | |
180 | # tv.transaction_open? # -> true | |
181 | # | |
182 | # tv.gsub!(/you/, "HAL") # -> "Hello, HAL." | |
183 | # # The following breaks out of the transaction block after | |
184 | # # aborting the transaction. | |
185 | # tv.abort_transaction # -> "Hello, you." | |
186 | # end | |
187 | # # v still has Transaction::Simple applied from here on out. | |
188 | # v.transaction_open? # -> false | |
189 | # | |
190 | # Transaction::Simple.start(v) do |tv| | |
191 | # tv.start_transaction # -> ... (a Marshal string) | |
192 | # | |
193 | # tv.transaction_open? # -> true | |
194 | # tv.gsub!(/you/, "HAL") # -> "Hello, HAL." | |
195 | # | |
196 | # # If #commit_transaction were called without having started a | |
197 | # # second transaction, then it would break out of the transaction | |
198 | # # block after committing the transaction. | |
199 | # tv.commit_transaction # -> "Hello, HAL." | |
200 | # tv.transaction_open? # -> true | |
201 | # tv.abort_transaction # -> "Hello, you." | |
202 | # end | |
203 | # v.transaction_open? # -> false | |
204 | # | |
205 | # == Named Transaction Usage | |
206 | # v = "Hello, you." # -> "Hello, you." | |
207 | # v.extend(Transaction::Simple) # -> "Hello, you." | |
208 | # | |
209 | # v.start_transaction(:first) # -> ... (a Marshal string) | |
210 | # v.transaction_open? # -> true | |
211 | # v.transaction_open?(:first) # -> true | |
212 | # v.transaction_open?(:second) # -> false | |
213 | # v.gsub!(/you/, "world") # -> "Hello, world." | |
214 | # | |
215 | # v.start_transaction(:second) # -> ... (a Marshal string) | |
216 | # v.gsub!(/world/, "HAL") # -> "Hello, HAL." | |
217 | # v.rewind_transaction(:first) # -> "Hello, you." | |
218 | # v.transaction_open? # -> true | |
219 | # v.transaction_open?(:first) # -> true | |
220 | # v.transaction_open?(:second) # -> false | |
221 | # | |
222 | # v.gsub!(/you/, "world") # -> "Hello, world." | |
223 | # v.start_transaction(:second) # -> ... (a Marshal string) | |
224 | # v.gsub!(/world/, "HAL") # -> "Hello, HAL." | |
225 | # v.transaction_name # -> :second | |
226 | # v.abort_transaction(:first) # -> "Hello, you." | |
227 | # v.transaction_open? # -> false | |
228 | # | |
229 | # v.start_transaction(:first) # -> ... (a Marshal string) | |
230 | # v.gsub!(/you/, "world") # -> "Hello, world." | |
231 | # v.start_transaction(:second) # -> ... (a Marshal string) | |
232 | # v.gsub!(/world/, "HAL") # -> "Hello, HAL." | |
233 | # | |
234 | # v.commit_transaction(:first) # -> "Hello, HAL." | |
235 | # v.transaction_open? # -> false | |
236 | # | |
237 | # == Thread Safety | |
238 | # Threadsafe version of Transaction::Simple and | |
239 | # Transaction::Simple::Group exist; these are loaded from | |
240 | # 'transaction/simple/threadsafe' and | |
241 | # 'transaction/simple/threadsafe/group', respectively, and are | |
242 | # represented in Ruby code as Transaction::Simple::ThreadSafe and | |
243 | # Transaction::Simple::ThreadSafe::Group, respectively. | |
244 | # | |
245 | # == Contraindications | |
246 | # While Transaction::Simple is very useful, it has some severe | |
247 | # limitations that must be understood. Transaction::Simple: | |
248 | # | |
249 | # * uses Marshal. Thus, any object which cannot be <i>Marshal</i>ed | |
250 | # cannot use Transaction::Simple. In my experience, this affects | |
251 | # singleton objects more often than any other object. It may be that | |
252 | # Ruby 2.0 will solve this problem. | |
253 | # * does not manage resources. Resources external to the object and its | |
254 | # instance variables are not managed at all. However, all instance | |
255 | # variables and objects "belonging" to those instance variables are | |
256 | # managed. If there are object reference counts to be handled, | |
257 | # Transaction::Simple will probably cause problems. | |
258 | # * is not inherently thread-safe. In the ACID ("atomic, consistent, | |
259 | # isolated, durable") test, Transaction::Simple provides CD, but it is | |
260 | # up to the user of Transaction::Simple to provide isolation and | |
261 | # atomicity. Transactions should be considered "critical sections" in | |
262 | # multi-threaded applications. If thread safety and atomicity is | |
263 | # absolutely required, use Transaction::Simple::ThreadSafe, which uses | |
264 | # a Mutex object to synchronize the accesses on the object during the | |
265 | # transaction operations. | |
266 | # * does not necessarily maintain Object#__id__ values on rewind or | |
267 | # abort. This may change for future versions that will be Ruby 1.8 or | |
268 | # better *only*. Certain objects that support #replace will maintain | |
269 | # Object#__id__. | |
270 | # * Can be a memory hog if you use many levels of transactions on many | |
271 | # objects. | |
272 | # | |
273 | module Simple | |
274 | TRANSACTION_SIMPLE_VERSION = '1.3.0' | |
275 | ||
276 | # Sets the Transaction::Simple debug object. It must respond to #<<. | |
277 | # Sets the transaction debug object. Debugging will be performed | |
278 | # automatically if there's a debug object. The generic transaction | |
279 | # error class. | |
280 | def self.debug_io=(io) | |
281 | if io.nil? | |
282 | @tdi = nil | |
283 | @debugging = false | |
284 | else | |
285 | unless io.respond_to?(:<<) | |
286 | raise TransactionError, Messages[:bad_debug_object] | |
287 | end | |
288 | @tdi = io | |
289 | @debugging = true | |
290 | end | |
291 | end | |
292 | ||
293 | # Returns +true+ if we are debugging. | |
294 | def self.debugging? | |
295 | @debugging | |
296 | end | |
297 | ||
298 | # Returns the Transaction::Simple debug object. It must respond to | |
299 | # #<<. | |
300 | def self.debug_io | |
301 | @tdi ||= "" | |
302 | @tdi | |
303 | end | |
304 | ||
305 | # If +name+ is +nil+ (default), then returns +true+ if there is | |
306 | # currently a transaction open. | |
307 | # | |
308 | # If +name+ is specified, then returns +true+ if there is currently a | |
309 | # transaction that responds to +name+ open. | |
310 | def transaction_open?(name = nil) | |
311 | if name.nil? | |
312 | if Transaction::Simple.debugging? | |
313 | Transaction::Simple.debug_io << "Transaction " << | |
314 | "[#{(@__transaction_checkpoint__.nil?) ? 'closed' : 'open'}]\n" | |
315 | end | |
316 | return (not @__transaction_checkpoint__.nil?) | |
317 | else | |
318 | if Transaction::Simple.debugging? | |
319 | Transaction::Simple.debug_io << "Transaction(#{name.inspect}) " << | |
320 | "[#{(@__transaction_checkpoint__.nil?) ? 'closed' : 'open'}]\n" | |
321 | end | |
322 | return ((not @__transaction_checkpoint__.nil?) and @__transaction_names__.include?(name)) | |
323 | end | |
324 | end | |
325 | ||
326 | # Returns the current name of the transaction. Transactions not | |
327 | # explicitly named are named +nil+. | |
328 | def transaction_name | |
329 | if @__transaction_checkpoint__.nil? | |
330 | raise TransactionError, Messages[:no_transaction_open] | |
331 | end | |
332 | if Transaction::Simple.debugging? | |
333 | Transaction::Simple.debug_io << "#{'|' * @__transaction_level__} " << | |
334 | "Transaction Name: #{@__transaction_names__[-1].inspect}\n" | |
335 | end | |
336 | if @__transaction_names__[-1].kind_of?(String) | |
337 | @__transaction_names__[-1].dup | |
338 | else | |
339 | @__transaction_names__[-1] | |
340 | end | |
341 | end | |
342 | ||
343 | # Starts a transaction. Stores the current object state. If a | |
344 | # transaction name is specified, the transaction will be named. | |
345 | # Transaction names must be unique. Transaction names of +nil+ will be | |
346 | # treated as unnamed transactions. | |
347 | def start_transaction(name = nil) | |
348 | @__transaction_level__ ||= 0 | |
349 | @__transaction_names__ ||= [] | |
350 | ||
351 | if name.nil? | |
352 | @__transaction_names__ << nil | |
353 | ss = "" if Transaction::Simple.debugging? | |
354 | else | |
355 | if @__transaction_names__.include?(name) | |
356 | raise TransactionError, Messages[:unique_names] | |
357 | end | |
358 | name = name.dup.freeze if name.kind_of?(String) | |
359 | @__transaction_names__ << name | |
360 | ss = "(#{name.inspect})" if Transaction::Simple.debugging? | |
361 | end | |
362 | ||
363 | @__transaction_level__ += 1 | |
364 | ||
365 | if Transaction::Simple.debugging? | |
366 | Transaction::Simple.debug_io << "#{'>' * @__transaction_level__} " << | |
367 | "Start Transaction#{ss}\n" | |
368 | end | |
369 | ||
370 | @__transaction_checkpoint__ = Marshal.dump(self) | |
371 | end | |
372 | ||
373 | # Rewinds the transaction. If +name+ is specified, then the | |
374 | # intervening transactions will be aborted and the named transaction | |
375 | # will be rewound. Otherwise, only the current transaction is rewound. | |
376 | def rewind_transaction(name = nil) | |
377 | if @__transaction_checkpoint__.nil? | |
378 | raise TransactionError, Messages[:cannot_rewind_no_transaction] | |
379 | end | |
380 | ||
381 | # Check to see if we are trying to rewind a transaction that is | |
382 | # outside of the current transaction block. | |
383 | if @__transaction_block__ and name | |
384 | nix = @__transaction_names__.index(name) + 1 | |
385 | if nix < @__transaction_block__ | |
386 | raise TransactionError, Messages[:cannot_rewind_transaction_before_block] | |
387 | end | |
388 | end | |
389 | ||
390 | if name.nil? | |
391 | __rewind_this_transaction | |
392 | ss = "" if Transaction::Simple.debugging? | |
393 | else | |
394 | unless @__transaction_names__.include?(name) | |
395 | raise TransactionError, Messages[:cannot_rewind_named_transaction] % name.inspect | |
396 | end | |
397 | ss = "(#{name})" if Transaction::Simple.debugging? | |
398 | ||
399 | while @__transaction_names__[-1] != name | |
400 | @__transaction_checkpoint__ = __rewind_this_transaction | |
401 | if Transaction::Simple.debugging? | |
402 | Transaction::Simple.debug_io << "#{'|' * @__transaction_level__} " << | |
403 | "Rewind Transaction#{ss}\n" | |
404 | end | |
405 | @__transaction_level__ -= 1 | |
406 | @__transaction_names__.pop | |
407 | end | |
408 | __rewind_this_transaction | |
409 | end | |
410 | if Transaction::Simple.debugging? | |
411 | Transaction::Simple.debug_io << "#{'|' * @__transaction_level__} " << | |
412 | "Rewind Transaction#{ss}\n" | |
413 | end | |
414 | self | |
415 | end | |
416 | ||
417 | # Aborts the transaction. Resets the object state to what it was | |
418 | # before the transaction was started and closes the transaction. If | |
419 | # +name+ is specified, then the intervening transactions and the named | |
420 | # transaction will be aborted. Otherwise, only the current transaction | |
421 | # is aborted. | |
422 | # | |
423 | # If the current or named transaction has been started by a block | |
424 | # (Transaction::Simple.start), then the execution of the block will be | |
425 | # halted with +break+ +self+. | |
426 | def abort_transaction(name = nil) | |
427 | if @__transaction_checkpoint__.nil? | |
428 | raise TransactionError, Messages[:cannot_abort_no_transaction] | |
429 | end | |
430 | ||
431 | # Check to see if we are trying to abort a transaction that is | |
432 | # outside of the current transaction block. Otherwise, raise | |
433 | # TransactionAborted if they are the same. | |
434 | if @__transaction_block__ and name | |
435 | nix = @__transaction_names__.index(name) + 1 | |
436 | if nix < @__transaction_block__ | |
437 | raise TransactionError, Messages[:cannot_abort_transaction_before_block] | |
438 | end | |
439 | ||
440 | raise TransactionAborted if @__transaction_block__ == nix | |
441 | end | |
442 | ||
443 | raise TransactionAborted if @__transaction_block__ == @__transaction_level__ | |
444 | ||
445 | if name.nil? | |
446 | __abort_transaction(name) | |
447 | else | |
448 | unless @__transaction_names__.include?(name) | |
449 | raise TransactionError, Messages[:cannot_abort_named_transaction] % name.inspect | |
450 | end | |
451 | __abort_transaction(name) while @__transaction_names__.include?(name) | |
452 | end | |
453 | self | |
454 | end | |
455 | ||
456 | # If +name+ is +nil+ (default), the current transaction level is | |
457 | # closed out and the changes are committed. | |
458 | # | |
459 | # If +name+ is specified and +name+ is in the list of named | |
460 | # transactions, then all transactions are closed and committed until | |
461 | # the named transaction is reached. | |
462 | def commit_transaction(name = nil) | |
463 | if @__transaction_checkpoint__.nil? | |
464 | raise TransactionError, Messages[:cannot_commit_no_transaction] | |
465 | end | |
466 | @__transaction_block__ ||= nil | |
467 | ||
468 | # Check to see if we are trying to commit a transaction that is | |
469 | # outside of the current transaction block. Otherwise, raise | |
470 | # TransactionCommitted if they are the same. | |
471 | if @__transaction_block__ and name | |
472 | nix = @__transaction_names__.index(name) + 1 | |
473 | if nix < @__transaction_block__ | |
474 | raise TransactionError, Messages[:cannot_commit_transaction_before_block] | |
475 | end | |
476 | ||
477 | raise TransactionCommitted if @__transaction_block__ == nix | |
478 | end | |
479 | ||
480 | raise TransactionCommitted if @__transaction_block__ == @__transaction_level__ | |
481 | ||
482 | if name.nil? | |
483 | ss = "" if Transaction::Simple.debugging? | |
484 | __commit_transaction | |
485 | if Transaction::Simple.debugging? | |
486 | Transaction::Simple.debug_io << "#{'<' * @__transaction_level__} " << | |
487 | "Commit Transaction#{ss}\n" | |
488 | end | |
489 | else | |
490 | unless @__transaction_names__.include?(name) | |
491 | raise TransactionError, Messages[:cannot_commit_named_transaction] % name.inspect | |
492 | end | |
493 | ss = "(#{name})" if Transaction::Simple.debugging? | |
494 | ||
495 | while @__transaction_names__[-1] != name | |
496 | if Transaction::Simple.debugging? | |
497 | Transaction::Simple.debug_io << "#{'<' * @__transaction_level__} " << | |
498 | "Commit Transaction#{ss}\n" | |
499 | end | |
500 | __commit_transaction | |
501 | end | |
502 | if Transaction::Simple.debugging? | |
503 | Transaction::Simple.debug_io << "#{'<' * @__transaction_level__} " << | |
504 | "Commit Transaction#{ss}\n" | |
505 | end | |
506 | __commit_transaction | |
507 | end | |
508 | ||
509 | self | |
510 | end | |
511 | ||
512 | # Alternative method for calling the transaction methods. An optional | |
513 | # name can be specified for named transaction support. | |
514 | # | |
515 | # #transaction(:start):: #start_transaction | |
516 | # #transaction(:rewind):: #rewind_transaction | |
517 | # #transaction(:abort):: #abort_transaction | |
518 | # #transaction(:commit):: #commit_transaction | |
519 | # #transaction(:name):: #transaction_name | |
520 | # #transaction:: #transaction_open? | |
521 | def transaction(action = nil, name = nil) | |
522 | case action | |
523 | when :start | |
524 | start_transaction(name) | |
525 | when :rewind | |
526 | rewind_transaction(name) | |
527 | when :abort | |
528 | abort_transaction(name) | |
529 | when :commit | |
530 | commit_transaction(name) | |
531 | when :name | |
532 | transaction_name | |
533 | when nil | |
534 | transaction_open?(name) | |
535 | end | |
536 | end | |
537 | ||
538 | # Allows specific variables to be excluded from transaction support. | |
539 | # Must be done after extending the object but before starting the | |
540 | # first transaction on the object. | |
541 | # | |
542 | # vv.transaction_exclusions << "@io" | |
543 | def transaction_exclusions | |
544 | @transaction_exclusions ||= [] | |
545 | end | |
546 | ||
547 | class << self | |
548 | def __common_start(name, vars, &block) | |
549 | if vars.empty? | |
550 | raise TransactionError, Messages[:cannot_start_empty_block_transaction] | |
551 | end | |
552 | ||
553 | if block | |
554 | begin | |
555 | vlevel = {} | |
556 | ||
557 | vars.each do |vv| | |
558 | vv.extend(Transaction::Simple) | |
559 | vv.start_transaction(name) | |
560 | vlevel[vv.__id__] = vv.instance_variable_get(:@__transaction_level__) | |
561 | vv.instance_variable_set(:@__transaction_block__, vlevel[vv.__id__]) | |
562 | end | |
563 | ||
564 | yield(*vars) | |
565 | rescue TransactionAborted | |
566 | vars.each do |vv| | |
567 | if name.nil? and vv.transaction_open? | |
568 | loop do | |
569 | tlevel = vv.instance_variable_get(:@__transaction_level__) || -1 | |
570 | vv.instance_variable_set(:@__transaction_block__, -1) | |
571 | break if tlevel < vlevel[vv.__id__] | |
572 | vv.abort_transaction if vv.transaction_open? | |
573 | end | |
574 | elsif vv.transaction_open?(name) | |
575 | vv.instance_variable_set(:@__transaction_block__, -1) | |
576 | vv.abort_transaction(name) | |
577 | end | |
578 | end | |
579 | rescue TransactionCommitted | |
580 | nil | |
581 | ensure | |
582 | vars.each do |vv| | |
583 | if name.nil? and vv.transaction_open? | |
584 | loop do | |
585 | tlevel = vv.instance_variable_get(:@__transaction_level__) || -1 | |
586 | break if tlevel < vlevel[vv.__id__] | |
587 | vv.instance_variable_set(:@__transaction_block__, -1) | |
588 | vv.commit_transaction if vv.transaction_open? | |
589 | end | |
590 | elsif vv.transaction_open?(name) | |
591 | vv.instance_variable_set(:@__transaction_block__, -1) | |
592 | vv.commit_transaction(name) | |
593 | end | |
594 | end | |
595 | end | |
596 | else | |
597 | vars.each do |vv| | |
598 | vv.extend(Transaction::Simple) | |
599 | vv.start_transaction(name) | |
600 | end | |
601 | end | |
602 | end | |
603 | private :__common_start | |
604 | ||
605 | def start_named(name, *vars, &block) | |
606 | __common_start(name, vars, &block) | |
607 | end | |
608 | ||
609 | def start(*vars, &block) | |
610 | __common_start(nil, vars, &block) | |
611 | end | |
612 | end | |
613 | ||
614 | def __abort_transaction(name = nil) #:nodoc: | |
615 | @__transaction_checkpoint__ = __rewind_this_transaction | |
616 | ||
617 | if name.nil? | |
618 | ss = "" if Transaction::Simple.debugging? | |
619 | else | |
620 | ss = "(#{name.inspect})" if Transaction::Simple.debugging? | |
621 | end | |
622 | ||
623 | if Transaction::Simple.debugging? | |
624 | Transaction::Simple.debug_io << "#{'<' * @__transaction_level__} " << | |
625 | "Abort Transaction#{ss}\n" | |
626 | end | |
627 | @__transaction_level__ -= 1 | |
628 | @__transaction_names__.pop | |
629 | if @__transaction_level__ < 1 | |
630 | @__transaction_level__ = 0 | |
631 | @__transaction_names__ = [] | |
632 | end | |
633 | end | |
634 | ||
635 | TRANSACTION_CHECKPOINT = "@__transaction_checkpoint__" #:nodoc: | |
636 | SKIP_TRANSACTION_VARS = [TRANSACTION_CHECKPOINT, "@__transaction_level__"] #:nodoc: | |
637 | ||
638 | def __rewind_this_transaction #:nodoc: | |
639 | rr = Marshal.restore(@__transaction_checkpoint__) | |
640 | ||
641 | begin | |
642 | self.replace(rr) if respond_to?(:replace) | |
643 | rescue | |
644 | nil | |
645 | end | |
646 | ||
647 | rr.instance_variables.each do |vv| | |
648 | next if SKIP_TRANSACTION_VARS.include?(vv) | |
649 | next if self.transaction_exclusions.include?(vv) | |
650 | if respond_to?(:instance_variable_get) | |
651 | instance_variable_set(vv, rr.instance_variable_get(vv)) | |
652 | else | |
653 | instance_eval(%q|#{vv} = rr.instance_eval("#{vv}")|) | |
654 | end | |
655 | end | |
656 | ||
657 | new_ivar = instance_variables - rr.instance_variables - SKIP_TRANSACTION_VARS | |
658 | new_ivar.each do |vv| | |
659 | if respond_to?(:instance_variable_set) | |
660 | instance_variable_set(vv, nil) | |
661 | else | |
662 | instance_eval(%q|#{vv} = nil|) | |
663 | end | |
664 | end | |
665 | ||
666 | if respond_to?(:instance_variable_get) | |
667 | rr.instance_variable_get(TRANSACTION_CHECKPOINT) | |
668 | else | |
669 | rr.instance_eval(TRANSACTION_CHECKPOINT) | |
670 | end | |
671 | end | |
672 | ||
673 | def __commit_transaction #:nodoc: | |
674 | if respond_to?(:instance_variable_get) | |
675 | @__transaction_checkpoint__ = Marshal.restore(@__transaction_checkpoint__).instance_variable_get(TRANSACTION_CHECKPOINT) | |
676 | else | |
677 | @__transaction_checkpoint__ = Marshal.restore(@__transaction_checkpoint__).instance_eval(TRANSACTION_CHECKPOINT) | |
678 | end | |
679 | ||
680 | @__transaction_level__ -= 1 | |
681 | @__transaction_names__.pop | |
682 | ||
683 | if @__transaction_level__ < 1 | |
684 | @__transaction_level__ = 0 | |
685 | @__transaction_names__ = [] | |
686 | end | |
687 | end | |
688 | ||
689 | private :__abort_transaction | |
690 | private :__rewind_this_transaction | |
691 | private :__commit_transaction | |
692 | end | |
693 | end |
rool/rails/typo/trunk/vendor/rails/activerecord/lib/active_record/version.rb:
prev. | current | |
module ActiveRecord | ||
module VERSION #:nodoc: | ||
MAJOR = 1 | ||
4 | | |
4 | MINOR = 14 | |
TINY = 2 | ||
STRING = [MAJOR, MINOR, TINY].join('.') |
rool/rails/typo/trunk/vendor/rails/activerecord/test/aaa_create_tables_test.rb:
prev. | current | |
# The filename begins with "aaa" to ensure this is the first test. | ||
require 'abstract_unit' | ||
4 | ||
4 | class AAACreateTablesTest < Test::Unit::TestCase | |
5 | self.use_transactional_fixtures = false | |
6 | ||
def setup | ||
@base_path = "#{File.dirname(__FILE__)}/fixtures/db_definitions" | ||
end | ||
... | ... | |
recreate ActiveRecord::Base | ||
assert true | ||
end | ||
15 | ||
16 | def test_load_schema | |
17 | eval(File.read("#{File.dirname(__FILE__)}/fixtures/db_definitions/schema.rb")) | |
18 | assert true | |
19 | end | |
def test_drop_and_create_courses_table | ||
recreate Course, '2' | ||
... | ... | |
end | ||
def execute_sql_file(path, connection) | ||
28 | | |
29 | | |
30 | | |
31 | | |
32 | | |
35 | # OpenBase has a different format for sql files | |
36 | if current_adapter?(:OpenBaseAdapter) then | |
37 | File.read(path).split("go").each_with_index do |sql, i| | |
38 | begin | |
39 | # OpenBase does not support comments embedded in sql | |
40 | connection.execute(sql,"SQL statement ##{i}") unless sql.blank? | |
41 | rescue ActiveRecord::StatementInvalid | |
42 | #$stderr.puts "warning: #{$!}" | |
43 | end | |
44 | end | |
45 | else | |
46 | File.read(path).split(';').each_with_index do |sql, i| | |
47 | begin | |
48 | connection.execute("\n\n-- statement ##{i}\n#{sql}\n") unless sql.blank? | |
49 | rescue ActiveRecord::StatementInvalid | |
50 | #$stderr.puts "warning: #{$!}" | |
51 | end | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/abstract_unit.rb:
prev. | current | |
self.use_transactional_fixtures = (ENV['AR_NO_TX_FIXTURES'] != "yes") | ||
def create_fixtures(*table_names, &block) | ||
19 | | |
19 | Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures/", table_names, {}, &block) | |
end | ||
21 | ||
22 | def assert_date_from_db(expected, actual, message = nil) | |
23 | # SQL Server doesn't have a separate column type just for dates, | |
24 | # so the time is in the string and incorrectly formatted | |
25 | if current_adapter?(:SQLServerAdapter) | |
26 | assert_equal expected.strftime("%Y/%m/%d 00:00:00"), actual.strftime("%Y/%m/%d 00:00:00") | |
27 | elsif current_adapter?(:SybaseAdapter) | |
28 | assert_equal expected.to_s, actual.to_date.to_s, message | |
29 | else | |
30 | assert_equal expected.to_s, actual.to_s, message | |
31 | end | |
32 | end | |
33 | ||
34 | def assert_queries(num = 1) | |
35 | ActiveRecord::Base.connection.class.class_eval do | |
36 | self.query_count = 0 | |
37 | alias_method :execute, :execute_with_query_counting | |
38 | end | |
39 | yield | |
40 | ensure | |
41 | ActiveRecord::Base.connection.class.class_eval do | |
42 | alias_method :execute, :execute_without_query_counting | |
43 | end | |
44 | assert_equal num, ActiveRecord::Base.connection.query_count, "#{ActiveRecord::Base.connection.query_count} instead of #{num} queries were executed." | |
45 | end | |
46 | ||
47 | def assert_no_queries(&block) | |
48 | assert_queries(0, &block) | |
49 | end | |
end | ||
def current_adapter?(type) | ||
... | ... | |
ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters.const_get(type)) | ||
end | ||
57 | ActiveRecord::Base.connection.class.class_eval do | |
58 | cattr_accessor :query_count | |
59 | alias_method :execute_without_query_counting, :execute | |
60 | def execute_with_query_counting(sql, name = nil) | |
61 | self.query_count += 1 | |
62 | execute_without_query_counting(sql, name) | |
63 | end | |
64 | end | |
65 | ||
#ActiveRecord::Base.logger = Logger.new(STDOUT) | ||
#ActiveRecord::Base.colorize_logging = false |
rool/rails/typo/trunk/vendor/rails/activerecord/test/adapter_test.rb:
prev. | current | |
end | ||
def test_indexes | ||
21 | idx_name = "accounts_idx" | |
22 | ||
if @connection.respond_to?(:indexes) | ||
indexes = @connection.indexes("accounts") | ||
assert indexes.empty? | ||
25 | | |
27 | @connection.add_index :accounts, :firm_id, :name => idx_name | |
indexes = @connection.indexes("accounts") | ||
assert_equal "accounts", indexes.first.table | ||
28 | | |
30 | # OpenBase does not have the concept of a named index | |
31 | # Indexes are merely properties of columns. | |
32 | assert_equal idx_name, indexes.first.name unless current_adapter?(:OpenBaseAdapter) | |
assert !indexes.first.unique | ||
assert_equal ["firm_id"], indexes.first.columns | ||
else | ||
... | ... | |
end | ||
ensure | ||
36 | | |
40 | @connection.remove_index(:accounts, :name => idx_name) rescue nil | |
end | ||
42 | ||
43 | def test_current_database | |
44 | if @connection.respond_to?(:current_database) | |
45 | assert_equal ENV['ARUNIT_DB_NAME'] || "activerecord_unittest", @connection.current_database | |
46 | end | |
47 | end | |
49 | def test_table_alias | |
50 | def @connection.test_table_alias_length() 10; end | |
51 | class << @connection | |
52 | alias_method :old_table_alias_length, :table_alias_length | |
53 | alias_method :table_alias_length, :test_table_alias_length | |
54 | end | |
55 | ||
56 | assert_equal 'posts', @connection.table_alias_for('posts') | |
57 | assert_equal 'posts_comm', @connection.table_alias_for('posts_comments') | |
58 | assert_equal 'dbo_posts', @connection.table_alias_for('dbo.posts') | |
59 | ||
60 | class << @connection | |
61 | alias_method :table_alias_length, :old_table_alias_length | |
62 | end | |
63 | end | |
64 | ||
# test resetting sequences in odd tables in postgreSQL | ||
if ActiveRecord::Base.connection.respond_to?(:reset_pk_sequence!) | ||
require 'fixtures/movie' | ||
... | ... | |
sub = Subscriber.new(:name => 'robert drake') | ||
sub.id = 'bob drake' | ||
55 | | |
81 | assert_nothing_raised { sub.save! } | |
end | ||
end | ||
84 | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/associations_go_eager_test.rb:
prev. | current | |
require 'fixtures/author' | ||
require 'fixtures/category' | ||
require 'fixtures/company' | ||
7 | require 'fixtures/person' | |
8 | require 'fixtures/reader' | |
class EagerAssociationTest < Test::Unit::TestCase | ||
fixtures :posts, :comments, :authors, :categories, :categories_posts, | ||
10 | | |
12 | :companies, :accounts, :tags, :people, :readers | |
def test_loading_with_one_association | ||
posts = Post.find(:all, :include => :comments) | ||
... | ... | |
end | ||
def test_eager_association_loading_with_belongs_to_and_limit_and_multiple_associations | ||
93 | | |
95 | posts = Post.find(:all, :include => [:author, :very_special_comment], :limit => 1, :order => 'posts.id') | |
assert_equal 1, posts.length | ||
95 | | |
97 | assert_equal [1], posts.collect { |p| p.id } | |
end | ||
def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_multiple_associations | ||
99 | | |
100 | | |
101 | | |
101 | posts = Post.find(:all, :include => [:author, :very_special_comment], :limit => 1, :offset => 1, :order => 'posts.id') | |
102 | assert_equal 1, posts.length | |
103 | assert_equal [2], posts.collect { |p| p.id } | |
end | ||
106 | def test_eager_with_has_many_through | |
107 | posts_with_comments = people(:michael).posts.find(:all, :include => :comments ) | |
108 | posts_with_author = people(:michael).posts.find(:all, :include => :author ) | |
109 | posts_with_comments_and_author = people(:michael).posts.find(:all, :include => [ :comments, :author ]) | |
110 | assert_equal 2, posts_with_comments.inject(0) { |sum, post| sum += post.comments.size } | |
111 | assert_equal authors(:david), assert_no_queries { posts_with_author.first.author } | |
112 | assert_equal authors(:david), assert_no_queries { posts_with_comments_and_author.first.author } | |
113 | end | |
114 | ||
def test_eager_with_has_many_and_limit | ||
posts = Post.find(:all, :order => 'posts.id asc', :include => [ :author, :comments ], :limit => 2) | ||
assert_equal 2, posts.size | ||
... | ... | |
end | ||
def test_eager_with_has_many_and_limit_and_conditions_array_on_the_eagers | ||
123 | | |
124 | | |
125 | | |
134 | posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => [ "authors.name = ?", 'David' ]) | |
135 | assert_equal 2, posts.size | |
136 | ||
137 | count = Post.count(:include => [ :author, :comments ], :limit => 2, :conditions => [ "authors.name = ?", 'David' ]) | |
138 | assert_equal count, posts.size | |
end | ||
141 | def test_eager_with_has_many_and_limit_ond_high_offset | |
142 | posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ]) | |
143 | assert_equal 0, posts.size | |
144 | end | |
145 | ||
146 | def test_count_eager_with_has_many_and_limit_ond_high_offset | |
147 | posts = Post.count(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ]) | |
148 | assert_equal 0, posts | |
149 | end | |
150 | ||
def test_eager_with_has_many_and_limit_with_no_results | ||
posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => "posts.title = 'magic forest'") | ||
assert_equal 0, posts.size | ||
... | ... | |
end | ||
def test_eager_with_has_many_and_limit_and_conditions_on_the_eagers | ||
144 | | |
145 | | |
146 | | |
147 | | |
148 | | |
149 | | |
150 | | |
167 | posts = authors(:david).posts.find(:all, | |
168 | :include => :comments, | |
169 | :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'", | |
170 | :limit => 2 | |
171 | ) | |
172 | assert_equal 2, posts.size | |
173 | ||
174 | count = Post.count( | |
175 | :include => [ :comments, :author ], | |
176 | :conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')", | |
177 | :limit => 2 | |
178 | ) | |
179 | assert_equal count, posts.size | |
end | ||
def test_eager_association_loading_with_habtm | ||
... | ... | |
post = Post.find(6, :include=>[ :monkeys, :elephants ]) | ||
} | ||
end | ||
237 | ||
238 | def find_all_ordered(className, include=nil) | |
239 | className.find(:all, :order=>"#{className.table_name}.#{className.primary_key}", :include=>include) | |
240 | end | |
242 | def test_eager_with_multiple_associations_with_same_table_has_many_and_habtm | |
243 | # Eager includes of has many and habtm associations aren't necessarily sorted in the same way | |
244 | def assert_equal_after_sort(item1, item2, item3 = nil) | |
245 | assert_equal(item1.sort{|a,b| a.id <=> b.id}, item2.sort{|a,b| a.id <=> b.id}) | |
246 | assert_equal(item3.sort{|a,b| a.id <=> b.id}, item2.sort{|a,b| a.id <=> b.id}) if item3 | |
247 | end | |
248 | # Test regular association, association with conditions, association with | |
249 | # STI, and association with conditions assured not to be true | |
250 | post_types = [:posts, :hello_posts, :special_posts, :nonexistent_posts] | |
251 | # test both has_many and has_and_belongs_to_many | |
252 | [Author, Category].each do |className| | |
253 | d1 = find_all_ordered(className) | |
254 | # test including all post types at once | |
255 | d2 = find_all_ordered(className, post_types) | |
256 | d1.each_index do |i| | |
257 | assert_equal(d1[i], d2[i]) | |
258 | assert_equal_after_sort(d1[i].posts, d2[i].posts) | |
259 | post_types[1..-1].each do |post_type| | |
260 | # test including post_types together | |
261 | d3 = find_all_ordered(className, [:posts, post_type]) | |
262 | assert_equal(d1[i], d3[i]) | |
263 | assert_equal_after_sort(d1[i].posts, d3[i].posts) | |
264 | assert_equal_after_sort(d1[i].send(post_type), d2[i].send(post_type), d3[i].send(post_type)) | |
265 | end | |
266 | end | |
267 | end | |
268 | end | |
269 | ||
270 | def test_eager_with_multiple_associations_with_same_table_has_one | |
271 | d1 = find_all_ordered(Firm) | |
272 | d2 = find_all_ordered(Firm, :account) | |
273 | d1.each_index do |i| | |
274 | assert_equal(d1[i], d2[i]) | |
275 | assert_equal(d1[i].account, d2[i].account) | |
276 | end | |
277 | end | |
278 | ||
279 | def test_eager_with_multiple_associations_with_same_table_belongs_to | |
280 | firm_types = [:firm, :firm_with_basic_id, :firm_with_other_name, :firm_with_condition] | |
281 | d1 = find_all_ordered(Client) | |
282 | d2 = find_all_ordered(Client, firm_types) | |
283 | d1.each_index do |i| | |
284 | assert_equal(d1[i], d2[i]) | |
285 | firm_types.each { |type| assert_equal(d1[i].send(type), d2[i].send(type)) } | |
286 | end | |
287 | end | |
def test_eager_with_valid_association_as_string_not_symbol | ||
assert_nothing_raised { Post.find(:all, :include => 'comments') } | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/associations_test.rb:
prev. | current | |
require 'fixtures/computer' | ||
require 'fixtures/customer' | ||
require 'fixtures/order' | ||
10 | require 'fixtures/category' | |
require 'fixtures/post' | ||
require 'fixtures/author' | ||
... | ... | |
def test_triple_equality | ||
assert Account === companies(:first_firm).account | ||
83 | assert companies(:first_firm).account === Account | |
end | ||
def test_type_mismatch | ||
... | ... | |
assert_equal "can't be empty", account.errors.on("credit_limit") | ||
end | ||
162 | def test_build_association_twice_without_saving_affects_nothing | |
163 | count_of_account = Account.count | |
164 | firm = Firm.find(:first) | |
165 | account1 = firm.build_account("credit_limit" => 1000) | |
166 | account2 = firm.build_account("credit_limit" => 2000) | |
167 | ||
168 | assert_equal count_of_account, Account.count | |
169 | end | |
170 | ||
def test_create_association | ||
firm = Firm.new("name" => "GlobalMegaCorp") | ||
firm.save | ||
... | ... | |
assert_equal 2, Firm.find(:first).clients.length | ||
end | ||
294 | def test_find_many_with_merged_options | |
295 | assert_equal 1, companies(:first_firm).limited_clients.size | |
296 | assert_equal 1, companies(:first_firm).limited_clients.find(:all).size | |
297 | assert_equal 2, companies(:first_firm).limited_clients.find(:all, :limit => nil).size | |
298 | end | |
299 | ||
300 | def test_triple_equality | |
301 | assert !(Array === Firm.find(:first).clients) | |
302 | assert Firm.find(:first).clients === Array | |
303 | end | |
304 | ||
def test_finding_default_orders | ||
assert_equal "Summit", Firm.find(:first).clients.first.name | ||
end | ||
... | ... | |
assert_equal 0, companies(:first_firm).clients_of_firm.size | ||
assert_equal 0, companies(:first_firm).clients_of_firm(true).size | ||
end | ||
553 | ||
554 | def test_delete_all | |
555 | force_signal37_to_load_all_clients_of_firm | |
556 | companies(:first_firm).clients_of_firm.create("name" => "Another Client") | |
557 | assert_equal 2, companies(:first_firm).clients_of_firm.size | |
558 | companies(:first_firm).clients_of_firm.delete_all | |
559 | assert_equal 0, companies(:first_firm).clients_of_firm.size | |
560 | assert_equal 0, companies(:first_firm).clients_of_firm(true).size | |
561 | end | |
563 | def test_delete_all_with_not_yet_loaded_association_collection | |
564 | force_signal37_to_load_all_clients_of_firm | |
565 | companies(:first_firm).clients_of_firm.create("name" => "Another Client") | |
566 | assert_equal 2, companies(:first_firm).clients_of_firm.size | |
567 | companies(:first_firm).clients_of_firm.reset | |
568 | companies(:first_firm).clients_of_firm.delete_all | |
569 | assert_equal 0, companies(:first_firm).clients_of_firm.size | |
570 | assert_equal 0, companies(:first_firm).clients_of_firm(true).size | |
571 | end | |
572 | ||
def test_clearing_an_association_collection | ||
firm = companies(:first_firm) | ||
client_id = firm.clients_of_firm.first.id | ||
... | ... | |
def test_three_levels_of_dependence | ||
topic = Topic.create "title" => "neat and simple" | ||
reply = topic.replies.create "title" => "neat and simple", "content" => "still digging it" | ||
644 | | |
685 | silly_reply = reply.replies.create "title" => "neat and simple", "content" => "ain't complaining" | |
assert_nothing_raised { topic.destroy } | ||
end | ||
... | ... | |
assert_equal num_accounts - 1, Account.count | ||
end | ||
667 | ||
def test_depends_and_nullify | ||
num_accounts = Account.count | ||
num_companies = Company.count | ||
... | ... | |
assert_nothing_raised { account.firm = account.firm } | ||
end | ||
790 | def test_triple_equality | |
791 | assert Client.find(3).firm === Firm | |
792 | assert Firm === Client.find(3).firm | |
793 | end | |
794 | ||
def test_type_mismatch | ||
assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = 1 } | ||
assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = Project.find(1) } | ||
... | ... | |
assert_equal 0, Topic.find(debate.id).send(:read_attribute, "replies_count"), "First reply deleted" | ||
end | ||
852 | def test_belongs_to_counter_with_reassigning | |
853 | t1 = Topic.create("title" => "t1") | |
854 | t2 = Topic.create("title" => "t2") | |
855 | r1 = Reply.new("title" => "r1", "content" => "r1") | |
856 | r1.topic = t1 | |
857 | ||
858 | assert r1.save | |
859 | assert_equal 1, Topic.find(t1.id).replies.size | |
860 | assert_equal 0, Topic.find(t2.id).replies.size | |
861 | ||
862 | r1.topic = Topic.find(t2.id) | |
863 | ||
864 | assert r1.save | |
865 | assert_equal 0, Topic.find(t1.id).replies.size | |
866 | assert_equal 1, Topic.find(t2.id).replies.size | |
867 | ||
868 | r1.topic = nil | |
869 | ||
870 | assert_equal 0, Topic.find(t1.id).replies.size | |
871 | assert_equal 0, Topic.find(t2.id).replies.size | |
872 | ||
873 | r1.topic = t1 | |
874 | ||
875 | assert_equal 1, Topic.find(t1.id).replies.size | |
876 | assert_equal 0, Topic.find(t2.id).replies.size | |
877 | ||
878 | r1.destroy | |
879 | ||
880 | assert_equal 0, Topic.find(t1.id).replies.size | |
881 | assert_equal 0, Topic.find(t2.id).replies.size | |
882 | end | |
883 | ||
def test_assignment_before_parent_saved | ||
client = Client.find(:first) | ||
apple = Firm.new("name" => "Apple") | ||
... | ... | |
assert_not_nil computer.developer, ":foreign key == attribute didn't lock up" # ' | ||
end | ||
863 | | |
864 | | |
865 | | |
866 | ||
867 | | |
868 | | |
940 | def test_counter_cache | |
941 | topic = Topic.create :title => "Zoom-zoom-zoom" | |
942 | assert_equal 0, topic[:replies_count] | |
870 | | |
871 | | |
944 | reply = Reply.create(:title => "re: zoom", :content => "speedy quick!") | |
945 | reply.topic = topic | |
873 | | |
874 | | |
947 | assert_equal 1, topic.reload[:replies_count] | |
948 | assert_equal 1, topic.replies.size | |
876 | | |
877 | | |
950 | topic[:replies_count] = 15 | |
951 | assert_equal 15, topic.replies.size | |
end | ||
954 | def test_custom_counter_cache | |
955 | reply = Reply.create(:title => "re: zoom", :content => "speedy quick!") | |
956 | assert_equal 0, reply[:replies_count] | |
957 | ||
958 | silly = SillyReply.create(:title => "gaga", :content => "boo-boo") | |
959 | silly.reply = reply | |
960 | ||
961 | assert_equal 1, reply.reload[:replies_count] | |
962 | assert_equal 1, reply.replies.size | |
963 | ||
964 | reply[:replies_count] = 17 | |
965 | assert_equal 17, reply.replies.size | |
966 | end | |
967 | ||
def test_store_two_association_with_one_save | ||
num_orders = Order.count | ||
num_customers = Customer.count | ||
... | ... | |
class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase | ||
1015 | | |
1103 | fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects | |
def test_has_and_belongs_to_many | ||
david = Developer.find(1) | ||
... | ... | |
active_record = Project.find(1) | ||
assert !active_record.developers.empty? | ||
1025 | | |
1113 | assert_equal 3, active_record.developers.size | |
assert active_record.developers.include?(david) | ||
end | ||
1117 | def test_triple_equality | |
1118 | assert !(Array === Developer.find(1).projects) | |
1119 | assert Developer.find(1).projects === Array | |
1120 | end | |
1121 | ||
def test_adding_single | ||
jamis = Developer.find(2) | ||
jamis.projects.reload # causing the collection to load | ||
... | ... | |
no_of_devels = Developer.count | ||
no_of_projects = Project.count | ||
now = Date.today | ||
1152 | | |
ken = Developer.new("name" => "Ken") | ||
ken.projects.push_with_attributes( Project.find(1), :joined_on => now ) | ||
p = Project.new("name" => "Foomatic") | ||
... | ... | |
assert_equal 2, ken.projects(true).size | ||
kenReloaded = Developer.find_by_name 'Ken' | ||
1167 | | |
1168 | | |
1169 | | |
1170 | | |
1171 | | |
1172 | | |
1259 | kenReloaded.projects.each {|prj| assert_date_from_db(now, prj.joined_on)} | |
1260 | end | |
1261 | ||
1262 | def test_habtm_saving_multiple_relationships | |
1263 | new_project = Project.new("name" => "Grimetime") | |
1264 | amount_of_developers = 4 | |
1265 | developers = (0..amount_of_developers).collect {|i| Developer.create(:name => "JME #{i}") } | |
1266 | ||
1267 | new_project.developer_ids = [developers[0].id, developers[1].id] | |
1268 | new_project.developers_with_callback_ids = [developers[2].id, developers[3].id] | |
1269 | assert new_project.save | |
1270 | ||
1271 | new_project.reload | |
1272 | assert_equal amount_of_developers, new_project.developers.size | |
1273 | amount_of_developers.times do |i| | |
1274 | assert_equal developers[i].name, new_project.developers[i].name | |
end | ||
end | ||
... | ... | |
def test_uniq_before_the_fact | ||
projects(:active_record).developers << developers(:jamis) | ||
projects(:active_record).developers << developers(:david) | ||
1203 | | |
1305 | assert_equal 3, projects(:active_record, :reload).developers.size | |
end | ||
def test_deleting | ||
... | ... | |
active_record = Project.find(1) | ||
david.projects.reload | ||
assert_equal 2, david.projects.size | ||
1211 | | |
1313 | assert_equal 3, active_record.developers.size | |
david.projects.delete(active_record) | ||
assert_equal 1, david.projects.size | ||
assert_equal 1, david.projects(true).size | ||
1217 | | |
1319 | assert_equal 2, active_record.developers(true).size | |
end | ||
def test_deleting_array | ||
... | ... | |
david = Developer.find(1) | ||
active_record = Project.find(1) | ||
active_record.developers.reload | ||
1232 | | |
1334 | assert_equal 3, active_record.developers_by_sql.size | |
active_record.developers_by_sql.delete(david) | ||
1235 | | |
1337 | assert_equal 2, active_record.developers_by_sql(true).size | |
end | ||
def test_deleting_array_with_sql | ||
active_record = Project.find(1) | ||
active_record.developers.reload | ||
1241 | | |
1343 | assert_equal 3, active_record.developers_by_sql.size | |
active_record.developers_by_sql.delete(Developer.find(:all)) | ||
assert_equal 0, active_record.developers_by_sql(true).size | ||
... | ... | |
end | ||
def test_additional_columns_from_join_table | ||
1264 | | |
1265 | | |
1266 | | |
1267 | | |
1268 | | |
1269 | | |
1270 | | |
1366 | assert_date_from_db Date.new(2004, 10, 10), Developer.find(1).projects.first.joined_on | |
end | ||
def test_destroy_all | ||
... | ... | |
def test_rich_association | ||
jamis = developers(:jamis) | ||
jamis.projects.push_with_attributes(projects(:action_controller), :joined_on => Date.today) | ||
1285 | | |
1286 | | |
1287 | | |
1288 | | |
1289 | | |
1290 | | |
1291 | | |
1292 | | |
1293 | | |
1381 | ||
1382 | assert_date_from_db Date.today, jamis.projects.select { |p| p.name == projects(:action_controller).name }.first.joined_on | |
1383 | assert_date_from_db Date.today, developers(:jamis).projects.select { |p| p.name == projects(:action_controller).name }.first.joined_on | |
end | ||
def test_associations_with_conditions | ||
1297 | | |
1387 | assert_equal 3, projects(:active_record).developers.size | |
assert_equal 1, projects(:active_record).developers_named_david.size | ||
assert_equal developers(:david), projects(:active_record).developers_named_david.find(developers(:david).id) | ||
assert_equal developers(:david), projects(:active_record).salaried_developers.find(developers(:david).id) | ||
projects(:active_record).developers_named_david.clear | ||
1304 | | |
1394 | assert_equal 2, projects(:active_record, :reload).developers.size | |
end | ||
def test_find_in_association | ||
... | ... | |
assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id.to_s), "SQL find" | ||
end | ||
1419 | def test_find_with_merged_options | |
1420 | assert_equal 1, projects(:active_record).limited_developers.size | |
1421 | assert_equal 1, projects(:active_record).limited_developers.find(:all).size | |
1422 | assert_equal 3, projects(:active_record).limited_developers.find(:all, :limit => nil).size | |
1423 | end | |
def test_new_with_values_in_collection | ||
jamis = DeveloperForProjectWithAfterCreateHook.find_by_name('Jamis') | ||
... | ... | |
assert project.developers.include?(david) | ||
end | ||
1342 | | |
1437 | def test_find_in_association_with_options | |
developers = projects(:active_record).developers.find(:all) | ||
1344 | | |
1439 | assert_equal 3, developers.size | |
1346 | | |
1347 | | |
1441 | assert_equal developers(:poor_jamis), projects(:active_record).developers.find(:first, :conditions => "salary < 10000") | |
1442 | assert_equal developers(:jamis), projects(:active_record).developers.find(:first, :order => "salary DESC") | |
end | ||
def test_replace_with_less | ||
... | ... | |
AND developer_id = #{developer.id} | ||
end_sql | ||
end | ||
1492 | ||
1493 | def test_updating_attributes_on_non_rich_associations | |
1494 | welcome = categories(:technology).posts.first | |
1495 | welcome.title = "Something else" | |
1496 | assert welcome.save! | |
1497 | end | |
1498 | ||
1499 | def test_updating_attributes_on_rich_associations | |
1500 | david = projects(:action_controller).developers.first | |
1501 | david.name = "DHH" | |
1502 | assert_raises(ActiveRecord::ReadOnlyRecord) { david.save! } | |
1503 | end | |
1504 | ||
1505 | ||
1506 | def test_updating_attributes_on_rich_associations_with_limited_find | |
1507 | david = projects(:action_controller).developers.find(:all, :select => "developers.*").first | |
1508 | david.name = "DHH" | |
1509 | assert david.save! | |
1510 | end | |
1511 | ||
1512 | def test_join_table_alias | |
1513 | assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL').size | |
1514 | end | |
end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/base_test.rb:
prev. | current | |
require 'fixtures/topic' | ||
require 'fixtures/reply' | ||
require 'fixtures/company' | ||
5 | require 'fixtures/customer' | |
require 'fixtures/developer' | ||
require 'fixtures/project' | ||
require 'fixtures/default' | ||
... | ... | |
class Post < ActiveRecord::Base; end | ||
class Computer < ActiveRecord::Base; end | ||
class NonExistentTable < ActiveRecord::Base; end | ||
20 | ||
21 | class TestOracleDefault < ActiveRecord::Base; end | |
class LoosePerson < ActiveRecord::Base | ||
attr_protected :credit_rating, :administrator | ||
25 | self.abstract_class = true | |
end | ||
class LooseDescendant < LoosePerson | ||
... | ... | |
topic = Topic.new | ||
topic.title = "New Topic" | ||
topic.save | ||
136 | | |
137 | | |
138 | topic_reloaded = Topic.find(topic.id) | |
139 | assert_equal("New Topic", topic_reloaded.title) | |
end | ||
142 | def test_save! | |
143 | topic = Topic.new(:title => "New Topic") | |
144 | assert topic.save! | |
145 | end | |
146 | ||
147 | def test_hashes_not_mangled | |
148 | new_topic = { :title => "New Topic" } | |
149 | new_topic_values = { :title => "AnotherTopic" } | |
150 | ||
151 | topic = Topic.new(new_topic) | |
152 | assert_equal new_topic[:title], topic.title | |
153 | ||
154 | topic.attributes= new_topic_values | |
155 | assert_equal new_topic_values[:title], topic.title | |
156 | end | |
157 | ||
def test_create_many | ||
topics = Topic.create([ { "title" => "first" }, { "title" => "second" }]) | ||
assert_equal 2, topics.size | ||
... | ... | |
if ActiveRecord::Base.generate_read_methods | ||
assert_readers(Topic, %w(type replies_count)) | ||
assert_readers(Firm, %w(type)) | ||
252 | | |
270 | assert_readers(Client, %w(type ruby_type rating?)) | |
else | ||
[Topic, Firm, Client].each {|klass| assert_equal klass.read_methods, {}} | ||
end | ||
... | ... | |
# SQL Server doesn't have a separate column type just for dates, so all are returned as time | ||
return true if current_adapter?(:SQLServerAdapter) | ||
276 | | |
277 | | |
278 | | |
279 | | |
294 | if current_adapter?(:SybaseAdapter) | |
295 | # Sybase ctlib does not (yet?) support the date type; use datetime instead. | |
296 | assert_kind_of( | |
297 | Time, Topic.find(1).last_read, | |
298 | "The last_read attribute should be of the Time class" | |
299 | ) | |
300 | else | |
301 | assert_kind_of( | |
302 | Date, Topic.find(1).last_read, | |
303 | "The last_read attribute should be of the Date class" | |
304 | ) | |
305 | end | |
end | ||
def test_preserving_time_objects | ||
... | ... | |
assert_equal 2, Topic.update_all("content = 'bulk updated!'") | ||
assert_equal "bulk updated!", Topic.find(1).content | ||
assert_equal "bulk updated!", Topic.find(2).content | ||
437 | | |
463 | assert_equal 2, Topic.update_all(['content = ?', 'bulk updated again!']) | |
assert_equal "bulk updated again!", Topic.find(1).content | ||
assert_equal "bulk updated again!", Topic.find(2).content | ||
end | ||
... | ... | |
# Oracle has some funky default handling, so it requires a bit of | ||
# extra testing. See ticket #2788. | ||
518 | | |
519 | | |
544 | if current_adapter?(:OracleAdapter) | |
545 | test = TestOracleDefault.new | |
assert_equal "X", test.test_char | ||
assert_equal "hello", test.test_string | ||
assert_equal 3, test.test_int | ||
... | ... | |
def test_utc_as_time_zone | ||
# Oracle and SQLServer do not have a TIME datatype. | ||
528 | | |
554 | return true if current_adapter?(:SQLServerAdapter) || current_adapter?(:OracleAdapter) | |
Topic.default_timezone = :utc | ||
attributes = { "bonus_time" => "5:42:00AM" } | ||
... | ... | |
topic = Topic.find(topic.id) | ||
assert_nil topic.last_read | ||
547 | | |
573 | ||
574 | # Sybase adapter does not allow nulls in boolean columns | |
575 | if current_adapter?(:SybaseAdapter) | |
576 | assert topic.approved == false | |
577 | else | |
578 | assert_nil topic.approved | |
579 | end | |
end | ||
def test_equality | ||
551 | | |
583 | assert_equal Topic.find(1), Topic.find(2).topic | |
end | ||
def test_equality_of_new_records | ||
... | ... | |
end | ||
def test_hashing | ||
559 | | |
591 | assert_equal [ Topic.find(1) ], [ Topic.find(2).topic ] & [ Topic.find(1) ] | |
end | ||
def test_destroy_new_record | ||
... | ... | |
end | ||
def test_multiparameter_attributes_on_date | ||
641 | | |
642 | | |
643 | ||
attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "24" } | ||
topic = Topic.find(1) | ||
topic.attributes = attributes | ||
# note that extra #to_date call allows test to pass for Oracle, which | ||
# treats dates/times the same | ||
649 | | |
678 | assert_date_from_db Date.new(2004, 6, 24), topic.last_read.to_date | |
end | ||
def test_multiparameter_attributes_on_date_with_empty_date | ||
653 | | |
654 | | |
655 | ||
attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "" } | ||
topic = Topic.find(1) | ||
topic.attributes = attributes | ||
# note that extra #to_date call allows test to pass for Oracle, which | ||
# treats dates/times the same | ||
661 | | |
687 | assert_date_from_db Date.new(2004, 6, 1), topic.last_read.to_date | |
end | ||
def test_multiparameter_attributes_on_date_with_all_empty | ||
... | ... | |
task.attributes = attributes | ||
assert_equal time, task.starting | ||
end | ||
725 | ||
726 | def test_multiparameter_assignment_of_aggregation | |
727 | customer = Customer.new | |
728 | address = Address.new("The Street", "The City", "The Country") | |
729 | attributes = { "address(1)" => address.street, "address(2)" => address.city, "address(3)" => address.country } | |
730 | customer.attributes = attributes | |
731 | assert_equal address, customer.address | |
732 | end | |
def test_attributes_on_dummy_time | ||
# Oracle and SQL Server do not have a TIME datatype. | ||
702 | | |
736 | return true if current_adapter?(:SQLServerAdapter) || current_adapter?(:OracleAdapter) | |
attributes = { | ||
"bonus_time" => "5:42:00AM" | ||
... | ... | |
b_true = Booleantest.find(true_id) | ||
assert b_true.value? | ||
end | ||
757 | ||
758 | def test_boolean_cast_from_string | |
759 | b_false = Booleantest.create({ "value" => "0" }) | |
760 | false_id = b_false.id | |
761 | b_true = Booleantest.create({ "value" => "1" }) | |
762 | true_id = b_true.id | |
763 | ||
764 | b_false = Booleantest.find(false_id) | |
765 | assert !b_false.value? | |
766 | b_true = Booleantest.find(true_id) | |
767 | assert b_true.value? | |
768 | end | |
def test_clone | ||
topic = Topic.find(1) | ||
... | ... | |
def test_default | ||
default = Default.new | ||
787 | | |
788 | | |
789 | | |
790 | | |
791 | | |
792 | ||
793 | | |
794 | | |
795 | | |
796 | | |
797 | | |
# fixed dates / times | ||
assert_equal Date.new(2004, 1, 1), default.fixed_date | ||
assert_equal Time.local(2004, 1,1,0,0,0,0), default.fixed_time | ||
... | ... | |
def test_count_with_join | ||
res = Post.count_by_sql "SELECT COUNT(*) FROM posts LEFT JOIN comments ON posts.id=comments.post_id WHERE posts.#{QUOTED_TYPE} = 'Post'" | ||
1048 | | |
1083 | res2 = nil | |
assert_nothing_raised do | ||
res2 = Post.count("posts.#{QUOTED_TYPE} = 'Post'", | ||
"LEFT JOIN comments ON posts.id=comments.post_id") | ||
end | ||
assert_equal res, res2 | ||
1089 | ||
1090 | res3 = nil | |
1091 | assert_nothing_raised do | |
1092 | res3 = Post.count(:conditions => "posts.#{QUOTED_TYPE} = 'Post'", | |
1093 | :joins => "LEFT JOIN comments ON posts.id=comments.post_id") | |
1094 | end | |
1095 | assert_equal res, res3 | |
1096 | ||
1097 | res4 = Post.count_by_sql "SELECT COUNT(p.id) FROM posts p, comments c WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=c.post_id" | |
1098 | res5 = nil | |
1099 | assert_nothing_raised do | |
1100 | res5 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=c.post_id", | |
1101 | :joins => "p, comments c", | |
1102 | :select => "p.id") | |
1103 | end | |
1104 | ||
1105 | assert_equal res4, res5 | |
1106 | ||
1107 | res6 = Post.count_by_sql "SELECT COUNT(DISTINCT p.id) FROM posts p, comments c WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=c.post_id" | |
1108 | res7 = nil | |
1109 | assert_nothing_raised do | |
1110 | res7 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=c.post_id", | |
1111 | :joins => "p, comments c", | |
1112 | :select => "p.id", | |
1113 | :distinct => true) | |
1114 | end | |
1115 | assert_equal res6, res7 | |
end | ||
def test_clear_association_cache_stored | ||
... | ... | |
end | ||
def test_scoped_find_conditions | ||
1085 | | |
1147 | scoped_developers = Developer.with_scope(:find => { :conditions => 'salary > 90000' }) do | |
Developer.find(:all, :conditions => 'id < 5') | ||
end | ||
1088 | | |
1089 | | |
1090 | | |
1150 | assert !scoped_developers.include?(developers(:david)) # David's salary is less than 90,000 | |
1151 | assert_equal 3, scoped_developers.size | |
end | ||
def test_scoped_find_limit_offset | ||
1094 | | |
1155 | scoped_developers = Developer.with_scope(:find => { :limit => 3, :offset => 2 }) do | |
Developer.find(:all, :order => 'id') | ||
end | ||
1097 | | |
1098 | | |
1099 | | |
1100 | | |
1101 | | |
1158 | assert !scoped_developers.include?(developers(:david)) | |
1159 | assert !scoped_developers.include?(developers(:jamis)) | |
1160 | assert_equal 3, scoped_developers.size | |
# Test without scoped find conditions to ensure we get the whole thing | ||
developers = Developer.find(:all, :order => 'id') | ||
1105 | | |
1164 | assert_equal Developer.count, developers.size | |
end | ||
1166 | ||
1167 | def test_base_class | |
1168 | assert LoosePerson.abstract_class? | |
1169 | assert !LooseDescendant.abstract_class? | |
1170 | assert_equal LoosePerson, LoosePerson.base_class | |
1171 | assert_equal LooseDescendant, LooseDescendant.base_class | |
1172 | assert_equal TightPerson, TightPerson.base_class | |
1173 | assert_equal TightPerson, TightDescendant.base_class | |
1174 | end | |
1175 | ||
1176 | def test_assert_queries | |
1177 | query = lambda { ActiveRecord::Base.connection.execute 'select count(*) from developers' } | |
1178 | assert_queries(2) { 2.times { query.call } } | |
1179 | assert_queries 1, &query | |
1180 | assert_no_queries { assert true } | |
1181 | end | |
1182 | ||
1183 | def test_to_xml | |
1184 | xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true) | |
1185 | bonus_time_in_current_timezone = topics(:first).bonus_time.xmlschema | |
1186 | written_on_in_current_timezone = topics(:first).written_on.xmlschema | |
1187 | last_read_in_current_timezone = topics(:first).last_read.xmlschema | |
1188 | assert_equal "<topic>", xml.first(7) | |
1189 | assert xml.include?(%(<title>The First Topic</title>)) | |
1190 | assert xml.include?(%(<author-name>David</author-name>)) | |
1191 | assert xml.include?(%(<id type="integer">1</id>)) | |
1192 | assert xml.include?(%(<replies-count type="integer">0</replies-count>)) | |
1193 | assert xml.include?(%(<written-on type="datetime">#{written_on_in_current_timezone}</written-on>)) | |
1194 | assert xml.include?(%(<content>Have a nice day</content>)) | |
1195 | assert xml.include?(%(<author-email-address>david@loudthinking.com</author-email-address>)) | |
1196 | assert xml.include?(%(<parent-id></parent-id>)) | |
1197 | if current_adapter?(:SybaseAdapter) or current_adapter?(:SQLServerAdapter) | |
1198 | assert xml.include?(%(<last-read type="datetime">#{last_read_in_current_timezone}</last-read>)) | |
1199 | else | |
1200 | assert xml.include?(%(<last-read type="date">2004-04-15</last-read>)) | |
1201 | end | |
1202 | # Oracle and DB2 don't have true boolean or time-only fields | |
1203 | unless current_adapter?(:OracleAdapter) || current_adapter?(:DB2Adapter) | |
1204 | assert xml.include?(%(<approved type="boolean">false</approved>)), "Approved should be a boolean" | |
1205 | assert xml.include?(%(<bonus-time type="datetime">#{bonus_time_in_current_timezone}</bonus-time>)) | |
1206 | end | |
1207 | end | |
1209 | def test_to_xml_skipping_attributes | |
1210 | xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :except => :title) | |
1211 | assert_equal "<topic>", xml.first(7) | |
1212 | assert !xml.include?(%(<title>The First Topic</title>)) | |
1213 | assert xml.include?(%(<author-name>David</author-name>)) | |
1214 | ||
1215 | xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :except => [ :title, :author_name ]) | |
1216 | assert !xml.include?(%(<title>The First Topic</title>)) | |
1217 | assert !xml.include?(%(<author-name>David</author-name>)) | |
1218 | end | |
1219 | ||
1220 | def test_to_xml_including_has_many_association | |
1221 | xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :include => :replies) | |
1222 | assert_equal "<topic>", xml.first(7) | |
1223 | assert xml.include?(%(<replies><reply>)) | |
1224 | assert xml.include?(%(<title>The Second Topic's of the day</title>)) | |
1225 | end | |
1226 | ||
1227 | def test_to_xml_including_belongs_to_association | |
1228 | xml = companies(:first_client).to_xml(:indent => 0, :skip_instruct => true, :include => :firm) | |
1229 | assert !xml.include?("<firm>") | |
1230 | ||
1231 | xml = companies(:second_client).to_xml(:indent => 0, :skip_instruct => true, :include => :firm) | |
1232 | assert xml.include?("<firm>") | |
1233 | end | |
1234 | ||
1235 | def test_to_xml_including_multiple_associations | |
1236 | xml = companies(:first_firm).to_xml(:indent => 0, :skip_instruct => true, :include => [ :clients, :account ]) | |
1237 | assert_equal "<firm>", xml.first(6) | |
1238 | assert xml.include?(%(<account>)) | |
1239 | assert xml.include?(%(<clients><client>)) | |
1240 | end | |
1241 | ||
1242 | def test_to_xml_including_multiple_associations_with_options | |
1243 | xml = companies(:first_firm).to_xml( | |
1244 | :indent => 0, :skip_instruct => true, | |
1245 | :include => { :clients => { :only => :name } } | |
1246 | ) | |
1247 | ||
1248 | assert_equal "<firm>", xml.first(6) | |
1249 | assert xml.include?(%(<client><name>Summit</name></client>)) | |
1250 | assert xml.include?(%(<clients><client>)) | |
1251 | end | |
1252 | ||
1253 | def test_except_attributes | |
1254 | assert_equal( | |
1255 | %w( author_name type id approved replies_count bonus_time written_on content author_email_address parent_id last_read), | |
1256 | topics(:first).attributes(:except => :title).keys | |
1257 | ) | |
1258 | ||
1259 | assert_equal( | |
1260 | %w( replies_count bonus_time written_on content author_email_address parent_id last_read), | |
1261 | topics(:first).attributes(:except => [ :title, :id, :type, :approved, :author_name ]).keys | |
1262 | ) | |
1263 | end | |
1264 | ||
1265 | def test_include_attributes | |
1266 | assert_equal(%w( title ), topics(:first).attributes(:only => :title).keys) | |
1267 | assert_equal(%w( title author_name type id approved ), topics(:first).attributes(:only => [ :title, :id, :type, :approved, :author_name ]).keys) | |
1268 | end | |
1269 | ||
1270 | def test_type_name_with_module_should_handle_beginning | |
1271 | assert_equal 'ActiveRecord::Person', ActiveRecord::Base.send(:type_name_with_module, 'Person') | |
1272 | assert_equal '::Person', ActiveRecord::Base.send(:type_name_with_module, '::Person') | |
1273 | end | |
1274 | ||
# FIXME: this test ought to run, but it needs to run sandboxed so that it | ||
# doesn't b0rk the current test environment by undefing everything. | ||
# | ||
... | ... | |
private | ||
def assert_readers(model, exceptions) | ||
1132 | | |
1133 | | |
1299 | expected_readers = Set.new(model.column_names - (model.serialized_attributes.keys + ['id'])) | |
1300 | expected_readers += expected_readers.map { |col| "#{col}?" } | |
1301 | expected_readers -= exceptions | |
1302 | assert_equal expected_readers, model.read_methods | |
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/binary_test.rb:
prev. | current | |
# Without using prepared statements, it makes no sense to test | ||
# BLOB data with DB2 or Firebird, because the length of a statement | ||
# is limited to 32KB. | ||
23 | | |
23 | unless %w(SQLServer Sybase DB2 Oracle Firebird).include? ActiveRecord::Base.connection.adapter_name | |
def test_load_save | ||
bin = Binary.new | ||
bin.data = @data |
rool/rails/typo/trunk/vendor/rails/activerecord/test/callbacks_test.rb:
prev. | current | |
def test_before_save_returning_false | ||
david = ImmutableDeveloper.find(1) | ||
assert david.valid? | ||
327 | | |
328 | | |
327 | assert !david.save | |
328 | assert_raises(ActiveRecord::RecordNotSaved) { david.save! } | |
david = ImmutableDeveloper.find(1) | ||
david.salary = 10_000_000 | ||
assert !david.valid? | ||
assert !david.save | ||
334 | | |
335 | ||
336 | | |
337 | | |
338 | | |
339 | | |
340 | ||
341 | | |
342 | | |
343 | | |
344 | | |
345 | | |
334 | assert_raises(ActiveRecord::RecordInvalid) { david.save! } | |
end | ||
def test_before_destroy_returning_false | ||
david = ImmutableDeveloper.find(1) | ||
350 | | |
351 | | |
339 | assert !david.destroy | |
assert_not_nil ImmutableDeveloper.find_by_id(1) | ||
341 | end | |
354 | | |
355 | | |
356 | | |
357 | | |
358 | | |
359 | ||
360 | ||
def test_zzz_callback_returning_false # must be run last since we modify CallbackDeveloper | ||
david = CallbackDeveloper.find(1) | ||
CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :returning_false]; return false } |
rool/rails/typo/trunk/vendor/rails/activerecord/test/class_inheritable_attributes_test.rb:
prev. | current | |
require 'test/unit' | ||
require 'abstract_unit' | ||
3 | ||
3 | require 'active_support/core_ext/class/inheritable_attributes' | |
class A | ||
include ClassInheritableAttributes |
rool/rails/typo/trunk/vendor/rails/activerecord/test/column_alias_test.rb:
prev. | current | |
class TestColumnAlias < Test::Unit::TestCase | ||
fixtures :topics | ||
7 | | |
7 | QUERY = if 'Oracle' == ActiveRecord::Base.connection.adapter_name | |
'SELECT id AS pk FROM topics WHERE ROWNUM < 2' | ||
else | ||
'SELECT id AS pk FROM topics' |
rool/rails/typo/trunk/vendor/rails/activerecord/test/connections/native_mysql/connection.rb:
prev. | current | |
ActiveRecord::Base.establish_connection( | ||
:adapter => "mysql", | ||
:username => "rails", | ||
13 | :encoding => "utf8", | |
:database => db1 | ||
) | ||
rool/rails/typo/trunk/vendor/rails/activerecord/test/connections/native_sqlite/connection.rb:
prev. | current | |
make_connection(ActiveRecord::Base, sqlite_test_db, 'sqlite.sql') | ||
make_connection(Course, sqlite_test_db2, 'sqlite2.sql') | ||
37 | ||
37 | load(File.join(BASE_DIR, 'db_definitions', 'schema.rb')) |
rool/rails/typo/trunk/vendor/rails/activerecord/test/connections/native_sqlite3/connection.rb:
prev. | current | |
make_connection(ActiveRecord::Base, sqlite_test_db, 'sqlite.sql') | ||
make_connection(Course, sqlite_test_db2, 'sqlite2.sql') | ||
37 | load(File.join(BASE_DIR, 'db_definitions', 'schema.rb')) |
rool/rails/typo/trunk/vendor/rails/activerecord/test/connections/native_sqlite3/in_memory_connection.rb:
prev. | current | |
make_connection(ActiveRecord::Base, 'sqlite.sql') | ||
make_connection(Course, 'sqlite2.sql') | ||
18 | load("#{File.dirname(__FILE__)}/../../fixtures/db_definitions/schema.rb")) |
rool/rails/typo/trunk/vendor/rails/activerecord/test/deprecated_associations_test.rb:
prev. | current | |
active_record = Project.find(1) | ||
assert active_record.has_developers? | ||
184 | | |
184 | assert_equal 3, active_record.developers_count | |
assert active_record.developers.include?(david) | ||
end | ||
... | ... | |
david.remove_projects(active_record) | ||
assert_equal 1, david.projects_count | ||
195 | | |
195 | assert_equal 2, active_record.developers_count | |
end | ||
def test_has_and_belongs_to_many_zero |
rool/rails/typo/trunk/vendor/rails/activerecord/test/deprecated_finder_test.rb:
prev. | current | |
assert_nil Company.find_first(["name = :name", { :name => "37signals!" }]) | ||
assert_nil Company.find_first(["name = :name", { :name => "37signals!' OR 1=1" }]) | ||
assert_kind_of Time, Topic.find_first(["id = :id", { :id => 1 }]).written_on | ||
77 | | |
78 | | |
79 | | |
80 | | |
81 | | |
82 | | |
end | ||
def test_count |
rool/rails/typo/trunk/vendor/rails/activerecord/test/finder_test.rb:
prev. | current | |
require 'abstract_unit' | ||
require 'fixtures/company' | ||
require 'fixtures/topic' | ||
4 | require 'fixtures/reply' | |
require 'fixtures/entrant' | ||
require 'fixtures/developer' | ||
require 'fixtures/post' | ||
class FinderTest < Test::Unit::TestCase | ||
9 | | |
10 | fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :accounts | |
def test_find | ||
assert_equal(topics(:first).title, Topic.find(1).title) | ||
... | ... | |
assert_equal(entrants(:third).name, entrants.first.name) | ||
end | ||
61 | def test_find_all_with_limit_and_offset_and_multiple_orderings | |
62 | developers = Developer.find(:all, :order => "salary ASC, id DESC", :limit => 3, :offset => 1) | |
63 | assert_equal ["David", "fixture_10", "fixture_9"], developers.collect {|d| d.name} | |
64 | end | |
65 | ||
def test_find_with_limit_and_condition | ||
developers = Developer.find(:all, :order => "id DESC", :conditions => "salary = 100000", :limit => 3, :offset =>7) | ||
assert_equal(1, developers.size) | ||
... | ... | |
Topic.find(1).parent | ||
} | ||
95 | | |
101 | Topic.find(2).topic | |
end | ||
def test_find_only_some_columns | ||
... | ... | |
assert_nil Company.find(:first, :conditions => ["name = :name", { :name => "37signals!" }]) | ||
assert_nil Company.find(:first, :conditions => ["name = :name", { :name => "37signals!' OR 1=1" }]) | ||
assert_kind_of Time, Topic.find(:first, :conditions => ["id = :id", { :id => 1 }]).written_on | ||
160 | | |
161 | | |
162 | | |
163 | | |
164 | | |
165 | | |
end | ||
168 | | |
169 | | |
170 | | |
171 | | |
172 | | |
173 | | |
174 | | |
175 | | |
176 | | |
177 | ||
def test_bind_enumerable | ||
assert_equal '1,2,3', bind('?', [1, 2, 3]) | ||
assert_equal %('a','b','c'), bind('?', %w(a b c)) | ||
... | ... | |
assert_nil Topic.find_by_title("The First Topic!") | ||
end | ||
209 | def test_find_by_one_attribute_with_order_option | |
210 | assert_equal accounts(:signals37), Account.find_by_credit_limit(50, :order => 'id') | |
211 | assert_equal accounts(:rails_core_account), Account.find_by_credit_limit(50, :order => 'id DESC') | |
212 | end | |
213 | ||
214 | def test_find_by_one_attribute_with_conditions | |
215 | assert_equal accounts(:rails_core_account), Account.find_by_credit_limit(50, :conditions => ['firm_id = ?', 6]) | |
216 | end | |
217 | ||
218 | def test_find_by_one_attribute_with_several_options | |
219 | assert_equal accounts(:unknown), Account.find_by_credit_limit(50, :order => 'id DESC', :conditions => ['id != ?', 3]) | |
220 | end | |
221 | ||
def test_find_by_one_missing_attribute | ||
assert_raises(NoMethodError) { Topic.find_by_undertitle("The First Topic!") } | ||
end | ||
... | ... | |
end | ||
def test_find_or_create_from_two_attributes | ||
289 | | |
290 | | |
291 | | |
292 | | |
292 | number_of_topics = Topic.count | |
293 | another = Topic.find_or_create_by_title_and_author_name("Another topic","John") | |
294 | assert_equal number_of_topics + 1, Topic.count | |
295 | assert_equal another, Topic.find_or_create_by_title_and_author_name("Another topic", "John") | |
end | ||
def test_find_with_bad_sql | ||
... | ... | |
:joins => 'LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id', | ||
:conditions => 'project_id=1' | ||
) | ||
344 | | |
347 | assert_equal 3, developers_on_project_one.length | |
developer_names = developers_on_project_one.map { |d| d.name } | ||
assert developer_names.include?('David') | ||
assert developer_names.include?('Jamis') |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/accounts.yml:
prev. | current | |
id: 3 | ||
firm_id: 6 | ||
credit_limit: 50 | ||
14 | ||
15 | last_account: | |
16 | id: 4 | |
17 | firm_id: 2 | |
18 | credit_limit: 60 | |
19 | ||
20 | rails_core_account_2: | |
21 | id: 5 | |
22 | firm_id: 6 | |
23 | credit_limit: 55 | |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/author.rb:
prev. | current | |
has_many :posts_with_comments, :include => :comments, :class_name => "Post" | ||
has_many :posts_with_categories, :include => :categories, :class_name => "Post" | ||
has_many :posts_with_comments_and_categories, :include => [ :comments, :categories ], :order => "posts.id", :class_name => "Post" | ||
6 | has_many :comments, :through => :posts | |
7 | has_many :funky_comments, :through => :posts, :source => :comments | |
9 | has_many :special_posts, :class_name => "Post" | |
10 | has_many :hello_posts, :class_name => "Post", :conditions=>"\#{aliased_table_name}.body = 'hello'" | |
11 | has_many :nonexistent_posts, :class_name => "Post", :conditions=>"\#{aliased_table_name}.body = 'nonexistent'" | |
has_many :posts_with_callbacks, :class_name => "Post", :before_add => :log_before_adding, | ||
8 | | |
9 | | |
13 | :after_add => :log_after_adding, | |
14 | :before_remove => :log_before_removing, | |
15 | :after_remove => :log_after_removing | |
has_many :posts_with_proc_callbacks, :class_name => "Post", | ||
11 | | |
12 | | |
17 | :before_add => Proc.new {|o, r| o.post_log << "before_adding#{r.id}"}, | |
18 | :after_add => Proc.new {|o, r| o.post_log << "after_adding#{r.id}"}, | |
:before_remove => Proc.new {|o, r| o.post_log << "before_removing#{r.id}"}, | ||
14 | | |
20 | :after_remove => Proc.new {|o, r| o.post_log << "after_removing#{r.id}"} | |
has_many :posts_with_multiple_callbacks, :class_name => "Post", | ||
:before_add => [:log_before_adding, Proc.new {|o, r| o.post_log << "before_adding_proc#{r.id}"}], | ||
17 | | |
23 | :after_add => [:log_after_adding, Proc.new {|o, r| o.post_log << "after_adding_proc#{r.id}"}] | |
has_many :unchangable_posts, :class_name => "Post", :before_add => :raise_exception, :after_add => :log_after_adding | ||
26 | has_many :categorizations | |
27 | has_many :categories, :through => :categorizations | |
28 | ||
29 | has_many :nothings, :through => :kateggorisatons, :class_name => 'Category' | |
30 | ||
31 | has_many :author_favorites | |
32 | has_many :favorite_authors, :through => :author_favorites, :order => 'name' | |
33 | ||
34 | has_many :tagging, :through => :posts # through polymorphic has_one | |
35 | has_many :taggings, :through => :posts, :source => :taggings # through polymorphic has_many | |
36 | has_many :tags, :through => :posts # through has_many :through | |
37 | has_many :post_categories, :through => :posts, :source => :categories | |
38 | ||
39 | belongs_to :author_address | |
40 | ||
attr_accessor :post_log | ||
def after_initialize | ||
... | ... | |
raise Exception.new("You can't add a post") | ||
end | ||
end | ||
68 | ||
69 | class AuthorAddress < ActiveRecord::Base | |
70 | has_one :author | |
71 | end | |
72 | ||
73 | class AuthorFavorite < ActiveRecord::Base | |
74 | belongs_to :author | |
75 | belongs_to :favorite_author, :class_name => "Author", :foreign_key => 'favorite_author_id' | |
76 | end | |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/categories_posts.yml:
prev. | current | |
sti_test_sti_habtm: | ||
category_id: 3 | ||
post_id: 6 | ||
20 | ||
21 | general_hello: | |
22 | category_id: 1 | |
23 | post_id: 4 |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/category.rb:
prev. | current | |
class Category < ActiveRecord::Base | ||
has_and_belongs_to_many :posts | ||
3 | has_and_belongs_to_many :special_posts, :class_name => "Post" | |
4 | has_and_belongs_to_many :hello_posts, :class_name => "Post", :conditions => "\#{aliased_table_name}.body = 'hello'" | |
5 | has_and_belongs_to_many :nonexistent_posts, :class_name => "Post", :conditions=>"\#{aliased_table_name}.body = 'nonexistent'" | |
def self.what_are_you | ||
'a category...' | ||
end | ||
10 | ||
11 | has_many :categorizations | |
12 | has_many :authors, :through => :categorizations, :select => 'authors.*, categorizations.post_id' | |
end | ||
class SpecialCategory < Category |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/company.rb:
prev. | current | |
set_sequence_name :companies_nonstd_seq | ||
validates_presence_of :name | ||
6 | ||
7 | has_one :dummy_account, :foreign_key => "firm_id", :class_name => "Account" | |
end | ||
class Firm < Company | ||
10 | | |
12 | has_many :clients, :order => "id", :dependent => :destroy, :counter_sql => | |
"SELECT COUNT(*) FROM companies WHERE firm_id = 1 " + | ||
"AND (#{QUOTED_TYPE} = 'Client' OR #{QUOTED_TYPE} = 'SpecialClient' OR #{QUOTED_TYPE} = 'VerySpecialClient' )" | ||
has_many :clients_sorted_desc, :class_name => "Client", :order => "id DESC" | ||
has_many :clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id" | ||
15 | | |
16 | | |
17 | has_many :dependent_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id", :dependent => :destroy | |
18 | has_many :exclusively_dependent_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id", :dependent => :delete_all | |
19 | has_many :limited_clients, :class_name => "Client", :order => "id", :limit => 1 | |
has_many :clients_like_ms, :conditions => "name = 'Microsoft'", :class_name => "Client", :order => "id" | ||
has_many :clients_using_sql, :class_name => "Client", :finder_sql => 'SELECT * FROM companies WHERE client_of = #{id}' | ||
has_many :clients_using_counter_sql, :class_name => "Client", | ||
... | ... | |
:finder_sql => 'SELECT * FROM companies WHERE client_of = 1000', | ||
:counter_sql => 'SELECT COUNT(*) FROM companies WHERE client_of = 1000' | ||
29 | | |
32 | has_one :account, :foreign_key => "firm_id", :dependent => :destroy | |
end | ||
class DependentFirm < Company | ||
... | ... | |
belongs_to :firm, :foreign_key => "client_of" | ||
belongs_to :firm_with_basic_id, :class_name => "Firm", :foreign_key => "firm_id" | ||
belongs_to :firm_with_other_name, :class_name => "Firm", :foreign_key => "client_of" | ||
42 | | |
45 | belongs_to :firm_with_condition, :class_name => "Firm", :foreign_key => "client_of", :conditions => ["1 = ?", 1] | |
# Record destruction so we can test whether firm.clients.clear has | ||
# is calling client.destroy, deleting from the database, or setting | ||
... | ... | |
end | ||
true | ||
end | ||
60 | ||
61 | # Used to test that read and question methods are not generated for these attributes | |
62 | def ruby_type | |
63 | read_attribute :ruby_type | |
64 | end | |
65 | ||
66 | def rating? | |
67 | query_attribute :rating | |
68 | end | |
end | ||
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/company_in_module.rb:
prev. | current | |
end | ||
class Firm < Company | ||
8 | | |
8 | has_many :clients, :order => "id", :dependent => :destroy | |
has_many :clients_sorted_desc, :class_name => "Client", :order => "id DESC" | ||
has_many :clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id" | ||
has_many :clients_like_ms, :conditions => "name = 'Microsoft'", :class_name => "Client", :order => "id" | ||
has_many :clients_using_sql, :class_name => "Client", :finder_sql => 'SELECT * FROM companies WHERE client_of = #{id}' | ||
14 | | |
14 | has_one :account, :dependent => :destroy | |
end | ||
class Client < Company | ||
... | ... | |
end | ||
end | ||
36 | | |
36 | ||
module Billing | ||
38 | class Firm < ActiveRecord::Base | |
39 | self.table_name = 'companies' | |
40 | end | |
41 | ||
42 | module Nested | |
43 | class Firm < ActiveRecord::Base | |
44 | self.table_name = 'companies' | |
45 | end | |
46 | end | |
47 | ||
class Account < ActiveRecord::Base | ||
39 | | |
40 | | |
49 | belongs_to :firm, :class_name => 'MyApplication::Business::Firm' | |
50 | belongs_to :qualified_billing_firm, :class_name => 'MyApplication::Billing::Firm' | |
51 | belongs_to :unqualified_billing_firm, :class_name => 'Firm' | |
52 | belongs_to :nested_qualified_billing_firm, :class_name => 'MyApplication::Billing::Nested::Firm' | |
53 | belongs_to :nested_unqualified_billing_firm, :class_name => 'Nested::Firm' | |
54 | ||
protected | ||
def validate | ||
errors.add_on_empty "credit_limit" |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/customer.rb:
prev. | current | |
def close_to?(other_address) | ||
city == other_address.city && country == other_address.country | ||
end | ||
17 | ||
18 | def ==(other) | |
19 | other.is_a?(self.class) && other.street == street && other.city == city && other.country == country | |
20 | end | |
end | ||
class Money |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/db2.drop.sql:
prev. | current | |
DROP TABLE accounts; | ||
2 | DROP TABLE funny_jokes; | |
DROP TABLE companies; | ||
DROP TABLE topics; | ||
DROP TABLE developers; | ||
... | ... | |
DROP TABLE colnametests; | ||
DROP TABLE mixins; | ||
DROP TABLE people; | ||
18 | DROP TABLE readers; | |
DROP TABLE binaries; | ||
DROP TABLE computers; | ||
DROP TABLE posts; | ||
... | ... | |
DROP TABLE fk_test_has_pk; | ||
DROP TABLE fk_test_has_fk; | ||
DROP TABLE keyboards; | ||
30 | DROP TABLE legacy_things; |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/db2.sql:
prev. | current | |
CREATE TABLE accounts ( | ||
2 | | |
3 | | |
4 | | |
2 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
3 | firm_id INT DEFAULT NULL, | |
4 | credit_limit INT DEFAULT NULL, | |
PRIMARY KEY (id) | ||
); | ||
8 | CREATE TABLE funny_jokes ( | |
9 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
10 | name VARCHAR(50) DEFAULT NULL, | |
11 | PRIMARY KEY (id) | |
12 | ); | |
13 | ||
CREATE TABLE companies ( | ||
9 | | |
10 | | |
11 | | |
12 | | |
13 | | |
14 | | |
15 | | |
15 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
16 | type VARCHAR(50) DEFAULT NULL, | |
17 | ruby_type VARCHAR(50) DEFAULT NULL, | |
18 | firm_id INT DEFAULT NULL, | |
19 | name VARCHAR(50) DEFAULT NULL, | |
20 | client_of INT DEFAULT NULL, | |
21 | rating INT DEFAULT 1, | |
PRIMARY KEY (id) | ||
); | ||
CREATE TABLE topics ( | ||
20 | | |
21 | | |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
30 | | |
31 | | |
26 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
27 | title VARCHAR(255) DEFAULT NULL, | |
28 | author_name VARCHAR(255) DEFAULT NULL, | |
29 | author_email_address VARCHAR(255) DEFAULT NULL, | |
30 | written_on TIMESTAMP DEFAULT NULL, | |
31 | bonus_time TIME DEFAULT NULL, | |
32 | last_read DATE DEFAULT NULL, | |
33 | content VARCHAR(3000), | |
34 | approved SMALLINT DEFAULT 1, | |
35 | replies_count INT DEFAULT 0, | |
36 | parent_id INT DEFAULT NULL, | |
37 | type VARCHAR(50) DEFAULT NULL, | |
PRIMARY KEY (id) | ||
); | ||
CREATE TABLE developers ( | ||
36 | | |
37 | | |
38 | | |
39 | | |
40 | | |
42 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
43 | name VARCHAR(100) DEFAULT NULL, | |
44 | salary INT DEFAULT 70000, | |
45 | created_at TIMESTAMP DEFAULT NULL, | |
46 | updated_at TIMESTAMP DEFAULT NULL, | |
PRIMARY KEY (id) | ||
); | ||
CREATE TABLE projects ( | ||
45 | | |
46 | | |
47 | | |
51 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
52 | name VARCHAR(100) DEFAULT NULL, | |
53 | type VARCHAR(255) DEFAULT NULL, | |
PRIMARY KEY (id) | ||
); | ||
CREATE TABLE developers_projects ( | ||
52 | | |
53 | | |
54 | | |
55 | | |
58 | developer_id INT NOT NULL, | |
59 | project_id INT NOT NULL, | |
60 | joined_on DATE DEFAULT NULL, | |
61 | access_level SMALLINT DEFAULT 1 | |
); | ||
CREATE TABLE orders ( | ||
59 | | |
60 | | |
61 | | |
62 | | |
65 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
66 | name VARCHAR(100) DEFAULT NULL, | |
67 | billing_customer_id INT DEFAULT NULL, | |
68 | shipping_customer_id INT DEFAULT NULL, | |
PRIMARY KEY (id) | ||
); | ||
CREATE TABLE customers ( | ||
67 | | |
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
73 | | |
73 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
74 | name VARCHAR(100) DEFAULT NULL, | |
75 | balance INT DEFAULT 0, | |
76 | address_street VARCHAR(100) DEFAULT NULL, | |
77 | address_city VARCHAR(100) DEFAULT NULL, | |
78 | address_country VARCHAR(100) DEFAULT NULL, | |
79 | gps_location VARCHAR(100) DEFAULT NULL, | |
PRIMARY KEY (id) | ||
); | ||
CREATE TABLE movies ( | ||
78 | | |
79 | | |
84 | movieid INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
85 | name VARCHAR(100) DEFAULT NULL, | |
PRIMARY KEY (movieid) | ||
); | ||
CREATE TABLE subscribers ( | ||
84 | | |
85 | | |
90 | nick VARCHAR(100) NOT NULL, | |
91 | name VARCHAR(100) DEFAULT NULL, | |
PRIMARY KEY (nick) | ||
); | ||
CREATE TABLE booleantests ( | ||
90 | | |
91 | | |
96 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
97 | value INT DEFAULT NULL, | |
PRIMARY KEY (id) | ||
); | ||
CREATE TABLE auto_id_tests ( | ||
96 | | |
97 | | |
102 | auto_id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
103 | value INT DEFAULT NULL, | |
PRIMARY KEY (auto_id) | ||
); | ||
CREATE TABLE entrants ( | ||
102 | | |
103 | | |
104 | | |
108 | id INT NOT NULL PRIMARY KEY, | |
109 | name VARCHAR(255) NOT NULL, | |
110 | course_id INT NOT NULL | |
); | ||
CREATE TABLE colnametests ( | ||
108 | | |
109 | | |
114 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
115 | references INT NOT NULL, | |
PRIMARY KEY (id) | ||
); | ||
CREATE TABLE mixins ( | ||
114 | | |
115 | | |
116 | | |
117 | | |
118 | | |
119 | | |
120 | | |
121 | | |
122 | | |
120 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
121 | parent_id INT DEFAULT NULL, | |
122 | pos INT DEFAULT NULL, | |
123 | created_at TIMESTAMP DEFAULT NULL, | |
124 | updated_at TIMESTAMP DEFAULT NULL, | |
125 | lft INT DEFAULT NULL, | |
126 | rgt INT DEFAULT NULL, | |
127 | root_id INT DEFAULT NULL, | |
128 | type VARCHAR(40) DEFAULT NULL, | |
PRIMARY KEY (id) | ||
); | ||
CREATE TABLE people ( | ||
127 | | |
128 | | |
129 | | |
130 | | |
133 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
134 | first_name VARCHAR(40) NOT NULL, | |
135 | lock_version INT DEFAULT 0, | |
136 | PRIMARY KEY (id) | |
); | ||
139 | CREATE TABLE readers ( | |
140 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
141 | post_id INT NOT NULL, | |
142 | person_id INT NOT NULL, | |
143 | PRIMARY KEY (id) | |
144 | ); | |
145 | ||
CREATE TABLE binaries ( | ||
134 | | |
135 | | |
136 | | |
147 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
148 | data BLOB(50000), | |
149 | PRIMARY KEY (id) | |
); | ||
CREATE TABLE computers ( | ||
140 | | |
141 | | |
142 | | |
153 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
154 | developer INT NOT NULL, | |
155 | extendedWarranty INT NOT NULL | |
); | ||
CREATE TABLE posts ( | ||
146 | | |
147 | | |
148 | | |
149 | | |
150 | | |
159 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
160 | author_id INT DEFAULT NULL, | |
161 | title VARCHAR(255) DEFAULT NULL, | |
162 | type VARCHAR(255) DEFAULT NULL, | |
163 | body VARCHAR(3000) DEFAULT NULL | |
); | ||
CREATE TABLE comments ( | ||
154 | | |
155 | | |
156 | | |
157 | | |
167 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
168 | post_id INT DEFAULT NULL, | |
169 | type VARCHAR(255) DEFAULT NULL, | |
170 | body VARCHAR(3000) DEFAULT NULL | |
); | ||
CREATE TABLE authors ( | ||
161 | | |
162 | | |
174 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
175 | name VARCHAR(255) DEFAULT NULL | |
); | ||
CREATE TABLE tasks ( | ||
166 | | |
167 | | |
168 | | |
179 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
180 | starting TIMESTAMP DEFAULT NULL, | |
181 | ending TIMESTAMP DEFAULT NULL | |
); | ||
CREATE TABLE categories ( | ||
172 | | |
173 | | |
174 | | |
185 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
186 | name VARCHAR(255) NOT NULL, | |
187 | type VARCHAR(40) DEFAULT NULL | |
); | ||
CREATE TABLE categories_posts ( | ||
178 | | |
179 | | |
191 | category_id INT NOT NULL, | |
192 | post_id INT NOT NULL | |
); | ||
CREATE TABLE keyboards ( | ||
183 | | |
196 | key_number INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
name VARCHAR(255) | ||
); | ||
CREATE TABLE fk_test_has_pk ( | ||
188 | | |
201 | id INT NOT NULL PRIMARY KEY | |
); | ||
CREATE TABLE fk_test_has_fk ( | ||
192 | | |
193 | | |
205 | id INT NOT NULL PRIMARY KEY, | |
206 | fk_id INT NOT NULL, | |
FOREIGN KEY (fk_id) REFERENCES fk_test_has_pk(id) | ||
); | ||
210 | ||
211 | --This table has an altered lock_version column name | |
212 | CREATE TABLE legacy_things ( | |
213 | id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), | |
214 | tps_report_number INT DEFAULT NULL, | |
215 | version INT DEFAULT 0, | |
216 | PRIMARY KEY (id) | |
217 | ); |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/db22.sql:
prev. | current | |
CREATE TABLE courses ( | ||
2 | | |
3 | | |
2 | id INT NOT NULL PRIMARY KEY, | |
3 | name VARCHAR(255) NOT NULL | |
); | ||
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/firebird.drop.sql:
prev. | current | |
DROP TABLE accounts; | ||
2 | DROP TABLE funny_jokes; | |
DROP TABLE companies; | ||
DROP TABLE topics; | ||
DROP TABLE developers; | ||
... | ... | |
DROP TABLE colnametests; | ||
DROP TABLE mixins; | ||
DROP TABLE people; | ||
18 | DROP TABLE readers; | |
DROP TABLE binaries; | ||
DROP TABLE computers; | ||
DROP TABLE posts; | ||
... | ... | |
DROP TABLE fk_test_has_pk; | ||
DROP TABLE keyboards; | ||
DROP TABLE defaults; | ||
31 | DROP TABLE legacy_things; | |
DROP DOMAIN D_BOOLEAN; | ||
DROP GENERATOR accounts_seq; | ||
36 | DROP GENERATOR funny_jokes_seq; | |
DROP GENERATOR companies_nonstd_seq; | ||
DROP GENERATOR topics_seq; | ||
DROP GENERATOR developers_seq; |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/firebird.sql:
prev. | current | |
CREATE GENERATOR accounts_seq; | ||
SET GENERATOR accounts_seq TO 10000; | ||
12 | CREATE TABLE funny_jokes ( | |
13 | id BIGINT NOT NULL, | |
14 | name VARCHAR(50), | |
15 | PRIMARY KEY (id) | |
16 | ); | |
17 | CREATE GENERATOR funny_jokes_seq; | |
18 | SET GENERATOR funny_jokes_seq TO 10000; | |
19 | ||
CREATE TABLE companies ( | ||
id BIGINT NOT NULL, | ||
"TYPE" VARCHAR(50), | ||
... | ... | |
CREATE GENERATOR people_seq; | ||
SET GENERATOR people_seq TO 10000; | ||
172 | CREATE TABLE readers ( | |
173 | id BIGINT NOT NULL, | |
174 | post_id BIGINT NOT NULL, | |
175 | person_id BIGINT NOT NULL, | |
176 | PRIMARY KEY (id) | |
177 | ); | |
178 | CREATE GENERATOR readers_seq; | |
179 | SET GENERATOR readers_seq TO 10000; | |
180 | ||
CREATE TABLE binaries ( | ||
id BIGINT NOT NULL, | ||
data BLOB, | ||
... | ... | |
); | ||
CREATE GENERATOR defaults_seq; | ||
SET GENERATOR defaults_seq TO 10000; | ||
277 | ||
278 | CREATE TABLE legacy_things ( | |
279 | id BIGINT NOT NULL, | |
280 | tps_report_number INTEGER, | |
281 | version INTEGER DEFAULT 0 NOT NULL, | |
282 | PRIMARY KEY (id) | |
283 | ); | |
284 | CREATE GENERATOR legacy_things_seq; | |
285 | SET GENERATOR legacy_things_seq TO 10000; |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/mysql.drop.sql:
prev. | current | |
DROP TABLE accounts; | ||
2 | DROP TABLE funny_jokes; | |
DROP TABLE companies; | ||
DROP TABLE topics; | ||
DROP TABLE developers; | ||
... | ... | |
DROP TABLE colnametests; | ||
DROP TABLE mixins; | ||
DROP TABLE people; | ||
18 | DROP TABLE readers; | |
DROP TABLE binaries; | ||
DROP TABLE computers; | ||
DROP TABLE tasks; | ||
... | ... | |
DROP TABLE fk_test_has_fk; | ||
DROP TABLE fk_test_has_pk; | ||
DROP TABLE keyboards; | ||
30 | DROP TABLE legacy_things; |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/mysql.sql:
prev. | current | |
PRIMARY KEY (`id`) | ||
) TYPE=InnoDB; | ||
8 | CREATE TABLE `funny_jokes` ( | |
9 | `id` int(11) NOT NULL auto_increment, | |
10 | `name` varchar(50) default NULL, | |
11 | PRIMARY KEY (`id`) | |
12 | ) TYPE=InnoDB; | |
13 | ||
CREATE TABLE `companies` ( | ||
`id` int(11) NOT NULL auto_increment, | ||
`type` varchar(50) default NULL, | ||
... | ... | |
`bonus_time` time default NULL, | ||
`last_read` date default NULL, | ||
`content` text, | ||
29 | | |
35 | `approved` tinyint(1) default 1, | |
`replies_count` int(11) default 0, | ||
`parent_id` int(11) default NULL, | ||
`type` varchar(50) default NULL, | ||
... | ... | |
`lock_version` INTEGER NOT NULL DEFAULT 0 | ||
) TYPE=InnoDB; | ||
139 | CREATE TABLE `readers` ( | |
140 | `id` int(11) NOT NULL PRIMARY KEY, | |
141 | `post_id` INTEGER NOT NULL, | |
142 | `person_id` INTEGER NOT NULL | |
143 | ) TYPE=InnoDB; | |
144 | ||
CREATE TABLE `binaries` ( | ||
`id` int(11) NOT NULL auto_increment, | ||
`data` mediumblob, | ||
... | ... | |
`key_number` int(11) NOT NULL auto_increment primary key, | ||
`name` varchar(50) default NULL | ||
); | ||
212 | ||
213 | -- Altered lock_version column name. | |
214 | CREATE TABLE `legacy_things` ( | |
215 | `id` int(11) NOT NULL auto_increment, | |
216 | `tps_report_number` int(11) default NULL, | |
217 | `version` int(11) NOT NULL default 0, | |
218 | PRIMARY KEY (`id`) | |
219 | ) TYPE=InnoDB; |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/postgresql.drop.sql:
prev. | current | |
1 | DROP SEQUENCE accounts_id_seq; | |
DROP TABLE accounts; | ||
3 | DROP TABLE funny_jokes; | |
DROP TABLE companies; | ||
DROP SEQUENCE companies_nonstd_seq; | ||
DROP TABLE topics; | ||
... | ... | |
DROP TABLE colnametests; | ||
DROP TABLE mixins; | ||
DROP TABLE people; | ||
20 | DROP TABLE readers; | |
DROP TABLE binaries; | ||
DROP TABLE computers; | ||
DROP TABLE posts; | ||
... | ... | |
DROP TABLE fk_test_has_pk; | ||
DROP TABLE geometrics; | ||
DROP TABLE keyboards; | ||
34 | DROP TABLE legacy_things; |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/postgresql.sql:
prev. | current | |
PRIMARY KEY (id) | ||
); | ||
10 | CREATE TABLE funny_jokes ( | |
11 | id serial, | |
12 | name character varying(50) | |
13 | ); | |
14 | ||
CREATE SEQUENCE companies_nonstd_seq START 101; | ||
CREATE TABLE companies ( | ||
... | ... | |
fixed_time timestamp default '2004-01-01 00:00:00.000000-00', | ||
char1 char(1) default 'Y', | ||
char2 character varying(50) default 'a varchar field', | ||
114 | | |
119 | char3 text default 'a text field', | |
120 | positive_integer integer default 1, | |
121 | negative_integer integer default -1 | |
); | ||
CREATE TABLE auto_id_tests ( | ||
... | ... | |
PRIMARY KEY (id) | ||
); | ||
161 | CREATE TABLE readers ( | |
162 | id serial, | |
163 | post_id integer NOT NULL, | |
164 | person_id integer NOT NULL, | |
165 | primary key (id) | |
166 | ); | |
167 | ||
CREATE TABLE binaries ( | ||
id serial , | ||
data bytea, | ||
... | ... | |
key_number serial primary key, | ||
"name" character varying(50) | ||
); | ||
242 | ||
243 | --Altered lock_version column name. | |
244 | CREATE TABLE legacy_things ( | |
245 | id serial primary key, | |
246 | tps_report_number integer, | |
247 | version integer default 0 | |
248 | ); |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/sqlite.drop.sql:
prev. | current | |
DROP TABLE accounts; | ||
2 | DROP TABLE funny_jokes; | |
DROP TABLE companies; | ||
DROP TABLE topics; | ||
DROP TABLE developers; | ||
... | ... | |
DROP TABLE colnametests; | ||
DROP TABLE mixins; | ||
DROP TABLE people; | ||
18 | DROP TABLE readers; | |
DROP TABLE binaries; | ||
DROP TABLE computers; | ||
DROP TABLE tasks; | ||
... | ... | |
DROP TABLE fk_test_has_fk; | ||
DROP TABLE fk_test_has_pk; | ||
DROP TABLE keyboards; | ||
30 | DROP TABLE legacy_things; |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/sqlite.sql:
prev. | current | |
'credit_limit' INTEGER DEFAULT NULL | ||
); | ||
7 | CREATE TABLE 'funny_jokes' ( | |
8 | 'id' INTEGER PRIMARY KEY NOT NULL, | |
9 | 'name' TEXT DEFAULT NULL | |
10 | ); | |
11 | ||
CREATE TABLE 'companies' ( | ||
'id' INTEGER PRIMARY KEY NOT NULL, | ||
'type' VARCHAR(255) DEFAULT NULL, | ||
... | ... | |
'lock_version' INTEGER NOT NULL DEFAULT 0 | ||
); | ||
126 | CREATE TABLE 'readers' ( | |
127 | 'id' INTEGER NOT NULL PRIMARY KEY, | |
128 | 'post_id' INTEGER NOT NULL, | |
129 | 'person_id' INTEGER NOT NULL | |
130 | ); | |
131 | ||
CREATE TABLE 'binaries' ( | ||
'id' INTEGER NOT NULL PRIMARY KEY, | ||
'data' BLOB DEFAULT NULL | ||
... | ... | |
'key_number' INTEGER PRIMARY KEY NOT NULL, | ||
'name' VARCHAR(255) DEFAULT NULL | ||
); | ||
195 | ||
196 | --Altered lock_version column name. | |
197 | CREATE TABLE 'legacy_things' ( | |
198 | 'id' INTEGER NOT NULL PRIMARY KEY, | |
199 | 'tps_report_number' INTEGER DEFAULT NULL, | |
200 | 'version' INTEGER NOT NULL DEFAULT 0 | |
201 | ) |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/sqlserver.drop.sql:
prev. | current | |
DROP TABLE accounts; | ||
2 | DROP TABLE funny_jokes; | |
DROP TABLE companies; | ||
DROP TABLE topics; | ||
DROP TABLE developers; | ||
... | ... | |
DROP TABLE colnametests; | ||
DROP TABLE mixins; | ||
DROP TABLE people; | ||
18 | DROP TABLE readers; | |
DROP TABLE binaries; | ||
DROP TABLE computers; | ||
DROP TABLE posts; | ||
... | ... | |
DROP TABLE fk_test_has_fk; | ||
DROP TABLE fk_test_has_pk; | ||
DROP TABLE keyboards; | ||
30 | DROP TABLE legacy_things; |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/db_definitions/sqlserver.sql:
prev. | current | |
credit_limit int default NULL | ||
); | ||
7 | CREATE TABLE funny_jokes ( | |
8 | id int NOT NULL IDENTITY(1, 1) PRIMARY KEY, | |
9 | name varchar(50) default NULL | |
10 | ); | |
11 | ||
CREATE TABLE companies ( | ||
id int NOT NULL IDENTITY(1, 1) PRIMARY KEY, | ||
type varchar(50) default NULL, | ||
... | ... | |
bonus_time datetime default NULL, | ||
last_read datetime default NULL, | ||
content varchar(255) default NULL, | ||
26 | | |
31 | approved bit default 1, | |
replies_count int default 0, | ||
parent_id int default NULL, | ||
type varchar(50) default NULL | ||
... | ... | |
PRIMARY KEY (id) | ||
); | ||
126 | CREATE TABLE readers ( | |
127 | id int NOT NULL IDENTITY(1, 1), | |
128 | post_id int NOT NULL, | |
129 | person_id int NOT NULL, | |
130 | primary key (id) | |
131 | ); | |
132 | ||
CREATE TABLE binaries ( | ||
id int NOT NULL IDENTITY(1, 1) PRIMARY KEY, | ||
data image NULL | ||
... | ... | |
author_id int default NULL, | ||
title varchar(255) default NULL, | ||
type varchar(255) default NULL, | ||
137 | | |
149 | body varchar(4096) default NULL | |
); | ||
CREATE TABLE comments ( | ||
id int NOT NULL IDENTITY(1, 1) PRIMARY KEY, | ||
post_id int default NULL, | ||
type varchar(255) default NULL, | ||
144 | | |
156 | body varchar(4096) default NULL | |
); | ||
CREATE TABLE authors ( | ||
... | ... | |
key_number int NOT NULL IDENTITY(1, 1) PRIMARY KEY, | ||
name varchar(50) default NULL | ||
); | ||
196 | ||
197 | --This table has an altered lock_version column name. | |
198 | CREATE TABLE legacy_things ( | |
199 | id int NOT NULL IDENTITY(1, 1), | |
200 | tps_report_number int default NULL, | |
201 | version int default 0, | |
202 | PRIMARY KEY (id) | |
203 | ); |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/developers.yml:
prev. | current | |
id: <%= digit %> | ||
name: fixture_<%= digit %> | ||
salary: 100000 | ||
16 | ||
17 | <% end %> | |
18 | ||
19 | poor_jamis: | |
20 | id: 11 | |
21 | name: Jamis | |
22 | salary: 9000 | |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/developers_projects.yml:
prev. | current | |
jamis_active_record: | ||
developer_id: 2 | ||
project_id: 1 | ||
14 | ||
15 | poor_jamis_active_record: | |
16 | developer_id: 11 | |
17 | project_id: 1 | |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/mixin.rb:
prev. | current | |
end | ||
class NestedSet < Mixin | ||
33 | | |
33 | acts_as_nested_set :scope => "root_id IS NULL" | |
def self.table_name() "mixins" end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/person.rb:
prev. | current | |
1 | ||
1 | class Person < ActiveRecord::Base | |
2 | has_many :readers | |
3 | has_many :posts, :through => :readers | |
4 | end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/post.rb:
prev. | current | |
has_many :special_comments | ||
has_and_belongs_to_many :categories | ||
21 | | |
21 | has_and_belongs_to_many :special_categories, :join_table => "categories_posts", :association_foreign_key => 'category_id' | |
22 | ||
23 | has_many :taggings, :as => :taggable | |
24 | has_many :tags, :through => :taggings, :include => :tagging do | |
25 | def add_joins_and_select | |
26 | find :all, :select => 'tags.*, authors.id as author_id', :include => false, | |
27 | :joins => 'left outer join posts on taggings.taggable_id = posts.id left outer join authors on posts.author_id = authors.id' | |
28 | end | |
29 | end | |
31 | has_many :funky_tags, :through => :taggings, :source => :tag | |
32 | has_many :super_tags, :through => :taggings | |
33 | has_one :tagging, :as => :taggable | |
34 | ||
35 | has_many :invalid_taggings, :as => :taggable, :class_name => "Tagging", :conditions => 'taggings.id < 0' | |
36 | has_many :invalid_tags, :through => :invalid_taggings, :source => :tag | |
37 | ||
38 | has_many :categorizations, :foreign_key => :category_id | |
39 | has_many :authors, :through => :categorizations | |
40 | ||
41 | has_many :readers | |
42 | has_many :people, :through => :readers | |
43 | ||
def self.what_are_you | ||
'a post...' | ||
end | ||
... | ... | |
class SpecialPost < Post; end; | ||
class StiPost < Post | ||
52 | self.abstract_class = true | |
has_one :special_comment, :class_name => "SpecialComment" | ||
end | ||
55 | ||
56 | class SubStiPost < StiPost | |
57 | end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/project.rb:
prev. | current | |
class Project < ActiveRecord::Base | ||
has_and_belongs_to_many :developers, :uniq => true | ||
3 | has_and_belongs_to_many :limited_developers, :class_name => "Developer", :limit => 1 | |
has_and_belongs_to_many :developers_named_david, :class_name => "Developer", :conditions => "name = 'David'", :uniq => true | ||
has_and_belongs_to_many :salaried_developers, :class_name => "Developer", :conditions => "salary > 0" | ||
has_and_belongs_to_many :developers_with_finder_sql, :class_name => "Developer", :finder_sql => 'SELECT t.*, j.* FROM developers_projects j, developers t WHERE t.id = j.developer_id AND j.project_id = #{id}' |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/reply.rb:
prev. | current | |
class Reply < Topic | ||
belongs_to :topic, :foreign_key => "parent_id", :counter_cache => true | ||
5 | | |
5 | has_many :replies, :class_name => "SillyReply", :dependent => :destroy, :foreign_key => "parent_id" | |
validate :errors_on_empty_content | ||
validate_on_create :title_is_wrong_create | ||
... | ... | |
end | ||
class SillyReply < Reply | ||
36 | belongs_to :reply, :foreign_key => "parent_id", :counter_cache => :replies_count | |
end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/tasks.yml:
prev. | current | |
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html | ||
first_task: | ||
id: 1 | ||
4 | | |
5 | | |
4 | starting: 2005-03-30t06:30:00.00+01:00 | |
5 | ending: 2005-03-30t08:30:00.00+01:00 | |
another_task: | ||
id: 2 |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/topic.rb:
prev. | current | |
class Topic < ActiveRecord::Base | ||
2 | | |
2 | has_many :replies, :dependent => :destroy, :foreign_key => "parent_id" | |
serialize :content | ||
before_create :default_written_on | ||
before_destroy :destroy_children | ||
def parent | ||
9 | | |
9 | Topic.find(parent_id) | |
end | ||
protected |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures/topics.yml:
prev. | current | |
approved: true | ||
replies_count: 2 | ||
parent_id: 1 | ||
22 | type: Reply |
rool/rails/typo/trunk/vendor/rails/activerecord/test/fixtures_test.rb:
prev. | current | |
require 'fixtures/company' | ||
require 'fixtures/task' | ||
require 'fixtures/reply' | ||
7 | require 'fixtures/joke' | |
8 | require 'fixtures/category' | |
class FixturesTest < Test::Unit::TestCase | ||
self.use_instantiated_fixtures = true | ||
self.use_transactional_fixtures = false | ||
12 | | |
14 | fixtures :topics, :developers, :accounts, :tasks, :categories, :funny_jokes | |
FIXTURES = %w( accounts companies customers | ||
developers developers_projects entrants | ||
... | ... | |
t.column :written_on, :datetime | ||
t.column :bonus_time, :time | ||
t.column :last_read, :date | ||
63 | | |
65 | t.column :content, :string | |
t.column :approved, :boolean, :default => true | ||
t.column :replies_count, :integer, :default => 0 | ||
t.column :parent_id, :integer | ||
... | ... | |
topics = create_fixtures("topics") | ||
80 | | |
81 | | |
82 | | |
83 | ||
firstRow = ActiveRecord::Base.connection.select_one("SELECT * FROM prefix_topics_suffix WHERE author_name = 'David'") | ||
assert_equal("The First Topic", firstRow["title"]) | ||
secondRow = ActiveRecord::Base.connection.select_one("SELECT * FROM prefix_topics_suffix WHERE author_name = 'Mary'") | ||
assert_nil(secondRow["author_email_address"]) | ||
ensure | ||
88 | # Restore prefix/suffix to its previous values | |
89 | ActiveRecord::Base.table_name_prefix = old_prefix | |
90 | ActiveRecord::Base.table_name_suffix = old_suffix | |
91 | ||
ActiveRecord::Base.connection.drop_table :prefix_topics_suffix rescue nil | ||
end | ||
end | ||
... | ... | |
def test_deprecated_yaml_extension | ||
assert_raise(Fixture::FormatError) { | ||
113 | | |
115 | Fixtures.new(nil, 'bad_extension', 'BadExtension', File.join(File.dirname(__FILE__), 'fixtures')) | |
} | ||
end | ||
... | ... | |
end | ||
def test_erb_in_fixtures | ||
139 | | |
141 | assert_equal 11, @developers.size | |
assert_equal "fixture_5", @dev_5.name | ||
end | ||
def test_empty_yaml_fixture | ||
144 | | |
146 | assert_not_nil Fixtures.new( Account.connection, "accounts", 'Account', File.dirname(__FILE__) + "/fixtures/naked/yml/accounts") | |
end | ||
def test_empty_yaml_fixture_with_a_comment_in_it | ||
148 | | |
150 | assert_not_nil Fixtures.new( Account.connection, "companies", 'Company', File.dirname(__FILE__) + "/fixtures/naked/yml/companies") | |
end | ||
def test_dirty_dirty_yaml_file | ||
assert_raises(Fixture::FormatError) do | ||
153 | | |
155 | Fixtures.new( Account.connection, "courses", 'Course', File.dirname(__FILE__) + "/fixtures/naked/yml/courses") | |
end | ||
end | ||
def test_empty_csv_fixtures | ||
158 | | |
160 | assert_not_nil Fixtures.new( Account.connection, "accounts", 'Account', File.dirname(__FILE__) + "/fixtures/naked/csv/accounts") | |
end | ||
def test_omap_fixtures | ||
assert_nothing_raised do | ||
163 | | |
165 | fixtures = Fixtures.new(Account.connection, 'categories', 'Category', File.dirname(__FILE__) + '/fixtures/categories_ordered') | |
i = 0 | ||
fixtures.each do |name, fixture| | ||
... | ... | |
end | ||
end | ||
end | ||
175 | ||
176 | ||
177 | def test_yml_file_in_subdirectory | |
178 | assert_equal(categories(:sub_special_1).name, "A special category in a subdir file") | |
179 | assert_equal(categories(:sub_special_1).class, SpecialCategory) | |
180 | end | |
181 | ||
182 | def test_subsubdir_file_with_arbitrary_name | |
183 | assert_equal(categories(:sub_special_3).name, "A special category in an arbitrarily named subsubdir file") | |
184 | assert_equal(categories(:sub_special_3).class, SpecialCategory) | |
185 | end | |
186 | ||
187 | ||
end | ||
if Account.connection.respond_to?(:reset_pk_sequence!) | ||
... | ... | |
assert true | ||
end | ||
end | ||
327 | ||
328 | class SetTableNameFixturesTest < Test::Unit::TestCase | |
329 | set_fixture_class :funny_jokes => 'Joke' | |
330 | fixtures :funny_jokes | |
331 | ||
332 | def test_table_method | |
333 | assert_kind_of Joke, funny_jokes(:a_joke) | |
334 | end | |
335 | end | |
336 | ||
337 | class InvalidTableNameFixturesTest < Test::Unit::TestCase | |
338 | fixtures :funny_jokes | |
339 | ||
340 | def test_raises_error | |
341 | assert_raises FixtureClassNotFound do | |
342 | funny_jokes(:a_joke) | |
343 | end | |
344 | end | |
345 | end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/inheritance_test.rb:
prev. | current | |
def test_a_bad_type_column | ||
#SQLServer need to turn Identity Insert On before manually inserting into the Identity column | ||
11 | | |
11 | if current_adapter?(:SQLServerAdapter) || current_adapter?(:SybaseAdapter) | |
Company.connection.execute "SET IDENTITY_INSERT companies ON" | ||
end | ||
Company.connection.insert "INSERT INTO companies (id, #{QUOTED_TYPE}, name) VALUES(100, 'bad_class!', 'Not happening')" | ||
#We then need to turn it back Off before continuing. | ||
17 | | |
17 | if current_adapter?(:SQLServerAdapter) || current_adapter?(:SybaseAdapter) | |
Company.connection.execute "SET IDENTITY_INSERT companies OFF" | ||
end | ||
assert_raises(ActiveRecord::SubclassNotFound) { Company.find(100) } |
rool/rails/typo/trunk/vendor/rails/activerecord/test/locking_test.rb:
prev. | current | |
require 'abstract_unit' | ||
require 'fixtures/person' | ||
3 | require 'fixtures/legacy_thing' | |
class LockingTest < Test::Unit::TestCase | ||
5 | | |
6 | fixtures :people, :legacy_things | |
def test_lock_existing | ||
p1 = Person.find(1) | ||
... | ... | |
p2.first_name = "should fail" | ||
p2.save | ||
} | ||
32 | end | |
33 | ||
34 | def test_lock_column_name_existing | |
35 | t1 = LegacyThing.find(1) | |
36 | t2 = LegacyThing.find(1) | |
37 | t1.tps_report_number = 400 | |
38 | t1.save | |
39 | ||
40 | assert_raises(ActiveRecord::StaleObjectError) { | |
41 | t2.tps_report_number = 300 | |
42 | t2.save | |
43 | } | |
end | ||
45 | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/method_scoping_test.rb:
prev. | current | |
require 'abstract_unit' | ||
require 'fixtures/developer' | ||
3 | require 'fixtures/project' | |
require 'fixtures/comment' | ||
require 'fixtures/post' | ||
require 'fixtures/category' | ||
class MethodScopingTest < Test::Unit::TestCase | ||
8 | | |
9 | fixtures :developers, :projects, :comments, :posts | |
def test_set_conditions | ||
Developer.with_scope(:find => { :conditions => 'just a test...' }) do | ||
12 | | |
13 | assert_equal 'just a test...', Developer.send(:current_scoped_methods)[:find][:conditions] | |
end | ||
end | ||
... | ... | |
end | ||
end | ||
29 | def test_scoped_find_combines_conditions | |
30 | Developer.with_scope(:find => { :conditions => "salary = 9000" }) do | |
31 | assert_equal developers(:poor_jamis), Developer.find(:first, :conditions => "name = 'Jamis'") | |
32 | end | |
33 | end | |
34 | ||
35 | def test_scoped_find_sanitizes_conditions | |
36 | Developer.with_scope(:find => { :conditions => ['salary = ?', 9000] }) do | |
37 | assert_equal developers(:poor_jamis), Developer.find(:first) | |
38 | end | |
39 | end | |
40 | ||
41 | def test_scoped_find_combines_and_sanitizes_conditions | |
42 | Developer.with_scope(:find => { :conditions => ['salary = ?', 9000] }) do | |
43 | assert_equal developers(:poor_jamis), Developer.find(:first, :conditions => ['name = ?', 'Jamis']) | |
44 | end | |
45 | end | |
46 | ||
def test_scoped_find_all | ||
Developer.with_scope(:find => { :conditions => "name = 'David'" }) do | ||
30 | | |
49 | assert_equal [developers(:david)], Developer.find(:all) | |
end | ||
end | ||
... | ... | |
end | ||
end | ||
64 | def test_scoped_find_include | |
65 | # with the include, will retrieve only developers for the given project | |
66 | scoped_developers = Developer.with_scope(:find => { :include => :projects }) do | |
67 | Developer.find(:all, :conditions => 'projects.id = 2') | |
68 | end | |
69 | assert scoped_developers.include?(developers(:david)) | |
70 | assert !scoped_developers.include?(developers(:jamis)) | |
71 | assert_equal 1, scoped_developers.size | |
72 | end | |
73 | ||
74 | def test_scoped_count_include | |
75 | # with the include, will retrieve only developers for the given project | |
76 | Developer.with_scope(:find => { :include => :projects }) do | |
77 | assert_equal 1, Developer.count('projects.id = 2') | |
78 | end | |
79 | end | |
80 | ||
def test_scoped_create | ||
new_comment = nil | ||
VerySpecialComment.with_scope(:create => { :post_id => 1 }) do | ||
49 | | |
85 | assert_equal({ :post_id => 1 }, VerySpecialComment.send(:current_scoped_methods)[:create]) | |
new_comment = VerySpecialComment.create :body => "Wonderful world" | ||
end | ||
... | ... | |
end | ||
end | ||
72 | | |
73 | | |
74 | | |
75 | | |
108 | def test_scoped_with_duck_typing | |
109 | scoping = Struct.new(:method_scoping).new(:find => { :conditions => ["name = ?", 'David'] }) | |
110 | Developer.with_scope(scoping) do | |
111 | assert_equal %w(David), Developer.find(:all).map { |d| d.name } | |
112 | end | |
113 | end | |
114 | ||
115 | def test_ensure_that_method_scoping_is_correctly_restored | |
116 | scoped_methods = Developer.instance_eval('current_scoped_methods') | |
117 | ||
118 | begin | |
119 | Developer.with_scope(:find => { :conditions => "name = 'Jamis'" }) do | |
120 | raise "an exception" | |
end | ||
122 | rescue | |
end | ||
124 | assert_equal scoped_methods, Developer.instance_eval('current_scoped_methods') | |
end | ||
end | ||
128 | class NestedScopingTest < Test::Unit::TestCase | |
129 | fixtures :developers, :projects, :comments, :posts | |
130 | ||
131 | def test_merge_options | |
132 | Developer.with_scope(:find => { :conditions => 'salary = 80000' }) do | |
133 | Developer.with_scope(:find => { :limit => 10 }) do | |
134 | merged_option = Developer.instance_eval('current_scoped_methods')[:find] | |
135 | assert_equal({ :conditions => 'salary = 80000', :limit => 10 }, merged_option) | |
136 | end | |
137 | end | |
138 | end | |
139 | ||
140 | def test_replace_options | |
141 | Developer.with_scope(:find => { :conditions => "name = 'David'" }) do | |
142 | Developer.with_exclusive_scope(:find => { :conditions => "name = 'Jamis'" }) do | |
143 | assert_equal({:find => { :conditions => "name = 'Jamis'" }}, Developer.instance_eval('current_scoped_methods')) | |
144 | assert_equal({:find => { :conditions => "name = 'Jamis'" }}, Developer.send(:scoped_methods)[-1]) | |
145 | end | |
146 | end | |
147 | end | |
148 | ||
149 | def test_append_conditions | |
150 | Developer.with_scope(:find => { :conditions => "name = 'David'" }) do | |
151 | Developer.with_scope(:find => { :conditions => 'salary = 80000' }) do | |
152 | appended_condition = Developer.instance_eval('current_scoped_methods')[:find][:conditions] | |
153 | assert_equal("( name = 'David' ) AND ( salary = 80000 )", appended_condition) | |
154 | assert_equal(1, Developer.count) | |
155 | end | |
156 | Developer.with_scope(:find => { :conditions => "name = 'Maiha'" }) do | |
157 | assert_equal(0, Developer.count) | |
158 | end | |
159 | end | |
160 | end | |
161 | ||
162 | def test_merge_and_append_options | |
163 | Developer.with_scope(:find => { :conditions => 'salary = 80000', :limit => 10 }) do | |
164 | Developer.with_scope(:find => { :conditions => "name = 'David'" }) do | |
165 | merged_option = Developer.instance_eval('current_scoped_methods')[:find] | |
166 | assert_equal({ :conditions => "( salary = 80000 ) AND ( name = 'David' )", :limit => 10 }, merged_option) | |
167 | end | |
168 | end | |
169 | end | |
170 | ||
171 | def test_nested_scoped_find | |
172 | Developer.with_scope(:find => { :conditions => "name = 'Jamis'" }) do | |
173 | Developer.with_exclusive_scope(:find => { :conditions => "name = 'David'" }) do | |
174 | assert_nothing_raised { Developer.find(1) } | |
175 | assert_equal('David', Developer.find(:first).name) | |
176 | end | |
177 | assert_equal('Jamis', Developer.find(:first).name) | |
178 | end | |
179 | end | |
180 | ||
181 | def test_nested_scoped_find_include | |
182 | Developer.with_scope(:find => { :include => :projects }) do | |
183 | Developer.with_scope(:find => { :conditions => "projects.id = 2" }) do | |
184 | assert_nothing_raised { Developer.find(1) } | |
185 | assert_equal('David', Developer.find(:first).name) | |
186 | end | |
187 | end | |
188 | end | |
189 | ||
190 | def test_nested_scoped_find_merged_include | |
191 | # :include's remain unique and don't "double up" when merging | |
192 | Developer.with_scope(:find => { :include => :projects, :conditions => "projects.id = 2" }) do | |
193 | Developer.with_scope(:find => { :include => :projects }) do | |
194 | assert_equal 1, Developer.instance_eval('current_scoped_methods')[:find][:include].length | |
195 | assert_equal('David', Developer.find(:first).name) | |
196 | end | |
197 | end | |
198 | ||
199 | # the nested scope doesn't remove the first :include | |
200 | Developer.with_scope(:find => { :include => :projects, :conditions => "projects.id = 2" }) do | |
201 | Developer.with_scope(:find => { :include => [] }) do | |
202 | assert_equal 1, Developer.instance_eval('current_scoped_methods')[:find][:include].length | |
203 | assert_equal('David', Developer.find(:first).name) | |
204 | end | |
205 | end | |
206 | ||
207 | # mixing array and symbol include's will merge correctly | |
208 | Developer.with_scope(:find => { :include => [:projects], :conditions => "projects.id = 2" }) do | |
209 | Developer.with_scope(:find => { :include => :projects }) do | |
210 | assert_equal 1, Developer.instance_eval('current_scoped_methods')[:find][:include].length | |
211 | assert_equal('David', Developer.find(:first).name) | |
212 | end | |
213 | end | |
214 | end | |
215 | ||
216 | def test_nested_scoped_find_replace_include | |
217 | Developer.with_scope(:find => { :include => :projects }) do | |
218 | Developer.with_exclusive_scope(:find => { :include => [] }) do | |
219 | assert_equal 0, Developer.instance_eval('current_scoped_methods')[:find][:include].length | |
220 | end | |
221 | end | |
222 | end | |
223 | ||
224 | def test_three_level_nested_exclusive_scoped_find | |
225 | Developer.with_scope(:find => { :conditions => "name = 'Jamis'" }) do | |
226 | assert_equal('Jamis', Developer.find(:first).name) | |
227 | ||
228 | Developer.with_exclusive_scope(:find => { :conditions => "name = 'David'" }) do | |
229 | assert_equal('David', Developer.find(:first).name) | |
230 | ||
231 | Developer.with_exclusive_scope(:find => { :conditions => "name = 'Maiha'" }) do | |
232 | assert_equal(nil, Developer.find(:first)) | |
233 | end | |
234 | ||
235 | # ensure that scoping is restored | |
236 | assert_equal('David', Developer.find(:first).name) | |
237 | end | |
238 | ||
239 | # ensure that scoping is restored | |
240 | assert_equal('Jamis', Developer.find(:first).name) | |
241 | end | |
242 | end | |
243 | ||
244 | def test_merged_scoped_find | |
245 | poor_jamis = developers(:poor_jamis) | |
246 | Developer.with_scope(:find => { :conditions => "salary < 100000" }) do | |
247 | Developer.with_scope(:find => { :offset => 1 }) do | |
248 | assert_equal(poor_jamis, Developer.find(:first, :order => 'id asc')) | |
249 | end | |
250 | end | |
251 | end | |
252 | ||
253 | def test_merged_scoped_find_sanitizes_conditions | |
254 | Developer.with_scope(:find => { :conditions => ["name = ?", 'David'] }) do | |
255 | Developer.with_scope(:find => { :conditions => ['salary = ?', 9000] }) do | |
256 | assert_raise(ActiveRecord::RecordNotFound) { developers(:poor_jamis) } | |
257 | end | |
258 | end | |
259 | end | |
260 | ||
261 | def test_nested_scoped_find_combines_and_sanitizes_conditions | |
262 | Developer.with_scope(:find => { :conditions => ["name = ?", 'David'] }) do | |
263 | Developer.with_exclusive_scope(:find => { :conditions => ['salary = ?', 9000] }) do | |
264 | assert_equal developers(:poor_jamis), Developer.find(:first) | |
265 | assert_equal developers(:poor_jamis), Developer.find(:first, :conditions => ['name = ?', 'Jamis']) | |
266 | end | |
267 | end | |
268 | end | |
269 | ||
270 | def test_merged_scoped_find_combines_and_sanitizes_conditions | |
271 | Developer.with_scope(:find => { :conditions => ["name = ?", 'David'] }) do | |
272 | Developer.with_scope(:find => { :conditions => ['salary > ?', 9000] }) do | |
273 | assert_equal %w(David), Developer.find(:all).map { |d| d.name } | |
274 | end | |
275 | end | |
276 | end | |
277 | ||
278 | def test_immutable_nested_scope | |
279 | options1 = { :conditions => "name = 'Jamis'" } | |
280 | options2 = { :conditions => "name = 'David'" } | |
281 | Developer.with_scope(:find => options1) do | |
282 | Developer.with_exclusive_scope(:find => options2) do | |
283 | assert_equal %w(David), Developer.find(:all).map { |d| d.name } | |
284 | options1[:conditions] = options2[:conditions] = nil | |
285 | assert_equal %w(David), Developer.find(:all).map { |d| d.name } | |
286 | end | |
287 | end | |
288 | end | |
289 | ||
290 | def test_immutable_merged_scope | |
291 | options1 = { :conditions => "name = 'Jamis'" } | |
292 | options2 = { :conditions => "salary > 10000" } | |
293 | Developer.with_scope(:find => options1) do | |
294 | Developer.with_scope(:find => options2) do | |
295 | assert_equal %w(Jamis), Developer.find(:all).map { |d| d.name } | |
296 | options1[:conditions] = options2[:conditions] = nil | |
297 | assert_equal %w(Jamis), Developer.find(:all).map { |d| d.name } | |
298 | end | |
299 | end | |
300 | end | |
301 | ||
302 | def test_ensure_that_method_scoping_is_correctly_restored | |
303 | Developer.with_scope(:find => { :conditions => "name = 'David'" }) do | |
304 | scoped_methods = Developer.instance_eval('current_scoped_methods') | |
305 | begin | |
306 | Developer.with_scope(:find => { :conditions => "name = 'Maiha'" }) do | |
307 | raise "an exception" | |
308 | end | |
309 | rescue | |
310 | end | |
311 | assert_equal scoped_methods, Developer.instance_eval('current_scoped_methods') | |
312 | end | |
313 | end | |
314 | end | |
315 | ||
class HasManyScopingTest< Test::Unit::TestCase | ||
fixtures :comments, :posts | ||
... | ... | |
assert_equal 2, @welcome.comments.find_all_by_type('Comment').size | ||
end | ||
103 | | |
338 | def test_nested_scope | |
Comment.with_scope(:find => { :conditions => '1=1' }) do | ||
105 | | |
340 | assert_equal 'a comment...', @welcome.comments.what_are_you | |
end | ||
end | ||
end | ||
... | ... | |
end | ||
def test_forwarding_to_dynamic_finders | ||
124 | | |
359 | assert_equal 4, Category.find_all_by_type('SpecialCategory').size | |
assert_equal 0, @welcome.categories.find_all_by_type('SpecialCategory').size | ||
assert_equal 2, @welcome.categories.find_all_by_type('Category').size | ||
end | ||
129 | | |
364 | def test_nested_scope | |
Category.with_scope(:find => { :conditions => '1=1' }) do | ||
131 | | |
366 | assert_equal 'a comment...', @welcome.comments.what_are_you | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/migration_test.rb:
prev. | current | |
if ActiveRecord::Base.connection.supports_migrations? | ||
class Reminder < ActiveRecord::Base; end | ||
9 | class ActiveRecord::Migration | |
10 | class <<self | |
11 | attr_accessor :message_count | |
12 | def puts(text="") | |
13 | self.message_count ||= 0 | |
14 | self.message_count += 1 | |
15 | end | |
16 | end | |
17 | end | |
18 | ||
class MigrationTest < Test::Unit::TestCase | ||
self.use_transactional_fixtures = false | ||
def setup | ||
23 | ActiveRecord::Migration.verbose = true | |
24 | PeopleHaveLastNames.message_count = 0 | |
end | ||
def teardown | ||
... | ... | |
Person.connection.remove_column("people", "administrator") rescue nil | ||
Person.reset_column_information | ||
end | ||
34 | | |
46 | ||
def test_add_index | ||
Person.connection.add_column "people", "last_name", :string | ||
Person.connection.add_column "people", "administrator", :boolean | ||
... | ... | |
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) } | ||
assert_nothing_raised { Person.connection.remove_index("people", "last_name") } | ||
45 | | |
46 | | |
57 | # Sybase adapter does not support indexes on :boolean columns | |
58 | unless current_adapter?(:SybaseAdapter) | |
59 | assert_nothing_raised { Person.connection.add_index("people", %w(last_name first_name administrator), :name => "named_admin") } | |
60 | assert_nothing_raised { Person.connection.remove_index("people", :name => "named_admin") } | |
61 | end | |
end | ||
def test_create_table_adds_id | ||
... | ... | |
four = columns.detect { |c| c.name == "four" } | ||
assert_equal "hello", one.default | ||
87 | | |
102 | if current_adapter?(:OracleAdapter) | |
# Oracle doesn't support native booleans | ||
assert_equal true, two.default == 1 | ||
assert_equal false, three.default != 0 | ||
... | ... | |
Person.connection.drop_table :testings rescue nil | ||
end | ||
101 | | |
116 | # SQL Server and Sybase will not allow you to add a NOT NULL column | |
# to a table without specifying a default value, so the | ||
# following test must be skipped | ||
104 | | |
119 | unless current_adapter?(:SQLServerAdapter) || current_adapter?(:SybaseAdapter) | |
def test_add_column_not_null_without_default | ||
Person.connection.create_table :testings do |t| | ||
t.column :foo, :string | ||
... | ... | |
assert_equal Fixnum, bob.age.class | ||
assert_equal Time, bob.birthday.class | ||
156 | | |
157 | | |
171 | if current_adapter?(:SQLServerAdapter) || current_adapter?(:OracleAdapter) || current_adapter?(:SybaseAdapter) | |
172 | # SQL Server, Sybase, and Oracle don't differentiate between date/time | |
assert_equal Time, bob.favorite_day.class | ||
else | ||
assert_equal Date, bob.favorite_day.class | ||
... | ... | |
ActiveRecord::Base.connection.rename_table :octopuses, :octopi | ||
assert_nothing_raised do | ||
244 | | |
245 | | |
246 | | |
259 | if current_adapter?(:OracleAdapter) | |
260 | # Oracle requires the explicit sequence value for the pk | |
261 | ActiveRecord::Base.connection.execute "INSERT INTO octopi (id, url) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" | |
else | ||
ActiveRecord::Base.connection.execute "INSERT INTO octopi (url) VALUES ('http://www.foreverflying.com/octopus-black7.jpg')" | ||
end | ||
... | ... | |
end | ||
def test_change_column | ||
261 | | |
262 | | |
276 | Person.connection.add_column 'people', 'age', :integer | |
277 | old_columns = Person.connection.columns(Person.table_name, "#{name} Columns") | |
278 | assert old_columns.find { |c| c.name == 'age' and c.type == :integer } | |
279 | ||
280 | assert_nothing_raised { Person.connection.change_column "people", "age", :string } | |
281 | ||
282 | new_columns = Person.connection.columns(Person.table_name, "#{name} Columns") | |
283 | assert_nil new_columns.find { |c| c.name == 'age' and c.type == :integer } | |
284 | assert new_columns.find { |c| c.name == 'age' and c.type == :string } | |
end | ||
def test_change_column_with_new_default | ||
... | ... | |
assert !Reminder.table_exists? | ||
end | ||
363 | def test_migrator_verbosity | |
364 | ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1) | |
365 | assert PeopleHaveLastNames.message_count > 0 | |
366 | PeopleHaveLastNames.message_count = 0 | |
367 | ||
368 | ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 0) | |
369 | assert PeopleHaveLastNames.message_count > 0 | |
370 | PeopleHaveLastNames.message_count = 0 | |
371 | end | |
372 | ||
373 | def test_migrator_verbosity_off | |
374 | PeopleHaveLastNames.verbose = false | |
375 | ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1) | |
376 | assert PeopleHaveLastNames.message_count.zero? | |
377 | ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 0) | |
378 | assert PeopleHaveLastNames.message_count.zero? | |
379 | end | |
380 | ||
def test_migrator_going_down_due_to_version_target | ||
ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1) | ||
ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations/', 0) | ||
... | ... | |
Reminder.reset_sequence_name | ||
end | ||
458 | def test_create_table_with_binary_column | |
459 | Person.connection.drop_table :binary_testings rescue nil | |
460 | ||
461 | assert_nothing_raised { | |
462 | Person.connection.create_table :binary_testings do |t| | |
463 | t.column "data", :binary, :default => "", :null => false | |
464 | end | |
465 | } | |
466 | ||
467 | columns = Person.connection.columns(:binary_testings) | |
468 | data_column = columns.detect { |c| c.name == "data" } | |
469 | ||
470 | if current_adapter?(:OracleAdapter) | |
471 | assert_equal "empty_blob()", data_column.default | |
472 | else | |
473 | assert_equal "", data_column.default | |
474 | end | |
475 | ||
476 | Person.connection.drop_table :binary_testings rescue nil | |
477 | end | |
478 | ||
def test_migrator_with_duplicates | ||
assert_raises(ActiveRecord::DuplicateMigrationVersionError) do | ||
ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations_with_duplicate/', nil) |
rool/rails/typo/trunk/vendor/rails/activerecord/test/mixin_nested_set_test.rb:
prev. | current | |
def test_mixing_in_methods | ||
ns = NestedSet.new | ||
assert( ns.respond_to?( :all_children ) ) | ||
12 | | |
12 | assert_equal( ns.scope_condition, "root_id IS NULL" ) | |
check_method_mixins ns | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/modules_test.rb:
prev. | current | |
end | ||
def test_associations_spanning_cross_modules | ||
21 | | |
21 | account = MyApplication::Billing::Account.find(:first, :order => 'id') | |
22 | assert_kind_of MyApplication::Business::Firm, account.firm | |
23 | assert_kind_of MyApplication::Billing::Firm, account.qualified_billing_firm | |
24 | assert_kind_of MyApplication::Billing::Firm, account.unqualified_billing_firm | |
25 | assert_kind_of MyApplication::Billing::Nested::Firm, account.nested_qualified_billing_firm | |
26 | assert_kind_of MyApplication::Billing::Nested::Firm, account.nested_unqualified_billing_firm | |
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/readonly_test.rb:
prev. | current | |
require 'fixtures/comment' | ||
require 'fixtures/developer' | ||
require 'fixtures/project' | ||
6 | require 'fixtures/reader' | |
7 | require 'fixtures/person' | |
# Dummy class methods to test implicit association scoping. | ||
def Comment.foo() find :first end | ||
... | ... | |
def test_habtm_find_readonly | ||
dev = Developer.find(1) | ||
assert !dev.projects.empty? | ||
53 | | |
54 | | |
55 | | |
55 | assert dev.projects.all?(&:readonly?) | |
56 | assert dev.projects.find(:all).all?(&:readonly?) | |
57 | assert dev.projects.find(:all, :readonly => true).all?(&:readonly?) | |
end | ||
def test_has_many_find_readonly | ||
post = Post.find(1) | ||
assert !post.comments.empty? | ||
61 | | |
62 | | |
63 | | |
63 | assert !post.comments.any?(&:readonly?) | |
64 | assert !post.comments.find(:all).any?(&:readonly?) | |
65 | assert post.comments.find(:all, :readonly => true).all?(&:readonly?) | |
end | ||
68 | def test_has_many_with_through_is_not_implicitly_marked_readonly | |
69 | assert people = Post.find(1).people | |
70 | assert !people.any?(&:readonly?) | |
71 | end | |
def test_readonly_scoping | ||
Post.with_scope(:find => { :conditions => '1=1' }) do | ||
... | ... | |
# Oracle barfs on this because the join includes unqualified and | ||
# conflicting column names | ||
82 | | |
88 | unless current_adapter?(:OracleAdapter) | |
Post.with_scope(:find => { :joins => ', developers' }) do | ||
assert Post.find(1).readonly? | ||
assert Post.find(1, :readonly => true).readonly? |
rool/rails/typo/trunk/vendor/rails/activerecord/test/reflection_test.rb:
prev. | current | |
require 'fixtures/customer' | ||
require 'fixtures/company' | ||
require 'fixtures/company_in_module' | ||
6 | require 'fixtures/subscriber' | |
class ReflectionTest < Test::Unit::TestCase | ||
8 | | |
9 | fixtures :topics, :customers, :companies, :subscribers | |
def setup | ||
@first = Topic.find(1) | ||
end | ||
15 | def test_column_null_not_null | |
16 | subscriber = Subscriber.find(:first) | |
17 | assert subscriber.column_for_attribute("name").null | |
18 | assert !subscriber.column_for_attribute("nick").null | |
19 | end | |
20 | ||
def test_read_attribute_names | ||
assert_equal( | ||
%w( id title author_name author_email_address bonus_time written_on last_read content approved replies_count parent_id type ).sort, | ||
... | ... | |
:composed_of, :gps_location, { }, Customer | ||
) | ||
63 | | |
64 | | |
65 | | |
66 | | |
70 | assert Customer.reflect_on_all_aggregations.include?(reflection_for_gps_location) | |
71 | assert Customer.reflect_on_all_aggregations.include?(reflection_for_balance) | |
72 | assert Customer.reflect_on_all_aggregations.include?(reflection_for_address) | |
assert_equal reflection_for_address, Customer.reflect_on_aggregation(:address) | ||
assert_equal Address, Customer.reflect_on_aggregation(:address).klass | ||
77 | ||
78 | assert_equal Money, Customer.reflect_on_aggregation(:balance).klass | |
end | ||
def test_has_many_reflection | ||
74 | | |
82 | reflection_for_clients = ActiveRecord::Reflection::AssociationReflection.new(:has_many, :clients, { :order => "id", :dependent => :destroy }, Firm) | |
assert_equal reflection_for_clients, Firm.reflect_on_association(:clients) | ||
... | ... | |
end | ||
def test_has_one_reflection | ||
86 | | |
94 | reflection_for_account = ActiveRecord::Reflection::AssociationReflection.new(:has_one, :account, { :foreign_key => "firm_id", :dependent => :destroy }, Firm) | |
assert_equal reflection_for_account, Firm.reflect_on_association(:account) | ||
assert_equal Account, Firm.reflect_on_association(:account).klass | ||
... | ... | |
end | ||
def test_association_reflection_in_modules | ||
94 | | |
95 | | |
102 | assert_reflection MyApplication::Business::Firm, | |
103 | :clients_of_firm, | |
104 | :klass => MyApplication::Business::Client, | |
105 | :class_name => 'Client', | |
106 | :table_name => 'companies' | |
107 | ||
108 | assert_reflection MyApplication::Billing::Account, | |
109 | :firm, | |
110 | :klass => MyApplication::Business::Firm, | |
111 | :class_name => 'MyApplication::Business::Firm', | |
112 | :table_name => 'companies' | |
113 | ||
114 | assert_reflection MyApplication::Billing::Account, | |
115 | :qualified_billing_firm, | |
116 | :klass => MyApplication::Billing::Firm, | |
117 | :class_name => 'MyApplication::Billing::Firm', | |
118 | :table_name => 'companies' | |
119 | ||
120 | assert_reflection MyApplication::Billing::Account, | |
121 | :unqualified_billing_firm, | |
122 | :klass => MyApplication::Billing::Firm, | |
123 | :class_name => 'Firm', | |
124 | :table_name => 'companies' | |
125 | ||
126 | assert_reflection MyApplication::Billing::Account, | |
127 | :nested_qualified_billing_firm, | |
128 | :klass => MyApplication::Billing::Nested::Firm, | |
129 | :class_name => 'MyApplication::Billing::Nested::Firm', | |
130 | :table_name => 'companies' | |
131 | ||
132 | assert_reflection MyApplication::Billing::Account, | |
133 | :nested_unqualified_billing_firm, | |
134 | :klass => MyApplication::Billing::Nested::Firm, | |
135 | :class_name => 'Nested::Firm', | |
136 | :table_name => 'companies' | |
end | ||
138 | ||
139 | def test_reflection_of_all_associations | |
140 | assert_equal 13, Firm.reflect_on_all_associations.size | |
141 | assert_equal 11, Firm.reflect_on_all_associations(:has_many).size | |
142 | assert_equal 2, Firm.reflect_on_all_associations(:has_one).size | |
143 | assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size | |
144 | end | |
145 | ||
146 | private | |
147 | def assert_reflection(klass, association, options) | |
148 | assert reflection = klass.reflect_on_association(association) | |
149 | options.each do |method, value| | |
150 | assert_equal(value, reflection.send(method)) | |
151 | end | |
152 | end | |
end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/schema_dumper_test.rb:
prev. | current | |
assert_match %r{create_table "authors"}, output | ||
assert_no_match %r{create_table "schema_info"}, output | ||
end | ||
17 | ||
18 | def test_schema_dump_includes_not_null_columns | |
19 | stream = StringIO.new | |
20 | ||
21 | ActiveRecord::SchemaDumper.ignore_tables = [/^[^s]/] | |
22 | ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream) | |
23 | output = stream.string | |
24 | assert_match %r{:null => false}, output | |
25 | end | |
26 | ||
27 | def test_schema_dump_with_string_ignored_table | |
28 | stream = StringIO.new | |
29 | ||
30 | ActiveRecord::SchemaDumper.ignore_tables = ['accounts'] | |
31 | ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream) | |
32 | output = stream.string | |
33 | assert_no_match %r{create_table "accounts"}, output | |
34 | assert_match %r{create_table "authors"}, output | |
35 | assert_no_match %r{create_table "schema_info"}, output | |
36 | end | |
37 | ||
38 | ||
39 | def test_schema_dump_with_regexp_ignored_table | |
40 | stream = StringIO.new | |
41 | ||
42 | ActiveRecord::SchemaDumper.ignore_tables = [/^account/] | |
43 | ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream) | |
44 | output = stream.string | |
45 | assert_no_match %r{create_table "accounts"}, output | |
46 | assert_match %r{create_table "authors"}, output | |
47 | assert_no_match %r{create_table "schema_info"}, output | |
48 | end | |
49 | ||
50 | ||
51 | def test_schema_dump_illegal_ignored_table_value | |
52 | stream = StringIO.new | |
53 | ActiveRecord::SchemaDumper.ignore_tables = [5] | |
54 | assert_raise(StandardError) do | |
55 | ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream) | |
56 | end | |
57 | end | |
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/threaded_connections_test.rb:
prev. | current | |
def setup | ||
@connection = ActiveRecord::Base.remove_connection | ||
@connections = [] | ||
12 | @allow_concurrency = ActiveRecord::Base.allow_concurrency | |
end | ||
15 | def teardown | |
16 | # clear the connection cache | |
17 | ActiveRecord::Base.send(:clear_all_cached_connections!) | |
18 | # set allow_concurrency to saved value | |
19 | ActiveRecord::Base.allow_concurrency = @allow_concurrency | |
20 | # reestablish old connection | |
21 | ActiveRecord::Base.establish_connection(@connection) | |
22 | end | |
23 | ||
def gather_connections(use_threaded_connections) | ||
ActiveRecord::Base.allow_concurrency = use_threaded_connections | ||
ActiveRecord::Base.establish_connection(@connection) |
rool/rails/typo/trunk/vendor/rails/activerecord/test/unconnected_test.rb:
prev. | current | |
self.use_transactional_fixtures = false | ||
def setup | ||
10 | | |
10 | @underlying = ActiveRecord::Base.connection | |
11 | @specification = ActiveRecord::Base.remove_connection | |
end | ||
def teardown | ||
14 | | |
15 | @underlying = nil | |
16 | ActiveRecord::Base.establish_connection(@specification) | |
end | ||
17 | | |
19 | def test_connection_no_longer_established | |
assert_raise(ActiveRecord::ConnectionNotEstablished) do | ||
19 | | |
21 | TestRecord.find(1) | |
end | ||
23 | ||
assert_raise(ActiveRecord::ConnectionNotEstablished) do | ||
22 | | |
25 | TestRecord.new.save | |
end | ||
end | ||
28 | ||
29 | def test_underlying_adapter_no_longer_active | |
30 | assert !@underlying.active?, "Removed adapter should no longer be active" | |
31 | end | |
end |
rool/rails/typo/trunk/vendor/rails/activerecord/test/validations_test.rb:
prev. | current | |
def test_errors_on_boundary_breaking | ||
developer = Developer.new("name" => "xs") | ||
assert !developer.save | ||
159 | | |
159 | assert_equal "is too short (minimum is 3 characters)", developer.errors.on("name") | |
developer.name = "All too very long for this boundary, it really is" | ||
assert !developer.save | ||
163 | | |
163 | assert_equal "is too long (maximum is 20 characters)", developer.errors.on("name") | |
developer.name = "Just right" | ||
assert developer.save | ||
... | ... | |
assert r3.valid?, "Saving r3" | ||
end | ||
283 | def test_validate_uniqueness_with_scope_array | |
284 | Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id]) | |
285 | ||
286 | t = Topic.create("title" => "The earth is actually flat!") | |
287 | ||
288 | r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply" | |
289 | assert r1.valid?, "Saving r1" | |
290 | ||
291 | r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..." | |
292 | assert !r2.valid?, "Saving r2. Double reply by same author." | |
293 | ||
294 | r2.author_email_address = "jeremy_alt_email@rubyonrails.com" | |
295 | assert r2.save, "Saving r2 the second time." | |
296 | ||
297 | r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic" | |
298 | assert !r3.valid?, "Saving r3" | |
299 | ||
300 | r3.author_name = "jj" | |
301 | assert r3.save, "Saving r3 the second time." | |
302 | ||
303 | r3.author_name = "jeremy" | |
304 | assert !r3.save, "Saving r3 the third time." | |
305 | end | |
306 | ||
def test_validate_format | ||
Topic.validates_format_of(:title, :content, :with => /^Validation\smacros \w+!$/, :message => "is bad data") | ||
... | ... | |
assert_raise(ArgumentError) { Topic.validates_format_of(:title, :content) } | ||
end | ||
323 | ||
324 | # testing ticket #3142 | |
325 | def test_validate_format_numeric | |
326 | Topic.validates_format_of(:title, :content, :with => /^[1-9][0-9]*$/, :message => "is bad data") | |
328 | t = Topic.create("title" => "72x", "content" => "6789") | |
329 | assert !t.valid?, "Shouldn't be valid" | |
330 | assert !t.save, "Shouldn't save because it's invalid" | |
331 | assert_equal "is bad data", t.errors.on(:title) | |
332 | assert_nil t.errors.on(:content) | |
333 | ||
334 | t.title = "-11" | |
335 | assert !t.valid?, "Shouldn't be valid" | |
336 | ||
337 | t.title = "03" | |
338 | assert !t.valid?, "Shouldn't be valid" | |
339 | ||
340 | t.title = "z44" | |
341 | assert !t.valid?, "Shouldn't be valid" | |
342 | ||
343 | t.title = "5v7" | |
344 | assert !t.valid?, "Shouldn't be valid" | |
345 | ||
346 | t.title = "1" | |
347 | ||
348 | assert t.save | |
349 | assert_nil t.errors.on(:title) | |
350 | end | |
351 | ||
def test_validates_inclusion_of | ||
Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ) ) | ||
... | ... | |
t.title = "not" | ||
assert !t.valid? | ||
assert t.errors.on(:title) | ||
353 | | |
405 | assert_equal "is too short (minimum is 5 characters)", t.errors["title"] | |
t.title = "" | ||
assert !t.valid? | ||
assert t.errors.on(:title) | ||
358 | | |
410 | assert_equal "is too short (minimum is 5 characters)", t.errors["title"] | |
t.title = nil | ||
assert !t.valid? | ||
assert t.errors.on(:title) | ||
363 | | |
415 | assert_equal "is too short (minimum is 5 characters)", t.errors["title"] | |
end | ||
def test_optionally_validates_length_of_using_minimum | ||
... | ... | |
t.title = "notvalid" | ||
assert !t.valid? | ||
assert t.errors.on(:title) | ||
385 | | |
437 | assert_equal "is too long (maximum is 5 characters)", t.errors["title"] | |
t.title = "" | ||
assert t.valid? | ||
... | ... | |
t = Topic.new("title" => "a!", "content" => "I'm ooooooooh so very long") | ||
assert !t.valid? | ||
409 | | |
410 | | |
461 | assert_equal "is too short (minimum is 3 characters)", t.errors.on(:title) | |
462 | assert_equal "is too long (maximum is 5 characters)", t.errors.on(:content) | |
t.title = nil | ||
t.content = nil | ||
assert !t.valid? | ||
415 | | |
416 | | |
467 | assert_equal "is too short (minimum is 3 characters)", t.errors.on(:title) | |
468 | assert_equal "is too short (minimum is 3 characters)", t.errors.on(:content) | |
t.title = "abe" | ||
t.content = "mad" | ||
... | ... | |
assert_equal "hoo 5", t.errors["title"] | ||
end | ||
645 | def kcode_scope(kcode) | |
646 | orig_kcode = $KCODE | |
647 | $KCODE = kcode | |
648 | begin | |
649 | yield | |
650 | ensure | |
651 | $KCODE = orig_kcode | |
652 | end | |
653 | end | |
654 | ||
655 | def test_validates_length_of_using_minimum_utf8 | |
656 | kcode_scope('UTF8') do | |
657 | Topic.validates_length_of :title, :minimum => 5 | |
658 | ||
659 | t = Topic.create("title" => "一二三四五", "content" => "whatever") | |
660 | assert t.valid? | |
661 | ||
662 | t.title = "一二三四" | |
663 | assert !t.valid? | |
664 | assert t.errors.on(:title) | |
665 | assert_equal "is too short (minimum is 5 characters)", t.errors["title"] | |
666 | end | |
667 | end | |
668 | ||
669 | def test_validates_length_of_using_maximum_utf8 | |
670 | kcode_scope('UTF8') do | |
671 | Topic.validates_length_of :title, :maximum => 5 | |
672 | ||
673 | t = Topic.create("title" => "一二三四五", "content" => "whatever") | |
674 | assert t.valid? | |
675 | ||
676 | t.title = "一二34五å…" | |
677 | assert !t.valid? | |
678 | assert t.errors.on(:title) | |
679 | assert_equal "is too long (maximum is 5 characters)", t.errors["title"] | |
680 | end | |
681 | end | |
682 | ||
683 | def test_validates_length_of_using_within_utf8 | |
684 | kcode_scope('UTF8') do | |
685 | Topic.validates_length_of(:title, :content, :within => 3..5) | |
686 | ||
687 | t = Topic.new("title" => "一二", "content" => "12三四五å…七") | |
688 | assert !t.valid? | |
689 | assert_equal "is too short (minimum is 3 characters)", t.errors.on(:title) | |
690 | assert_equal "is too long (maximum is 5 characters)", t.errors.on(:content) | |
691 | t.title = "一二三" | |
692 | t.content = "12三" | |
693 | assert t.valid? | |
694 | end | |
695 | end | |
696 | ||
697 | def test_optionally_validates_length_of_using_within_utf8 | |
698 | kcode_scope('UTF8') do | |
699 | Topic.validates_length_of :title, :content, :within => 3..5, :allow_nil => true | |
700 | ||
701 | t = Topic.create('title' => '一二三', 'content' => '一二三四五') | |
702 | assert t.valid? | |
703 | ||
704 | t.title = nil | |
705 | assert t.valid? | |
706 | end | |
707 | end | |
708 | ||
709 | def test_optionally_validates_length_of_using_within_on_create_utf8 | |
710 | kcode_scope('UTF8') do | |
711 | Topic.validates_length_of :title, :content, :within => 5..10, :on => :create, :too_long => "é•·ã™ãŽã¾ã™: %d" | |
712 | ||
713 | t = Topic.create("title" => "一二三四五å…七八ä¹åA", "content" => "whatever") | |
714 | assert !t.save | |
715 | assert t.errors.on(:title) | |
716 | assert_equal "é•·ã™ãŽã¾ã™: 10", t.errors[:title] | |
717 | ||
718 | t.title = "一二三四五å…七八ä¹" | |
719 | assert t.save | |
720 | ||
721 | t.title = "一二3" | |
722 | assert t.save | |
723 | ||
724 | t.content = "一二三四五å…七八ä¹å" | |
725 | assert t.save | |
726 | ||
727 | t.content = t.title = "一二三四五å…" | |
728 | assert t.save | |
729 | end | |
730 | end | |
731 | ||
732 | def test_optionally_validates_length_of_using_within_on_update_utf8 | |
733 | kcode_scope('UTF8') do | |
734 | Topic.validates_length_of :title, :content, :within => 5..10, :on => :update, :too_short => "çŸã™ãŽã¾ã™: %d" | |
735 | ||
736 | t = Topic.create("title" => "一二三4", "content" => "whatever") | |
737 | assert !t.save | |
738 | assert t.errors.on(:title) | |
739 | ||
740 | t.title = "1二三4" | |
741 | assert !t.save | |
742 | assert t.errors.on(:title) | |
743 | assert_equal "çŸã™ãŽã¾ã™: 5", t.errors[:title] | |
744 | ||
745 | t.title = "valid" | |
746 | t.content = "一二三四五å…七八ä¹åA" | |
747 | assert !t.save | |
748 | assert t.errors.on(:content) | |
749 | ||
750 | t.content = "一二345" | |
751 | assert t.save | |
752 | end | |
753 | end | |
754 | ||
755 | def test_validates_length_of_using_is_utf8 | |
756 | kcode_scope('UTF8') do | |
757 | Topic.validates_length_of :title, :is => 5 | |
758 | ||
759 | t = Topic.create("title" => "一二345", "content" => "whatever") | |
760 | assert t.valid? | |
761 | ||
762 | t.title = "一二345å…" | |
763 | assert !t.valid? | |
764 | assert t.errors.on(:title) | |
765 | assert_equal "is the wrong length (should be 5 characters)", t.errors["title"] | |
766 | end | |
767 | end | |
768 | ||
769 | def test_validates_size_of_association_utf8 | |
770 | kcode_scope('UTF8') do | |
771 | assert_nothing_raised { Topic.validates_size_of :replies, :minimum => 1 } | |
772 | t = Topic.new('title' => 'ã‚ã„ã†ãˆãŠ', 'content' => 'ã‹ããã‘ã“') | |
773 | assert !t.save | |
774 | assert t.errors.on(:replies) | |
775 | t.replies.create('title' => 'ã‚ã„ã†ãˆãŠ', 'content' => 'ã‹ããã‘ã“') | |
776 | assert t.valid? | |
777 | end | |
778 | end | |
779 | ||
def test_validates_associated_many | ||
Topic.validates_associated( :replies ) | ||
t = Topic.create("title" => "uhohuhoh", "content" => "whatever") |
rool/rails/typo/trunk/vendor/rails/activesupport/CHANGELOG:
prev. | current | |
1 | *1.3.1* (April 6th, 2005) | |
2 | ||
3 | * Clean paths inside of exception messages and traces. [Nicholas Seckar] | |
4 | ||
5 | * Add Pathname.clean_within for cleaning all the paths inside of a string. [Nicholas Seckar] | |
6 | ||
7 | * provide an empty Dependencies::LoadingModule.load which prints deprecation warnings. Lets 1.0 applications function with .13-style environment.rb. | |
8 | ||
9 | ||
10 | *1.3.0* (March 27th, 2005) | |
11 | ||
12 | * When possible, avoid incorrectly obtaining constants from parent modules. Fixes #4221. [Nicholas Seckar] | |
13 | ||
14 | * Add more tests for dependencies; refactor existing cases. [Nicholas Seckar] | |
15 | ||
16 | * Move Module#parent and Module#as_load_path into core_ext. Add Module#parent. [Nicholas Seckar] | |
17 | ||
18 | * Add CachingTools::HashCaching to simplify the creation of nested, autofilling hashes. [Nicholas Seckar] | |
19 | ||
20 | * Remove a hack intended to avoid unloading the same class twice, but which would not work anyways. [Nicholas Seckar] | |
21 | ||
22 | * Update Object.subclasses_of to locate nested classes. This affects Object.remove_subclasses_of in that nested classes will now be unloaded. [Nicholas Seckar] | |
23 | ||
24 | * Update Object.remove_subclasses_of to use Class.remove_class, reducing duplication. [Nicholas Seckar] | |
25 | ||
26 | * Added Fixnum#seconds for consistency, so you can say 5.minutes + 30.seconds instead of 5.minutes + 30 #4389 [François Beausoleil] | |
27 | ||
28 | * Added option to String#camelize to generate lower-cased camel case by passing in :lower, like "super_man".camelize(:lower) # => "superMan" [DHH] | |
29 | ||
30 | * Added Hash#diff to show the difference between two hashes [Chris McGrath] | |
31 | ||
32 | * Added Time#advance to do precise time time calculations for cases where a month being approximated to 30 days won't do #1860 [Rick Olson] | |
33 | ||
34 | * Enhance Inflector.underscore to convert '-' into '_' (as the inverse of Inflector.dasherize) [Jamis Buck] | |
35 | ||
36 | * Switched to_xml to use the xml schema format for datetimes. This allows the encoding of time zones and should improve operability. [Koz] | |
37 | ||
38 | * Added a note to the documentation for the Date related Numeric extensions to indicate that they're | |
39 | approximations and shouldn't be used for critical calculations. [Koz] | |
40 | ||
41 | * Added Hash#to_xml and Array#to_xml that makes it much easier to produce XML from basic structures [DHH]. Examples: | |
42 | ||
43 | { :name => "David", :street_name => "Paulina", :age => 26, :moved_on => Date.new(2005, 11, 15) }.to_xml | |
44 | ||
45 | ...returns: | |
46 | ||
47 | <person> | |
48 | <street-name>Paulina</street-name> | |
49 | <name>David</name> | |
50 | <age type="integer">26</age> | |
51 | <moved-on type="date">2005-11-15</moved-on> | |
52 | </person> | |
53 | ||
54 | * Moved Jim Weirich's wonderful Builder from Action Pack to Active Support (it's simply too useful to be stuck in AP) [DHH] | |
55 | ||
56 | * Fixed that Array#to_sentence will return "" on an empty array instead of ", and" #3842, #4031 [rubyonrails@beautifulpixel.com] | |
57 | ||
58 | * Add Enumerable#group_by for grouping collections based on the result of some | |
59 | block. Useful, for example, for grouping records by date. | |
60 | ||
61 | ex. | |
62 | ||
63 | latest_transcripts.group_by(&:day).each do |day, transcripts| | |
64 | p "#{day} -> #{transcripts.map(&:class) * ', '}" | |
65 | end | |
66 | "2006-03-01 -> Transcript" | |
67 | "2006-02-28 -> Transcript" | |
68 | "2006-02-27 -> Transcript, Transcript" | |
69 | "2006-02-26 -> Transcript, Transcript" | |
70 | ||
71 | Add Array#in_groups_of, for iterating over an array in groups of a certain | |
72 | size. | |
73 | ||
74 | ex. | |
75 | ||
76 | %w(1 2 3 4 5 6 7).in_groups_of(3) {|g| p g} | |
77 | ["1", "2", "3"] | |
78 | ["4", "5", "6"] | |
79 | ["7", nil, nil] | |
80 | ||
81 | [Marcel Molina Jr., Sam Stephenson] | |
82 | ||
83 | * Added Kernel#daemonize to turn the current process into a daemon that can be killed with a TERM signal [DHH] | |
84 | ||
85 | * Add 'around' methods to Logger, to make it easy to log before and after messages for a given block as requested in #3809. [Michael Koziarski] Example: | |
86 | ||
87 | logger.around_info("Start rendering component (#{options.inspect}): ", | |
88 | "\n\nEnd of component rendering") { yield } | |
89 | ||
90 | * Added Time#beginning_of_quarter #3607 [cohen.jeff@gmail.com] | |
91 | ||
92 | * Fix Object.subclasses_of to only return currently defined objects [Jonathan Viney <jonathan@bluewire.net.nz>] | |
93 | ||
94 | * Fix constantize to properly handle names beginning with '::'. [Nicholas Seckar] | |
95 | ||
96 | * Make String#last return the string instead of nil when it is shorter than the limit [Scott Barron]. | |
97 | ||
98 | * Added delegation support to Module that allows multiple delegations at once (unlike Forwardable in the stdlib) [DHH]. Example: | |
99 | ||
100 | class Account < ActiveRecord::Base | |
101 | has_one :subscription | |
102 | delegate :free?, :paying?, :to => :subscription | |
103 | delegate :overdue?, :to => "subscription.last_payment" | |
104 | end | |
105 | ||
106 | account.free? # => account.subscription.free? | |
107 | account.overdue? # => account.subscription.last_payment.overdue? | |
108 | ||
109 | * Fix Reloadable to handle the case where a class that has been 'removed' has not yet been garbage collected. [Nicholas Seckar] | |
110 | ||
111 | * Don't allow Reloadable to be included into Modules. | |
112 | ||
113 | * Remove LoadingModule. [Nicholas Seckar] | |
114 | ||
115 | * Add documentation for Reloadable::Subclasses. [Nicholas Seckar] | |
116 | ||
117 | * Add Reloadable::Subclasses which handles the common case where a base class should not be reloaded, but its subclasses should be. [Nicholas Seckar] | |
118 | ||
119 | * Further improvements to reloading code [Nicholas Seckar, Trevor Squires] | |
120 | ||
121 | - All classes/modules which include Reloadable can define reloadable? for fine grained control of reloading | |
122 | - Class.remove_class uses Module#parent to access the parent module | |
123 | - Class.remove_class expanded to handle multiple classes in a single call | |
124 | - LoadingModule.clear! has been removed as it is no longer required | |
125 | - Module#remove_classes_including has been removed in favor of Reloadable.reloadable_classes | |
126 | ||
127 | * Added reusable reloading support through the inclusion of the Relodable module that all subclasses of ActiveRecord::Base, ActiveRecord::Observer, ActiveController::Base, and ActionMailer::Base automatically gets. This means that these classes will be reloaded by the dispatcher when Dependencies.mechanism = :load. You can make your own models reloadable easily: | |
128 | ||
129 | class Setting | |
130 | include Reloadable | |
131 | end | |
132 | ||
133 | Reloading a class is done by removing its constant which will cause it to be loaded again on the next reference. [DHH] | |
134 | ||
135 | * Added auto-loading support for classes in modules, so Conductor::Migration will look for conductor/migration.rb and Conductor::Database::Settings will look for conductor/database/settings.rb [Nicholas Seckar] | |
136 | ||
137 | * Add Object#instance_exec, like instance_eval but passes its arguments to the block. (Active Support will not override the Ruby 1.9 implementation of this method.) [Sam Stephenson] | |
138 | ||
139 | * Add Proc#bind(object) for changing a proc or block's self by returning a Method bound to the given object. Based on why the lucky stiff's "cloaker" method. [Sam Stephenson] | |
140 | ||
141 | * Fix merge and dup for hashes with indifferent access #3404 [kenneth.miller@bitfield.net] | |
142 | ||
143 | * Fix the requires in option_merger_test to unbreak AS tests. [Sam Stephenson] | |
144 | ||
145 | * Make HashWithIndifferentAccess#update behave like Hash#update by returning the hash. #3419, #3425 [asnem@student.ethz.ch, JanPrill@blauton.de, Marcel Molina Jr.] | |
146 | ||
147 | * Add ActiveSupport::JSON and Object#to_json for converting Ruby objects to JSON strings. [Sam Stephenson] | |
148 | ||
149 | * Add Object#with_options for DRYing up multiple calls to methods having shared options. [Sam Stephenson] Example: | |
150 | ||
151 | ActionController::Routing::Routes.draw do |map| | |
152 | # Account routes | |
153 | map.with_options(:controller => 'account') do |account| | |
154 | account.home '', :action => 'dashboard' | |
155 | account.signup 'signup', :action => 'new' | |
156 | account.logout 'logout', :action => 'logout' | |
157 | end | |
158 | end | |
159 | ||
160 | * Introduce Dependencies.warnings_on_first_load setting. If true, enables warnings on first load of a require_dependency. Otherwise, loads without warnings. Disabled (set to false) by default. [Jeremy Kemper] | |
161 | ||
162 | * Active Support is warnings-safe. #1792 [Eric Hodel] | |
163 | ||
164 | * Introduce enable_warnings counterpart to silence_warnings. Turn warnings on when loading a file for the first time if Dependencies.mechanism == :load. Common mistakes such as redefined methods will print warnings to stderr. [Jeremy Kemper] | |
165 | ||
166 | * Add Symbol#to_proc, which allows for, e.g. [:foo, :bar].map(&:to_s). [Marcel Molina Jr.] | |
167 | ||
168 | * Added the following methods [Marcel Molina Jr., Sam Stephenson]: | |
169 | * Object#copy_instance_variables_from(object) to copy instance variables from one object to another | |
170 | * Object#extended_by to get an instance's included/extended modules | |
171 | * Object#extend_with_included_modules_from(object) to extend an instance with the modules from another instance | |
172 | ||
*1.2.5* (December 13th, 2005) | ||
* Become part of Rails 1.0 | ||
... | ... | |
3 | ||
4 | ||
5 | ||
* Rename Version constant to VERSION. #2802 [Marcel Molina Jr.] | ||
8 | ||
*1.2.3* (November 7th, 2005) |
rool/rails/typo/trunk/vendor/rails/activesupport/Rakefile:
prev. | current | |
task :default => :test | ||
Rake::TestTask.new { |t| | ||
t.pattern = 'test/**/*_test.rb' | ||
20 | t.verbose = true | |
21 | t.warning = false | |
} | ||
# Create compressed packages | ||
... | ... | |
Rake::RDocTask.new { |rdoc| | ||
rdoc.rdoc_dir = 'doc' | ||
rdoc.title = "Active Support -- Utility classes and standard library extensions from Rails" | ||
30 | | |
32 | rdoc.options << '--line-numbers' << '--inline-source' | |
rdoc.template = "#{ENV['template']}.rb" if ENV['template'] | ||
rdoc.rdoc_files.include('README', 'CHANGELOG') | ||
rdoc.rdoc_files.include('lib/active_support.rb') | ||
... | ... | |
end | ||
desc "Publish the release files to RubyForge." | ||
72 | ||
73 | | |
74 | task :release => [ :package ] do | |
75 | `rubyforge login` | |
75 | | |
76 | | |
77 | | |
78 | ||
79 | | |
80 | | |
81 | | |
82 | | |
83 | ||
84 | | |
85 | | |
86 | | |
87 | | |
88 | | |
89 | | |
90 | | |
91 | ||
92 | | |
93 | | |
94 | | |
95 | | |
96 | | |
97 | | |
98 | | |
99 | | |
100 | ||
101 | | |
102 | | |
103 | | |
104 | ||
105 | | |
106 | | |
107 | | |
108 | | |
109 | ||
110 | | |
111 | | |
112 | ||
113 | | |
114 | | |
115 | | |
116 | | |
117 | ||
118 | | |
119 | ||
120 | | |
121 | | |
122 | | |
123 | | |
124 | | |
125 | | |
126 | | |
127 | | |
128 | | |
129 | | |
130 | ||
131 | | |
132 | | |
133 | | |
134 | | |
135 | | |
136 | | |
137 | | |
138 | | |
139 | | |
140 | | |
141 | | |
142 | | |
143 | | |
144 | | |
145 | | |
146 | | |
147 | | |
148 | | |
149 | | |
150 | | |
151 | | |
152 | | |
153 | | |
154 | | |
155 | ||
156 | | |
157 | | |
158 | | |
159 | ||
160 | | |
161 | | |
162 | | |
163 | | |
164 | | |
165 | | |
166 | | |
167 | ||
168 | | |
169 | | |
170 | | |
171 | ||
172 | | |
173 | | |
174 | | |
175 | ||
176 | | |
177 | | |
178 | | |
179 | | |
180 | ||
181 | | |
182 | | |
77 | for ext in %w( gem tgz zip ) | |
78 | release_command = "rubyforge add_release #{PKG_NAME} #{PKG_NAME} 'REL #{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" | |
79 | puts release_command | |
80 | system(release_command) | |
end | ||
184 | ||
82 | end | |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support.rb:
prev. | current | |
#++ | ||
$:.unshift(File.dirname(__FILE__)) | ||
25 | $:.unshift(File.dirname(__FILE__) + "/active_support/vendor") | |
26 | ||
27 | ||
27 | require 'builder' | |
28 | ||
require 'active_support/inflector' | ||
require 'active_support/core_ext' | ||
require 'active_support/clean_logger' | ||
require 'active_support/dependencies' | ||
34 | require 'active_support/reloadable' | |
require 'active_support/ordered_options' | ||
37 | require 'active_support/option_merger' | |
36 | ||
40 | require 'active_support/values/time_zone' | |
41 | ||
42 | require 'active_support/json' | |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/breakpoint.rb:
prev. | current | |
# license please contact me. | ||
require 'irb' | ||
19 | ||
19 | require File.dirname(__FILE__) + '/binding_of_caller' unless defined? Binding.of_caller | |
require 'drb' | ||
require 'drb/acl' | ||
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/clean_logger.rb:
prev. | current | |
require 'logger' | ||
2 | ||
2 | require File.dirname(__FILE__) + '/core_ext/class/attribute_accessors' | |
class Logger #:nodoc: | ||
cattr_accessor :silencer | ||
... | ... | |
end | ||
private | ||
23 | alias old_format_message format_message | |
24 | ||
# Ruby 1.8.3 transposed the msg and progname arguments to format_message. | ||
# We can't test RUBY_VERSION because some distributions don't keep Ruby | ||
# and its standard library in sync, leading to installations of Ruby 1.8.2 |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/array.rb:
prev. | current | |
class Array #:nodoc: | ||
include ActiveSupport::CoreExtensions::Array::Conversions | ||
5 | ||
6 | # Iterate over an array in groups of a certain size, padding any remaining | |
7 | # slots with specified value (<tt>nil</tt> by default). | |
8 | # | |
9 | # E.g. | |
10 | # | |
11 | # %w(1 2 3 4 5 6 7).in_groups_of(3) {|g| p g} | |
12 | # ["1", "2", "3"] | |
13 | # ["4", "5", "6"] | |
14 | # ["7", nil, nil] | |
15 | def in_groups_of(number, fill_with = nil, &block) | |
16 | require 'enumerator' | |
17 | collection = dup | |
18 | collection << fill_with until collection.size.modulo(number).zero? | |
19 | collection.each_slice(number, &block) | |
20 | end | |
end |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/array/conversions.rb:
prev. | current | |
module ActiveSupport #:nodoc: | ||
module CoreExtensions #:nodoc: | ||
module Array #:nodoc: | ||
4 | | |
module Conversions | ||
# Converts the array to comma-seperated sentence where the last element is joined by the connector word. Options: | ||
# * <tt>:connector</tt>: The word used to join the last element in arrays with more than two elements (default: "and") | ||
8 | | |
7 | # * <tt>:skip_last_comma</tt>: Set to true to return "a, b, and c" instead of "a, b and c". | |
def to_sentence(options = {}) | ||
options.assert_valid_keys(:connector, :skip_last_comma) | ||
options.reverse_merge! :connector => 'and', :skip_last_comma => false | ||
case length | ||
13 | when 0 | |
14 | "" | |
when 1 | ||
self[0] | ||
when 2 | ||
... | ... | |
def to_param | ||
join '/' | ||
end | ||
28 | ||
29 | def to_xml(options = {}) | |
30 | raise "Not all elements respond to to_xml" unless all? { |e| e.respond_to? :to_xml } | |
31 | ||
32 | options[:root] ||= all? { |e| e.is_a?(first.class) && first.class.to_s != "Hash" } ? first.class.to_s.underscore.pluralize : "records" | |
33 | options[:children] ||= options[:root].singularize | |
34 | options[:indent] ||= 2 | |
35 | options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent]) | |
36 | ||
37 | root = options.delete(:root) | |
38 | children = options.delete(:children) | |
39 | ||
40 | options[:builder].instruct! unless options.delete(:skip_instruct) | |
41 | options[:builder].tag!(root.to_s.dasherize) { each { |e| e.to_xml(options.merge({ :skip_instruct => true, :root => children })) } } | |
42 | end | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/blank.rb:
prev. | current | |
1 | ||
1 | class Object #:nodoc: | |
2 | # "", " ", nil, [], and {} are blank | |
3 | def blank? | |
4 | if respond_to?(:empty?) && respond_to?(:strip) | |
5 | empty? or strip.empty? | |
6 | elsif respond_to?(:empty?) | |
7 | empty? | |
8 | else | |
9 | !self | |
10 | end | |
11 | end | |
12 | end | |
13 | ||
class NilClass #:nodoc: | ||
def blank? | ||
true | ||
... | ... | |
def blank? | ||
false | ||
end | ||
38 | ||
50 | end | |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/date/conversions.rb:
prev. | current | |
def to_time(form = :local) | ||
::Time.send(form, year, month, day) | ||
end | ||
28 | ||
29 | alias :xmlschema :to_s | |
end | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/enumerable.rb:
prev. | current | |
end | ||
match | ||
end | ||
9 | ||
10 | ||
11 | # Collect an enumerable into sets, grouped by the result of a block. Useful, | |
12 | # for example, for grouping records by date. | |
13 | # | |
14 | # e.g. | |
15 | # | |
16 | # latest_transcripts.group_by(&:day).each do |day, transcripts| | |
17 | # p "#{day} -> #{transcripts.map(&:class) * ', '}" | |
18 | # end | |
19 | # "2006-03-01 -> Transcript" | |
20 | # "2006-02-28 -> Transcript" | |
21 | # "2006-02-27 -> Transcript, Transcript" | |
22 | # "2006-02-26 -> Transcript, Transcript" | |
23 | # "2006-02-25 -> Transcript" | |
24 | # "2006-02-24 -> Transcript, Transcript" | |
25 | # "2006-02-23 -> Transcript" | |
26 | def group_by | |
27 | inject({}) do |groups, element| | |
28 | (groups[yield(element)] ||= []) << element | |
29 | groups | |
30 | end | |
31 | end | |
32 | end |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/exception.rb:
prev. | current | |
1 | ||
1 | class Exception # :nodoc: | |
2 | def clean_message | |
3 | Pathname.clean_within message | |
4 | end | |
3 | | |
4 | | |
TraceSubstitutions = [] | ||
6 | | |
7 | FrameworkRegexp = /generated|vendor|dispatch|ruby|script\/\w+/ | |
def clean_backtrace | ||
backtrace.collect do |line| | ||
10 | | |
11 | Pathname.clean_within(TraceSubstitutions.inject(line) do |line, (regexp, sub)| | |
line.gsub regexp, sub | ||
12 | | |
13 | end) | |
end | ||
end | ||
def application_backtrace | ||
before_application_frame = true | ||
19 | | |
20 | | |
20 | trace = clean_backtrace.reject do |line| | |
21 | non_app_frame = (line =~ FrameworkRegexp) | |
before_application_frame = false unless non_app_frame | ||
non_app_frame && ! before_application_frame | ||
end | ||
25 | ||
26 | # If we didn't find any application frames, return an empty app trace. | |
27 | before_application_frame ? [] : trace | |
end | ||
def framework_backtrace |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/hash.rb:
prev. | current | |
require File.dirname(__FILE__) + '/hash/keys' | ||
require File.dirname(__FILE__) + '/hash/indifferent_access' | ||
require File.dirname(__FILE__) + '/hash/reverse_merge' | ||
4 | require File.dirname(__FILE__) + '/hash/conversions' | |
5 | require File.dirname(__FILE__) + '/hash/diff' | |
class Hash #:nodoc: | ||
include ActiveSupport::CoreExtensions::Hash::Keys | ||
include ActiveSupport::CoreExtensions::Hash::IndifferentAccess | ||
include ActiveSupport::CoreExtensions::Hash::ReverseMerge | ||
11 | include ActiveSupport::CoreExtensions::Hash::Conversions | |
12 | include ActiveSupport::CoreExtensions::Hash::Diff | |
end |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb:
prev. | current | |
1 | ||
1 | # this class has dubious semantics and we only have it so that | |
2 | # people can write params[:key] instead of params['key'] | |
3 | ||
class HashWithIndifferentAccess < Hash | ||
def initialize(constructor = {}) | ||
if constructor.is_a?(Hash) | ||
... | ... | |
end | ||
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer) | ||
19 | alias_method :regular_update, :update unless method_defined?(:regular_update) | |
def []=(key, value) | ||
regular_writer(convert_key(key), convert_value(value)) | ||
end | ||
21 | | |
22 | | |
24 | ||
25 | def update(other_hash) | |
26 | other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) } | |
27 | self | |
end | ||
29 | ||
30 | alias_method :merge!, :update | |
def key?(key) | ||
super(convert_key(key)) | ||
... | ... | |
indices.collect {|key| self[convert_key(key)]} | ||
end | ||
48 | def dup | |
49 | HashWithIndifferentAccess.new(self) | |
50 | end | |
51 | ||
52 | def merge(hash) | |
53 | self.dup.update(hash) | |
54 | end | |
55 | ||
56 | def delete(key) | |
57 | super(convert_key(key)) | |
58 | end | |
59 | ||
protected | ||
def convert_key(key) | ||
key.kind_of?(Symbol) ? key.to_s : key |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/integer/inflections.rb:
prev. | current | |
1 | ||
1 | require File.dirname(__FILE__) + '/../../inflector' unless defined? Inflector | |
module ActiveSupport #:nodoc: | ||
module CoreExtensions #:nodoc: | ||
module Integer #:nodoc: |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/kernel.rb:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
5 | | |
6 | | |
7 | | |
8 | | |
9 | | |
10 | | |
11 | | |
12 | | |
13 | | |
14 | | |
15 | | |
16 | | |
17 | | |
18 | | |
19 | | |
20 | | |
21 | | |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
30 | | |
31 | ||
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | | |
38 | | |
39 | | |
40 | | |
41 | | |
42 | | |
43 | | |
44 | | |
45 | | |
46 | | |
47 | ||
48 | | |
49 | | |
50 | | |
51 | | |
52 | | |
53 | | |
54 | | |
55 | | |
56 | | |
57 | | |
58 | | |
59 | | |
60 | | |
61 | | |
62 | | |
63 | | |
64 | | |
65 | | |
66 | | |
67 | | |
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
73 | | |
74 | | |
75 | | |
76 | | |
77 | ||
78 | ||
79 | ||
1 | require File.dirname(__FILE__) + '/kernel/daemonizing' | |
2 | require File.dirname(__FILE__) + '/kernel/reporting' | |
3 | require File.dirname(__FILE__) + '/kernel/agnostics' | |
4 | require File.dirname(__FILE__) + '/kernel/requires' |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/numeric/time.rb:
prev. | current | |
module ActiveSupport #:nodoc: | ||
module CoreExtensions #:nodoc: | ||
module Numeric #:nodoc: | ||
4 | | |
4 | # Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years. | |
5 | # | |
6 | # If you need precise date calculations that doesn't just treat months as 30 days, then have | |
7 | # a look at Time#advance. | |
8 | # | |
9 | # Some of these methods are approximations, Ruby's core | |
10 | # Date[http://stdlib.rubyonrails.org/libdoc/date/rdoc/index.html] and | |
11 | # Time[http://stdlib.rubyonrails.org/libdoc/time/rdoc/index.html] should be used for precision | |
12 | # date and time arithmetic | |
module Time | ||
14 | def seconds | |
15 | self | |
16 | end | |
17 | alias :second :seconds | |
18 | ||
def minutes | ||
self * 60 | ||
end |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/string.rb:
prev. | current | |
require File.dirname(__FILE__) + '/string/conversions' | ||
require File.dirname(__FILE__) + '/string/access' | ||
require File.dirname(__FILE__) + '/string/starts_ends_with' | ||
5 | require File.dirname(__FILE__) + '/string/iterators' | |
class String #:nodoc: | ||
include ActiveSupport::CoreExtensions::String::Access | ||
include ActiveSupport::CoreExtensions::String::Conversions | ||
include ActiveSupport::CoreExtensions::String::Inflections | ||
include ActiveSupport::CoreExtensions::String::StartsEndsWith | ||
12 | include ActiveSupport::CoreExtensions::String::Iterators | |
end |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/string/access.rb:
prev. | current | |
# "hello".last(2) # => "lo" | ||
# "hello".last(10) # => "hello" | ||
def last(limit = 1) | ||
53 | | |
53 | self[(-limit)..-1] || self | |
end | ||
end | ||
end | ||
end | ||
58 | ||
59 | end |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/string/inflections.rb:
prev. | current | |
1 | ||
1 | require File.dirname(__FILE__) + '/../../inflector' unless defined? Inflector | |
module ActiveSupport #:nodoc: | ||
module CoreExtensions #:nodoc: | ||
module String #:nodoc: | ||
... | ... | |
Inflector.singularize(self) | ||
end | ||
15 | | |
16 | | |
15 | def camelize(first_letter = :upper) | |
16 | case first_letter | |
17 | when :upper then Inflector.camelize(self, true) | |
18 | when :lower then Inflector.camelize(self, false) | |
19 | end | |
end | ||
alias_method :camelcase, :camelize | ||
... | ... | |
Inflector.underscore(self) | ||
end | ||
32 | def dasherize | |
33 | Inflector.dasherize(self) | |
34 | end | |
35 | ||
def demodulize | ||
Inflector.demodulize(self) | ||
end |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/time/calculations.rb:
prev. | current | |
options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : self.usec) | ||
) | ||
end | ||
47 | ||
48 | # Uses Date to provide precise Time calculations for years, months, and days. The +options+ parameter takes a hash with | |
49 | # any of these keys: :months, :days, :years. | |
50 | def advance(options) | |
51 | d = ::Date.new(year + (options.delete(:years) || 0), month, day) | |
52 | d = d >> options.delete(:months) if options[:months] | |
53 | d = d + options.delete(:days) if options[:days] | |
54 | change(options.merge(:year => d.year, :month => d.month, :mday => d.day)) | |
55 | end | |
# Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension | ||
# Do not use this method in combination with x.months, use months_ago instead! | ||
... | ... | |
change(:mday => last_day,:hour => 0, :min => 0, :sec => 0, :usec => 0) | ||
end | ||
alias :at_end_of_month :end_of_month | ||
164 | ||
165 | # Returns a new Time representing the start of the quarter (1st of january, april, july, october, 0:00) | |
166 | def beginning_of_quarter | |
167 | beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= self.month }) | |
168 | end | |
169 | alias :at_beginning_of_quarter :beginning_of_quarter | |
# Returns a new Time representing the start of the year (1st of january, 0:00) | ||
def beginning_of_year |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/core_ext/time/conversions.rb:
prev. | current | |
require 'date' | ||
2 | require 'time' | |
module ActiveSupport #:nodoc: | ||
module CoreExtensions #:nodoc: |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/dependencies.rb:
prev. | current | |
1 | ||
1 | require 'set' | |
2 | require File.dirname(__FILE__) + '/core_ext/module/attribute_accessors' | |
require File.dirname(__FILE__) + '/core_ext/load_error' | ||
4 | require File.dirname(__FILE__) + '/core_ext/kernel' | |
module Dependencies #:nodoc: | ||
extend self | ||
7 | | |
9 | # Should we turn on Ruby warnings on the first load of dependent files? | |
10 | mattr_accessor :warnings_on_first_load | |
11 | self.warnings_on_first_load = false | |
12 | ||
13 | # All files ever loaded. | |
14 | mattr_accessor :history | |
15 | self.history = Set.new | |
16 | ||
17 | # All files currently loaded. | |
mattr_accessor :loaded | ||
19 | self.loaded = Set.new | |
10 | | |
21 | # Should we load files or require them? | |
mattr_accessor :mechanism | ||
12 | | |
23 | self.mechanism = :load | |
24 | ||
def load? | ||
mechanism == :load | ||
end | ||
16 | | |
17 | | |
18 | | |
19 | | |
21 | | |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
29 | def depend_on(file_name, swallow_load_errors = false) | |
30 | require_or_load(file_name) | |
31 | rescue LoadError | |
32 | raise unless swallow_load_errors | |
end | ||
def associate_with(file_name) | ||
depend_on(file_name, true) | ||
end | ||
32 | | |
38 | ||
def clear | ||
34 | | |
40 | loaded.clear | |
end | ||
36 | | |
42 | ||
def require_or_load(file_name) | ||
38 | | |
39 | | |
40 | | |
41 | | |
42 | | |
43 | | |
44 | | |
45 | | |
46 | | |
47 | | |
48 | | |
49 | | |
50 | | |
51 | | |
52 | | |
53 | | |
54 | | |
55 | | |
56 | | |
57 | | |
58 | | |
59 | | |
60 | | |
61 | | |
62 | | |
63 | | |
64 | | |
65 | | |
66 | | |
67 | | |
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
73 | | |
74 | | |
75 | | |
76 | | |
77 | | |
78 | | |
44 | file_name = $1 if file_name =~ /^(.*)\.rb$/ | |
45 | return if loaded.include?(file_name) | |
80 | | |
81 | | |
82 | | |
47 | # Record that we've seen this file *before* loading it to avoid an | |
48 | # infinite loop with mutual dependencies. | |
49 | loaded << file_name | |
84 | | |
85 | | |
86 | | |
87 | | |
88 | | |
89 | | |
90 | | |
91 | | |
92 | | |
93 | | |
94 | | |
95 | | |
96 | | |
97 | | |
98 | | |
99 | | |
100 | | |
101 | | |
102 | | |
103 | | |
104 | | |
105 | | |
106 | | |
107 | | |
51 | if load? | |
52 | begin | |
53 | # Enable warnings iff this file has not been loaded before and | |
54 | # warnings_on_first_load is set. | |
55 | if !warnings_on_first_load or history.include?(file_name) | |
56 | load "#{file_name}.rb" | |
57 | else | |
58 | enable_warnings { load "#{file_name}.rb" } | |
end | ||
60 | rescue | |
61 | loaded.delete file_name | |
62 | raise | |
end | ||
110 | | |
111 | | |
64 | else | |
65 | require file_name | |
end | ||
113 | | |
114 | | |
115 | | |
116 | | |
117 | | |
118 | | |
119 | | |
120 | | |
121 | | |
122 | | |
124 | | |
125 | | |
126 | | |
127 | ||
128 | | |
129 | ||
130 | | |
131 | | |
132 | | |
133 | | |
134 | | |
135 | | |
136 | ||
137 | | |
138 | | |
139 | | |
140 | | |
141 | | |
142 | | |
143 | | |
68 | # Record history *after* loading so first load gets warnings. | |
69 | history << file_name | |
end | ||
146 | | |
147 | | |
148 | | |
149 | | |
150 | | |
151 | | |
152 | | |
153 | | |
154 | | |
155 | | |
156 | ||
157 | | |
158 | | |
159 | | |
72 | class LoadingModule | |
73 | # Old style environment.rb referenced this method directly. Please note, it doesn't | |
74 | # actualy *do* anything any more. | |
75 | def self.root(*args) | |
76 | if defined?(RAILS_DEFAULT_LOGGER) | |
77 | RAILS_DEFAULT_LOGGER.warn "Your environment.rb uses the old syntax, it may not continue to work in future releases." | |
78 | RAILS_DEFAULT_LOGGER.warn "For upgrade instructions please see: http://manuals.rubyonrails.com/read/book/19" | |
end | ||
161 | ||
162 | | |
163 | ||
164 | | |
end | ||
166 | | |
167 | | |
168 | | |
169 | | |
170 | ||
171 | | |
172 | | |
173 | | |
end | ||
end | ||
... | ... | |
class Module #:nodoc: | ||
# Rename the original handler so we can chain it to the new one | ||
alias :rails_original_const_missing :const_missing | ||
184 | ||
91 | ||
# Use const_missing to autoload associations so we don't have to | ||
# require_association when using single-table inheritance. | ||
def const_missing(class_id) | ||
188 | | |
189 | | |
190 | | |
191 | | |
file_name = class_id.to_s.demodulize.underscore | ||
96 | file_path = as_load_path.empty? ? file_name : "#{as_load_path}/#{file_name}" | |
begin | ||
194 | | |
195 | | |
196 | | |
98 | require_dependency(file_path) | |
99 | brief_name = self == Object ? '' : "#{name}::" | |
100 | raise NameError.new("uninitialized constant #{brief_name}#{class_id}") unless const_defined?(class_id) | |
101 | return const_get(class_id) | |
rescue MissingSourceFile => e | ||
198 | | |
199 | | |
103 | # Re-raise the error if it does not concern the file we were trying to load. | |
104 | raise unless e.is_missing? file_path | |
105 | ||
106 | # Look for a directory in the load path that we ought to load. | |
107 | if $LOAD_PATH.any? { |base| File.directory? "#{base}/#{file_path}" } | |
108 | mod = Module.new | |
109 | const_set class_id, mod # Create the new module | |
110 | return mod | |
111 | end | |
112 | ||
113 | # Attempt to access the name from the parent, unless we don't have a valid | |
114 | # parent, or the constant is already defined in the parent. If the latter | |
115 | # is the case, then we are being queried via self::class_id, and we should | |
116 | # avoid returning the constant from the parent if possible. | |
117 | if parent && parent != self && ! parents.any? { |p| p.const_defined?(class_id) } | |
118 | suppress(NameError) do | |
119 | return parent.send(:const_missing, class_id) | |
120 | end | |
121 | end | |
122 | ||
raise NameError.new("uninitialized constant #{class_id}").copy_blame!(e) | ||
end | ||
end | ||
end | ||
128 | class Class | |
129 | def const_missing(class_id) | |
130 | if [Object, Kernel].include?(self) || parent == self | |
131 | super | |
132 | else | |
133 | parent.send :const_missing, class_id | |
134 | end | |
135 | end | |
136 | end | |
137 | ||
class Object #:nodoc: | ||
def load(file, *extras) | ||
super(file, *extras) | ||
... | ... | |
@blamed_files = exc.blamed_files.clone | ||
self | ||
end | ||
240 | ||
173 | end | |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/inflections.rb:
prev. | current | |
Inflector.inflections do |inflect| | ||
2 | | |
3 | | |
4 | | |
5 | | |
6 | | |
7 | | |
8 | | |
9 | | |
10 | | |
11 | | |
12 | | |
13 | | |
14 | | |
15 | | |
16 | | |
17 | | |
18 | | |
19 | | |
2 | inflect.plural(/$/, 's') | |
3 | inflect.plural(/s$/i, 's') | |
4 | inflect.plural(/(ax|test)is$/i, '\1es') | |
5 | inflect.plural(/(octop|vir)us$/i, '\1i') | |
6 | inflect.plural(/(alias|status)$/i, '\1es') | |
7 | inflect.plural(/(bu)s$/i, '\1ses') | |
8 | inflect.plural(/(buffal|tomat)o$/i, '\1oes') | |
9 | inflect.plural(/([ti])um$/i, '\1a') | |
10 | inflect.plural(/sis$/i, 'ses') | |
11 | inflect.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves') | |
12 | inflect.plural(/(hive)$/i, '\1s') | |
13 | inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies') | |
14 | inflect.plural(/([^aeiouy]|qu)ies$/i, '\1y') | |
15 | inflect.plural(/(x|ch|ss|sh)$/i, '\1es') | |
16 | inflect.plural(/(matr|vert|ind)ix|ex$/i, '\1ices') | |
17 | inflect.plural(/([m|l])ouse$/i, '\1ice') | |
18 | inflect.plural(/^(ox)$/i, '\1en') | |
19 | inflect.plural(/(quiz)$/i, '\1zes') | |
21 | | |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
29 | | |
30 | | |
31 | | |
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | | |
38 | | |
39 | | |
40 | | |
41 | | |
42 | | |
43 | | |
44 | | |
21 | inflect.singular(/s$/i, '') | |
22 | inflect.singular(/(n)ews$/i, '\1ews') | |
23 | inflect.singular(/([ti])a$/i, '\1um') | |
24 | inflect.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '\1\2sis') | |
25 | inflect.singular(/(^analy)ses$/i, '\1sis') | |
26 | inflect.singular(/([^f])ves$/i, '\1fe') | |
27 | inflect.singular(/(hive)s$/i, '\1') | |
28 | inflect.singular(/(tive)s$/i, '\1') | |
29 | inflect.singular(/([lr])ves$/i, '\1f') | |
30 | inflect.singular(/([^aeiouy]|qu)ies$/i, '\1y') | |
31 | inflect.singular(/(s)eries$/i, '\1eries') | |
32 | inflect.singular(/(m)ovies$/i, '\1ovie') | |
33 | inflect.singular(/(x|ch|ss|sh)es$/i, '\1') | |
34 | inflect.singular(/([m|l])ice$/i, '\1ouse') | |
35 | inflect.singular(/(bus)es$/i, '\1') | |
36 | inflect.singular(/(o)es$/i, '\1') | |
37 | inflect.singular(/(shoe)s$/i, '\1') | |
38 | inflect.singular(/(cris|ax|test)es$/i, '\1is') | |
39 | inflect.singular(/([octop|vir])i$/i, '\1us') | |
40 | inflect.singular(/(alias|status)es$/i, '\1') | |
41 | inflect.singular(/^(ox)en/i, '\1') | |
42 | inflect.singular(/(vert|ind)ices$/i, '\1ex') | |
43 | inflect.singular(/(matr)ices$/i, '\1ix') | |
44 | inflect.singular(/(quiz)zes$/i, '\1') | |
46 | | |
47 | | |
48 | | |
49 | | |
50 | | |
46 | inflect.irregular('person', 'people') | |
47 | inflect.irregular('man', 'men') | |
48 | inflect.irregular('child', 'children') | |
49 | inflect.irregular('sex', 'sexes') | |
50 | inflect.irregular('move', 'moves') | |
52 | | |
52 | inflect.uncountable(%w(equipment information rice money species series fish sheep)) | |
end |
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/inflector.rb:
prev. | current | |
end | ||
end | ||
112 | | |
113 | | |
112 | def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true) | |
113 | if first_letter_in_uppercase | |
114 | lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase } | |
115 | else | |
116 | lower_case_and_underscored_word.first + camelize(lower_case_and_underscored_word)[1..-1] | |
117 | end | |
end | ||
def titleize(word) | ||
... | ... | |
end | ||
def underscore(camel_cased_word) | ||
121 | | |
125 | camel_cased_word.to_s.gsub(/::/, '/'). | |
126 | gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). | |
127 | gsub(/([a-z\d])([A-Z])/,'\1_\2'). | |
128 | tr("-", "_"). | |
129 | downcase | |
end | ||
131 | ||
132 | def dasherize(underscored_word) | |
133 | underscored_word.gsub(/_/, '-') | |
134 | end | |
def humanize(lower_case_and_underscored_word) | ||
lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize | ||
... | ... | |
def constantize(camel_cased_word) | ||
raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!" unless | ||
146 | | |
158 | /^(::)?([A-Z]\w*)(::[A-Z]\w*)*$/ =~ camel_cased_word | |
148 | | |
160 | camel_cased_word = "::#{camel_cased_word}" unless $1 | |
Object.module_eval(camel_cased_word, __FILE__, __LINE__) | ||
end | ||
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/ordered_options.rb:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
1 | class OrderedHash < Array #:nodoc: | |
2 | def []=(key, value) | |
if pair = find_pair(key) | ||
pair.pop | ||
pair << value | ||
... | ... | |
end | ||
def [](key) | ||
14 | | |
12 | pair = find_pair(key) | |
pair ? pair.last : nil | ||
end | ||
16 | def keys | |
17 | self.collect { |i| i.first } | |
18 | end | |
19 | ||
20 | private | |
21 | def find_pair(key) | |
22 | self.each { |i| return i if i.first == key } | |
23 | return false | |
24 | end | |
25 | end | |
26 | ||
27 | class OrderedOptions < OrderedHash #:nodoc: | |
28 | def []=(key, value) | |
29 | super(key.to_sym, value) | |
30 | end | |
31 | ||
32 | def [](key) | |
33 | super(key.to_sym) | |
34 | end | |
35 | ||
def method_missing(name, *args) | ||
if name.to_s =~ /(.*)=$/ | ||
self[$1.to_sym] = args.first | ||
... | ... | |
self[name] | ||
end | ||
end | ||
25 | ||
26 | | |
27 | | |
28 | | |
29 | | |
30 | | |
end | ||
rool/rails/typo/trunk/vendor/rails/activesupport/lib/active_support/version.rb:
prev. | current | |
module ActiveSupport | ||
module VERSION #:nodoc: | ||
MAJOR = 1 | ||
4 | | |
5 | | |
4 | MINOR = 3 | |
5 | TINY = 1 | |
STRING = [MAJOR, MINOR, TINY].join('.') | ||
end |
rool/rails/typo/trunk/vendor/rails/activesupport/test/class_inheritable_attributes_test.rb:
prev. | current | |
require 'test/unit' | ||
2 | ||
2 | require File.dirname(__FILE__) + '/../lib/active_support/core_ext/class/inheritable_attributes' | |
class ClassInheritableAttributesTest < Test::Unit::TestCase | ||
def setup |
rool/rails/typo/trunk/vendor/rails/activesupport/test/clean_logger_test.rb:
prev. | current | |
require 'test/unit' | ||
require 'stringio' | ||
require File.dirname(__FILE__) + '/../lib/active_support/clean_logger' | ||
4 | require File.dirname(__FILE__) + '/../lib/active_support/core_ext/kernel.rb' unless defined? silence_warnings | |
class CleanLoggerTest < Test::Unit::TestCase | ||
def setup | ||
... | ... | |
class CleanLogger_182_to_183_Test < Test::Unit::TestCase | ||
def setup | ||
48 | | |
49 | | |
50 | | |
51 | | |
52 | | |
49 | silence_warnings do | |
50 | if Logger.method_defined?(:formatter=) | |
51 | Logger.send(:alias_method, :hide_formatter=, :formatter=) | |
52 | Logger.send(:undef_method, :formatter=) | |
53 | else | |
54 | Logger.send(:define_method, :formatter=) { } | |
55 | end | |
56 | load File.dirname(__FILE__) + '/../lib/active_support/clean_logger.rb' | |
end | ||
54 | | |
@out = StringIO.new | ||
@logger = Logger.new(@out) | ||
... | ... | |
end | ||
def teardown | ||
62 | | |
63 | | |
64 | | |
65 | | |
65 | silence_warnings do | |
66 | if Logger.method_defined?(:hide_formatter=) | |
67 | Logger.send(:alias_method, :formatter=, :hide_formatter=) | |
68 | else | |
69 | Logger.send(:undef_method, :formatter=) | |
70 | end | |
71 | load File.dirname(__FILE__) + '/../lib/active_support/clean_logger.rb' | |
end | ||
67 | | |
end | ||
# Since we've fooled Logger into thinking we're on 1.8.2 if we're on 1.8.3 |
rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/array_ext_test.rb:
prev. | current | |
require 'test/unit' | ||
2 | ||
2 | require File.dirname(__FILE__) + '/../../lib/active_support' | |
class ArrayExtToParamTests < Test::Unit::TestCase | ||
def test_string_array | ||
... | ... | |
class ArrayExtConversionTests < Test::Unit::TestCase | ||
def test_plain_array_to_sentence | ||
18 | assert_equal "", [].to_sentence | |
19 | assert_equal "one", ['one'].to_sentence | |
20 | assert_equal "one and two", ['one', 'two'].to_sentence | |
assert_equal "one, two, and three", ['one', 'two', 'three'].to_sentence | ||
22 | ||
end | ||
def test_to_sentence_with_connector | ||
... | ... | |
end | ||
def test_to_sentence_with_skip_last_comma | ||
26 | | |
30 | assert_equal "one, two, and three", ['one', 'two', 'three'].to_sentence(:skip_last_comma => false) | |
end | ||
def test_two_elements | ||
... | ... | |
assert_equal "one", ['one'].to_sentence | ||
end | ||
end | ||
41 | ||
42 | class ArrayExtGroupingTests < Test::Unit::TestCase | |
43 | def test_group_by_with_perfect_fit | |
44 | groups = [] | |
45 | ('a'..'i').to_a.in_groups_of(3) do |group| | |
46 | groups << group | |
47 | end | |
48 | ||
49 | assert_equal [%w(a b c), %w(d e f), %w(g h i)], groups | |
50 | end | |
51 | ||
52 | def test_group_by_with_padding | |
53 | groups = [] | |
54 | ('a'..'g').to_a.in_groups_of(3) do |group| | |
55 | groups << group | |
56 | end | |
57 | ||
58 | assert_equal [%w(a b c), %w(d e f), ['g', nil, nil]], groups | |
59 | end | |
60 | ||
61 | def test_group_by_pads_with_specified_values | |
62 | groups = [] | |
63 | ||
64 | ('a'..'g').to_a.in_groups_of(3, false) do |group| | |
65 | groups << group | |
66 | end | |
67 | ||
68 | assert_equal [%w(a b c), %w(d e f), ['g', false, false]], groups | |
69 | end | |
70 | end | |
71 | ||
72 | class ArraToXmlTests < Test::Unit::TestCase | |
73 | def test_to_xml | |
74 | xml = [ | |
75 | { :name => "David", :age => 26 }, { :name => "Jason", :age => 31 } | |
76 | ].to_xml(:skip_instruct => true, :indent => 0) | |
77 | ||
78 | assert_equal "<records><record>", xml.first(17) | |
79 | assert xml.include?(%(<age type="integer">26</age>)) | |
80 | assert xml.include?(%(<name>David</name>)) | |
81 | assert xml.include?(%(<age type="integer">31</age>)) | |
82 | assert xml.include?(%(<name>Jason</name>)) | |
83 | end | |
84 | ||
85 | def test_to_xml_with_dedicated_name | |
86 | xml = [ | |
87 | { :name => "David", :age => 26 }, { :name => "Jason", :age => 31 } | |
88 | ].to_xml(:skip_instruct => true, :indent => 0, :root => "people") | |
89 | ||
90 | assert_equal "<people><person>", xml.first(16) | |
91 | end | |
92 | ||
93 | def test_to_xml_with_options | |
94 | xml = [ | |
95 | { :name => "David", :street_address => "Paulina" }, { :name => "Jason", :street_address => "Evergreen" } | |
96 | ].to_xml(:skip_instruct => true, :skip_types => true, :indent => 0) | |
97 | ||
98 | assert_equal "<records><record>", xml.first(17) | |
99 | assert xml.include?(%(<street-address>Paulina</street-address>)) | |
100 | assert xml.include?(%(<name>David</name>)) | |
101 | assert xml.include?(%(<street-address>Evergreen</street-address>)) | |
102 | assert xml.include?(%(<name>Jason</name>)) | |
103 | end | |
104 | end | |
rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/blank_test.rb:
prev. | current | |
require 'test/unit' | ||
2 | ||
2 | require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/object' | |
require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/blank' | ||
class BlankTest < Test::Unit::TestCase |
rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/enumerable_test.rb:
prev. | current | |
assert_equal true, (1..10).first_match {|x| x > 9} | ||
assert_equal :aba, {:a => 10, :aba => 50, :bac => 40}.first_match {|k, v| k if v > 45} | ||
end | ||
15 | ||
16 | ||
17 | def test_group_by | |
18 | names = %w(marcel sam david jeremy) | |
19 | klass = Class.new | |
20 | klass.send(:attr_accessor, :name) | |
21 | objects = (1..50).inject([]) do |people,| | |
22 | p = klass.new | |
23 | p.name = names.sort_by { rand }.first | |
24 | people << p | |
25 | end | |
26 | ||
27 | objects.group_by {|object| object.name}.each do |name, group| | |
28 | assert group.all? {|person| person.name == name} | |
29 | end | |
30 | end | |
31 | end |
rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/exception_test.rb:
prev. | current | |
assert_kind_of Exception, e | ||
assert_equal ['vendor/file.rb some stuff', ' vendor/file.rb some stuff'], e.framework_backtrace | ||
end | ||
44 | ||
46 | ||
46 | def test_backtrace_should_clean_paths | |
47 | Exception::TraceSubstitutions << [/\s*hidden.*/, ''] | |
48 | e = get_exception RuntimeError, 'RAWR', ['a/b/c/../d/../../../bhal.rb', 'rawh hid den stuff is not here', 'almost all'] | |
49 | assert_kind_of Exception, e | |
50 | assert_equal ['bhal.rb', 'rawh hid den stuff is not here', 'almost all'], e.clean_backtrace | |
51 | end | |
52 | ||
53 | def test_clean_message_should_clean_paths | |
54 | Exception::TraceSubstitutions << [/\s*hidden.*/, ''] | |
55 | e = get_exception RuntimeError, "I dislike a/z/x/../../b/y/../c", ['a/b/c/../d/../../../bhal.rb', 'rawh hid den stuff is not here', 'almost all'] | |
56 | assert_kind_of Exception, e | |
57 | assert_equal "I dislike a/b/c", e.clean_message | |
58 | end | |
59 | ||
60 | def test_app_trace_should_be_empty_when_no_app_frames | |
61 | Exception::TraceSubstitutions << [/\s*hidden.*/, ''] | |
62 | e = get_exception RuntimeError, 'RAWR', ['vendor/file.rb some stuff', 'generated/bhal.rb', ' vendor/file.rb some stuff', 'generated/almost all'] | |
63 | assert_kind_of Exception, e | |
64 | assert_equal [], e.application_backtrace | |
65 | end | |
66 | end |
rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/hash_ext_test.rb:
prev. | current | |
require 'test/unit' | ||
2 | ||
2 | require File.dirname(__FILE__) + '/../../lib/active_support' | |
class HashExtTest < Test::Unit::TestCase | ||
def setup | ||
... | ... | |
assert_equal hash[3], 3 | ||
end | ||
96 | def test_indifferent_update | |
97 | hash = HashWithIndifferentAccess.new | |
98 | hash[:a] = 'a' | |
99 | hash['b'] = 'b' | |
100 | ||
101 | updated_with_strings = hash.update(@strings) | |
102 | updated_with_symbols = hash.update(@symbols) | |
103 | updated_with_mixed = hash.update(@mixed) | |
104 | ||
105 | assert_equal updated_with_strings[:a], 1 | |
106 | assert_equal updated_with_strings['a'], 1 | |
107 | assert_equal updated_with_strings['b'], 2 | |
108 | ||
109 | assert_equal updated_with_symbols[:a], 1 | |
110 | assert_equal updated_with_symbols['b'], 2 | |
111 | assert_equal updated_with_symbols[:b], 2 | |
112 | ||
113 | assert_equal updated_with_mixed[:a], 1 | |
114 | assert_equal updated_with_mixed['b'], 2 | |
115 | ||
116 | assert [updated_with_strings, updated_with_symbols, updated_with_mixed].all? {|hash| hash.keys.size == 2} | |
117 | end | |
118 | ||
119 | def test_indifferent_merging | |
120 | hash = HashWithIndifferentAccess.new | |
121 | hash[:a] = 'failure' | |
122 | hash['b'] = 'failure' | |
123 | ||
124 | other = { 'a' => 1, :b => 2 } | |
125 | ||
126 | merged = hash.merge(other) | |
127 | ||
128 | assert_equal HashWithIndifferentAccess, merged.class | |
129 | assert_equal 1, merged[:a] | |
130 | assert_equal 2, merged['b'] | |
131 | ||
132 | hash.update(other) | |
133 | ||
134 | assert_equal 1, hash[:a] | |
135 | assert_equal 2, hash['b'] | |
136 | end | |
137 | ||
138 | def test_indifferent_deleting | |
139 | get_hash = proc{ { :a => 'foo' }.with_indifferent_access } | |
140 | hash = get_hash.call | |
141 | assert_equal hash.delete(:a), 'foo' | |
142 | assert_equal hash.delete(:a), nil | |
143 | hash = get_hash.call | |
144 | assert_equal hash.delete('a'), 'foo' | |
145 | assert_equal hash.delete('a'), nil | |
146 | end | |
147 | ||
def test_assert_valid_keys | ||
assert_nothing_raised do | ||
{ :failure => "stuff", :funny => "business" }.assert_valid_keys([ :failure, :funny ]) | ||
... | ... | |
def test_reverse_merge | ||
assert_equal({ :a => 1, :b => 2, :c => 10 }, { :a => 1, :b => 2 }.reverse_merge({:a => "x", :b => "y", :c => 10}) ) | ||
end | ||
177 | ||
178 | def test_diff | |
179 | assert_equal({ :a => 2 }, { :a => 2, :b => 5 }.diff({ :a => 1, :b => 5 })) | |
180 | end | |
end | ||
182 | ||
183 | class HashToXmlTest < Test::Unit::TestCase | |
184 | def setup | |
185 | @xml_options = { :root => :person, :skip_instruct => true, :indent => 0 } | |
186 | end | |
187 | ||
188 | def test_one_level | |
189 | xml = { :name => "David", :street => "Paulina" }.to_xml(@xml_options) | |
190 | assert_equal "<person>", xml.first(8) | |
191 | assert xml.include?(%(<street>Paulina</street>)) | |
192 | assert xml.include?(%(<name>David</name>)) | |
193 | end | |
194 | ||
195 | def test_one_level_with_types | |
196 | xml = { :name => "David", :street => "Paulina", :age => 26, :moved_on => Date.new(2005, 11, 15) }.to_xml(@xml_options) | |
197 | assert_equal "<person>", xml.first(8) | |
198 | assert xml.include?(%(<street>Paulina</street>)) | |
199 | assert xml.include?(%(<name>David</name>)) | |
200 | assert xml.include?(%(<age type="integer">26</age>)) | |
201 | assert xml.include?(%(<moved-on type="date">2005-11-15</moved-on>)) | |
202 | end | |
203 | ||
204 | def test_one_level_with_nils | |
205 | xml = { :name => "David", :street => "Paulina", :age => nil }.to_xml(@xml_options) | |
206 | assert_equal "<person>", xml.first(8) | |
207 | assert xml.include?(%(<street>Paulina</street>)) | |
208 | assert xml.include?(%(<name>David</name>)) | |
209 | assert xml.include?(%(<age></age>)) | |
210 | end | |
211 | ||
212 | def test_one_level_with_skipping_types | |
213 | xml = { :name => "David", :street => "Paulina", :age => nil }.to_xml(@xml_options.merge(:skip_types => true)) | |
214 | assert_equal "<person>", xml.first(8) | |
215 | assert xml.include?(%(<street>Paulina</street>)) | |
216 | assert xml.include?(%(<name>David</name>)) | |
217 | assert xml.include?(%(<age></age>)) | |
218 | end | |
219 | ||
220 | def test_two_levels | |
221 | xml = { :name => "David", :address => { :street => "Paulina" } }.to_xml(@xml_options) | |
222 | assert_equal "<person>", xml.first(8) | |
223 | assert xml.include?(%(<address><street>Paulina</street></address>)) | |
224 | assert xml.include?(%(<name>David</name>)) | |
225 | end | |
226 | ||
227 | def test_two_levels_with_array | |
228 | xml = { :name => "David", :addresses => [{ :street => "Paulina" }, { :street => "Evergreen" }] }.to_xml(@xml_options) | |
229 | assert_equal "<person>", xml.first(8) | |
230 | assert xml.include?(%(<addresses><address>)) | |
231 | assert xml.include?(%(<address><street>Paulina</street></address>)) | |
232 | assert xml.include?(%(<address><street>Evergreen</street></address>)) | |
233 | assert xml.include?(%(<name>David</name>)) | |
234 | end | |
235 | ||
236 | ||
237 | def test_three_levels_with_array | |
238 | xml = { :name => "David", :addresses => [{ :streets => [ { :name => "Paulina" }, { :name => "Paulina" } ] } ] }.to_xml(@xml_options) | |
239 | assert xml.include?(%(<addresses><address><streets><street><name>)) | |
240 | end | |
241 | end |
rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/kernel_test.rb:
prev. | current | |
require 'test/unit' | ||
2 | ||
2 | require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/kernel' unless defined? silence_warnings | |
class KernelTest < Test::Unit::TestCase | ||
def test_silence_warnings | ||
... | ... | |
def test_silence_warnings_verbose_invariant | ||
old_verbose = $VERBOSE | ||
12 | | |
13 | | |
14 | | |
15 | | |
16 | | |
17 | | |
12 | silence_warnings { raise } | |
13 | flunk | |
14 | rescue | |
15 | assert_equal old_verbose, $VERBOSE | |
end | ||
19 | | |
20 | | |
21 | | |
17 | ||
18 | ||
19 | def test_enable_warnings | |
20 | enable_warnings { assert_equal true, $VERBOSE } | |
21 | assert_equal 1234, enable_warnings { 1234 } | |
end | ||
23 | | |
23 | ||
24 | def test_enable_warnings_verbose_invariant | |
25 | old_verbose = $VERBOSE | |
26 | enable_warnings { raise } | |
27 | flunk | |
28 | rescue | |
29 | assert_equal old_verbose, $VERBOSE | |
30 | end | |
31 | ||
32 | ||
def test_silence_stderr | ||
old_stderr_position = STDERR.tell | ||
silence_stderr { STDERR.puts 'hello world' } | ||
assert_equal old_stderr_position, STDERR.tell | ||
end | ||
29 | | |
38 | ||
def test_silence_stderr_with_return_value | ||
assert_equal 1, silence_stderr { 1 } | ||
end |
rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/object_and_class_ext_test.rb:
prev. | current | |
require 'test/unit' | ||
2 | ||
2 | require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/object' | |
3 | require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/class' | |
class ClassA; end | ||
class ClassB < ClassA; end | ||
class ClassC < ClassB; end | ||
class ClassD < ClassA; end | ||
10 | class ClassI; end | |
11 | class ClassJ < ClassI; end | |
12 | ||
13 | class ClassK | |
14 | end | |
15 | module Nested | |
16 | class ClassL < ClassK | |
17 | end | |
18 | end | |
19 | ||
20 | module Bar | |
21 | def bar; end | |
22 | end | |
23 | ||
24 | module Baz | |
25 | def baz; end | |
26 | end | |
27 | ||
28 | class Foo | |
29 | include Bar | |
30 | end | |
31 | ||
class ClassExtTest < Test::Unit::TestCase | ||
def test_methods | ||
assert defined?(ClassB) | ||
... | ... | |
assert !defined?(ClassC) | ||
assert !defined?(ClassD) | ||
end | ||
44 | ||
45 | def test_subclasses_of | |
46 | assert_equal [ClassJ], Object.subclasses_of(ClassI) | |
47 | ClassI.remove_subclasses | |
48 | assert_equal [], Object.subclasses_of(ClassI) | |
49 | end | |
50 | ||
51 | def test_subclasses_of_should_find_nested_classes | |
52 | assert Object.subclasses_of(ClassK).include?(Nested::ClassL) | |
53 | end | |
54 | ||
55 | def test_subclasses_of_should_not_return_removed_classes | |
56 | # First create the removed class | |
57 | old_class = Nested.send :remove_const, :ClassL | |
58 | new_class = Class.new(ClassK) | |
59 | Nested.const_set :ClassL, new_class | |
60 | assert_equal "Nested::ClassL", new_class.name # Sanity check | |
61 | ||
62 | subclasses = Object.subclasses_of(ClassK) | |
63 | assert subclasses.include?(new_class) | |
64 | assert ! subclasses.include?(old_class) | |
65 | end | |
end | ||
class ObjectTests < Test::Unit::TestCase | ||
... | ... | |
suppress(LoadError, ArgumentError) { raise LoadError } | ||
suppress(LoadError, ArgumentError) { raise ArgumentError } | ||
end | ||
78 | ||
79 | def test_extended_by | |
80 | foo = Foo.new | |
81 | assert foo.extended_by.include?(Bar) | |
82 | foo.extend(Baz) | |
83 | assert ([Bar, Baz] - foo.extended_by).empty?, "Expected Bar, Baz in #{foo.extended_by.inspect}" | |
84 | end | |
85 | ||
86 | def test_extend_with_included_modules_from | |
87 | foo, object = Foo.new, Object.new | |
88 | assert !object.respond_to?(:bar) | |
89 | assert !object.respond_to?(:baz) | |
90 | ||
91 | object.extend_with_included_modules_from(foo) | |
92 | assert object.respond_to?(:bar) | |
93 | assert !object.respond_to?(:baz) | |
94 | ||
95 | foo.extend(Baz) | |
96 | object.extend_with_included_modules_from(foo) | |
97 | assert object.respond_to?(:bar) | |
98 | assert object.respond_to?(:baz) | |
99 | end | |
100 | ||
end | ||
102 | ||
103 | class ObjectInstanceVariableTest < Test::Unit::TestCase | |
104 | def setup | |
105 | @source, @dest = Object.new, Object.new | |
106 | @source.instance_variable_set(:@bar, 'bar') | |
107 | @source.instance_variable_set(:@baz, 'baz') | |
108 | end | |
109 | ||
110 | def test_copy_instance_variables_from_without_explicit_excludes | |
111 | assert_equal [], @dest.instance_variables | |
112 | @dest.copy_instance_variables_from(@source) | |
113 | ||
114 | assert_equal %w(@bar @baz), @dest.instance_variables.sort | |
115 | %w(@bar @baz).each do |name| | |
116 | assert_equal @source.instance_variable_get(name).object_id, | |
117 | @dest.instance_variable_get(name).object_id | |
118 | end | |
119 | end | |
120 | ||
121 | def test_copy_instance_variables_from_with_explicit_excludes | |
122 | @dest.copy_instance_variables_from(@source, ['@baz']) | |
123 | assert !@dest.instance_variables.include?('@baz') | |
124 | assert_equal 'bar', @dest.instance_variable_get('@bar') | |
125 | end | |
126 | ||
127 | def test_copy_instance_variables_automatically_excludes_protected_instance_variables | |
128 | @source.instance_variable_set(:@quux, 'quux') | |
129 | class << @source | |
130 | def protected_instance_variables | |
131 | ['@bar', :@quux] | |
132 | end | |
133 | end | |
134 | ||
135 | @dest.copy_instance_variables_from(@source) | |
136 | assert !@dest.instance_variables.include?('@bar') | |
137 | assert !@dest.instance_variables.include?('@quux') | |
138 | assert_equal 'baz', @dest.instance_variable_get('@baz') | |
139 | end | |
140 | ||
141 | def test_instance_values | |
142 | object = Object.new | |
143 | object.instance_variable_set :@a, 1 | |
144 | object.instance_variable_set :@b, 2 | |
145 | assert_equal({'a' => 1, 'b' => 2}, object.instance_values) | |
146 | end | |
147 | ||
148 | def test_instance_exec_passes_arguments_to_block | |
149 | block = Proc.new { |value| [self, value] } | |
150 | assert_equal %w(hello goodbye), 'hello'.instance_exec('goodbye', &block) | |
151 | end | |
152 | ||
153 | end |
rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/string_ext_test.rb:
prev. | current | |
require 'test/unit' | ||
require 'date' | ||
require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/string' | ||
4 | ||
4 | require File.dirname(__FILE__) + '/../inflector_test' unless defined? InflectorTest | |
6 | ||
7 | | |
8 | ||
9 | ||
class StringInflectionsTest < Test::Unit::TestCase | ||
def test_pluralize | ||
InflectorTest::SingularToPlural.each do |singular, plural| | ||
... | ... | |
assert_equal "o", s.last | ||
assert_equal "llo", s.last(3) | ||
80 | ||
81 | assert_equal 'x', 'x'.first | |
82 | assert_equal 'x', 'x'.first(4) | |
83 | ||
84 | assert_equal 'x', 'x'.last | |
85 | assert_equal 'x', 'x'.last(4) | |
end | ||
def test_starts_ends_with | ||
... | ... | |
assert s.ends_with?('lo') | ||
assert !s.ends_with?('el') | ||
end | ||
98 | ||
99 | def test_each_char_with_utf8_string_when_kcode_is_utf8 | |
100 | old_kcode, $KCODE = $KCODE, 'UTF8' | |
101 | '€2.99'.each_char do |char| | |
102 | assert_not_equal 1, char.length | |
103 | break | |
104 | end | |
105 | ensure | |
106 | $KCODE = old_kcode | |
107 | end | |
end |
rool/rails/typo/trunk/vendor/rails/activesupport/test/core_ext/time_ext_test.rb:
prev. | current | |
assert_equal Time.local(2005,2,1,0,0,0), Time.local(2005,2,22,10,10,10).beginning_of_month | ||
end | ||
33 | def test_beginning_of_quarter | |
34 | assert_equal Time.local(2005,1,1,0,0,0), Time.local(2005,2,15,10,10,10).beginning_of_quarter | |
35 | assert_equal Time.local(2005,1,1,0,0,0), Time.local(2005,1,1,0,0,0).beginning_of_quarter | |
36 | assert_equal Time.local(2005,10,1,0,0,0), Time.local(2005,12,31,10,10,10).beginning_of_quarter | |
37 | assert_equal Time.local(2005,4,1,0,0,0), Time.local(2005,6,30,23,59,59).beginning_of_quarter | |
38 | end | |
39 | ||
def test_end_of_month | ||
assert_equal Time.local(2005,3,31,0,0,0), Time.local(2005,3,20,10,10,10).end_of_month | ||
assert_equal Time.local(2005,2,28,0,0,0), Time.local(2005,2,20,10,10,10).end_of_month | ||
... | ... | |
assert_equal Time.utc(2005,2,22,16,45), Time.utc(2005,2,22,15,15,10).change(:hour => 16, :min => 45) | ||
assert_equal Time.utc(2005,2,22,15,45), Time.utc(2005,2,22,15,15,10).change(:min => 45) | ||
end | ||
132 | ||
133 | def test_plus | |
134 | assert_equal Time.local(2006,2,28,15,15,10), Time.local(2005,2,28,15,15,10).advance(:years => 1) | |
135 | assert_equal Time.local(2005,6,28,15,15,10), Time.local(2005,2,28,15,15,10).advance(:months => 4) | |
136 | assert_equal Time.local(2012,9,28,15,15,10), Time.local(2005,2,28,15,15,10).advance(:years => 7, :months => 7) | |
137 | assert_equal Time.local(2013,10,3,15,15,10), Time.local(2005,2,28,15,15,10).advance(:years => 7, :months => 19, :days => 5) | |
138 | end | |
140 | def test_utc_plus | |
141 | assert_equal Time.utc(2006,2,22,15,15,10), Time.utc(2005,2,22,15,15,10).advance(:years => 1) | |
142 | assert_equal Time.utc(2005,6,22,15,15,10), Time.utc(2005,2,22,15,15,10).advance(:months => 4) | |
143 | assert_equal Time.utc(2012,9,22,15,15,10), Time.utc(2005,2,22,15,15,10).advance(:years => 7, :months => 7) | |
144 | assert_equal Time.utc(2013,10,3,15,15,10), Time.utc(2005,2,22,15,15,10).advance(:years => 7, :months => 19, :days => 11) | |
145 | end | |
146 | ||
def test_next_week | ||
assert_equal Time.local(2005,2,28), Time.local(2005,2,22,15,15,10).next_week | ||
assert_equal Time.local(2005,2,29), Time.local(2005,2,22,15,15,10).next_week(:tuesday) | ||
... | ... | |
def test_last_month_on_31st | ||
assert_equal Time.local(2004, 2, 29), Time.local(2004, 3, 31).last_month | ||
end | ||
205 | ||
206 | def test_xmlschema_is_available | |
207 | assert_nothing_raised { Time.now.xmlschema } | |
208 | end | |
end |
rool/rails/typo/trunk/vendor/rails/activesupport/test/dependencies_test.rb:
prev. | current | |
require 'test/unit' | ||
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib/active_support/' | ||
3 | require 'core_ext/string' | |
require 'dependencies' | ||
class DependenciesTest < Test::Unit::TestCase | ||
def teardown | ||
Dependencies.clear | ||
end | ||
10 | ||
11 | def with_loading(from_dir = nil) | |
12 | prior_path = $LOAD_PATH.clone | |
13 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/#{from_dir}" if from_dir | |
14 | old_mechanism, Dependencies.mechanism = Dependencies.mechanism, :load | |
15 | yield | |
16 | ensure | |
17 | $LOAD_PATH.clear | |
18 | $LOAD_PATH.concat prior_path | |
19 | Dependencies.mechanism = old_mechanism | |
20 | end | |
10 | | |
22 | def test_tracking_loaded_files | |
require_dependency(File.dirname(__FILE__) + "/dependencies/service_one") | ||
require_dependency(File.dirname(__FILE__) + "/dependencies/service_two") | ||
assert_equal 2, Dependencies.loaded.size | ||
end | ||
15 | | |
16 | | |
27 | ||
28 | def test_tracking_identical_loaded_files | |
require_dependency(File.dirname(__FILE__) + "/dependencies/service_one") | ||
require_dependency(File.dirname(__FILE__) + "/dependencies/service_one") | ||
assert_equal 1, Dependencies.loaded.size | ||
end | ||
22 | | |
34 | def test_missing_dependency_raises_missing_source_file | |
assert_raises(MissingSourceFile) { require_dependency("missing_service") } | ||
end | ||
25 | | |
26 | | |
37 | ||
38 | def test_missing_association_raises_nothing | |
assert_nothing_raised { require_association("missing_model") } | ||
end | ||
29 | ||
42 | ||
43 | def test_dependency_which_raises_exception_isnt_added_to_loaded_set | |
44 | with_loading do | |
45 | filename = "#{File.dirname(__FILE__)}/dependencies/raises_exception" | |
46 | $raises_exception_load_count = 0 | |
47 | ||
48 | 5.times do |count| | |
49 | assert_raises(RuntimeError) { require_dependency filename } | |
50 | assert_equal count + 1, $raises_exception_load_count | |
51 | ||
52 | assert !Dependencies.loaded.include?(filename) | |
53 | assert !Dependencies.history.include?(filename) | |
54 | end | |
55 | end | |
56 | end | |
57 | ||
58 | def test_warnings_should_be_enabled_on_first_load | |
59 | with_loading do | |
60 | old_warnings, Dependencies.warnings_on_first_load = Dependencies.warnings_on_first_load, true | |
61 | ||
62 | filename = "#{File.dirname(__FILE__)}/dependencies/check_warnings" | |
63 | $check_warnings_load_count = 0 | |
64 | ||
65 | assert !Dependencies.loaded.include?(filename) | |
66 | assert !Dependencies.history.include?(filename) | |
67 | ||
68 | silence_warnings { require_dependency filename } | |
69 | assert_equal 1, $check_warnings_load_count | |
70 | assert_equal true, $checked_verbose, 'On first load warnings should be enabled.' | |
71 | ||
72 | assert Dependencies.loaded.include?(filename) | |
73 | Dependencies.clear | |
74 | assert !Dependencies.loaded.include?(filename) | |
75 | assert Dependencies.history.include?(filename) | |
76 | ||
77 | silence_warnings { require_dependency filename } | |
78 | assert_equal 2, $check_warnings_load_count | |
79 | assert_equal nil, $checked_verbose, 'After first load warnings should be left alone.' | |
80 | ||
81 | assert Dependencies.loaded.include?(filename) | |
82 | Dependencies.clear | |
83 | assert !Dependencies.loaded.include?(filename) | |
84 | assert Dependencies.history.include?(filename) | |
85 | ||
86 | enable_warnings { require_dependency filename } | |
87 | assert_equal 3, $check_warnings_load_count | |
88 | assert_equal true, $checked_verbose, 'After first load warnings should be left alone.' | |
89 | ||
90 | assert Dependencies.loaded.include?(filename) | |
91 | end | |
92 | end | |
93 | ||
94 | def test_mutual_dependencies_dont_infinite_loop | |
95 | with_loading 'dependencies' do | |
96 | $mutual_dependencies_count = 0 | |
97 | assert_nothing_raised { require_dependency 'mutual_one' } | |
98 | assert_equal 2, $mutual_dependencies_count | |
99 | ||
100 | Dependencies.clear | |
101 | ||
102 | $mutual_dependencies_count = 0 | |
103 | assert_nothing_raised { require_dependency 'mutual_two' } | |
104 | assert_equal 2, $mutual_dependencies_count | |
105 | end | |
106 | end | |
107 | ||
108 | def test_as_load_path | |
109 | assert_equal '', DependenciesTest.as_load_path | |
110 | end | |
111 | ||
112 | def test_module_loading | |
113 | with_loading 'autoloading_fixtures' do | |
114 | assert_kind_of Module, A | |
115 | assert_kind_of Class, A::B | |
116 | assert_kind_of Class, A::C::D | |
117 | assert_kind_of Class, A::C::E::F | |
118 | end | |
119 | end | |
120 | ||
121 | def test_non_existing_const_raises_name_error | |
122 | with_loading 'autoloading_fixtures' do | |
123 | assert_raises(NameError) { DoesNotExist } | |
124 | assert_raises(NameError) { NoModule::DoesNotExist } | |
125 | assert_raises(NameError) { A::DoesNotExist } | |
126 | assert_raises(NameError) { A::B::DoesNotExist } | |
127 | end | |
128 | end | |
129 | ||
130 | def test_directories_should_manifest_as_modules | |
131 | with_loading 'autoloading_fixtures' do | |
132 | assert_kind_of Module, ModuleFolder | |
133 | Object.send :remove_const, :ModuleFolder | |
134 | end | |
135 | end | |
136 | ||
137 | def test_nested_class_access | |
138 | with_loading 'autoloading_fixtures' do | |
139 | assert_kind_of Class, ModuleFolder::NestedClass | |
140 | Object.send :remove_const, :ModuleFolder | |
141 | end | |
142 | end | |
143 | ||
144 | def test_nested_class_can_access_sibling | |
145 | with_loading 'autoloading_fixtures' do | |
146 | sibling = ModuleFolder::NestedClass.class_eval "NestedSibling" | |
147 | assert defined?(ModuleFolder::NestedSibling) | |
148 | assert_equal ModuleFolder::NestedSibling, sibling | |
149 | Object.send :remove_const, :ModuleFolder | |
150 | end | |
151 | end | |
152 | ||
153 | def failing_test_access_thru_and_upwards_fails | |
154 | with_loading 'autoloading_fixtures' do | |
155 | assert ! defined?(ModuleFolder) | |
156 | assert_raises(NameError) { ModuleFolder::Object } | |
157 | assert_raises(NameError) { ModuleFolder::NestedClass::Object } | |
158 | Object.send :remove_const, :ModuleFolder | |
159 | end | |
160 | end | |
161 | ||
162 | end |
rool/rails/typo/trunk/vendor/rails/activesupport/test/inflector_test.rb:
prev. | current | |
require 'test/unit' | ||
2 | ||
2 | require File.dirname(__FILE__) + '/../lib/active_support/inflector' unless defined? Inflector | |
module Ace | ||
module Base | ||
... | ... | |
"Product" => "product", | ||
"SpecialGuest" => "special_guest", | ||
"ApplicationController" => "application_controller", | ||
113 | | |
113 | "Area51Controller" => "area51_controller" | |
} | ||
115 | ||
116 | UnderscoreToLowerCamel = { | |
117 | "product" => "product", | |
118 | "special_guest" => "specialGuest", | |
119 | "application_controller" => "applicationController", | |
120 | "area51_controller" => "area51Controller" | |
121 | } | |
CamelToUnderscoreWithoutReverse = { | ||
"HTMLTidy" => "html_tidy", | ||
... | ... | |
"1000" => "1000th", | ||
"1001" => "1001st" | ||
} | ||
197 | ||
198 | UnderscoresToDashes = { | |
199 | "street" => "street", | |
200 | "street_address" => "street-address", | |
201 | "person_street_address" => "person-street-address" | |
202 | } | |
def test_pluralize_plurals | ||
assert_equal "plurals", Inflector.pluralize("plurals") | ||
... | ... | |
def test_constantize | ||
assert_equal Ace::Base::Case, Inflector.constantize("Ace::Base::Case") | ||
290 | assert_equal Ace::Base::Case, Inflector.constantize("::Ace::Base::Case") | |
assert_equal InflectorTest, Inflector.constantize("InflectorTest") | ||
292 | assert_equal InflectorTest, Inflector.constantize("::InflectorTest") | |
assert_raises(NameError) { Inflector.constantize("UnknownClass") } | ||
assert_raises(NameError) { Inflector.constantize("An invalid string") } | ||
end | ||
... | ... | |
assert_equal(ordinalized, Inflector.ordinalize(number)) | ||
end | ||
end | ||
306 | ||
307 | def test_dasherize | |
308 | UnderscoresToDashes.each do |underscored, dasherized| | |
309 | assert_equal(dasherized, Inflector.dasherize(underscored)) | |
310 | end | |
311 | end | |
312 | ||
313 | def test_underscore_as_reverse_of_dasherize | |
314 | UnderscoresToDashes.each do |underscored, dasherized| | |
315 | assert_equal(underscored, Inflector.underscore(Inflector.dasherize(underscored))) | |
316 | end | |
317 | end | |
318 | ||
319 | def test_underscore_to_lower_camel | |
320 | UnderscoreToLowerCamel.each do |underscored, lower_camel| | |
321 | assert_equal(lower_camel, Inflector.camelize(underscored, false)) | |
322 | end | |
323 | end | |
end |
rool/rails/typo/trunk/vendor/rails/railties/CHANGELOG:
prev. | current | |
1 | ||
1 | *1.1.2* (April 9th, 2005) | |
3 | ||
3 | * Added rake rails:update:configs to update config/boot.rb from the latest (also included in rake rails:update) [DHH] | |
5 | ||
5 | * Fixed that boot.rb would set RAILS_GEM_VERSION twice, not respect an uncommented RAILS_GEM_VERSION line, and not use require_gem [DHH] | |
7 | ||
8 | *1.1.1* (April 6th, 2005) | |
9 | ||
10 | * Enhances plugin#discover allowing it to discover svn:// like URIs (closes #4565) [ruben.nine@gmail.com] | |
11 | ||
12 | * Update to Prototype 1.5.0_rc0 [Sam Stephenson] | |
13 | ||
14 | * Fixed that the -r/--ruby path option of the rails command was not being respected #4549 [ryan.raaum@gmail.com] | |
15 | ||
16 | * Added that Dispatcher exceptions should not be shown to the user unless a default log has not been configured. Instead show public/500.html [DHH] | |
17 | ||
18 | * Fixed that rake clone_structure_to_test should quit on pgsql if the dump is unsuccesful #4585 [augustz@augustz.com] | |
19 | ||
20 | * Fixed that rails --version should have the return code of 0 (success) #4560 [blair@orcaware.com] | |
21 | ||
22 | * Install alias so Rails::InfoController is accessible at /rails_info. Closes #4546. [Nicholas Seckar] | |
23 | ||
24 | * Fixed that spawner should daemonize if running in repeat mode [DHH] | |
25 | ||
26 | * Added TAG option for rake rails:freeze:edge, so you can say rake rails:freeze:edge TAG=rel_1-1-0 to lock to the 1.1.0 release [DHH] | |
27 | ||
28 | * Applied Prototype $() performance patches (#4465, #4477) and updated script.aculo.us [Sam Stephenson, Thomas Fuchs] | |
29 | ||
30 | * Use --simple-prompt instead of --prompt-mode simple for console compatibility with Windows/Ruby 1.8.2 #4532 [starr@starrnhorne.com] | |
31 | ||
32 | * Make Rails::VERSION implicitly loadable #4491. [Nicholas Seckar] | |
33 | ||
34 | * Fixed rake rails:freeze:gems #4518 [benji@silverinsanity.com] | |
35 | ||
36 | * Added -f/--freeze option to rails command for freezing the application to the Rails version it was generated with [DHH] | |
37 | ||
38 | * Added gem binding of apps generated through the rails command to the gems of they were generated with [Nicholas Seckar] | |
39 | ||
40 | * Added expiration settings for JavaScript, CSS, HTML, and images to default lighttpd.conf [DHH] | |
41 | ||
42 | * Added gzip compression for JavaScript, CSS, and HTML to default lighttpd.conf [DHH] | |
43 | ||
44 | * Avoid passing escapeHTML non-string in Rails' info controller [Nicholas Seckar] | |
45 | ||
46 | ||
47 | *1.1.0* (March 27th, 2005) | |
48 | ||
49 | * Allow db:fixtures:load to load a subset of the applications fixtures. [Chad Fowler] | |
50 | ||
51 | ex. | |
52 | ||
53 | rake db:fixtures:load FIXTURES=customers,plans | |
54 | ||
55 | * Update to Prototype 1.5.0_pre1 [Sam Stephenson] | |
56 | ||
57 | * Update to script.aculo.us 1.6 [Thomas Fuchs] | |
58 | ||
59 | * Add an integration_test generator [Jamis Buck] | |
60 | ||
61 | * Make all ActionView helpers available in the console from the helper method for debugging purposes. n.b.: Only an 80% solution. Some stuff won't work, most will. [Marcel Molina Jr.] | |
62 | ||
63 | ex. | |
64 | ||
65 | >> puts helper.options_for_select([%w(a 1), %w(b 2), %w(c 3)]) | |
66 | <option value="1">a</option> | |
67 | <option value="2">b</option> | |
68 | <option value="3">c</option> | |
69 | => nil | |
70 | ||
71 | * Replaced old session rake tasks with db:sessions:create to generate a migration, and db:sessions:clear to remove sessions. [Rick Olson] | |
72 | ||
73 | * Reject Ruby 1.8.3 when loading Rails; extract version checking code. [Chad Fowler] | |
74 | ||
75 | * Remove explicit loading of RailsInfo and RailsInfoController. [Nicholas Seckar] | |
76 | ||
77 | * Move RailsInfo and RailsInfoController to Rails::Info and Rails::InfoController. [Nicholas Seckar] | |
78 | ||
79 | * Extend load path with Railties' builtin directory to make adding support code easy. [Nicholas Seckar] | |
80 | ||
81 | * Fix the rails_info controller by explicitly loading it, and marking it as not reloadable. [Nicholas Seckar] | |
82 | ||
83 | * Fixed rails:freeze:gems for Windows #3274 [paul@paulbutcher.com] | |
84 | ||
85 | * Added 'port open?' check to the spawner when running in repeat mode so we don't needlessly boot the dispatcher if the port is already in use anyway #4089 [guy.naor@famundo.com] | |
86 | ||
87 | * Add verification to generated scaffolds, don't allow get for unsafe actions [Michael Koziarski] | |
88 | ||
89 | * Don't replace application.js in public/javascripts if it already exists [Cody Fauser] | |
90 | ||
91 | * Change test:uncommitted to delay execution of `svn status` by using internal Rake API's. [Nicholas Seckar] | |
92 | ||
93 | * Use require_library_or_gem to load rake in commands/server.rb. Closes #4205. [rob.rasmussen@gmail.com] | |
94 | ||
95 | * Use the Rake API instead of shelling out to create the tmp directory in commands/server.rb. [Chad Fowler] | |
96 | ||
97 | * Added a backtrace to the evil WSOD (White Screen of Death). Closes #4073. TODO: Clearer exceptions [Rick Olson] | |
98 | ||
99 | * Added tracking of database and framework versions in script/about #4088 [charles.gerungan@gmail.com/Rick Olson] | |
100 | ||
101 | * Added public/javascripts/application.js as a sample since it'll automatically be included in javascript_include_tag :defaults [DHH] | |
102 | ||
103 | * Added socket cleanup for lighttpd, both before and after [DHH] | |
104 | ||
105 | * Added automatic creation of tmp/ when running script/server [DHH] | |
106 | ||
107 | * Added silence_stream that'll work on both STDERR or STDOUT or any other stream and deprecated silence_stderr in the process [DHH] | |
108 | ||
109 | * Added reload! method to script/console to reload all models and others that include Reloadable without quitting the console #4056 [esad@esse.at] | |
110 | ||
111 | * Added that rake rails:freeze:edge will now just export all the contents of the frameworks instead of just lib, so stuff like rails:update:scripts, rails:update:javascripts, and script/server on lighttpd still just works #4047 [DHH] | |
112 | ||
113 | * Added fix for upload problems with lighttpd from Safari/IE to config/lighttpd.conf #3999 [thijs@fngtps.com] | |
114 | ||
115 | * Added test:uncommitted to test changes since last checkin to Subversion #4035 [technomancy@gmail.com] | |
116 | ||
117 | * Help script/about print the correct svn revision when in a non-English locale. #4026 [babie7a0@ybb.ne.jp] | |
118 | ||
119 | * Add 'app' accessor to script/console as an instance of Integration::Session [Jamis Buck] | |
120 | ||
121 | * Generator::Base#usage takes an optional message argument which defaults to Generator::Base#usage_message. [Jeremy Kemper] | |
122 | ||
123 | * Remove the extraneous AR::Base.threaded_connections setting from the webrick server. [Jeremy Kemper] | |
124 | ||
125 | * Add integration test support to app generation and testing [Jamis Buck] | |
126 | ||
127 | * Added namespaces to all tasks, so for example load_fixtures is now db:fixtures:load. All the old task names are still valid, they just point to the new namespaced names. "rake -T" will only show the namespaced ones, though [DHH] | |
128 | ||
129 | * CHANGED DEFAULT: ActiveRecord::Base.schema_format is now :ruby by default instead of :sql. This means that we'll assume you want to live in the world of db/schema.rb where the grass is green and the girls are pretty. If your schema contains un-dumpable elements, such as constraints or database-specific column types, you just got an invitation to either 1) patch the dumper to include foreign key support, 2) stop being db specific, or 3) just change the default in config/environment.rb to config.active_record.schema_format = :sql -- we even include an example for that on new Rails skeletons now. Brought to you by the federation of opinionated framework builders! [DHH] | |
130 | ||
131 | * Added -r/--repeat option to script/process/spawner that offers the same loop protection as the spinner did. This deprecates the script/process/spinner, so it's no longer included in the default Rails skeleton, but still available for backwards compatibility #3461 [ror@andreas-s.net] | |
132 | ||
133 | * Added collision option to template generation in generators #3329 [anna@wota.jp]. Examples: | |
134 | ||
135 | m.template "stuff.config" , "config/stuff.config" , :collision => :skip | |
136 | m.template "auto-stamping", "config/generator.log", :collision => :force | |
137 | ||
138 | * Added more information to script/plugin's doings to ease debugging #3755 [Rick Olson] | |
139 | ||
140 | * Changed the default configuration for lighttpd to use tmp/sockets instead of log/ for the FastCGI sockets [DHH] | |
141 | ||
142 | * Added a default configuration of the FileStore for fragment caching if tmp/cache is available, which makes action/fragment caching ready to use out of the box with no additional configuration [DHH] | |
143 | ||
144 | * Changed the default session configuration to place sessions in tmp/sessions, if that directory is available, instead of /tmp (this essentially means a goodbye to 9/10 White Screen of Death errors and should have web hosting firms around the world cheering) [DHH] | |
145 | ||
146 | * Added tmp/sessions, tmp/cache, and tmp/sockets as default directories in the Rails skeleton [DHH] | |
147 | ||
148 | * Added that script/generate model will now automatically create a migration file for the model created. This can be turned off by calling the generator with --skip-migration [DHH] | |
149 | ||
150 | * Added -d/--database option to the rails command, so you can do "rails --database=sqlite2 myapp" to start a new application preconfigured to use SQLite2 as the database. Removed the configuration examples from SQLite and PostgreSQL from the default MySQL configuration [DHH] | |
151 | ||
152 | * Allow script/server -c /path/to/lighttpd.conf [Jeremy Kemper] | |
153 | ||
154 | * Remove hardcoded path to reaper script in script/server [Jeremy Kemper] | |
155 | ||
156 | * Update script.aculo.us to V1.5.3 [Thomas Fuchs] | |
157 | ||
158 | * Added SIGTRAP signal handler to RailsFCGIHandler that'll force the process into a breakpoint after the next request. This breakpoint can then be caught with script/breakpointer and give you access to the Ruby image inside that process. Useful for debugging memory leaks among other things [DHH] | |
159 | ||
160 | * Changed default lighttpd.conf to use CWD from lighttpd 1.4.10 that allows the same configuration to be used for both detach and not. Also ensured that auto-repeaping of FCGIs only happens when lighttpd is not detached. [DHH] | |
161 | ||
162 | * Added Configuration#after_initialize for registering a block which gets called after the framework is fully initialized. Useful for things like per-environment configuration of plugins. [Michael Koziarski] | |
163 | ||
164 | * Added check for RAILS_FRAMEWORK_ROOT constant that allows the Rails framework to be found in a different place than vendor/rails. Should be set in boot.rb. [DHH] | |
165 | ||
166 | * Fixed that static requests could unlock the mutex guarding dynamic requests in the WEBrick servlet #3433 [tom@craz8.com] | |
167 | ||
168 | * Fixed documentation tasks to work with Rake 0.7.0 #3563 [kazuhiko@fdiary.net] | |
169 | ||
170 | * Update to Prototype 1.5.0_pre0 [Sam Stephenson] | |
171 | ||
172 | * Sort the list of plugins so we load in a consistent order [Rick Olson] | |
173 | ||
174 | * Show usage when script/plugin is called without arguments [tom@craz8.com] | |
175 | ||
176 | * Corrected problems with plugin loader where plugins set 'name' incorrectly #3297 [anna@wota.jp] | |
177 | ||
178 | * Make migration generator only report on exact duplicate names, not partial dupliate names. #3442 [jeremy@planetargon.com Marcel Molina Jr.] | |
179 | ||
180 | * Fix typo in mailer generator USAGE. #3458 [chriztian.steinmeier@gmail.com] | |
181 | ||
182 | * Ignore version mismatch between pg_dump and the database server. #3457 [simon.stapleton@gmail.com] | |
183 | ||
184 | * Reap FCGI processes after lighttpd exits. [Sam Stephenson] | |
185 | ||
186 | * Honor ActiveRecord::Base.pluralize_table_names when creating and destroying session store table. #3204. [rails@bencurtis.com, Marcel Molina Jr.] | |
187 | ||
188 | *1.0.0* (December 13th, 2005) | |
189 | ||
* Update instructions on how to find and install generators. #3172. [Chad Fowler] | ||
* Generator looks in vendor/generators also. [Chad Fowler] | ||
* Generator copies files in binary mode. #3156 [minimudboy@gmail.com] | ||
196 | * Add builtin/ to the gemspec. Closes #3047. [Nicholas Seckar, Sam Stephenson] | |
14 | ||
198 | * Add install.rb file to plugin generation which is loaded, if it exists, when you install a plugin. [Marcel Molina Jr.] | |
16 | ||
17 | ||
* Run initialize_logger in script/lighttpd to ensure the log file exists before tailing it. [Sam Stephenson] | ||
* Make load_fixtures include csv fixtures. #3053. [me@mdaines.com] | ||
* Fix freeze_gems so that the latest rails version is dumped by default. [Nicholas Seckar] | ||
206 | * script/plugin: handle root paths and plugin names which contain spaces. #2995 [justin@aspect.net] | |
207 | ||
* Model generator: correct relative path to test_helper in unit test. [Jeremy Kemper] | ||
* Make the db_schema_dump task honor the SCHEMA environment variable if present the way db_schema_import does. #2931. [Blair Zajac] | ||
212 | * Have the lighttpd server script report the actual ip to which the server is bound. #2903. [Adam] | |
213 | ||
214 | * Add plugin library directories to the load path after the lib directory so that libraries in the lib directory get precedence. #2910. [james.adam@gmail.com] | |
215 | ||
* Make help for the console command more explicit about how to specify the desired environment in which to run the console. #2911. [anonymous] | ||
* PostgreSQL: the purge_test_database Rake task shouldn't explicitly specify the template0 template when creating a fresh test database. #2964 [dreamer3@gmail.com] | ||
* Introducing the session_migration generator. Creates an add_session_table migration. Allows generator to specify migrations directory. #2958, #2960 [Rick Olson] | ||
34 | ||
222 | * script/console uses RAILS_ENV environment variable if present. #2932 [Blair Zajac <blair@orcaware.com> | |
224 | * Windows: eliminate the socket option in database.yml. #2924 [Wayne Vucenic <waynev@gmail.com>] | |
225 | ||
* Eliminate nil from newly generated logfiles. #2927 [Blair Zajac <blair@orcaware.com>] | ||
38 | ||
39 | ||
* Rename Version constant to VERSION. #2802 [Marcel Molina Jr.] | ||
42 | ||
230 | * Eliminate Subversion dependencies in scripts/plugin. Correct install options. Introduce --force option to reinstall a plugin. Remove useless --long option for list. Use --quiet to quiet the download output and --revision to update to a specific svn revision. #2842 [Chad Fowler, Rick Olson] | |
* SQLite: the clone_structure_to_test and purge_test_database Rake tasks should always use the test environment. #2846 [Rick Olson] | ||
rool/rails/typo/trunk/vendor/rails/railties/README:
prev. | current | |
== Getting started | ||
30 | ||
31 | | |
32 | ||
33 | ||
30 | 1. Start the web server: <tt>ruby script/server</tt> (run with --help for options) | |
31 | 2. Go to http://localhost:3000/ and get "Welcome aboard: You’re riding the Rails!" | |
32 | 3. Follow the guidelines to start developing your application | |
35 | == Web servers | |
36 | ||
37 | Rails uses the built-in web server in Ruby called WEBrick by default, so you don't | |
38 | have to install or configure anything to play around. | |
39 | ||
40 | If you have lighttpd installed, though, it'll be used instead when running script/server. | |
41 | It's considerably faster than WEBrick and suited for production use, but requires additional | |
42 | installation and currently only works well on OS X/Unix (Windows users are encouraged | |
43 | to start with WEBrick). We recommend version 1.4.11 and higher. You can download it from | |
44 | http://www.lighttpd.net. | |
45 | ||
46 | If you want something that's halfway between WEBrick and lighttpd, we heartily recommend | |
47 | Mongrel. It's a Ruby-based web server with a C-component (so it requires compilation) that | |
48 | also works very well with Windows. See more at http://mongrel.rubyforge.org/. | |
49 | ||
50 | But of course its also possible to run Rails with the premiere open source web server Apache. | |
51 | To get decent performance, though, you'll need to install FastCGI. For Apache 1.3, you want | |
52 | to use mod_fastcgi. For Apache 2.0+, you want to use mod_fcgid. | |
53 | ||
54 | See http://wiki.rubyonrails.com/rails/pages/FastCGI for more information on FastCGI. | |
55 | ||
== Example for Apache conf | ||
<VirtualHost *:80> | ||
... | ... | |
Here you'll have all parts of the application configured, just like it is when the | ||
application is running. You can inspect domain models, change values, and save to the | ||
database. Starting the script without arguments will launch it in the development environment. | ||
105 | ||
125 | Passing an argument will specify a different environment, like <tt>script/console production</tt>. | |
== Description of contents | ||
... | ... | |
app/helpers | ||
Holds view helpers that should be named like weblog_helper.rb. | ||
151 | app/apis | |
152 | Holds API classes for web services. | |
153 | ||
config | ||
Configuration files for the Rails environment, the routing map, the database, and other dependencies. | ||
components | ||
Self-contained mini-applications that can bundle together controllers, models, and views. | ||
160 | db | |
161 | Contains the database schema in schema.rb. db/migrate contains all | |
162 | the sequence of Migrations for your schema. | |
163 | ||
lib | ||
Application specific libraries. Basically, any kind of custom code that doesn't | ||
belong under controllers, models, or helpers. This directory is in the load path. |
rool/rails/typo/trunk/vendor/rails/railties/Rakefile:
prev. | current | |
require 'date' | ||
require 'rbconfig' | ||
10 | ||
10 | require File.join(File.dirname(__FILE__), 'lib/rails', 'version') | |
PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : '' | ||
PKG_NAME = 'rails' | ||
... | ... | |
# end | ||
31 | ||
31 | BASE_DIRS = %w( | |
32 | app config/environments components db doc log lib lib/tasks public script script/performance script/process test vendor vendor/plugins | |
33 | tmp/sessions tmp/cache tmp/sockets | |
34 | ) | |
35 | ||
APP_DIRS = %w( models controllers helpers views views/layouts ) | ||
PUBLIC_DIRS = %w( images javascripts stylesheets ) | ||
TEST_DIRS = %w( fixtures unit functional mocks mocks/development mocks/test ) | ||
LOG_FILES = %w( server.log development.log test.log production.log ) | ||
HTML_FILES = %w( 404.html 500.html index.html robots.txt favicon.ico images/rails.png | ||
38 | | |
42 | javascripts/prototype.js javascripts/application.js | |
javascripts/effects.js javascripts/dragdrop.js javascripts/controls.js ) | ||
40 | ||
44 | BIN_FILES = %w( about breakpointer console destroy generate performance/benchmarker performance/profiler process/reaper process/spawner runner server plugin ) | |
VENDOR_LIBS = %w( actionpack activerecord actionmailer activesupport actionwebservice railties ) | ||
... | ... | |
desc "Updates railties to the latest version of the javascript spinoffs" | ||
task :update_js do | ||
74 | | |
78 | for js in %w( prototype controls dragdrop effects ) | |
rm "html/javascripts/#{js}.js" | ||
cp "./../actionpack/lib/action_view/helpers/javascripts/#{js}.js", "html/javascripts" | ||
end | ||
... | ... | |
# Make directory structure ---------------------------------------------------------------- | ||
def make_dest_dirs(dirs, path = nil) | ||
83 | | |
87 | mkdir_p dirs.map { |dir| File.join(PKG_DESTINATION, path.to_s, dir) } | |
end | ||
desc "Make the directory structure for the new Rails application" | ||
... | ... | |
task :copy_vendor_libraries do | ||
mkdir File.join(PKG_DESTINATION, 'vendor', 'rails') | ||
VENDOR_LIBS.each { |dir| cp_r File.join('..', dir), File.join(PKG_DESTINATION, 'vendor', 'rails', dir) } | ||
121 | FileUtils.rm_r(Dir.glob(File.join(PKG_DESTINATION, 'vendor', 'rails', "**", ".svn"))) | |
end | ||
desc "Link in all the Rails packages to vendor" | ||
... | ... | |
app_name = "rails" | ||
socket = nil | ||
require 'erb' | ||
161 | | |
166 | File.open("#{PKG_DESTINATION}/config/database.yml", 'w') {|f| f.write ERB.new(IO.read("configs/databases/mysql.yml"), nil, '-').result(binding)} | |
cp "configs/routes.rb", "#{PKG_DESTINATION}/config/routes.rb" | ||
... | ... | |
Rake::RDocTask.new { |rdoc| | ||
rdoc.rdoc_dir = 'doc' | ||
rdoc.title = "Railties -- Gluing the Engine to the Rails" | ||
236 | | |
241 | rdoc.options << '--line-numbers' << '--inline-source' << '--accessor' << 'cattr_accessor=object' | |
rdoc.template = "#{ENV['template']}.rb" if ENV['template'] | ||
rdoc.rdoc_files.include('README', 'CHANGELOG') | ||
rdoc.rdoc_files.include('lib/*.rb') | ||
... | ... | |
on top of either MySQL, PostgreSQL, SQLite, DB2, SQL Server, or Oracle with eRuby- or Builder-based templates. | ||
EOF | ||
275 | | |
276 | | |
277 | | |
278 | | |
279 | | |
280 | | |
280 | s.add_dependency('rake', '>= 0.7.1') | |
281 | s.add_dependency('activesupport', '= 1.3.1' + PKG_BUILD) | |
282 | s.add_dependency('activerecord', '= 1.14.2' + PKG_BUILD) | |
283 | s.add_dependency('actionpack', '= 1.12.1' + PKG_BUILD) | |
284 | s.add_dependency('actionmailer', '= 1.2.1' + PKG_BUILD) | |
285 | s.add_dependency('actionwebservice', '= 1.1.2' + PKG_BUILD) | |
s.rdoc_options << '--exclude' << '.' | ||
s.has_rdoc = false | ||
... | ... | |
end | ||
desc "Publish the release files to RubyForge." | ||
310 | ||
311 | | |
312 | ||
313 | | |
314 | | |
315 | | |
316 | ||
317 | | |
318 | | |
319 | | |
320 | | |
321 | ||
322 | | |
323 | | |
324 | | |
325 | | |
326 | | |
327 | | |
328 | | |
329 | ||
330 | | |
331 | | |
332 | | |
333 | | |
334 | | |
335 | | |
336 | | |
337 | | |
338 | ||
339 | | |
340 | | |
341 | | |
342 | ||
343 | | |
344 | | |
345 | | |
346 | | |
347 | ||
348 | | |
349 | | |
350 | ||
351 | | |
352 | | |
353 | | |
354 | | |
355 | ||
356 | | |
357 | ||
358 | | |
359 | | |
360 | | |
361 | | |
362 | | |
363 | | |
364 | | |
365 | | |
366 | | |
367 | | |
368 | ||
369 | | |
370 | | |
371 | | |
372 | | |
373 | | |
374 | | |
375 | | |
376 | | |
377 | | |
378 | | |
379 | | |
380 | | |
381 | | |
382 | | |
383 | | |
384 | | |
385 | | |
386 | | |
387 | | |
388 | | |
389 | | |
390 | | |
391 | | |
392 | | |
393 | ||
394 | | |
395 | | |
396 | | |
397 | ||
398 | | |
399 | | |
400 | | |
401 | | |
402 | | |
403 | | |
404 | | |
405 | ||
406 | | |
407 | | |
408 | | |
409 | ||
410 | | |
411 | | |
412 | | |
413 | ||
414 | | |
415 | | |
416 | | |
417 | | |
418 | ||
419 | | |
420 | | |
421 | | |
422 | ||
315 | task :release => [ :gem ] do | |
316 | `rubyforge login` | |
317 | release_command = "rubyforge add_release #{PKG_NAME} #{PKG_NAME} 'REL #{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.gem" | |
318 | puts release_command | |
319 | system(release_command) | |
320 | end | |
rool/rails/typo/trunk/vendor/rails/railties/bin/rails:
prev. | current | |
1 | ||
2 | ||
3 | ||
4 | | |
1 | require File.dirname(__FILE__) + '/../lib/ruby_version_check' | |
2 | Signal.trap("INT") { puts; exit } | |
6 | | |
7 | | |
8 | ||
9 | | |
4 | require File.dirname(__FILE__) + '/../lib/rails/version' | |
5 | if %w(--version -v).include? ARGV.first | |
6 | puts "Rails #{Rails::VERSION::STRING}" | |
7 | exit(0) | |
end | ||
12 | ||
10 | freeze = ARGV.any? { |option| %w(--freeze -f).include?(option) } | |
11 | app_path = ARGV.first | |
14 | ||
15 | ||
16 | ||
require File.dirname(__FILE__) + '/../lib/rails_generator' | ||
require 'rails_generator/scripts/generate' | ||
Rails::Generator::Base.use_application_sources! | ||
Rails::Generator::Scripts::Generate.new.run(ARGV, :generator => 'app') | ||
18 | ||
19 | Dir.chdir(app_path) { `rake rails:freeze:gems`; puts "froze" } if freeze | |
rool/rails/typo/trunk/vendor/rails/railties/configs/lighttpd.conf:
prev. | current | |
# Default configuration file for the lighttpd web server | ||
# Start using ./script/server lighttpd | ||
4 | server.bind = "0.0.0.0" | |
server.port = 3000 | ||
6 | ||
7 | server.modules = ( "mod_rewrite", "mod_accesslog", "mod_fastcgi", "mod_compress", "mod_expire" ) | |
8 | ||
server.error-handler-404 = "/dispatch.fcgi" | ||
8 | ||
10 | server.document-root = CWD + "/public/" | |
10 | ||
11 | ||
12 | server.errorlog = CWD + "/log/lighttpd.error.log" | |
13 | accesslog.filename = CWD + "/log/lighttpd.access.log" | |
url.rewrite = ( "^/$" => "index.html", "^([^.]+)$" => "$1.html" ) | ||
17 | compress.filetype = ( "text/plain", "text/html", "text/css", "text/javascript" ) | |
18 | compress.cache-dir = CWD + "/tmp/cache" | |
19 | ||
20 | expire.url = ( "/favicon.ico" => "access 3 days", | |
21 | "/images/" => "access 3 days", | |
22 | "/stylesheets/" => "access 3 days", | |
23 | "/javascripts/" => "access 3 days" ) | |
24 | ||
25 | ||
# Change *-procs to 2 if you need to use Upload Progress or other tasks that | ||
# *need* to execute a second request while the first is still pending. | ||
17 | ||
18 | | |
19 | | |
20 | | |
21 | | |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | ||
28 | fastcgi.server = ( ".fcgi" => ( "localhost" => ( | |
29 | "min-procs" => 1, | |
30 | "max-procs" => 1, | |
31 | "socket" => CWD + "/tmp/sockets/fcgi.socket", | |
32 | "bin-path" => CWD + "/public/dispatch.fcgi", | |
33 | "bin-environment" => ( "RAILS_ENV" => "development" ) | |
34 | ) ) ) | |
mimetype.assign = ( | ||
".css" => "text/css", | ||
... | ... | |
".swf" => "application/x-shockwave-flash", | ||
".txt" => "text/plain" | ||
) | ||
48 | ||
49 | # Making sure file uploads above 64k always work when using IE or Safari | |
50 | # For more information, see http://trac.lighttpd.net/trac/ticket/360 | |
51 | $HTTP["useragent"] =~ "^(.*MSIE.*)|(.*AppleWebKit.*)$" { | |
52 | server.max-keep-alive-requests = 0 | |
53 | } |
rool/rails/typo/trunk/vendor/rails/railties/configs/routes.rb:
prev. | current | |
ActionController::Routing::Routes.draw do |map| | ||
2 | | |
# The priority is based upon order of creation: first created -> highest priority. | ||
5 | | |
4 | # Sample of regular route: | |
# map.connect 'products/:id', :controller => 'catalog', :action => 'view' | ||
# Keep in mind you can assign values other than :controller and :action | ||
8 | # Sample of named route: | |
9 | # map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase' | |
10 | # This route can be invoked with purchase_url(:id => product.id) | |
11 | ||
# You can have the root of your site routed by hooking up '' | ||
# -- just remember to delete public/index.html. | ||
# map.connect '', :controller => "welcome" |
rool/rails/typo/trunk/vendor/rails/railties/environments/boot.rb:
prev. | current | |
unless defined?(RAILS_ROOT) | ||
root_path = File.join(File.dirname(__FILE__), '..') | ||
5 | ||
unless RUBY_PLATFORM =~ /mswin32/ | ||
require 'pathname' | ||
root_path = Pathname.new(root_path).cleanpath(true).to_s | ||
end | ||
10 | ||
RAILS_ROOT = root_path | ||
end | ||
12 | ||
13 | | |
14 | ||
15 | | |
16 | | |
17 | ||
14 | unless defined?(Rails::Initializer) | |
15 | if File.directory?("#{RAILS_ROOT}/vendor/rails") | |
16 | require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer" | |
17 | else | |
18 | require 'rubygems' | |
19 | ||
20 | environment_without_comments = IO.readlines(File.dirname(__FILE__) + '/environment.rb').reject { |l| l =~ /^#/ }.join | |
21 | environment_without_comments =~ /[^#]RAILS_GEM_VERSION = '([\d.]+)'/ | |
22 | rails_gem_version = $1 | |
23 | ||
24 | if version = defined?(RAILS_GEM_VERSION) ? RAILS_GEM_VERSION : rails_gem_version | |
25 | rails_gem = Gem.cache.search('rails', "=#{version}").first | |
26 | ||
27 | if rails_gem | |
28 | require_gem "rails", "=#{version}" | |
29 | require rails_gem.full_gem_path + '/lib/initializer' | |
30 | else | |
31 | STDERR.puts %(Cannot find gem for Rails =#{version}: | |
32 | Install the missing gem with 'gem install -v=#{version} rails', or | |
33 | change environment.rb to define RAILS_GEM_VERSION with your desired version. | |
34 | ) | |
35 | exit 1 | |
36 | end | |
37 | else | |
38 | require_gem "rails" | |
39 | require 'initializer' | |
40 | end | |
41 | end | |
42 | ||
43 | Rails::Initializer.run(:set_load_path) | |
44 | end | |
rool/rails/typo/trunk/vendor/rails/railties/environments/development.rb:
prev. | current | |
# In the development environment your application's code is reloaded on | ||
# every request. This slows down response time but is perfect for development | ||
# since you don't have to restart the webserver when you make code changes. | ||
6 | ||
6 | config.cache_classes = false | |
# Log error messages when you accidentally call methods on nil. | ||
9 | ||
9 | config.whiny_nils = true | |
# Enable the breakpoint server that script/breakpointer connects to | ||
config.breakpoint_server = true | ||
... | ... | |
# Show full error reports and disable caching | ||
config.action_controller.consider_all_requests_local = true | ||
config.action_controller.perform_caching = false | ||
17 | config.action_view.cache_template_extensions = false | |
18 | config.action_view.debug_rjs = true | |
# Don't care if the mailer can't send | ||
config.action_mailer.raise_delivery_errors = false |
rool/rails/typo/trunk/vendor/rails/railties/environments/environment.rb:
prev. | current | |
# you don't control web/app server and can't set it the proper way | ||
# ENV['RAILS_ENV'] ||= 'production' | ||
7 | # Specifies gem version of Rails to use when vendor/rails is not present | |
8 | <%= '# ' if freeze %>RAILS_GEM_VERSION = '<%= Rails::VERSION::STRING %>' | |
9 | ||
# Bootstrap the Rails environment, frameworks, and default configuration | ||
require File.join(File.dirname(__FILE__), 'boot') | ||
... | ... | |
# config.log_level = :debug | ||
# Use the database for sessions instead of the file system | ||
24 | | |
27 | # (create the session table with 'rake db:sessions:create') | |
# config.action_controller.session_store = :active_record_store | ||
27 | | |
28 | | |
29 | | |
30 | # Use SQL instead of Active Record's schema dumper when creating the test database. | |
31 | # This is necessary if your schema can't be completely dumped by the schema dumper, | |
32 | # like if you have constraints or database-specific column types | |
33 | # config.active_record.schema_format = :sql | |
# Activate observers that should always be running | ||
# config.active_record.observers = :cacher, :garbage_collector | ||
... | ... | |
# Make Active Record use UTC-base instead of local time | ||
# config.active_record.default_timezone = :utc | ||
37 | | |
38 | | |
39 | | |
40 | ||
# See Rails::Configuration for more options | ||
end | ||
rool/rails/typo/trunk/vendor/rails/railties/environments/production.rb:
prev. | current | |
config.cache_classes = true | ||
# Use a different logger for distributed setups | ||
8 | ||
8 | # config.logger = SyslogLogger.new | |
10 | ||
# Full error reports are disabled and caching is turned on | ||
config.action_controller.consider_all_requests_local = false | ||
config.action_controller.perform_caching = true |
rool/rails/typo/trunk/vendor/rails/railties/environments/test.rb:
prev. | current | |
config.cache_classes = true | ||
# Log error messages when you accidentally call methods on nil. | ||
10 | ||
10 | config.whiny_nils = true | |
# Show full error reports and disable caching | ||
config.action_controller.consider_all_requests_local = true |
rool/rails/typo/trunk/vendor/rails/railties/fresh_rakefile:
prev. | current | |
# Add your own tasks in files placed in lib/tasks ending in .rake, | ||
2 | ||
2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. | |
require(File.join(File.dirname(__FILE__), 'config', 'boot')) | ||
... | ... | |
require 'rake/testtask' | ||
require 'rake/rdoctask' | ||
10 | ||
11 | require 'tasks/rails' |
rool/rails/typo/trunk/vendor/rails/railties/html/500.html:
prev. | current | |
"http://www.w3.org/TR/html4/loose.dtd"> | ||
<html> | ||
<body> | ||
5 | | |
5 | <h1>Application error</h1> | |
<p>Change this error message for exceptions thrown outside of an action (like in Dispatcher setups or broken Ruby code) in public/500.html</p> | ||
</body> | ||
</html> | ||
rool/rails/typo/trunk/vendor/rails/railties/html/index.html:
prev. | current | |
<script type="text/javascript"> | ||
function about() { | ||
if (Element.empty('about-content')) { | ||
186 | | |
186 | new Ajax.Updater('about-content', 'rails/info/properties', { | |
method: 'get', | ||
onFailure: function() {Element.classNames('about-content').add('failure')}, | ||
onComplete: function() {new Effect.BlindDown('about-content', {duration: 0.25})} | ||
... | ... | |
<h3>Browse the documentation</h3> | ||
<ul class="links"> | ||
<li><a href="http://api.rubyonrails.org/">Rails API</a></li> | ||
233 | | |
234 | | |
233 | <li><a href="http://stdlib.rubyonrails.org/">Ruby standard library</a></li> | |
234 | <li><a href="http://corelib.rubyonrails.org/">Ruby core</a></li> | |
</ul> | ||
</li> | ||
</ul> | ||
... | ... | |
</div> | ||
<div id="about"> | ||
247 | | |
247 | <h3><a href="rails/info/properties" onclick="about(); return false">About your application’s environment</a></h3> | |
<div id="about-content" style="display: none"></div> | ||
</div> | ||
rool/rails/typo/trunk/vendor/rails/railties/html/javascripts/controls.js:
prev. | current | |
return; | ||
} | ||
else | ||
144 | | |
145 | | |
144 | if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || | |
145 | (navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return; | |
this.changed = true; | ||
this.hasFocus = true; | ||
... | ... | |
setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); | ||
}, | ||
155 | activate: function() { | |
156 | this.changed = false; | |
157 | this.hasFocus = true; | |
158 | this.getUpdatedChoices(); | |
159 | }, | |
160 | ||
onHover: function(event) { | ||
var element = Event.findElement(event, 'LI'); | ||
if(this.index != element.autocompleteIndex) | ||
... | ... | |
this.options.updateElement(selectedElement); | ||
return; | ||
} | ||
224 | ||
225 | | |
230 | var value = ''; | |
231 | if (this.options.select) { | |
232 | var nodes = document.getElementsByClassName(this.options.select, selectedElement) || []; | |
233 | if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); | |
234 | } else | |
235 | value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); | |
236 | ||
var lastTokenPos = this.findLastToken(); | ||
if (lastTokenPos != -1) { | ||
var newValue = this.element.value.substr(0, lastTokenPos + 1); | ||
... | ... | |
Ajax.Autocompleter = Class.create(); | ||
Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), { | ||
initialize: function(element, update, url, options) { | ||
308 | | |
319 | this.baseInitialize(element, update, options); | |
this.options.asynchronous = true; | ||
this.options.onComplete = this.onComplete.bind(this); | ||
this.options.defaultParams = this.options.parameters || null; | ||
... | ... | |
this.element = $(element); | ||
this.options = Object.extend({ | ||
462 | okButton: true, | |
okText: "ok", | ||
464 | cancelLink: true, | |
cancelText: "cancel", | ||
savingText: "Saving...", | ||
clickToEditText: "Click to edit", | ||
... | ... | |
formClassName: 'inplaceeditor-form', | ||
highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor, | ||
highlightendcolor: "#FFFFFF", | ||
473 | | |
474 | | |
486 | externalControl: null, | |
487 | submitOnBlur: false, | |
488 | ajaxOptions: {}, | |
489 | evalScripts: false | |
}, options || {}); | ||
if(!this.options.formId && this.element.id) { | ||
... | ... | |
this.form.appendChild(br); | ||
} | ||
539 | | |
540 | | |
541 | | |
542 | | |
554 | if (this.options.okButton) { | |
555 | okButton = document.createElement("input"); | |
556 | okButton.type = "submit"; | |
557 | okButton.value = this.options.okText; | |
558 | okButton.className = 'editor_ok_button'; | |
559 | this.form.appendChild(okButton); | |
560 | } | |
544 | | |
545 | | |
546 | | |
547 | | |
548 | | |
562 | if (this.options.cancelLink) { | |
563 | cancelLink = document.createElement("a"); | |
564 | cancelLink.href = "#"; | |
565 | cancelLink.appendChild(document.createTextNode(this.options.cancelText)); | |
566 | cancelLink.onclick = this.onclickCancel.bind(this); | |
567 | cancelLink.className = 'editor_cancel'; | |
568 | this.form.appendChild(cancelLink); | |
569 | } | |
}, | ||
hasHTMLLineBreaks: function(string) { | ||
if (!this.options.handleLineBreaks) return false; | ||
... | ... | |
} else { | ||
text = this.getText(); | ||
} | ||
585 | ||
586 | var obj = this; | |
if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) { | ||
this.options.textarea = false; | ||
var textField = document.createElement("input"); | ||
591 | textField.obj = this; | |
textField.type = "text"; | ||
textField.name = "value"; | ||
textField.value = text; | ||
textField.style.backgroundColor = this.options.highlightcolor; | ||
596 | textField.className = 'editor_field'; | |
var size = this.options.size || this.options.cols || 0; | ||
if (size != 0) textField.size = size; | ||
599 | if (this.options.submitOnBlur) | |
600 | textField.onblur = this.onSubmit.bind(this); | |
this.editField = textField; | ||
} else { | ||
this.options.textarea = true; | ||
var textArea = document.createElement("textarea"); | ||
605 | textArea.obj = this; | |
textArea.name = "value"; | ||
textArea.value = this.convertHTMLLineBreaks(text); | ||
textArea.rows = this.options.rows; | ||
textArea.cols = this.options.cols || 40; | ||
610 | textArea.className = 'editor_field'; | |
611 | if (this.options.submitOnBlur) | |
612 | textArea.onblur = this.onSubmit.bind(this); | |
this.editField = textArea; | ||
} | ||
... | ... | |
// to be displayed indefinitely | ||
this.onLoading(); | ||
632 | | |
633 | | |
634 | | |
635 | | |
636 | | |
637 | | |
638 | | |
639 | | |
640 | | |
641 | | |
642 | | |
643 | | |
644 | | |
663 | if (this.options.evalScripts) { | |
664 | new Ajax.Request( | |
665 | this.url, Object.extend({ | |
666 | parameters: this.options.callback(form, value), | |
667 | onComplete: this.onComplete.bind(this), | |
668 | onFailure: this.onFailure.bind(this), | |
669 | asynchronous:true, | |
670 | evalScripts:true | |
671 | }, this.options.ajaxOptions)); | |
672 | } else { | |
673 | new Ajax.Updater( | |
674 | { success: this.element, | |
675 | // don't update on failure (this could be an option) | |
676 | failure: null }, | |
677 | this.url, Object.extend({ | |
678 | parameters: this.options.callback(form, value), | |
679 | onComplete: this.onComplete.bind(this), | |
680 | onFailure: this.onFailure.bind(this) | |
681 | }, this.options.ajaxOptions)); | |
682 | } | |
// stop the event to avoid a page refresh in Safari | ||
if (arguments.length > 1) { | ||
Event.stop(arguments[0]); | ||
... | ... | |
} | ||
}; | ||
764 | Ajax.InPlaceCollectionEditor = Class.create(); | |
765 | Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype); | |
766 | Object.extend(Ajax.InPlaceCollectionEditor.prototype, { | |
767 | createEditField: function() { | |
768 | if (!this.cached_selectTag) { | |
769 | var selectTag = document.createElement("select"); | |
770 | var collection = this.options.collection || []; | |
771 | var optionTag; | |
772 | collection.each(function(e,i) { | |
773 | optionTag = document.createElement("option"); | |
774 | optionTag.value = (e instanceof Array) ? e[0] : e; | |
775 | if(this.options.value==optionTag.value) optionTag.selected = true; | |
776 | optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e)); | |
777 | selectTag.appendChild(optionTag); | |
778 | }.bind(this)); | |
779 | this.cached_selectTag = selectTag; | |
780 | } | |
781 | ||
782 | this.editField = this.cached_selectTag; | |
783 | if(this.options.loadTextURL) this.loadExternalText(); | |
784 | this.form.appendChild(this.editField); | |
785 | this.options.callback = function(form, value) { | |
786 | return "value=" + encodeURIComponent(value); | |
787 | } | |
788 | } | |
789 | }); | |
790 | ||
// Delayed observer, like Form.Element.Observer, | ||
// but waits for delay after last key input | ||
// Ideal for live-search fields | ||
... | ... | |
this.timer = null; | ||
this.callback(this.element, $F(this.element)); | ||
} | ||
750 | ||
816 | }; |
rool/rails/typo/trunk/vendor/rails/railties/html/javascripts/dragdrop.js:
prev. | current | |
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) | ||
2 | // (c) 2005 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) | |
// | ||
// See scriptaculous.js for full license. | ||
... | ... | |
element = $(element); | ||
var options = Object.extend({ | ||
greedy: true, | ||
18 | | |
19 | hoverclass: null, | |
20 | tree: false | |
}, arguments[1] || {}); | ||
// cache containers | ||
... | ... | |
this.drops.push(options); | ||
}, | ||
42 | ||
43 | findDeepestChild: function(drops) { | |
44 | deepest = drops[0]; | |
45 | ||
46 | for (i = 1; i < drops.length; ++i) | |
47 | if (Element.isParent(drops[i].element, deepest.element)) | |
48 | deepest = drops[i]; | |
49 | ||
50 | return deepest; | |
51 | }, | |
isContained: function(element, drop) { | ||
42 | | |
43 | | |
54 | var containmentNode; | |
55 | if(drop.tree) { | |
56 | containmentNode = element.treeNode; | |
57 | } else { | |
58 | containmentNode = element.parentNode; | |
59 | } | |
60 | return drop._containers.detect(function(c) { return containmentNode == c }); | |
}, | ||
45 | ||
62 | ||
isAffected: function(point, element, drop) { | ||
return ( | ||
(drop.element!=element) && | ||
... | ... | |
show: function(point, element) { | ||
if(!this.drops.length) return; | ||
88 | var affected = []; | |
if(this.last_active) this.deactivate(this.last_active); | ||
this.drops.each( function(drop) { | ||
74 | | |
75 | | |
76 | | |
77 | | |
78 | | |
79 | | |
80 | | |
81 | | |
92 | if(Droppables.isAffected(point, element, drop)) | |
93 | affected.push(drop); | |
}); | ||
95 | ||
96 | if(affected.length>0) { | |
97 | drop = Droppables.findDeepestChild(affected); | |
98 | Position.within(drop.element, point[0], point[1]); | |
99 | if(drop.onHover) | |
100 | drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); | |
101 | ||
102 | Droppables.activate(drop); | |
103 | } | |
}, | ||
fire: function(event, element) { | ||
... | ... | |
this.activeDraggable = draggable; | ||
}, | ||
131 | | |
152 | deactivate: function() { | |
this.activeDraggable = null; | ||
}, | ||
... | ... | |
if(!this.activeDraggable) return; | ||
this._lastPointer = null; | ||
this.activeDraggable.endDrag(event); | ||
170 | this.activeDraggable = null; | |
}, | ||
keyPress: function(event) { | ||
... | ... | |
}, | ||
reverteffect: function(element, top_offset, left_offset) { | ||
var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; | ||
194 | | |
216 | element._revert = new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur}); | |
}, | ||
endeffect: function(element) { | ||
new Effect.Opacity(element, {duration:0.2, from:0.7, to:1.0}); | ||
}, | ||
zindex: 1000, | ||
revert: false, | ||
223 | scroll: false, | |
224 | scrollSensitivity: 20, | |
225 | scrollSpeed: 15, | |
snap: false // false, or xy or [x,y] or function(x,y){ return [x,y] } | ||
}, arguments[1] || {}); | ||
this.element = $(element); | ||
206 | | |
207 | | |
231 | if(options.handle && (typeof options.handle == 'string')) { | |
232 | var h = Element.childrenWithClassName(this.element, options.handle, true); | |
233 | if(h.length>0) this.handle = h[0]; | |
234 | } | |
if(!this.handle) this.handle = $(options.handle); | ||
if(!this.handle) this.handle = this.element; | ||
237 | ||
238 | if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) | |
239 | options.scroll = $(options.scroll); | |
Element.makePositioned(this.element); // fix IE | ||
... | ... | |
currentDelta: function() { | ||
return([ | ||
230 | | |
231 | | |
260 | parseInt(Element.getStyle(this.element,'left') || '0'), | |
261 | parseInt(Element.getStyle(this.element,'top') || '0')]); | |
}, | ||
initDrag: function(event) { | ||
... | ... | |
if(src.tagName && ( | ||
src.tagName=='INPUT' || | ||
src.tagName=='SELECT' || | ||
271 | src.tagName=='OPTION' || | |
src.tagName=='BUTTON' || | ||
src.tagName=='TEXTAREA')) return; | ||
... | ... | |
this.element.parentNode.insertBefore(this._clone, this.element); | ||
} | ||
303 | if(this.options.scroll) { | |
304 | if (this.options.scroll == window) { | |
305 | var where = this._getWindowScroll(this.options.scroll); | |
306 | this.originalScrollLeft = where.left; | |
307 | this.originalScrollTop = where.top; | |
308 | } else { | |
309 | this.originalScrollLeft = this.options.scroll.scrollLeft; | |
310 | this.originalScrollTop = this.options.scroll.scrollTop; | |
311 | } | |
312 | } | |
313 | ||
Draggables.notify('onStart', this, event); | ||
if(this.options.starteffect) this.options.starteffect(this.element); | ||
}, | ||
... | ... | |
this.draw(pointer); | ||
if(this.options.change) this.options.change(this); | ||
326 | if(this.options.scroll) { | |
327 | this.stopScrolling(); | |
328 | ||
329 | var p; | |
330 | if (this.options.scroll == window) { | |
331 | with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } | |
332 | } else { | |
333 | p = Position.page(this.options.scroll); | |
334 | p[0] += this.options.scroll.scrollLeft; | |
335 | p[1] += this.options.scroll.scrollTop; | |
336 | p.push(p[0]+this.options.scroll.offsetWidth); | |
337 | p.push(p[1]+this.options.scroll.offsetHeight); | |
338 | } | |
339 | var speed = [0,0]; | |
340 | if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); | |
341 | if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); | |
342 | if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); | |
343 | if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); | |
344 | this.startScrolling(speed); | |
345 | } | |
346 | ||
// fix AppleWebKit rendering | ||
if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); | ||
349 | ||
Event.stop(event); | ||
}, | ||
... | ... | |
}, | ||
keyPress: function(event) { | ||
323 | | |
387 | if(event.keyCode!=Event.KEY_ESC) return; | |
this.finishDrag(event, false); | ||
Event.stop(event); | ||
}, | ||
endDrag: function(event) { | ||
if(!this.dragging) return; | ||
394 | this.stopScrolling(); | |
this.finishDrag(event, true); | ||
Event.stop(event); | ||
}, | ||
... | ... | |
var d = this.currentDelta(); | ||
pos[0] -= d[0]; pos[1] -= d[1]; | ||
339 | | |
404 | if(this.options.scroll && (this.options.scroll != window)) { | |
405 | pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; | |
406 | pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; | |
407 | } | |
409 | var p = [0,1].map(function(i){ | |
410 | return (point[i]-pos[i]-this.offset[i]) | |
411 | }.bind(this)); | |
412 | ||
if(this.options.snap) { | ||
if(typeof this.options.snap == 'function') { | ||
p = this.options.snap(p[0],p[1]); | ||
... | ... | |
if((!this.options.constraint) || (this.options.constraint=='vertical')) | ||
style.top = p[1] + "px"; | ||
if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering | ||
432 | }, | |
433 | ||
434 | stopScrolling: function() { | |
435 | if(this.scrollInterval) { | |
436 | clearInterval(this.scrollInterval); | |
437 | this.scrollInterval = null; | |
438 | Draggables._lastScrollPointer = null; | |
439 | } | |
440 | }, | |
441 | ||
442 | startScrolling: function(speed) { | |
443 | this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; | |
444 | this.lastScrolled = new Date(); | |
445 | this.scrollInterval = setInterval(this.scroll.bind(this), 10); | |
446 | }, | |
447 | ||
448 | scroll: function() { | |
449 | var current = new Date(); | |
450 | var delta = current - this.lastScrolled; | |
451 | this.lastScrolled = current; | |
452 | if(this.options.scroll == window) { | |
453 | with (this._getWindowScroll(this.options.scroll)) { | |
454 | if (this.scrollSpeed[0] || this.scrollSpeed[1]) { | |
455 | var d = delta / 1000; | |
456 | this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); | |
457 | } | |
458 | } | |
459 | } else { | |
460 | this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; | |
461 | this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; | |
462 | } | |
463 | ||
464 | Position.prepare(); | |
465 | Droppables.show(Draggables._lastPointer, this.element); | |
466 | Draggables.notify('onDrag', this); | |
467 | Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); | |
468 | Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; | |
469 | Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; | |
470 | if (Draggables._lastScrollPointer[0] < 0) | |
471 | Draggables._lastScrollPointer[0] = 0; | |
472 | if (Draggables._lastScrollPointer[1] < 0) | |
473 | Draggables._lastScrollPointer[1] = 0; | |
474 | this.draw(Draggables._lastScrollPointer); | |
475 | ||
476 | if(this.options.change) this.options.change(this); | |
477 | }, | |
478 | ||
479 | _getWindowScroll: function(w) { | |
480 | var T, L, W, H; | |
481 | with (w.document) { | |
482 | if (w.document.documentElement && documentElement.scrollTop) { | |
483 | T = documentElement.scrollTop; | |
484 | L = documentElement.scrollLeft; | |
485 | } else if (w.document.body) { | |
486 | T = body.scrollTop; | |
487 | L = body.scrollLeft; | |
488 | } | |
489 | if (w.innerWidth) { | |
490 | W = w.innerWidth; | |
491 | H = w.innerHeight; | |
492 | } else if (w.document.documentElement && documentElement.clientWidth) { | |
493 | W = documentElement.clientWidth; | |
494 | H = documentElement.clientHeight; | |
495 | } else { | |
496 | W = body.offsetWidth; | |
497 | H = body.offsetHeight | |
498 | } | |
499 | } | |
500 | return { top: T, left: L, width: W, height: H }; | |
} | ||
} | ||
... | ... | |
} | ||
var Sortable = { | ||
385 | | |
526 | sortables: {}, | |
387 | | |
388 | | |
389 | | |
528 | _findRootElement: function(element) { | |
529 | while (element.tagName != "BODY") { | |
530 | if(element.id && Sortable.sortables[element.id]) return element; | |
531 | element = element.parentNode; | |
532 | } | |
}, | ||
534 | ||
535 | options: function(element) { | |
536 | element = Sortable._findRootElement($(element)); | |
537 | if(!element) return; | |
538 | return Sortable.sortables[element.id]; | |
539 | }, | |
destroy: function(element){ | ||
393 | | |
394 | | |
542 | var s = Sortable.options(element); | |
543 | ||
544 | if(s) { | |
Draggables.removeObserver(s.element); | ||
s.droppables.each(function(d){ Droppables.remove(d) }); | ||
s.draggables.invoke('destroy'); | ||
398 | | |
399 | | |
548 | ||
549 | delete Sortable.sortables[s.element.id]; | |
550 | } | |
}, | ||
401 | | |
552 | ||
create: function(element) { | ||
element = $(element); | ||
var options = Object.extend({ | ||
element: element, | ||
tag: 'li', // assumes li children, override with tag: 'tagname' | ||
dropOnEmpty: false, | ||
408 | | |
559 | tree: false, | |
560 | treeTag: 'ul', | |
overlap: 'vertical', // one of 'vertical', 'horizontal' | ||
constraint: 'vertical', // one of 'vertical', 'horizontal', false | ||
containment: element, // also takes array of elements (or id's); or false | ||
... | ... | |
only: false, | ||
hoverclass: null, | ||
ghosting: false, | ||
416 | | |
568 | scroll: false, | |
569 | scrollSensitivity: 20, | |
570 | scrollSpeed: 15, | |
571 | format: /^[^_]*_(.*)$/, | |
onChange: Prototype.emptyFunction, | ||
onUpdate: Prototype.emptyFunction | ||
}, arguments[1] || {}); | ||
... | ... | |
// build options for the draggables | ||
var options_for_draggable = { | ||
revert: true, | ||
582 | scroll: options.scroll, | |
583 | scrollSpeed: options.scrollSpeed, | |
584 | scrollSensitivity: options.scrollSensitivity, | |
ghosting: options.ghosting, | ||
constraint: options.constraint, | ||
handle: options.handle }; | ||
... | ... | |
var options_for_droppable = { | ||
overlap: options.overlap, | ||
containment: options.containment, | ||
610 | tree: options.tree, | |
hoverclass: options.hoverclass, | ||
453 | | |
454 | | |
612 | onHover: Sortable.onHover | |
613 | //greedy: !options.dropOnEmpty | |
} | ||
615 | ||
616 | var options_for_tree = { | |
617 | onHover: Sortable.onEmptyHover, | |
618 | overlap: options.overlap, | |
619 | containment: options.containment, | |
620 | hoverclass: options.hoverclass | |
621 | } | |
// fix for gecko engine | ||
Element.cleanWhitespace(element); | ||
... | ... | |
options.draggables = []; | ||
options.droppables = []; | ||
463 | | |
464 | ||
// drop on empty handling | ||
466 | | |
467 | | |
468 | | |
630 | if(options.dropOnEmpty || options.tree) { | |
631 | Droppables.add(element, options_for_tree); | |
options.droppables.push(element); | ||
} | ||
... | ... | |
options.draggables.push( | ||
new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); | ||
Droppables.add(e, options_for_droppable); | ||
642 | if(options.tree) e.treeNode = element; | |
options.droppables.push(e); | ||
}); | ||
645 | ||
646 | if(options.tree) { | |
647 | (Sortable.findTreeElements(element, options) || []).each( function(e) { | |
648 | Droppables.add(e, options_for_tree); | |
649 | e.treeNode = element; | |
650 | options.droppables.push(e); | |
651 | }); | |
652 | } | |
// keep reference | ||
483 | | |
655 | this.sortables[element.id] = options; | |
// for onupdate | ||
Draggables.addObserver(new SortableObserver(element, options.onUpdate)); | ||
... | ... | |
// return all suitable-for-sortable elements in a guaranteed order | ||
findElements: function(element, options) { | ||
492 | | |
493 | | |
494 | | |
495 | | |
496 | | |
497 | | |
498 | | |
499 | | |
500 | | |
501 | | |
502 | | |
503 | ||
504 | | |
664 | return Element.findChildren( | |
665 | element, options.only, options.tree ? true : false, options.tag); | |
}, | ||
667 | ||
668 | findTreeElements: function(element, options) { | |
669 | return Element.findChildren( | |
670 | element, options.only, options.tree ? true : false, options.treeTag); | |
671 | }, | |
onHover: function(element, dropon, overlap) { | ||
508 | | |
674 | if(Element.isParent(dropon, element)) return; | |
675 | ||
676 | if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { | |
677 | return; | |
678 | } else if(overlap>0.5) { | |
Sortable.mark(dropon, 'before'); | ||
if(dropon.previousSibling != element) { | ||
var oldParentNode = element.parentNode; | ||
... | ... | |
} | ||
} | ||
}, | ||
531 | ||
532 | | |
533 | | |
534 | | |
535 | | |
701 | ||
702 | onEmptyHover: function(element, dropon, overlap) { | |
703 | var oldParentNode = element.parentNode; | |
704 | var droponOptions = Sortable.options(dropon); | |
705 | ||
706 | if(!Element.isParent(dropon, element)) { | |
707 | var index; | |
708 | ||
709 | var children = Sortable.findElements(dropon, {tag: droponOptions.tag}); | |
710 | var child = null; | |
711 | ||
712 | if(children) { | |
713 | var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); | |
714 | ||
715 | for (index = 0; index < children.length; index += 1) { | |
716 | if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { | |
717 | offset -= Element.offsetSize (children[index], droponOptions.overlap); | |
718 | } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { | |
719 | child = index + 1 < children.length ? children[index + 1] : null; | |
720 | break; | |
721 | } else { | |
722 | child = children[index]; | |
723 | break; | |
724 | } | |
725 | } | |
726 | } | |
727 | ||
728 | dropon.insertBefore(element, child); | |
729 | ||
Sortable.options(oldParentNode).onChange(element); | ||
537 | | |
731 | droponOptions.onChange(element); | |
} | ||
}, | ||
... | ... | |
Element.show(Sortable._marker); | ||
}, | ||
763 | ||
764 | _tree: function(element, options, parent) { | |
765 | var children = Sortable.findElements(element, options) || []; | |
766 | ||
767 | for (var i = 0; i < children.length; ++i) { | |
768 | var match = children[i].id.match(options.format); | |
570 | | |
770 | if (!match) continue; | |
771 | ||
772 | var child = { | |
773 | id: encodeURIComponent(match ? match[1] : null), | |
774 | element: element, | |
775 | parent: parent, | |
776 | children: new Array, | |
777 | position: parent.children.length, | |
778 | container: Sortable._findChildrenElement(children[i], options.treeTag.toUpperCase()) | |
779 | } | |
780 | ||
781 | /* Get the element containing the children and recurse over it */ | |
782 | if (child.container) | |
783 | this._tree(child.container, options, child) | |
784 | ||
785 | parent.children.push (child); | |
786 | } | |
787 | ||
788 | return parent; | |
789 | }, | |
790 | ||
791 | /* Finds the first element of the given tag type within a parent element. | |
792 | Used for finding the first LI[ST] within a L[IST]I[TEM].*/ | |
793 | _findChildrenElement: function (element, containerTag) { | |
794 | if (element && element.hasChildNodes) | |
795 | for (var i = 0; i < element.childNodes.length; ++i) | |
796 | if (element.childNodes[i].tagName == containerTag) | |
797 | return element.childNodes[i]; | |
798 | ||
799 | return null; | |
800 | }, | |
801 | ||
802 | tree: function(element) { | |
element = $(element); | ||
var sortableOptions = this.options(element); | ||
var options = Object.extend({ | ||
574 | | |
806 | tag: sortableOptions.tag, | |
807 | treeTag: sortableOptions.treeTag, | |
only: sortableOptions.only, | ||
name: element.id, | ||
577 | | |
810 | format: sortableOptions.format | |
}, arguments[1] || {}); | ||
812 | ||
813 | var root = { | |
814 | id: null, | |
815 | parent: null, | |
816 | children: new Array, | |
817 | container: element, | |
818 | position: 0 | |
819 | } | |
820 | ||
821 | return Sortable._tree (element, options, root); | |
822 | }, | |
823 | ||
824 | /* Construct a [i] index for a particular node */ | |
825 | _constructIndex: function(node) { | |
826 | var index = ''; | |
827 | do { | |
828 | if (node.id) index = '[' + node.position + ']' + index; | |
829 | } while ((node = node.parent) != null); | |
830 | return index; | |
831 | }, | |
832 | ||
833 | sequence: function(element) { | |
834 | element = $(element); | |
835 | var options = Object.extend(this.options(element), arguments[1] || {}); | |
836 | ||
return $(this.findElements(element, options) || []).map( function(item) { | ||
580 | | |
581 | | |
582 | | |
838 | return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; | |
839 | }); | |
840 | }, | |
841 | ||
842 | setSequence: function(element, new_sequence) { | |
843 | element = $(element); | |
844 | var options = Object.extend(this.options(element), arguments[2] || {}); | |
845 | ||
846 | var nodeMap = {}; | |
847 | this.findElements(element, options).each( function(n) { | |
848 | if (n.id.match(options.format)) | |
849 | nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; | |
850 | n.parentNode.removeChild(n); | |
851 | }); | |
852 | ||
853 | new_sequence.each(function(ident) { | |
854 | var n = nodeMap[ident]; | |
855 | if (n) { | |
856 | n[1].appendChild(n[0]); | |
857 | delete nodeMap[ident]; | |
858 | } | |
859 | }); | |
860 | }, | |
861 | ||
862 | serialize: function(element) { | |
863 | element = $(element); | |
864 | var options = Object.extend(Sortable.options(element), arguments[1] || {}); | |
865 | var name = encodeURIComponent( | |
866 | (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); | |
867 | ||
868 | if (options.tree) { | |
869 | return Sortable.tree(element, arguments[1]).children.map( function (item) { | |
870 | return [name + Sortable._constructIndex(item) + "=" + | |
871 | encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); | |
872 | }).flatten().join('&'); | |
873 | } else { | |
874 | return Sortable.sequence(element, arguments[1]).map( function(item) { | |
875 | return name + "[]=" + encodeURIComponent(item); | |
876 | }).join('&'); | |
877 | } | |
} | ||
879 | } | |
880 | ||
881 | /* Returns true if child is contained within element */ | |
882 | Element.isParent = function(child, element) { | |
883 | if (!child.parentNode || child == element) return false; | |
884 | ||
885 | if (child.parentNode == element) return true; | |
886 | ||
887 | return Element.isParent(child.parentNode, element); | |
888 | } | |
889 | ||
890 | Element.findChildren = function(element, only, recursive, tagName) { | |
891 | if(!element.hasChildNodes()) return null; | |
892 | tagName = tagName.toUpperCase(); | |
893 | if(only) only = [only].flatten(); | |
894 | var elements = []; | |
895 | $A(element.childNodes).each( function(e) { | |
896 | if(e.tagName && e.tagName.toUpperCase()==tagName && | |
897 | (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) | |
898 | elements.push(e); | |
899 | if(recursive) { | |
900 | var grandchildren = Element.findChildren(e, only, recursive, tagName); | |
901 | if(grandchildren) elements.push(grandchildren); | |
902 | } | |
903 | }); | |
904 | ||
905 | return (elements.length>0 ? elements.flatten() : []); | |
906 | } | |
907 | ||
908 | Element.offsetSize = function (element, type) { | |
909 | if (type == 'vertical' || type == 'height') | |
910 | return element.offsetHeight; | |
911 | else | |
912 | return element.offsetWidth; | |
} | ||
rool/rails/typo/trunk/vendor/rails/railties/html/javascripts/effects.js:
prev. | current | |
// | ||
// See scriptaculous.js for full license. | ||
9 | ||
10 | | |
// converts rgb() and #xxx to #xxxxxx format, | ||
// returns self (or first argument) if not convertable | ||
String.prototype.parseColor = function() { | ||
... | ... | |
} | ||
} | ||
return(color.length==7 ? color : (arguments[0] || this)); | ||
25 | ||
23 | } | |
27 | ||
28 | | |
29 | | |
30 | | |
31 | | |
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | | |
38 | | |
39 | | |
40 | | |
41 | | |
25 | /*--------------------------------------------------------------------------*/ | |
26 | ||
27 | Element.collectTextNodes = function(element) { | |
28 | return $A($(element).childNodes).collect( function(node) { | |
29 | return (node.nodeType==3 ? node.nodeValue : | |
30 | (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); | |
31 | }).flatten().join(''); | |
} | ||
44 | ||
45 | | |
46 | | |
34 | Element.collectTextNodesIgnoreClass = function(element, className) { | |
35 | return $A($(element).childNodes).collect( function(node) { | |
36 | return (node.nodeType==3 ? node.nodeValue : | |
37 | ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? | |
38 | Element.collectTextNodesIgnoreClass(node, className) : '')); | |
39 | }).flatten().join(''); | |
} | ||
49 | ||
42 | Element.setContentZoom = function(element, percent) { | |
43 | element = $(element); | |
Element.setStyle(element, {fontSize: (percent/100) + 'em'}); | ||
51 | | |
45 | if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); | |
} | ||
Element.getOpacity = function(element){ | ||
... | ... | |
Element.setStyle(element, | ||
{ filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') + | ||
'alpha(opacity='+value*100+')' }); | ||
78 | | |
72 | } | |
} | ||
Element.getInlineOpacity = function(element){ | ||
return $(element).style.opacity || ''; | ||
} | ||
85 | ||
86 | | |
87 | | |
79 | Element.childrenWithClassName = function(element, className, findFirst) { | |
80 | var classNameRegExp = new RegExp("(^|\\s)" + className + "(\\s|$)"); | |
81 | var results = $A($(element).getElementsByTagName('*'))[findFirst ? 'detect' : 'select']( function(c) { | |
82 | return (c.className && c.className.match(classNameRegExp)); | |
83 | }); | |
84 | if(!results) results = []; | |
85 | return results; | |
} | ||
88 | Element.forceRerendering = function(element) { | |
89 | try { | |
90 | element = $(element); | |
91 | var n = document.createTextNode(' '); | |
92 | element.appendChild(n); | |
93 | element.removeChild(n); | |
94 | } catch(e) { } | |
95 | }; | |
96 | ||
97 | /*--------------------------------------------------------------------------*/ | |
98 | ||
Array.prototype.call = function() { | ||
var args = arguments; | ||
this.each(function(f){ f.apply(this, args) }); | ||
... | ... | |
$A(elements).each( function(element, index) { | ||
new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); | ||
}); | ||
141 | }, | |
142 | PAIRS: { | |
143 | 'slide': ['SlideDown','SlideUp'], | |
144 | 'blind': ['BlindDown','BlindUp'], | |
145 | 'appear': ['Appear','Fade'] | |
146 | }, | |
147 | toggle: function(element, effect) { | |
148 | element = $(element); | |
149 | effect = (effect || 'appear').toLowerCase(); | |
150 | var options = Object.extend({ | |
151 | queue: { position:'end', scope:(element.id || 'global'), limit: 1 } | |
152 | }, arguments[2] || {}); | |
153 | Effect[element.visible() ? | |
154 | Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); | |
} | ||
}; | ||
... | ... | |
/* ------------- core effects ------------- */ | ||
169 | ||
170 | | |
192 | Effect.ScopedQueue = Class.create(); | |
193 | Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { | |
194 | initialize: function() { | |
195 | this.effects = []; | |
196 | this.interval = null; | |
197 | }, | |
_each: function(iterator) { | ||
this.effects._each(iterator); | ||
}, | ||
174 | | |
add: function(effect) { | ||
var timestamp = new Date().getTime(); | ||
178 | | |
204 | var position = (typeof effect.options.queue == 'string') ? | |
205 | effect.options.queue : effect.options.queue.position; | |
206 | ||
207 | switch(position) { | |
case 'front': | ||
// move unstarted effects after this effect | ||
this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { | ||
... | ... | |
effect.startOn += timestamp; | ||
effect.finishOn += timestamp; | ||
194 | | |
223 | ||
224 | if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) | |
225 | this.effects.push(effect); | |
226 | ||
if(!this.interval) | ||
this.interval = setInterval(this.loop.bind(this), 40); | ||
}, | ||
... | ... | |
var timePos = new Date().getTime(); | ||
this.effects.invoke('loop', timePos); | ||
} | ||
241 | }); | |
242 | ||
243 | Effect.Queues = { | |
244 | instances: $H(), | |
245 | get: function(queueName) { | |
246 | if(typeof queueName != 'string') return queueName; | |
247 | ||
248 | if(!this.instances[queueName]) | |
249 | this.instances[queueName] = new Effect.ScopedQueue(); | |
250 | ||
251 | return this.instances[queueName]; | |
252 | } | |
} | ||
210 | ||
254 | Effect.Queue = Effect.Queues.get('global'); | |
256 | Effect.DefaultOptions = { | |
257 | transition: Effect.Transitions.sinoidal, | |
258 | duration: 1.0, // seconds | |
259 | fps: 25.0, // max. 25fps due to Effect.Queue implementation | |
260 | sync: false, // true for combining | |
261 | from: 0.0, | |
262 | to: 1.0, | |
263 | delay: 0.0, | |
264 | queue: 'parallel' | |
265 | } | |
266 | ||
Effect.Base = function() {}; | ||
Effect.Base.prototype = { | ||
position: null, | ||
215 | | |
216 | | |
217 | | |
218 | | |
219 | | |
220 | | |
221 | | |
222 | | |
223 | | |
224 | | |
225 | | |
226 | | |
start: function(options) { | ||
228 | | |
271 | this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {}); | |
this.currentFrame = 0; | ||
this.state = 'idle'; | ||
this.startOn = this.options.delay*1000; | ||
this.finishOn = this.startOn + (this.options.duration*1000); | ||
this.event('beforeStart'); | ||
234 | | |
277 | if(!this.options.sync) | |
278 | Effect.Queues.get(typeof this.options.queue == 'string' ? | |
279 | 'global' : this.options.queue.scope).add(this); | |
}, | ||
loop: function(timePos) { | ||
if(timePos >= this.startOn) { | ||
... | ... | |
} | ||
}, | ||
cancel: function() { | ||
272 | | |
317 | if(!this.options.sync) | |
318 | Effect.Queues.get(typeof this.options.queue == 'string' ? | |
319 | 'global' : this.options.queue.scope).remove(this); | |
this.state = 'finished'; | ||
}, | ||
event: function(eventName) { | ||
... | ... | |
this.element = $(element); | ||
// make this work on IE on elements without 'layout' | ||
if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout)) | ||
310 | | |
357 | this.element.setStyle({zoom: 1}); | |
var options = Object.extend({ | ||
312 | | |
359 | from: this.element.getOpacity() || 0.0, | |
to: 1.0 | ||
}, arguments[1] || {}); | ||
this.start(options); | ||
}, | ||
update: function(position) { | ||
318 | | |
365 | this.element.setOpacity(position); | |
} | ||
}); | ||
322 | ||
323 | ||
324 | | |
325 | | |
326 | | |
327 | | |
328 | | |
369 | Effect.Move = Class.create(); | |
370 | Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), { | |
371 | initialize: function(element) { | |
372 | this.element = $(element); | |
373 | var options = Object.extend({ | |
374 | x: 0, | |
375 | y: 0, | |
376 | mode: 'relative' | |
377 | }, arguments[1] || {}); | |
378 | this.start(options); | |
}, | ||
setup: function() { | ||
// Bug in Opera: Opera returns the "real" position of a static element or | ||
// relative element that does not have top/left explicitly set. | ||
// ==> Always set top and left for position relative elements in your stylesheets | ||
// (to 0 if you do not need them) | ||
335 | | |
336 | | |
337 | | |
385 | this.element.makePositioned(); | |
386 | this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); | |
387 | this.originalTop = parseFloat(this.element.getStyle('top') || '0'); | |
388 | if(this.options.mode == 'absolute') { | |
389 | // absolute movement, so we need to calc deltaX and deltaY | |
390 | this.options.x = this.options.x - this.originalLeft; | |
391 | this.options.y = this.options.y - this.originalTop; | |
392 | } | |
}, | ||
update: function(position) { | ||
340 | | |
341 | | |
342 | | |
395 | this.element.setStyle({ | |
396 | left: this.options.x * position + this.originalLeft + 'px', | |
397 | top: this.options.y * position + this.originalTop + 'px' | |
}); | ||
} | ||
}); | ||
402 | // for backwards compatibility | |
403 | Effect.MoveBy = function(element, toTop, toLeft) { | |
404 | return new Effect.Move(element, | |
405 | Object.extend({ x: toLeft, y: toTop }, arguments[3] || {})); | |
406 | }; | |
407 | ||
Effect.Scale = Class.create(); | ||
Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), { | ||
initialize: function(element, percent) { | ||
... | ... | |
}, | ||
setup: function() { | ||
this.restoreAfterFinish = this.options.restoreAfterFinish || false; | ||
364 | | |
425 | this.elementPositioning = this.element.getStyle('position'); | |
this.originalStyle = {}; | ||
['top','left','width','height','fontSize'].each( function(k) { | ||
... | ... | |
this.originalTop = this.element.offsetTop; | ||
this.originalLeft = this.element.offsetLeft; | ||
374 | | |
435 | var fontSize = this.element.getStyle('font-size') || '100%'; | |
['em','px','%'].each( function(fontSizeType) { | ||
if(fontSize.indexOf(fontSizeType)>0) { | ||
this.fontSize = parseFloat(fontSize); | ||
... | ... | |
update: function(position) { | ||
var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); | ||
if(this.options.scaleContent && this.fontSize) | ||
396 | | |
457 | this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); | |
this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); | ||
}, | ||
finish: function(position) { | ||
400 | | |
461 | if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); | |
}, | ||
setDimensions: function(height, width) { | ||
var d = {}; | ||
... | ... | |
if(this.options.scaleX) d.left = -leftd + 'px'; | ||
} | ||
} | ||
417 | | |
478 | this.element.setStyle(d); | |
} | ||
}); | ||
... | ... | |
}, | ||
setup: function() { | ||
// Prevent executing on elements not in the layout flow | ||
430 | | |
491 | if(this.element.getStyle('display')=='none') { this.cancel(); return; } | |
// Disable background image during the effect | ||
this.oldStyle = { | ||
433 | | |
434 | | |
494 | backgroundImage: this.element.getStyle('background-image') }; | |
495 | this.element.setStyle({backgroundImage: 'none'}); | |
if(!this.options.endcolor) | ||
436 | | |
497 | this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); | |
if(!this.options.restorecolor) | ||
438 | | |
499 | this.options.restorecolor = this.element.getStyle('background-color'); | |
// init color calculations | ||
this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); | ||
this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); | ||
}, | ||
update: function(position) { | ||
444 | | |
505 | this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ | |
return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) }); | ||
}, | ||
finish: function() { | ||
448 | | |
509 | this.element.setStyle(Object.extend(this.oldStyle, { | |
backgroundColor: this.options.restorecolor | ||
})); | ||
} | ||
... | ... | |
/* ------------- combination effects ------------- */ | ||
Effect.Fade = function(element) { | ||
482 | | |
543 | element = $(element); | |
544 | var oldOpacity = element.getInlineOpacity(); | |
var options = Object.extend({ | ||
484 | | |
546 | from: element.getOpacity() || 1.0, | |
to: 0.0, | ||
486 | | |
548 | afterFinishInternal: function(effect) { | |
if(effect.options.to!=0) return; | ||
488 | | |
489 | | |
490 | | |
550 | effect.element.hide(); | |
551 | effect.element.setStyle({opacity: oldOpacity}); | |
552 | }}, arguments[1] || {}); | |
return new Effect.Opacity(element,options); | ||
} | ||
Effect.Appear = function(element) { | ||
557 | element = $(element); | |
var options = Object.extend({ | ||
496 | | |
559 | from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), | |
to: 1.0, | ||
498 | | |
499 | | |
500 | | |
501 | | |
561 | // force Safari to render floated elements properly | |
562 | afterFinishInternal: function(effect) { | |
563 | effect.element.forceRerendering(); | |
564 | }, | |
565 | beforeSetup: function(effect) { | |
566 | effect.element.setOpacity(effect.options.from); | |
567 | effect.element.show(); | |
568 | }}, arguments[1] || {}); | |
return new Effect.Opacity(element,options); | ||
} | ||
Effect.Puff = function(element) { | ||
element = $(element); | ||
507 | | |
574 | var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position') }; | |
return new Effect.Parallel( | ||
[ new Effect.Scale(element, 200, | ||
{ sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), | ||
new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], | ||
Object.extend({ duration: 1.0, | ||
513 | | |
514 | | |
515 | | |
516 | | |
517 | | |
580 | beforeSetupInternal: function(effect) { | |
581 | effect.effects[0].element.setStyle({position: 'absolute'}); }, | |
582 | afterFinishInternal: function(effect) { | |
583 | effect.effects[0].element.hide(); | |
584 | effect.effects[0].element.setStyle(oldStyle); } | |
}, arguments[1] || {}) | ||
); | ||
} | ||
Effect.BlindUp = function(element) { | ||
element = $(element); | ||
524 | | |
591 | element.makeClipping(); | |
return new Effect.Scale(element, 0, | ||
Object.extend({ scaleContent: false, | ||
scaleX: false, | ||
restoreAfterFinish: true, | ||
529 | | |
530 | | |
596 | afterFinishInternal: function(effect) { | |
597 | effect.element.hide(); | |
598 | effect.element.undoClipping(); | |
599 | } | |
}, arguments[1] || {}) | ||
); | ||
} | ||
Effect.BlindDown = function(element) { | ||
element = $(element); | ||
537 | | |
538 | | |
606 | var elementDimensions = element.getDimensions(); | |
return new Effect.Scale(element, 100, | ||
Object.extend({ scaleContent: false, | ||
scaleX: false, | ||
scaleFrom: 0, | ||
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, | ||
restoreAfterFinish: true, | ||
545 | | |
546 | | |
547 | | |
548 | | |
549 | | |
550 | | |
551 | | |
552 | | |
553 | | |
613 | afterSetup: function(effect) { | |
614 | effect.element.makeClipping(); | |
615 | effect.element.setStyle({height: '0px'}); | |
616 | effect.element.show(); | |
617 | }, | |
618 | afterFinishInternal: function(effect) { | |
619 | effect.element.undoClipping(); | |
620 | } | |
}, arguments[1] || {}) | ||
); | ||
} | ||
Effect.SwitchOff = function(element) { | ||
element = $(element); | ||
560 | | |
627 | var oldOpacity = element.getInlineOpacity(); | |
return new Effect.Appear(element, { | ||
duration: 0.4, | ||
from: 0, | ||
... | ... | |
new Effect.Scale(effect.element, 1, { | ||
duration: 0.3, scaleFromCenter: true, | ||
scaleX: false, scaleContent: false, restoreAfterFinish: true, | ||
569 | | |
570 | | |
571 | | |
572 | | |
573 | | |
574 | | |
575 | | |
636 | beforeSetup: function(effect) { | |
637 | effect.element.makePositioned(); | |
638 | effect.element.makeClipping(); | |
639 | }, | |
640 | afterFinishInternal: function(effect) { | |
641 | effect.element.hide(); | |
642 | effect.element.undoClipping(); | |
643 | effect.element.undoPositioned(); | |
644 | effect.element.setStyle({opacity: oldOpacity}); | |
645 | } | |
}) | ||
} | ||
}); | ||
... | ... | |
Effect.DropOut = function(element) { | ||
element = $(element); | ||
var oldStyle = { | ||
584 | | |
585 | | |
586 | | |
654 | top: element.getStyle('top'), | |
655 | left: element.getStyle('left'), | |
656 | opacity: element.getInlineOpacity() }; | |
return new Effect.Parallel( | ||
588 | | |
658 | [ new Effect.Move(element, {x: 0, y: 100, sync: true }), | |
new Effect.Opacity(element, { sync: true, to: 0.0 }) ], | ||
Object.extend( | ||
{ duration: 0.5, | ||
592 | | |
593 | | |
594 | | |
595 | | |
596 | | |
662 | beforeSetup: function(effect) { | |
663 | effect.effects[0].element.makePositioned(); | |
664 | }, | |
665 | afterFinishInternal: function(effect) { | |
666 | effect.effects[0].element.hide(); | |
667 | effect.effects[0].element.undoPositioned(); | |
668 | effect.effects[0].element.setStyle(oldStyle); | |
669 | } | |
}, arguments[1] || {})); | ||
} | ||
Effect.Shake = function(element) { | ||
element = $(element); | ||
var oldStyle = { | ||
603 | | |
604 | | |
605 | | |
606 | | |
607 | | |
608 | | |
609 | | |
610 | | |
611 | | |
612 | | |
613 | | |
614 | | |
615 | | |
616 | | |
617 | | |
618 | | |
619 | | |
676 | top: element.getStyle('top'), | |
677 | left: element.getStyle('left') }; | |
678 | return new Effect.Move(element, | |
679 | { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { | |
680 | new Effect.Move(effect.element, | |
681 | { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { | |
682 | new Effect.Move(effect.element, | |
683 | { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { | |
684 | new Effect.Move(effect.element, | |
685 | { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { | |
686 | new Effect.Move(effect.element, | |
687 | { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { | |
688 | new Effect.Move(effect.element, | |
689 | { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { | |
690 | effect.element.undoPositioned(); | |
691 | effect.element.setStyle(oldStyle); | |
692 | }}) }}) }}) }}) }}) }}); | |
} | ||
Effect.SlideDown = function(element) { | ||
element = $(element); | ||
624 | | |
697 | element.cleanWhitespace(); | |
// SlideDown need to have the content of the element wrapped in a container element with fixed height! | ||
626 | | |
627 | | |
699 | var oldInnerBottom = $(element.firstChild).getStyle('bottom'); | |
700 | var elementDimensions = element.getDimensions(); | |
return new Effect.Scale(element, 100, Object.extend({ | ||
scaleContent: false, | ||
scaleX: false, | ||
scaleFrom: 0, | ||
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, | ||
restoreAfterFinish: true, | ||
634 | | |
635 | | |
636 | | |
637 | | |
638 | | |
639 | | |
640 | | |
641 | | |
642 | | |
643 | | |
644 | | |
645 | | |
646 | | |
647 | | |
648 | | |
707 | afterSetup: function(effect) { | |
708 | effect.element.makePositioned(); | |
709 | effect.element.firstChild.makePositioned(); | |
710 | if(window.opera) effect.element.setStyle({top: ''}); | |
711 | effect.element.makeClipping(); | |
712 | effect.element.setStyle({height: '0px'}); | |
713 | effect.element.show(); }, | |
714 | afterUpdateInternal: function(effect) { | |
715 | effect.element.firstChild.setStyle({bottom: | |
716 | (effect.dims[0] - effect.element.clientHeight) + 'px' }); | |
717 | }, | |
718 | afterFinishInternal: function(effect) { | |
719 | effect.element.undoClipping(); | |
720 | // IE will crash if child is undoPositioned first | |
721 | if(/MSIE/.test(navigator.userAgent)){ | |
722 | effect.element.undoPositioned(); | |
723 | effect.element.firstChild.undoPositioned(); | |
724 | }else{ | |
725 | effect.element.firstChild.undoPositioned(); | |
726 | effect.element.undoPositioned(); | |
727 | } | |
728 | effect.element.firstChild.setStyle({bottom: oldInnerBottom}); } | |
}, arguments[1] || {}) | ||
); | ||
} | ||
Effect.SlideUp = function(element) { | ||
element = $(element); | ||
655 | | |
656 | | |
735 | element.cleanWhitespace(); | |
736 | var oldInnerBottom = $(element.firstChild).getStyle('bottom'); | |
return new Effect.Scale(element, 0, | ||
Object.extend({ scaleContent: false, | ||
scaleX: false, | ||
scaleMode: 'box', | ||
scaleFrom: 100, | ||
restoreAfterFinish: true, | ||
663 | | |
664 | | |
665 | | |
666 | | |
667 | | |
668 | | |
669 | | |
670 | | |
671 | | |
672 | | |
673 | | |
674 | | |
675 | | |
676 | | |
743 | beforeStartInternal: function(effect) { | |
744 | effect.element.makePositioned(); | |
745 | effect.element.firstChild.makePositioned(); | |
746 | if(window.opera) effect.element.setStyle({top: ''}); | |
747 | effect.element.makeClipping(); | |
748 | effect.element.show(); }, | |
749 | afterUpdateInternal: function(effect) { | |
750 | effect.element.firstChild.setStyle({bottom: | |
751 | (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, | |
752 | afterFinishInternal: function(effect) { | |
753 | effect.element.hide(); | |
754 | effect.element.undoClipping(); | |
755 | effect.element.firstChild.undoPositioned(); | |
756 | effect.element.undoPositioned(); | |
757 | effect.element.setStyle({bottom: oldInnerBottom}); } | |
}, arguments[1] || {}) | ||
); | ||
} | ||
... | ... | |
Effect.Squish = function(element) { | ||
return new Effect.Scale(element, window.opera ? 1 : 0, | ||
{ restoreAfterFinish: true, | ||
685 | | |
686 | | |
687 | | |
688 | | |
689 | | |
766 | beforeSetup: function(effect) { | |
767 | effect.element.makeClipping(effect.element); }, | |
768 | afterFinishInternal: function(effect) { | |
769 | effect.element.hide(effect.element); | |
770 | effect.element.undoClipping(effect.element); } | |
}); | ||
} | ||
... | ... | |
element = $(element); | ||
var options = Object.extend({ | ||
direction: 'center', | ||
697 | | |
778 | moveTransition: Effect.Transitions.sinoidal, | |
scaleTransition: Effect.Transitions.sinoidal, | ||
opacityTransition: Effect.Transitions.full | ||
}, arguments[1] || {}); | ||
... | ... | |
left: element.style.left, | ||
height: element.style.height, | ||
width: element.style.width, | ||
706 | | |
787 | opacity: element.getInlineOpacity() }; | |
708 | | |
789 | var dims = element.getDimensions(); | |
var initialMoveX, initialMoveY; | ||
var moveX, moveY; | ||
... | ... | |
break; | ||
} | ||
740 | | |
821 | return new Effect.Move(element, { | |
822 | x: initialMoveX, | |
823 | y: initialMoveY, | |
duration: 0.01, | ||
742 | | |
743 | | |
744 | | |
745 | | |
746 | | |
825 | beforeSetup: function(effect) { | |
826 | effect.element.hide(); | |
827 | effect.element.makeClipping(); | |
828 | effect.element.makePositioned(); | |
829 | }, | |
afterFinishInternal: function(effect) { | ||
new Effect.Parallel( | ||
[ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), | ||
750 | | |
833 | new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), | |
new Effect.Scale(effect.element, 100, { | ||
scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, | ||
sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) | ||
], Object.extend({ | ||
755 | | |
756 | | |
757 | | |
758 | | |
759 | | |
760 | | |
838 | beforeSetup: function(effect) { | |
839 | effect.effects[0].element.setStyle({height: '0px'}); | |
840 | effect.effects[0].element.show(); | |
841 | }, | |
842 | afterFinishInternal: function(effect) { | |
843 | effect.effects[0].element.undoClipping(); | |
844 | effect.effects[0].element.undoPositioned(); | |
845 | effect.effects[0].element.setStyle(oldStyle); | |
846 | } | |
}, options) | ||
) | ||
} | ||
... | ... | |
element = $(element); | ||
var options = Object.extend({ | ||
direction: 'center', | ||
771 | | |
857 | moveTransition: Effect.Transitions.sinoidal, | |
scaleTransition: Effect.Transitions.sinoidal, | ||
opacityTransition: Effect.Transitions.none | ||
}, arguments[1] || {}); | ||
... | ... | |
left: element.style.left, | ||
height: element.style.height, | ||
width: element.style.width, | ||
780 | | |
866 | opacity: element.getInlineOpacity() }; | |
782 | | |
868 | var dims = element.getDimensions(); | |
var moveX, moveY; | ||
switch (options.direction) { | ||
... | ... | |
return new Effect.Parallel( | ||
[ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), | ||
new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), | ||
810 | | |
896 | new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) | |
], Object.extend({ | ||
812 | | |
813 | | |
814 | | |
815 | | |
816 | | |
898 | beforeStartInternal: function(effect) { | |
899 | effect.effects[0].element.makePositioned(); | |
900 | effect.effects[0].element.makeClipping(); }, | |
901 | afterFinishInternal: function(effect) { | |
902 | effect.effects[0].element.hide(); | |
903 | effect.effects[0].element.undoClipping(); | |
904 | effect.effects[0].element.undoPositioned(); | |
905 | effect.effects[0].element.setStyle(oldStyle); } | |
}, options) | ||
); | ||
} | ||
... | ... | |
Effect.Pulsate = function(element) { | ||
element = $(element); | ||
var options = arguments[1] || {}; | ||
824 | | |
913 | var oldOpacity = element.getInlineOpacity(); | |
var transition = options.transition || Effect.Transitions.sinoidal; | ||
var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) }; | ||
reverser.bind(transition); | ||
return new Effect.Opacity(element, | ||
Object.extend(Object.extend({ duration: 3.0, from: 0, | ||
830 | | |
919 | afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } | |
}, options), {transition: reverser})); | ||
} | ||
... | ... | |
new Effect.Scale(element, 1, { | ||
scaleContent: false, | ||
scaleY: false, | ||
849 | | |
850 | | |
851 | | |
852 | | |
938 | afterFinishInternal: function(effect) { | |
939 | effect.element.hide(); | |
940 | effect.element.undoClipping(); | |
941 | effect.element.setStyle(oldStyle); | |
942 | } }); | |
}}, arguments[1] || {})); | ||
854 | ||
944 | }; | |
945 | ||
946 | ['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', | |
947 | 'collectTextNodes','collectTextNodesIgnoreClass','childrenWithClassName'].each( | |
948 | function(f) { Element.Methods[f] = Element[f]; } | |
949 | ); | |
950 | ||
951 | Element.Methods.visualEffect = function(element, effect, options) { | |
952 | s = effect.gsub(/_/, '-').camelize(); | |
953 | effect_class = s.charAt(0).toUpperCase() + s.substring(1); | |
954 | new Effect[effect_class](element, options); | |
955 | return $(element); | |
956 | }; | |
957 | ||
958 | Element.addMethods(); | |
rool/rails/typo/trunk/vendor/rails/railties/html/javascripts/prototype.js:
prev. | current | |
1 | ||
1 | /* Prototype JavaScript framework, version 1.5.0_rc0 | |
* (c) 2005 Sam Stephenson <sam@conio.net> | ||
* | ||
4 | | |
5 | | |
6 | | |
* Prototype is freely distributable under the terms of an MIT-style license. | ||
8 | | |
* For details, see the Prototype web site: http://prototype.conio.net/ | ||
* | ||
/*--------------------------------------------------------------------------*/ | ||
var Prototype = { | ||
14 | | |
10 | Version: '1.5.0_rc0', | |
ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', | ||
emptyFunction: function() {}, | ||
... | ... | |
var Abstract = new Object(); | ||
Object.extend = function(destination, source) { | ||
32 | | |
28 | for (var property in source) { | |
destination[property] = source[property]; | ||
} | ||
return destination; | ||
... | ... | |
} | ||
} | ||
} | ||
119 | Object.extend(String.prototype, { | |
120 | gsub: function(pattern, replacement) { | |
121 | var result = '', source = this, match; | |
122 | replacement = arguments.callee.prepareReplacement(replacement); | |
124 | ||
124 | while (source.length > 0) { | |
125 | if (match = source.match(pattern)) { | |
126 | result += source.slice(0, match.index); | |
127 | result += (replacement(match) || '').toString(); | |
128 | source = source.slice(match.index + match[0].length); | |
129 | } else { | |
130 | result += source, source = ''; | |
131 | } | |
132 | } | |
133 | return result; | |
134 | }, | |
126 | ||
127 | | |
136 | sub: function(pattern, replacement, count) { | |
137 | replacement = this.gsub.prepareReplacement(replacement); | |
138 | count = count === undefined ? 1 : count; | |
129 | | |
130 | | |
131 | | |
132 | | |
140 | return this.gsub(pattern, function(match) { | |
141 | if (--count < 0) return match[0]; | |
142 | return replacement(match); | |
143 | }); | |
144 | }, | |
134 | | |
135 | | |
146 | scan: function(pattern, iterator) { | |
147 | this.gsub(pattern, iterator); | |
148 | return this; | |
149 | }, | |
137 | | |
138 | | |
151 | truncate: function(length, truncation) { | |
152 | length = length || 30; | |
153 | truncation = truncation === undefined ? '...' : truncation; | |
154 | return this.length > length ? | |
155 | this.slice(0, length - truncation.length) + truncation : this; | |
156 | }, | |
140 | | |
141 | ||
142 | ||
158 | strip: function() { | |
159 | return this.replace(/^\s+/, '').replace(/\s+$/, ''); | |
160 | }, | |
161 | ||
stripTags: function() { | ||
return this.replace(/<\/?[^>]+>/gi, ''); | ||
}, | ||
... | ... | |
}, | ||
evalScripts: function() { | ||
160 | | |
179 | return this.extractScripts().map(function(script) { return eval(script) }); | |
}, | ||
escapeHTML: function() { | ||
... | ... | |
}, | ||
inspect: function() { | ||
206 | | |
225 | return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'"; | |
} | ||
}); | ||
229 | String.prototype.gsub.prepareReplacement = function(replacement) { | |
230 | if (typeof replacement == 'function') return replacement; | |
231 | var template = new Template(replacement); | |
232 | return function(match) { return template.evaluate(match) }; | |
233 | } | |
234 | ||
String.prototype.parseQuery = String.prototype.toQueryParams; | ||
237 | var Template = Class.create(); | |
238 | Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; | |
239 | Template.prototype = { | |
240 | initialize: function(template, pattern) { | |
241 | this.template = template.toString(); | |
242 | this.pattern = pattern || Template.Pattern; | |
243 | }, | |
244 | ||
245 | evaluate: function(object) { | |
246 | return this.template.gsub(this.pattern, function(match) { | |
247 | var before = match[1]; | |
248 | if (before == '\\') return match[2]; | |
249 | return before + (object[match[3]] || '').toString(); | |
250 | }); | |
251 | } | |
252 | } | |
253 | ||
var $break = new Object(); | ||
var $continue = new Object(); | ||
... | ... | |
var result; | ||
this.each(function(value, index) { | ||
value = (iterator || Prototype.K)(value, index); | ||
316 | | |
358 | if (result == undefined || value >= result) | |
result = value; | ||
}); | ||
return result; | ||
... | ... | |
var result; | ||
this.each(function(value, index) { | ||
value = (iterator || Prototype.K)(value, index); | ||
326 | | |
368 | if (result == undefined || value < result) | |
result = value; | ||
}); | ||
return result; | ||
... | ... | |
var collections = [this].concat(args).map($A); | ||
return this.map(function(value, index) { | ||
378 | | |
379 | | |
420 | return iterator(collections.pluck(index)); | |
}); | ||
}, | ||
... | ... | |
Object.extend(Array.prototype, Enumerable); | ||
409 | ||
450 | if (!Array.prototype._reverse) | |
451 | Array.prototype._reverse = Array.prototype.reverse; | |
Object.extend(Array.prototype, { | ||
_each: function(iterator) { | ||
... | ... | |
flatten: function() { | ||
return this.inject([], function(array, value) { | ||
438 | | |
480 | return array.concat(value && value.constructor == Array ? | |
value.flatten() : [value]); | ||
}); | ||
}, | ||
... | ... | |
return (inline !== false ? this : this.toArray())._reverse(); | ||
}, | ||
460 | | |
461 | | |
462 | | |
463 | | |
464 | | |
465 | | |
466 | | |
467 | ||
inspect: function() { | ||
return '[' + this.map(Object.inspect).join(', ') + ']'; | ||
} | ||
}); | ||
var Hash = { | ||
_each: function(iterator) { | ||
474 | | |
508 | for (var key in this) { | |
var value = this[key]; | ||
if (typeof value == 'function') continue; | ||
... | ... | |
var Ajax = { | ||
getTransport: function() { | ||
return Try.these( | ||
586 | function() {return new XMLHttpRequest()}, | |
function() {return new ActiveXObject('Msxml2.XMLHTTP')}, | ||
553 | | |
554 | | |
588 | function() {return new ActiveXObject('Microsoft.XMLHTTP')} | |
) || false; | ||
}, | ||
... | ... | |
this.options = { | ||
method: 'post', | ||
asynchronous: true, | ||
640 | contentType: 'application/x-www-form-urlencoded', | |
parameters: '' | ||
} | ||
Object.extend(this.options, options || {}); | ||
... | ... | |
setRequestHeaders: function() { | ||
var requestHeaders = | ||
['X-Requested-With', 'XMLHttpRequest', | ||
665 | | |
700 | 'X-Prototype-Version', Prototype.Version, | |
701 | 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*']; | |
if (this.options.method == 'post') { | ||
668 | | |
669 | | |
704 | requestHeaders.push('Content-type', this.options.contentType); | |
/* Force "Connection: close" for Mozilla browsers to work around | ||
* a bug where XMLHttpReqeuest sends an incorrect Content-length | ||
... | ... | |
evalJSON: function() { | ||
try { | ||
700 | | |
735 | return eval('(' + this.header('X-JSON') + ')'); | |
} catch (e) {} | ||
}, | ||
... | ... | |
this.updater = new Ajax.Updater(this.container, this.url, this.options); | ||
} | ||
}); | ||
869 | function $() { | |
870 | var results = [], element; | |
871 | for (var i = 0; i < arguments.length; i++) { | |
872 | element = arguments[i]; | |
873 | if (typeof element == 'string') | |
874 | element = document.getElementById(element); | |
875 | results.push(Element.extend(element)); | |
876 | } | |
877 | return results.length < 2 ? results[0] : results; | |
878 | } | |
879 | ||
document.getElementsByClassName = function(className, parentElement) { | ||
var children = ($(parentElement) || document.body).getElementsByTagName('*'); | ||
return $A(children).inject([], function(elements, child) { | ||
if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) | ||
838 | | |
884 | elements.push(Element.extend(child)); | |
return elements; | ||
}); | ||
} | ||
/*--------------------------------------------------------------------------*/ | ||
845 | ||
891 | if (!window.Element) | |
var Element = new Object(); | ||
893 | ||
894 | Element.extend = function(element) { | |
895 | if (!element) return; | |
896 | if (_nativeExtensions) return element; | |
897 | ||
898 | if (!element._extended && element.tagName && element != window) { | |
899 | var methods = Element.Methods, cache = Element.extend.cache; | |
900 | for (property in methods) { | |
901 | var value = methods[property]; | |
902 | if (typeof value == 'function') | |
903 | element[property] = cache.findOrStore(value); | |
904 | } | |
905 | } | |
906 | ||
907 | element._extended = true; | |
908 | return element; | |
} | ||
849 | ||
911 | Element.extend.cache = { | |
912 | findOrStore: function(value) { | |
913 | return this[value] = this[value] || function() { | |
914 | return value.apply(null, [this].concat($A(arguments))); | |
915 | } | |
916 | } | |
917 | } | |
918 | ||
919 | Element.Methods = { | |
visible: function(element) { | ||
return $(element).style.display != 'none'; | ||
}, | ||
... | ... | |
setTimeout(function() {html.evalScripts()}, 10); | ||
}, | ||
955 | replace: function(element, html) { | |
956 | element = $(element); | |
957 | if (element.outerHTML) { | |
958 | element.outerHTML = html.stripScripts(); | |
959 | } else { | |
960 | var range = element.ownerDocument.createRange(); | |
961 | range.selectNodeContents(element); | |
962 | element.parentNode.replaceChild( | |
963 | range.createContextualFragment(html.stripScripts()), element); | |
964 | } | |
965 | setTimeout(function() {html.evalScripts()}, 10); | |
966 | }, | |
967 | ||
getHeight: function(element) { | ||
element = $(element); | ||
return element.offsetHeight; | ||
... | ... | |
return $(element).innerHTML.match(/^\s*$/); | ||
}, | ||
1006 | childOf: function(element, ancestor) { | |
1007 | element = $(element), ancestor = $(ancestor); | |
1008 | while (element = element.parentNode) | |
1009 | if (element == ancestor) return true; | |
1010 | return false; | |
1011 | }, | |
1012 | ||
scrollTo: function(element) { | ||
element = $(element); | ||
var x = element.x ? element.x : element.offsetLeft, | ||
... | ... | |
setStyle: function(element, style) { | ||
element = $(element); | ||
950 | | |
1040 | for (var name in style) | |
element.style[name.camelize()] = style[name]; | ||
}, | ||
... | ... | |
element.style.overflow = element._overflow; | ||
element._overflow = undefined; | ||
} | ||
1016 | ||
1106 | } | |
1108 | Object.extend(Element, Element.Methods); | |
1109 | ||
1110 | var _nativeExtensions = false; | |
1111 | ||
1112 | if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) { | |
1113 | var HTMLElement = {} | |
1114 | HTMLElement.prototype = document.createElement('div').__proto__; | |
1115 | } | |
1116 | ||
1117 | Element.addMethods = function(methods) { | |
1118 | Object.extend(Element.Methods, methods || {}); | |
1119 | ||
1120 | if(typeof HTMLElement != 'undefined') { | |
1121 | var methods = Element.Methods, cache = Element.extend.cache; | |
1122 | for (property in methods) { | |
1123 | var value = methods[property]; | |
1124 | if (typeof value == 'function') | |
1125 | HTMLElement.prototype[property] = cache.findOrStore(value); | |
1126 | } | |
1127 | _nativeExtensions = true; | |
1128 | } | |
1129 | } | |
1130 | ||
1131 | Element.addMethods(); | |
1132 | ||
var Toggle = new Object(); | ||
Toggle.display = Element.toggle; | ||
... | ... | |
try { | ||
this.element.insertAdjacentHTML(this.adjacency, this.content); | ||
} catch (e) { | ||
1036 | | |
1151 | var tagName = this.element.tagName.toLowerCase(); | |
1152 | if (tagName == 'tbody' || tagName == 'tr') { | |
this.insertContent(this.contentFromAnonymousTable()); | ||
} else { | ||
throw e; | ||
... | ... | |
} | ||
Object.extend(Element.ClassNames.prototype, Enumerable); | ||
1267 | var Selector = Class.create(); | |
1268 | Selector.prototype = { | |
1269 | initialize: function(expression) { | |
1270 | this.params = {classNames: []}; | |
1271 | this.expression = expression.toString().strip(); | |
1272 | this.parseExpression(); | |
1273 | this.compileMatcher(); | |
1274 | }, | |
1275 | ||
1276 | parseExpression: function() { | |
1277 | function abort(message) { throw 'Parse error in selector: ' + message; } | |
1278 | ||
1279 | if (this.expression == '') abort('empty expression'); | |
1280 | ||
1281 | var params = this.params, expr = this.expression, match, modifier, clause, rest; | |
1282 | while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) { | |
1283 | params.attributes = params.attributes || []; | |
1284 | params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''}); | |
1285 | expr = match[1]; | |
1286 | } | |
1287 | ||
1288 | if (expr == '*') return this.params.wildcard = true; | |
1289 | ||
1290 | while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) { | |
1291 | modifier = match[1], clause = match[2], rest = match[3]; | |
1292 | switch (modifier) { | |
1293 | case '#': params.id = clause; break; | |
1294 | case '.': params.classNames.push(clause); break; | |
1295 | case '': | |
1296 | case undefined: params.tagName = clause.toUpperCase(); break; | |
1297 | default: abort(expr.inspect()); | |
1298 | } | |
1299 | expr = rest; | |
1300 | } | |
1301 | ||
1302 | if (expr.length > 0) abort(expr.inspect()); | |
1303 | }, | |
1304 | ||
1305 | buildMatchExpression: function() { | |
1306 | var params = this.params, conditions = [], clause; | |
1307 | ||
1308 | if (params.wildcard) | |
1309 | conditions.push('true'); | |
1310 | if (clause = params.id) | |
1311 | conditions.push('element.id == ' + clause.inspect()); | |
1312 | if (clause = params.tagName) | |
1313 | conditions.push('element.tagName.toUpperCase() == ' + clause.inspect()); | |
1314 | if ((clause = params.classNames).length > 0) | |
1315 | for (var i = 0; i < clause.length; i++) | |
1316 | conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')'); | |
1317 | if (clause = params.attributes) { | |
1318 | clause.each(function(attribute) { | |
1319 | var value = 'element.getAttribute(' + attribute.name.inspect() + ')'; | |
1320 | var splitValueBy = function(delimiter) { | |
1321 | return value + ' && ' + value + '.split(' + delimiter.inspect() + ')'; | |
1322 | } | |
1323 | ||
1324 | switch (attribute.operator) { | |
1325 | case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break; | |
1326 | case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break; | |
1327 | case '|=': conditions.push( | |
1328 | splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect() | |
1329 | ); break; | |
1330 | case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break; | |
1331 | case '': | |
1332 | case undefined: conditions.push(value + ' != null'); break; | |
1333 | default: throw 'Unknown operator ' + attribute.operator + ' in selector'; | |
1334 | } | |
1335 | }); | |
1336 | } | |
1337 | ||
1338 | return conditions.join(' && '); | |
1339 | }, | |
1340 | ||
1341 | compileMatcher: function() { | |
1342 | this.match = new Function('element', 'if (!element.tagName) return false; \ | |
1343 | return ' + this.buildMatchExpression()); | |
1344 | }, | |
1345 | ||
1346 | findElements: function(scope) { | |
1347 | var element; | |
1348 | ||
1349 | if (element = $(this.params.id)) | |
1350 | if (this.match(element)) | |
1351 | if (!scope || Element.childOf(element, scope)) | |
1352 | return [element]; | |
1353 | ||
1354 | scope = (scope || document).getElementsByTagName(this.params.tagName || '*'); | |
1355 | ||
1356 | var results = []; | |
1357 | for (var i = 0; i < scope.length; i++) | |
1358 | if (this.match(element = scope[i])) | |
1359 | results.push(Element.extend(element)); | |
1360 | ||
1361 | return results; | |
1362 | }, | |
1363 | ||
1364 | toString: function() { | |
1365 | return this.expression; | |
1366 | } | |
1367 | } | |
1368 | ||
1369 | function $$() { | |
1370 | return $A(arguments).map(function(expression) { | |
1371 | return expression.strip().split(/\s+/).inject([null], function(results, expr) { | |
1372 | var selector = new Selector(expr); | |
1373 | return results.map(selector.findElements.bind(selector)).flatten(); | |
1374 | }); | |
1375 | }).flatten(); | |
1376 | } | |
var Field = { | ||
clear: function() { | ||
for (var i = 0; i < arguments.length; i++) | ||
... | ... | |
form = $(form); | ||
var elements = new Array(); | ||
1199 | | |
1425 | for (var tagName in Form.Element.Serializers) { | |
var tagElements = form.getElementsByTagName(tagName); | ||
for (var j = 0; j < tagElements.length; j++) | ||
elements.push(tagElements[j]); | ||
... | ... | |
var value = '', opt, index = element.selectedIndex; | ||
if (index >= 0) { | ||
opt = element.options[index]; | ||
1321 | | |
1322 | | |
1323 | | |
1547 | value = opt.value || opt.text; | |
} | ||
return [element.name, value]; | ||
}, | ||
selectMany: function(element) { | ||
1329 | | |
1553 | var value = []; | |
for (var i = 0; i < element.length; i++) { | ||
var opt = element.options[i]; | ||
1332 | | |
1333 | | |
1334 | | |
1335 | | |
1336 | | |
1337 | | |
1556 | if (opt.selected) | |
1557 | value.push(opt.value || opt.text); | |
} | ||
return [element.name, value]; | ||
} | ||
... | ... | |
}); | ||
/* prevent memory leaks in IE */ | ||
1554 | ||
1774 | if (navigator.appVersion.match(/\bMSIE\b/)) | |
1775 | Event.observe(window, 'unload', Event.unloadCache, false); | |
var Position = { | ||
// set to true if needed, warning: firefox performance problems | ||
// NOT neeeded for page scrolling, only if draggable contained in |
rool/rails/typo/trunk/vendor/rails/railties/lib/code_statistics.rb:
prev. | current | |
class CodeStatistics #:nodoc: | ||
3 | | |
3 | TEST_TYPES = %w(Units Functionals Unit\ tests Functional\ tests Integration\ tests) | |
def initialize(*pairs) | ||
@pairs = pairs |
rool/rails/typo/trunk/vendor/rails/railties/lib/commands/console.rb:
prev. | current | |
libs = " -r irb/completion" | ||
libs << " -r #{RAILS_ROOT}/config/environment" | ||
14 | libs << " -r console_app" | |
libs << " -r console_sandbox" if options[:sandbox] | ||
16 | libs << " -r console_with_helpers" | |
16 | ||
18 | ENV['RAILS_ENV'] = ARGV.first || ENV['RAILS_ENV'] || 'development' | |
if options[:sandbox] | ||
puts "Loading #{ENV['RAILS_ENV']} environment in sandbox." | ||
puts "Any modifications you make will be rolled back on exit." | ||
else | ||
puts "Loading #{ENV['RAILS_ENV']} environment." | ||
end | ||
23 | ||
25 | exec "#{options[:irb]} #{libs} --simple-prompt" |
rool/rails/typo/trunk/vendor/rails/railties/lib/commands/plugin.rb:
prev. | current | |
# look like subversion repositories with plugins: | ||
# http://wiki.rubyonrails.org/rails/pages/Plugins | ||
# | ||
34 | # * Unless you specify that you want to use svn, script/plugin uses plain old | |
35 | # HTTP for downloads. The following bullets are true if you specify | |
36 | # that you want to use svn. | |
37 | # | |
# * If `vendor/plugins` is under subversion control, the script will | ||
# modify the svn:externals property and perform an update. You can | ||
36 | ||
37 | ||
40 | # use normal subversion commands to keep the plugins up to date. | |
# | ||
# * Or, if `vendor/plugins` is not under subversion control, the | ||
# plugin is pulled via `svn checkout` or `svn export` but looks | ||
... | ... | |
def initialize(dir) | ||
@root = dir | ||
end | ||
61 | | |
64 | ||
def self.find(dir=nil) | ||
dir ||= pwd | ||
while dir.length > 1 | ||
... | ... | |
end | ||
def use_svn? | ||
96 | | |
99 | require 'active_support/core_ext/kernel' | |
100 | silence_stderr {`svn --version` rescue nil} | |
!$?.nil? && $?.success? | ||
end | ||
def use_externals? | ||
101 | | |
105 | use_svn? && File.directory?("#{root}/vendor/plugins/.svn") | |
end | ||
103 | | |
107 | ||
def use_checkout? | ||
# this is a bit of a guess. we assume that if the rails environment | ||
106 | | |
110 | # is under subversion then they probably want the plugin checked out | |
# instead of exported. This can be overridden on the command line | ||
File.directory?("#{root}/.svn") | ||
end | ||
110 | | |
114 | ||
def best_install_method | ||
return :http unless use_svn? | ||
case | ||
... | ... | |
def externals | ||
return [] unless use_externals? | ||
122 | | |
126 | ext = `svn propget svn:externals "#{root}/vendor/plugins"` | |
ext.reject{ |line| line.strip == '' }.map do |line| | ||
line.strip.split(/\s+/, 2) | ||
end | ||
end | ||
127 | | |
131 | ||
def externals=(items) | ||
unless items.is_a? String | ||
items = items.map{|name,uri| "#{name.ljust(29)} #{uri.chomp('/')}"}.join("\n") | ||
... | ... | |
Tempfile.open("svn-set-prop") do |file| | ||
file.write(items) | ||
file.flush | ||
135 | | |
139 | system("svn propset -q svn:externals -F #{file.path} \"#{root}/vendor/plugins\"") | |
end | ||
end | ||
... | ... | |
or rails_env.externals.detect{ |name, repo| self.uri == repo } | ||
end | ||
158 | | |
162 | def install(method=nil, options = {}) | |
method ||= rails_env.best_install_method? | ||
164 | method = :export if method == :http and @uri =~ /svn:\/\/*/ | |
165 | ||
166 | uninstall if installed? and options[:force] | |
167 | ||
unless installed? | ||
161 | | |
169 | send("install_using_#{method}", options) | |
170 | run_install_hook | |
else | ||
163 | | |
172 | puts "already installed: #{name} (#{uri}). pass --force to reinstall" | |
end | ||
end | ||
166 | | |
175 | ||
176 | def uninstall | |
177 | path = "#{rails_env.root}/vendor/plugins/#{name}" | |
178 | if File.directory?(path) | |
179 | puts "Removing 'vendor/plugins/#{name}'" if $verbose | |
180 | rm_r path | |
181 | else | |
182 | puts "Plugin doesn't exist: #{path}" | |
183 | end | |
184 | # clean up svn:externals | |
185 | externals = rails_env.externals | |
186 | externals.reject!{|n,u| name == n or name == u} | |
187 | rails_env.externals = externals | |
188 | end | |
189 | ||
private | ||
168 | | |
169 | | |
170 | | |
171 | | |
191 | ||
192 | def run_install_hook | |
193 | install_hook_file = "#{rails_env.root}/vendor/plugins/#{name}/install.rb" | |
194 | load install_hook_file if File.exists? install_hook_file | |
end | ||
196 | ||
197 | def install_using_export(options = {}) | |
198 | svn_command :export, options | |
199 | end | |
174 | | |
175 | | |
176 | | |
177 | | |
201 | def install_using_checkout(options = {}) | |
202 | svn_command :checkout, options | |
end | ||
180 | | |
205 | def install_using_externals(options = {}) | |
externals = rails_env.externals | ||
externals.push([@name, uri]) | ||
rails_env.externals = externals | ||
184 | | |
209 | install_using_checkout(options) | |
end | ||
187 | | |
212 | def install_using_http(options = {}) | |
root = rails_env.root | ||
mkdir_p "#{root}/vendor/plugins" | ||
Dir.chdir "#{root}/vendor/plugins" | ||
191 | | |
216 | puts "fetching from '#{uri}'" if $verbose | |
217 | fetcher = RecursiveHTTPFetcher.new(uri) | |
218 | fetcher.quiet = true if options[:quiet] | |
219 | fetcher.fetch | |
end | ||
222 | def svn_command(cmd, options = {}) | |
223 | root = rails_env.root | |
224 | mkdir_p "#{root}/vendor/plugins" | |
225 | base_cmd = "svn #{cmd} #{uri} \"#{root}/vendor/plugins/#{name}\"" | |
226 | base_cmd += ' -q' if options[:quiet] and not $verbose | |
227 | base_cmd += " -r #{options[:revision]}" if options[:revision] | |
228 | puts base_cmd if $verbose | |
229 | system(base_cmd) | |
230 | end | |
231 | ||
def guess_name(url) | ||
@name = File.basename(url) | ||
if @name == 'trunk' || @name.empty? | ||
... | ... | |
return plugin if plugin.name == name | ||
end | ||
end | ||
242 | | |
return nil | ||
end | ||
... | ... | |
attr_reader :uri, :plugins | ||
def initialize(uri) | ||
301 | | |
302 | | |
338 | @uri = uri.chomp('/') << "/" | |
@plugins = nil | ||
end | ||
... | ... | |
puts index | ||
end | ||
313 | | |
349 | @plugins = index.reject{ |line| line !~ /\/$/ } | |
@plugins.map! { |name| Plugin.new(File.join(@uri, name), name) } | ||
end | ||
... | ... | |
private | ||
def index | ||
326 | | |
362 | @index ||= RecursiveHTTPFetcher.new(@uri).ls | |
end | ||
end | ||
... | ... | |
command.parse!(sub) | ||
else | ||
puts "Unknown command: #{command}" | ||
414 | | |
450 | puts options | |
exit 1 | ||
end | ||
end | ||
... | ... | |
@sources = [] | ||
@local = false | ||
@remote = true | ||
438 | | |
end | ||
def options | ||
... | ... | |
o.on( "--remote", | ||
"List remotely availabled plugins. This is the default behavior", | ||
"unless --local is provided.") {|@remote|} | ||
456 | | |
457 | | |
end | ||
end | ||
... | ... | |
@sources.map{|r| r.plugins}.flatten.each do |plugin| | ||
if @local or !plugin.installed? | ||
puts plugin.to_s | ||
472 | | |
end | ||
end | ||
else | ||
cd "#{@base_command.environment.root}/vendor/plugins" | ||
Dir["*"].select{|p| File.directory?(p)}.each do |name| | ||
puts name | ||
479 | | |
end | ||
end | ||
end | ||
... | ... | |
puts "Scraping #{uri}" if $verbose | ||
dupes = [] | ||
content = open(uri).each do |line| | ||
628 | | |
659 | if line =~ /<a[^>]*href=['"]([^'"]*)['"]/ or line =~ /(svn:\/\/[^<|\n]*)/ | |
uri = $1 | ||
if uri =~ /\/plugins\// and uri !~ /\/browser\// | ||
uri = extract_repository_uri(uri) | ||
... | ... | |
class Install | ||
def initialize(base_command) | ||
@base_command = base_command | ||
647 | | |
678 | @method = :http | |
679 | @options = { :quiet => false, :revision => nil, :force => false } | |
end | ||
def options | ||
... | ... | |
o.on( "-o", "--checkout", | ||
"Use svn checkout to grab the plugin.", | ||
"Enables updating but does not add a svn:externals entry.") { |v| @method = :checkout } | ||
695 | o.on( "-q", "--quiet", | |
696 | "Suppresses the output from installation.", | |
697 | "Ignored if -v is passed (./script/plugin -v install ...)") { |v| @options[:quiet] = true } | |
698 | o.on( "-r REVISION", "--revision REVISION", | |
699 | "Checks out the given revision from subversion.", | |
700 | "Ignored if subversion is not used.") { |v| @options[:revision] = v } | |
701 | o.on( "-f", "--force", | |
702 | "Reinstalls a plugin if it's already installed.") { |v| @options[:force] = true } | |
o.separator "" | ||
o.separator "You can specify plugin names as given in 'plugin list' output or absolute URLs to " | ||
o.separator "a plugin repository." | ||
... | ... | |
case | ||
when (best == :http and @method != :http) | ||
msg = "Cannot install using subversion because `svn' cannot be found in your PATH" | ||
675 | | |
676 | | |
715 | when (best == :export and (@method != :export and @method != :http)) | |
716 | msg = "Cannot install using #{@method} because this project is not under subversion." | |
when (best != :externals and @method == :externals) | ||
msg = "Cannot install using externals because vendor/plugins is not under subversion." | ||
end | ||
... | ... | |
puts "Plugins will be installed using #{install_method}" if $verbose | ||
args.each do |name| | ||
if name =~ /\// then | ||
694 | | |
734 | ::Plugin.new(name).install(install_method, @options) | |
else | ||
plugin = Repositories.instance.find_plugin(name) | ||
unless plugin.nil? | ||
698 | | |
738 | plugin.install(install_method, @options) | |
else | ||
puts "Plugin not found: #{name}" | ||
exit 1 | ||
... | ... | |
end | ||
end | ||
708 | ||
709 | | |
748 | class Update | |
def initialize(base_command) | ||
@base_command = base_command | ||
end | ||
713 | | |
752 | ||
def options | ||
OptionParser.new do |o| | ||
o.set_summary_indent(' ') | ||
717 | | |
718 | | |
756 | o.banner = "Usage: #{@base_command.script_name} update [name [name]...]" | |
757 | o.on( "-r REVISION", "--revision REVISION", | |
758 | "Checks out the given revision from subversion.", | |
759 | "Ignored if subversion is not used.") { |v| @revision = v } | |
760 | o.define_head "Update plugins." | |
end | ||
end | ||
721 | | |
763 | ||
def parse!(args) | ||
options.parse!(args) | ||
root = @base_command.environment.root | ||
767 | cd root | |
768 | args = Dir["vendor/plugins/*"].map do |f| | |
769 | File.directory?("#{f}/.svn") ? File.basename(f) : nil | |
770 | end.compact if args.empty? | |
771 | cd "vendor/plugins" | |
args.each do |name| | ||
726 | | |
727 | | |
728 | | |
773 | if File.directory?(name) | |
774 | puts "Updating plugin: #{name}" | |
775 | system("svn #{$verbose ? '' : '-q'} up \"#{name}\" #{@revision ? "-r #{@revision}" : ''}") | |
else | ||
730 | | |
777 | puts "Plugin doesn't exist: #{name}" | |
end | ||
732 | | |
733 | | |
734 | | |
735 | | |
end | ||
end | ||
end | ||
740 | | |
783 | class Remove | |
def initialize(base_command) | ||
@base_command = base_command | ||
end | ||
... | ... | |
def options | ||
OptionParser.new do |o| | ||
o.set_summary_indent(' ') | ||
748 | | |
749 | | |
791 | o.banner = "Usage: #{@base_command.script_name} remove name [name]..." | |
792 | o.define_head "Remove plugins." | |
end | ||
end | ||
def parse!(args) | ||
options.parse!(args) | ||
root = @base_command.environment.root | ||
756 | | |
757 | | |
758 | | |
759 | | |
args.each do |name| | ||
761 | | |
762 | | |
763 | | |
764 | | |
765 | | |
766 | | |
800 | ::Plugin.new(name).uninstall | |
end | ||
end | ||
end | ||
... | ... | |
end | ||
class RecursiveHTTPFetcher | ||
808 | attr_accessor :quiet | |
def initialize(urls_to_fetch, cwd = ".") | ||
@cwd = cwd | ||
@urls_to_fetch = urls_to_fetch.to_a | ||
812 | @quiet = false | |
end | ||
815 | def ls | |
816 | @urls_to_fetch.collect do |url| | |
817 | if url =~ /^svn:\/\/.*/ | |
818 | `svn ls #{url}`.split("\n").map {|entry| "/#{entry}"} rescue nil | |
819 | else | |
820 | open(url) do |stream| | |
821 | links("", stream.read) | |
822 | end rescue nil | |
823 | end | |
824 | end.flatten | |
825 | end | |
826 | ||
def push_d(dir) | ||
@cwd = File.join(@cwd, dir) | ||
FileUtils.mkdir_p(@cwd) | ||
... | ... | |
end | ||
def download(link) | ||
799 | | |
847 | puts "+ #{File.join(@cwd, File.basename(link))}" unless @quiet | |
open(link) do |stream| | ||
File.open(File.join(@cwd, File.basename(link)), "wb") do |file| | ||
file.write(stream.read) |
rool/rails/typo/trunk/vendor/rails/railties/lib/commands/process/reaper.rb:
prev. | current | |
opts.parse! | ||
end | ||
130 | ||
130 | ProgramProcess.process_keywords(OPTIONS[:action], OPTIONS[:dispatcher]) | |
rool/rails/typo/trunk/vendor/rails/railties/lib/commands/process/spawner.rb:
prev. | current | |
require 'optparse' | ||
2 | require 'socket' | |
4 | def daemonize #:nodoc: | |
5 | exit if fork # Parent exits, child continues. | |
6 | Process.setsid # Become session leader. | |
7 | exit if fork # Zap session leader. See [1]. | |
8 | Dir.chdir "/" # Release old working directory. | |
9 | File.umask 0000 # Ensure sensible umask. Adjust as needed. | |
10 | STDIN.reopen "/dev/null" # Free file descriptors and | |
11 | STDOUT.reopen "/dev/null", "a" # point them somewhere sensible. | |
12 | STDERR.reopen STDOUT # STDOUT/ERR should better go to a logfile. | |
13 | end | |
14 | ||
def spawn(port) | ||
4 | | |
5 | | |
16 | print "Checking if something is already running on port #{port}..." | |
17 | begin | |
18 | srv = TCPServer.new('0.0.0.0', port) | |
19 | srv.close | |
20 | srv = nil | |
21 | print "NO\n " | |
22 | print "Starting FCGI on port: #{port}\n " | |
23 | system("#{OPTIONS[:spawner]} -f #{OPTIONS[:dispatcher]} -p #{port}") | |
24 | rescue | |
25 | print "YES\n" | |
26 | end | |
end | ||
28 | ||
29 | def spawn_all | |
30 | OPTIONS[:instances].times { |i| spawn(OPTIONS[:port] + i) } | |
31 | end | |
OPTIONS = { | ||
:environment => "production", | ||
:spawner => '/usr/bin/env spawn-fcgi', | ||
:dispatcher => File.expand_path(RAILS_ROOT + '/public/dispatch.fcgi'), | ||
:port => 8000, | ||
13 | | |
38 | :instances => 3, | |
39 | :repeat => nil | |
} | ||
ARGV.options do |opts| | ||
... | ... | |
You decide a starting port (default is 8000) and the number of FCGI process instances you'd | ||
like to run. So if you pick 9100 and 3 instances, you'll start processes on 9100, 9101, and 9102. | ||
57 | By setting the repeat option, you get a protection loop, which will attempt to restart any FCGI processes | |
58 | that might have been exited or outright crashed. | |
59 | ||
Examples: | ||
spawner # starts instances on 8000, 8001, and 8002 | ||
spawner -p 9100 -i 10 # starts 10 instances counting from 9100 to 9109 | ||
63 | spawner -p 9100 -r 5 # starts 3 instances counting from 9100 to 9102 and attempts start them every 5 seconds | |
EOF | ||
opts.on(" Options:") | ||
38 | | |
39 | | |
40 | | |
41 | | |
42 | | |
68 | opts.on("-p", "--port=number", Integer, "Starting port number (default: #{OPTIONS[:port]})") { |OPTIONS[:port]| } | |
69 | opts.on("-i", "--instances=number", Integer, "Number of instances (default: #{OPTIONS[:instances]})") { |OPTIONS[:instances]| } | |
70 | opts.on("-r", "--repeat=seconds", Integer, "Repeat spawn attempts every n seconds (default: off)") { |OPTIONS[:repeat]| } | |
71 | opts.on("-e", "--environment=name", String, "test|development|production (default: #{OPTIONS[:environment]})") { |OPTIONS[:environment]| } | |
72 | opts.on("-s", "--spawner=path", String, "default: #{OPTIONS[:spawner]}") { |OPTIONS[:spawner]| } | |
73 | opts.on("-d", "--dispatcher=path", String, "default: #{OPTIONS[:dispatcher]}") { |dispatcher| OPTIONS[:dispatcher] = File.expand_path(dispatcher) } | |
opts.separator "" | ||
... | ... | |
end | ||
ENV["RAILS_ENV"] = OPTIONS[:environment] | ||
52 | ||
84 | ||
85 | if OPTIONS[:repeat] | |
86 | daemonize | |
87 | trap("TERM") { exit } | |
88 | ||
89 | loop do | |
90 | spawn_all | |
91 | sleep(OPTIONS[:repeat]) | |
92 | end | |
93 | else | |
94 | spawn_all | |
95 | end |
rool/rails/typo/trunk/vendor/rails/railties/lib/commands/runner.rb:
prev. | current | |
RAILS_ENV.replace(options[:environment]) if defined?(RAILS_ENV) | ||
require RAILS_ROOT + '/config/environment' | ||
27 | ||
27 | ARGV.empty? ? puts("Usage: runner 'code' [options]") : eval(ARGV.first) |
rool/rails/typo/trunk/vendor/rails/railties/lib/commands/server.rb:
prev. | current | |
require 'active_support' | ||
2 | require 'fileutils' | |
begin | ||
require_library_or_gem 'fcgi' | ||
... | ... | |
puts "=> Booting lighttpd (use 'script/server webrick' to force WEBrick)" | ||
end | ||
28 | ||
30 | FileUtils.mkdir_p(%w( tmp/sessions tmp/cache tmp/sockets )) | |
31 | require "commands/servers/#{server}" |
rool/rails/typo/trunk/vendor/rails/railties/lib/commands/servers/lighttpd.rb:
prev. | current | |
1 | require 'rbconfig' | |
2 | ||
unless RUBY_PLATFORM !~ /mswin/ && !silence_stderr { `lighttpd -version` }.blank? | ||
puts "PROBLEM: Lighttpd is not available on your system (or not in your path)" | ||
exit 1 | ||
... | ... | |
require 'initializer' | ||
configuration = Rails::Initializer.run(:initialize_logger).configuration | ||
15 | default_config_file = config_file = Pathname.new("#{RAILS_ROOT}/config/lighttpd.conf").cleanpath | |
14 | ||
17 | require 'optparse' | |
19 | detach = false | |
20 | ||
21 | ARGV.options do |opt| | |
22 | opt.on('-c', "--config=#{config_file}", 'Specify a different lighttpd config file.') { |path| config_file = path } | |
23 | opt.on('-h', '--help', 'Show this message.') { puts opt; exit 0 } | |
24 | opt.on('-d', '-d', 'Call with -d to detach') { detach = true; puts "=> Configuration in config/lighttpd.conf" } | |
25 | opt.parse! | |
26 | end | |
27 | ||
unless File.exist?(config_file) | ||
29 | if config_file != default_config_file | |
30 | puts "=> #{config_file} not found." | |
31 | exit 1 | |
32 | end | |
33 | ||
require 'fileutils' | ||
35 | ||
source = File.expand_path(File.join(File.dirname(__FILE__), | ||
"..", "..", "..", "configs", "lighttpd.conf")) | ||
puts "=> #{config_file} not found, copying from #{source}" | ||
21 | | |
39 | ||
40 | FileUtils.cp(source, config_file) | |
end | ||
config = IO.read(config_file) | ||
... | ... | |
tail_thread = nil | ||
32 | ||
33 | | |
34 | | |
35 | ||
36 | | |
51 | if !detach | |
52 | puts "=> Call with -d to detach" | |
puts "=> Ctrl-C to shutdown server (see config/lighttpd.conf for options)" | ||
detach = false | ||
... | ... | |
end | ||
trap(:INT) { exit } | ||
59 | ||
60 | ||
75 | ||
76 | begin | |
77 | `rake tmp:sockets:clear` # Needed if lighttpd crashes or otherwise leaves FCGI sockets around | |
78 | `lighttpd #{!detach ? "-D " : ""}-f #{config_file}` | |
79 | ensure | |
80 | unless detach | |
81 | tail_thread.kill if tail_thread | |
82 | puts 'Exiting' | |
83 | ||
84 | # Ensure FCGI processes are reaped | |
85 | silence_stream(STDOUT) do | |
86 | ARGV.replace ['-a', 'kill'] | |
87 | require 'commands/process/reaper' | |
88 | end | |
89 | ||
90 | `rake tmp:sockets:clear` # Remove sockets on clean shutdown | |
91 | end | |
92 | end |
rool/rails/typo/trunk/vendor/rails/railties/lib/dispatcher.rb:
prev. | current | |
ActionController::Routing::Routes.recognize!(request).process(request, response).out(output) | ||
end | ||
rescue Object => exception | ||
41 | | |
41 | failsafe_response(output, '500 Internal Server Error', exception) do | |
ActionController::Base.process_with_exception(request, response, exception).out(output) | ||
end | ||
ensure | ||
... | ... | |
# mailers, and so forth. This allows them to be loaded again without having | ||
# to restart the server (WEBrick, FastCGI, etc.). | ||
def reset_application! | ||
53 | | |
Dependencies.clear | ||
ActiveRecord::Base.reset_subclasses | ||
56 | | |
57 | | |
55 | Class.remove_class(*Reloadable.reloadable_classes) | |
end | ||
private | ||
... | ... | |
def prepare_application | ||
ActionController::Routing::Routes.reload if Dependencies.load? | ||
prepare_breakpoint | ||
71 | | |
69 | require_dependency('application.rb') unless Object.const_defined?(:ApplicationController) | |
70 | ActiveRecord::Base.verify_active_connections! | |
end | ||
73 | | |
72 | ||
def reset_after_dispatch | ||
reset_application! if Dependencies.load? | ||
76 | | |
Breakpoint.deactivate_drb if defined?(BREAKPOINT_SERVER_PORT) | ||
end | ||
... | ... | |
end | ||
# If the block raises, send status code as a last-ditch response. | ||
90 | | |
88 | def failsafe_response(output, status, exception = nil) | |
yield | ||
rescue Object | ||
begin | ||
output.write "Status: #{status}\r\n" | ||
93 | ||
94 | if exception | |
95 | message = exception.to_s + "\r\n" + exception.backtrace.join("\r\n") | |
96 | error_path = File.join(RAILS_ROOT, 'public', '500.html') | |
97 | ||
98 | if defined?(RAILS_DEFAULT_LOGGER) && !RAILS_DEFAULT_LOGGER.nil? | |
99 | RAILS_DEFAULT_LOGGER.fatal(message) | |
100 | ||
101 | output.write "Content-Type: text/html\r\n\r\n" | |
102 | ||
103 | if File.exists?(error_path) | |
104 | output.write(IO.read(error_path)) | |
105 | else | |
106 | output.write("<html><body><h1>Application error (Rails)</h1></body></html>") | |
107 | end | |
108 | else | |
109 | output.write "Content-Type: text/plain\r\n\r\n" | |
110 | output.write(message) | |
111 | end | |
112 | end | |
rescue Object | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/railties/lib/fcgi_handler.rb:
prev. | current | |
class RailsFCGIHandler | ||
SIGNALS = { | ||
8 | | |
9 | | |
10 | | |
11 | | |
8 | 'HUP' => :reload, | |
9 | 'TERM' => :exit_now, | |
10 | 'USR1' => :exit, | |
11 | 'USR2' => :restart, | |
12 | 'SIGTRAP' => :breakpoint | |
} | ||
attr_reader :when_ready | ||
... | ... | |
when :exit | ||
close_connection(cgi) | ||
break | ||
65 | when :breakpoint | |
66 | close_connection(cgi) | |
67 | breakpoint! | |
end | ||
gc_countdown | ||
... | ... | |
@when_ready = :restart | ||
end | ||
144 | def breakpoint_handler(signal) | |
145 | dispatcher_log :info, "asked to breakpoint ASAP" | |
146 | @when_ready = :breakpoint | |
147 | end | |
148 | ||
def process_request(cgi) | ||
Dispatcher.dispatch(cgi) | ||
rescue Object => e | ||
... | ... | |
Dispatcher.reset_application! | ||
ActionController::Routing::Routes.reload | ||
end | ||
182 | ||
183 | def breakpoint! | |
184 | require 'breakpoint' | |
185 | port = defined?(BREAKPOINT_SERVER_PORT) ? BREAKPOINT_SERVER_PORT : 42531 | |
186 | Breakpoint.activate_drb("druby://localhost:#{port}", nil, !defined?(FastCGI)) | |
187 | dispatcher_log :info, "breakpointing" | |
188 | breakpoint | |
189 | @when_ready = nil | |
190 | end | |
def run_gc! | ||
@gc_request_countdown = gc_request_period |
rool/rails/typo/trunk/vendor/rails/railties/lib/initializer.rb:
prev. | current | |
# * #initialize_logger | ||
# * #initialize_framework_logging | ||
# * #initialize_framework_views | ||
64 | | |
# * #initialize_dependency_mechanism | ||
# * #initialize_breakpoints | ||
# * #initialize_whiny_nils | ||
# * #initialize_framework_settings | ||
# * #load_environment | ||
# * #load_plugins | ||
70 | # * #initialize_routing | |
# | ||
# (Note that #load_environment is invoked twice, once at the start and | ||
# once at the end, to support the legacy configuration style where the | ||
# environment could overwrite the defaults directly, instead of via the | ||
# Configuration instance. | ||
def process | ||
77 | check_ruby_version | |
set_load_path | ||
set_connection_adapters | ||
... | ... | |
initialize_dependency_mechanism | ||
initialize_breakpoints | ||
initialize_whiny_nils | ||
90 | | |
91 | initialize_temporary_directories | |
92 | ||
initialize_framework_settings | ||
# Support for legacy configuration style where the environment | ||
... | ... | |
# the individual base class configurations. | ||
load_environment | ||
98 | | |
100 | add_support_load_paths | |
load_plugins | ||
# Routing must be initialized after plugins to allow the former to extend the routes | ||
initialize_routing | ||
106 | ||
107 | # the framework is now fully initialized | |
108 | after_initialize | |
end | ||
105 | | |
110 | ||
111 | # Check for valid Ruby version | |
112 | # This is done in an external file, so we can use it | |
113 | # from the `rails` program as well without duplication. | |
114 | def check_ruby_version | |
115 | require 'ruby_version_check' | |
116 | end | |
117 | ||
# Set the <tt>$LOAD_PATH</tt> based on the value of | ||
# Configuration#load_paths. Duplicates are removed. | ||
def set_load_path | ||
... | ... | |
configuration.frameworks.each { |framework| require(framework.to_s) } | ||
end | ||
128 | | |
129 | | |
130 | | |
131 | | |
140 | # Add the load paths used by support functions such as the info controller | |
141 | def add_support_load_paths | |
142 | builtins = File.join(File.dirname(File.dirname(__FILE__)), 'builtin', '*') | |
143 | $LOAD_PATH.concat(Dir[builtins]) | |
end | ||
# Loads all plugins in <tt>config.plugin_paths</tt>. <tt>plugin_paths</tt> | ||
... | ... | |
# * evaluate <tt>init.rb</tt> if present | ||
# | ||
# After all plugins are loaded, duplicates are removed from the load path. | ||
156 | # Plugins are loaded in alphabetical order. | |
def load_plugins | ||
145 | | |
158 | find_plugins(configuration.plugin_paths).sort.each { |path| load_plugin path } | |
$LOAD_PATH.uniq! | ||
end | ||
... | ... | |
def initialize_routing | ||
return unless configuration.frameworks.include?(:action_controller) | ||
ActionController::Routing::Routes.reload | ||
227 | | |
end | ||
# Sets the dependency loading mechanism based on the value of | ||
... | ... | |
require('active_support/whiny_nil') if configuration.whiny_nils | ||
end | ||
248 | | |
260 | def initialize_temporary_directories | |
261 | if configuration.frameworks.include?(:action_controller) | |
262 | session_path = "#{RAILS_ROOT}/tmp/sessions/" | |
263 | ActionController::Base.session_options[:tmpdir] = File.exist?(session_path) ? session_path : Dir::tmpdir | |
264 | ||
265 | cache_path = "#{RAILS_ROOT}/tmp/cache/" | |
266 | if File.exist?(cache_path) | |
267 | ActionController::Base.fragment_cache_store = :file_store, cache_path | |
268 | end | |
269 | end | |
270 | end | |
271 | ||
272 | # Initializes framework-specific settings for each of the loaded frameworks | |
# (Configuration#frameworks). The available settings map to the accessors | ||
# on each of the corresponding Base classes. | ||
def initialize_framework_settings | ||
... | ... | |
end | ||
end | ||
end | ||
284 | ||
285 | # Fires the user-supplied after_initialize block (Configuration#after_initialize) | |
286 | def after_initialize | |
287 | configuration.after_initialize_block.call if configuration.after_initialize_block | |
288 | end | |
289 | ||
protected | ||
# Return a list of plugin paths within base_path. A plugin path is | ||
# a directory that contains either a lib directory or an init.rb file. | ||
# This recurses into directories which are not plugin paths, so you | ||
265 | | |
295 | # may organize your plugins within the plugin path. | |
def find_plugins(*base_paths) | ||
base_paths.flatten.inject([]) do |plugins, base_path| | ||
Dir.glob(File.join(base_path, '*')).each do |path| | ||
... | ... | |
has_lib = File.directory?(lib_path) | ||
has_init = File.file?(init_path) | ||
304 | | |
305 | | |
306 | | |
334 | # Add lib to load path *after* the application lib, to allow | |
335 | # application libraries to override plugin libraries. | |
336 | if has_lib | |
337 | application_lib_index = $LOAD_PATH.index(File.join(RAILS_ROOT, "lib")) || 0 | |
338 | $LOAD_PATH.insert(application_lib_index + 1, lib_path) | |
339 | end | |
340 | ||
# Allow plugins to reference the current configuration object | ||
config = configuration | ||
343 | ||
344 | # Add to set of loaded plugins before 'name' collapsed in eval. | |
345 | loaded_plugins << name | |
# Evaluate init.rb. | ||
silence_warnings { eval(IO.read(init_path), binding, init_path) } if has_init | ||
313 | | |
314 | | |
true | ||
end | ||
end | ||
... | ... | |
def environment | ||
::RAILS_ENV | ||
end | ||
438 | ||
473 | ||
474 | # Sets a block which will be executed after rails has been fully initialized. | |
475 | # Useful for per-environment configuration which depends on the framework being | |
476 | # fully initialized. | |
477 | def after_initialize(&after_initialize_block) | |
478 | @after_initialize_block = after_initialize_block | |
479 | end | |
480 | ||
481 | # Returns the block set in Configuration#after_initialize | |
482 | def after_initialize_block | |
483 | @after_initialize_block | |
484 | end | |
485 | ||
private | ||
def root_path | ||
::RAILS_ROOT | ||
end | ||
491 | def framework_root_path | |
492 | defined?(::RAILS_FRAMEWORK_ROOT) ? ::RAILS_FRAMEWORK_ROOT : "#{root_path}/vendor/rails" | |
493 | end | |
494 | ||
def default_frameworks | ||
[ :active_record, :action_controller, :action_view, :action_mailer, :action_web_service ] | ||
end | ||
def default_load_paths | ||
paths = ["#{root_path}/test/mocks/#{environment}"] | ||
501 | ||
502 | # Add the app's controller directory | |
503 | paths.concat(Dir["#{root_path}/app/controllers/"]) | |
# Then model subdirectories. | ||
# TODO: Don't include .rb models as load paths | ||
... | ... | |
paths.concat(Dir["#{root_path}/components/[_a-z]*"]) | ||
# Followed by the standard includes. | ||
457 | | |
paths.concat %w( | ||
app | ||
app/models | ||
... | ... | |
config | ||
lib | ||
vendor | ||
469 | | |
470 | | |
471 | | |
472 | | |
473 | | |
474 | | |
475 | | |
).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) } | ||
523 | ||
524 | # TODO: Don't include dirs for frameworks that are not used | |
525 | paths.concat %w( | |
526 | railties | |
527 | railties/lib | |
528 | actionpack/lib | |
529 | activesupport/lib | |
530 | activerecord/lib | |
531 | actionmailer/lib | |
532 | actionwebservice/lib | |
533 | ).map { |dir| "#{framework_root_path}/#{dir}" }.select { |dir| File.directory?(dir) } | |
end | ||
def default_log_path | ||
... | ... | |
# Needs to be duplicated from Active Support since its needed before Active | ||
# Support is available. | ||
523 | ||
524 | | |
525 | | |
526 | ||
580 | class OrderedHash < Array #:nodoc: | |
581 | def []=(key, value) | |
if pair = find_pair(key) | ||
pair.pop | ||
pair << value | ||
... | ... | |
self << [key, value] | ||
end | ||
end | ||
534 | ||
589 | ||
def [](key) | ||
536 | | |
591 | pair = find_pair(key) | |
pair ? pair.last : nil | ||
end | ||
540 | | |
541 | | |
542 | | |
543 | | |
544 | | |
545 | | |
595 | def keys | |
596 | self.collect { |i| i.first } | |
end | ||
private | ||
... | ... | |
return false | ||
end | ||
end | ||
605 | ||
606 | class OrderedOptions < OrderedHash #:nodoc: | |
607 | def []=(key, value) | |
608 | super(key.to_sym, value) | |
609 | end | |
610 | ||
611 | def [](key) | |
612 | super(key.to_sym) | |
613 | end | |
614 | ||
615 | def method_missing(name, *args) | |
616 | if name.to_s =~ /(.*)=$/ | |
617 | self[$1.to_sym] = args.first | |
618 | else | |
619 | self[name] | |
620 | end | |
621 | end | |
622 | end | |
rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/commands.rb:
prev. | current | |
end | ||
def existing_migrations(file_name) | ||
64 | | |
64 | Dir.glob("#{@migration_directory}/[0-9]*_*.rb").grep(/[0-9]+_#{file_name}.rb$/) | |
end | ||
def migration_exists?(file_name) | ||
... | ... | |
# Copy a file from source to destination with collision checking. | ||
# | ||
166 | | |
166 | # The file_options hash accepts :chmod and :shebang and :collision options. | |
# :chmod sets the permissions of the destination file: | ||
# file 'config/empty.log', 'log/test.log', :chmod => 0664 | ||
# :shebang sets the #!/usr/bin/ruby line for scripts | ||
# file 'bin/generate.rb', 'script/generate', :chmod => 0755, :shebang => '/usr/bin/env ruby' | ||
171 | # :collision sets the collision option only for the destination file: | |
172 | # file 'settings/server.yml', 'config/server.yml', :collision => :skip | |
# | ||
# Collisions are handled by checking whether the destination file | ||
# exists and either skipping the file, forcing overwrite, or asking | ||
... | ... | |
# Make a choice whether to overwrite the file. :force and | ||
# :skip already have their mind made up, but give :ask a shot. | ||
191 | | |
193 | choice = case (file_options[:collision] || options[:collision]).to_sym #|| :ask | |
when :ask then force_file_collision?(relative_destination) | ||
when :force then :force | ||
when :skip then :skip | ||
... | ... | |
# When creating a migration, it knows to find the first available file in db/migrate and use the migration.rb template. | ||
def migration_template(relative_source, relative_destination, template_options = {}) | ||
migration_directory relative_destination | ||
312 | | |
313 | | |
314 | migration_file_name = template_options[:migration_file_name] || file_name | |
315 | raise "Another migration is already named #{migration_file_name}: #{existing_migrations(migration_file_name).first}" if migration_exists?(migration_file_name) | |
316 | template(relative_source, "#{relative_destination}/#{next_migration_string}_#{migration_file_name}.rb", template_options) | |
end | ||
private | ||
... | ... | |
# When deleting a migration, it knows to delete every file named "[0-9]*_#{file_name}". | ||
def migration_template(relative_source, relative_destination, template_options = {}) | ||
migration_directory relative_destination | ||
426 | | |
427 | | |
429 | ||
430 | migration_file_name = template_options[:migration_file_name] || file_name | |
431 | unless migration_exists?(migration_file_name) | |
432 | puts "There is no migration named #{migration_file_name}" | |
433 | return | |
434 | end | |
435 | ||
436 | ||
437 | existing_migrations(migration_file_name).each do |file_path| | |
file(relative_source, file_path, template_options) | ||
end | ||
end |
rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/applications/app/app_generator.rb:
prev. | current | |
DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'], | ||
Config::CONFIG['ruby_install_name']) | ||
7 | | |
8 | | |
7 | DATABASES = %w( mysql oracle postgresql sqlite2 sqlite3 ) | |
8 | ||
9 | default_options :db => "mysql", :shebang => DEFAULT_SHEBANG, :freeze => false | |
10 | mandatory_options :source => "#{File.dirname(__FILE__)}/../../../../.." | |
def initialize(runtime_args, runtime_options = {}) | ||
super | ||
usage if args.empty? | ||
15 | usage("Databases supported for preconfiguration are: #{DATABASES.join(", ")}") if (options[:db] && !DATABASES.include?(options[:db])) | |
@destination_root = args.shift | ||
14 | | |
15 | | |
end | ||
def manifest | ||
19 | | |
20 | # Use /usr/bin/env if no special shebang was specified | |
21 | script_options = { :chmod => 0755, :shebang => options[:shebang] == DEFAULT_SHEBANG ? nil : options[:shebang] } | |
dispatcher_options = { :chmod => 0755, :shebang => options[:shebang] } | ||
record do |m| | ||
... | ... | |
m.template "helpers/test_helper.rb", "test/test_helper.rb" | ||
# database.yml and .htaccess | ||
37 | | |
39 | m.template "configs/databases/#{options[:db]}.yml", "config/database.yml", :assigns => { | |
:app_name => File.basename(File.expand_path(@destination_root)), | ||
39 | | |
41 | :socket => options[:db] == "mysql" ? mysql_socket_location : nil | |
} | ||
m.template "configs/routes.rb", "config/routes.rb" | ||
m.template "configs/apache.conf", "public/.htaccess" | ||
# Environments | ||
45 | | |
46 | | |
47 | m.file "environments/boot.rb", "config/boot.rb" | |
48 | m.template "environments/environment.rb", "config/environment.rb", :assigns => { :freeze => options[:freeze] } | |
m.file "environments/production.rb", "config/environments/production.rb" | ||
m.file "environments/development.rb", "config/environments/development.rb" | ||
m.file "environments/test.rb", "config/environments/test.rb" | ||
# Scripts | ||
52 | | |
54 | %w( about breakpointer console destroy generate performance/benchmarker performance/profiler process/reaper process/spawner runner server plugin ).each do |file| | |
m.file "bin/#{file}", "script/#{file}", script_options | ||
end | ||
... | ... | |
m.template "html/#{file}.html", "public/#{file}.html" | ||
end | ||
66 | | |
67 | | |
68 | m.template "html/favicon.ico", "public/favicon.ico" | |
69 | m.template "html/robots.txt", "public/robots.txt" | |
m.file "html/images/rails.png", "public/images/rails.png" | ||
# Javascripts | ||
71 | | |
72 | | |
73 | | |
74 | | |
73 | m.file "html/javascripts/prototype.js", "public/javascripts/prototype.js" | |
74 | m.file "html/javascripts/effects.js", "public/javascripts/effects.js" | |
75 | m.file "html/javascripts/dragdrop.js", "public/javascripts/dragdrop.js" | |
76 | m.file "html/javascripts/controls.js", "public/javascripts/controls.js" | |
77 | m.file "html/javascripts/application.js", "public/javascripts/application.js" | |
# Docs | ||
m.file "doc/README_FOR_APP", "doc/README_FOR_APP" | ||
... | ... | |
def add_options!(opt) | ||
opt.separator '' | ||
opt.separator 'Options:' | ||
94 | | |
95 | | |
96 | | |
97 | | |
98 | | |
97 | opt.on("-r", "--ruby=path", String, | |
98 | "Path to the Ruby binary of your choice (otherwise scripts use env, dispatchers current path).", | |
99 | "Default: #{DEFAULT_SHEBANG}") { |options[:shebang]| } | |
100 | ||
101 | opt.on("-d", "--database=name", String, | |
102 | "Preconfigure for selected database (options: mysql/oracle/postgresql/sqlite2/sqlite3).", | |
103 | "Default: mysql") { |options[:db]| } | |
104 | ||
105 | opt.on("-f", "--freeze", | |
106 | "Freeze Rails in vendor/rails from the gems generating the skeleton", | |
107 | "Default: false") { |options[:freeze]| } | |
end | ||
109 | ||
110 | def mysql_socket_location | |
111 | RUBY_PLATFORM =~ /mswin32/ ? MYSQL_SOCKET_LOCATIONS.find { |f| File.exists?(f) } : nil | |
112 | end | |
# Installation skeleton. Intermediate directories are automatically | ||
... | ... | |
script/process | ||
test/fixtures | ||
test/functional | ||
136 | test/integration | |
test/mocks/development | ||
test/mocks/test | ||
test/unit | ||
vendor | ||
vendor/plugins | ||
142 | tmp/sessions | |
143 | tmp/sockets | |
144 | tmp/cache | |
) | ||
MYSQL_SOCKET_LOCATIONS = [ |
rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/mailer/USAGE:
prev. | current | |
This will create a Notifications mailer class: | ||
Mailer: app/models/notifications.rb | ||
Views: app/views/notifications/signup.rhtml [...] | ||
16 | | |
16 | Test: test/unit/test/unit/notifications_test.rb | |
Fixtures: test/fixtures/notifications/signup [...] | ||
rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/migration/USAGE:
prev. | current | |
./script/generate migration AddSslFlag | ||
With 4 existing migrations, this will create an AddSslFlag migration in the | ||
14 | | |
15 | file db/migrate/005_add_ssl_flag.rb | |
rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/model/USAGE:
prev. | current | |
given in CamelCase or under_score and should not be suffixed with 'Model'. | ||
The generator creates a model class in app/models, a test suite in | ||
8 | | |
8 | test/unit, test fixtures in test/fixtures/singular_name.yml, and a migration | |
9 | in db/migrate. | |
Example: | ||
./script/generate model Account | ||
... | ... | |
Model: app/models/account.rb | ||
Test: test/unit/account_test.rb | ||
Fixtures: test/fixtures/accounts.yml | ||
18 | Migration: db/migrate/XXX_add_accounts.rb | |
rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/model/model_generator.rb:
prev. | current | |
class ModelGenerator < Rails::Generator::NamedBase | ||
2 | default_options :skip_migration => false | |
3 | ||
def manifest | ||
record do |m| | ||
# Check for class naming collisions. | ||
... | ... | |
m.template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb") | ||
m.template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb") | ||
m.template 'fixtures.yml', File.join('test/fixtures', class_path, "#{table_name}.yml") | ||
18 | ||
19 | unless options[:skip_migration] | |
20 | m.migration_template 'migration.rb', 'db/migrate', :assigns => { | |
21 | :migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}" | |
22 | }, :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}" | |
23 | end | |
end | ||
end | ||
26 | ||
27 | protected | |
28 | def add_options!(opt) | |
29 | opt.separator '' | |
30 | opt.separator 'Options:' | |
31 | opt.on("--skip-migration", | |
32 | "Don't generate a migration file for this model") { |options[:skip_migration]| } | |
33 | end | |
end |
rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/model/templates/unit_test.rb:
prev. | current | |
# Replace this with your real tests. | ||
def test_truth | ||
8 | | |
8 | assert true | |
end | ||
end |
rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/plugin/USAGE:
prev. | current | |
This will create: | ||
vendor/plugins/browser_filters/README | ||
vendor/plugins/browser_filters/init.rb | ||
19 | vendor/plugins/browser_filters/install.rb | |
vendor/plugins/browser_filters/lib/browser_filters.rb | ||
vendor/plugins/browser_filters/test/browser_filters_test.rb | ||
vendor/plugins/browser_filters/tasks/browser_filters_tasks.rake | ||
... | ... | |
This will create: | ||
vendor/plugins/browser_filters/README | ||
vendor/plugins/browser_filters/init.rb | ||
29 | vendor/plugins/browser_filters/install.rb | |
vendor/plugins/browser_filters/lib/browser_filters.rb | ||
vendor/plugins/browser_filters/test/browser_filters_test.rb | ||
vendor/plugins/browser_filters/tasks/browser_filters_tasks.rake | ||
vendor/plugins/browser_filters/generators/browser_filters/browser_filters_generator.rb | ||
vendor/plugins/browser_filters/generators/browser_filters/USAGE | ||
33 | | |
36 | vendor/plugins/browser_filters/generators/browser_filters/templates/ |
rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/plugin/plugin_generator.rb:
prev. | current | |
m.template 'README', "#{plugin_path}/README" | ||
m.template 'Rakefile', "#{plugin_path}/Rakefile" | ||
m.template 'init.rb', "#{plugin_path}/init.rb" | ||
19 | m.template 'install.rb', "#{plugin_path}/install.rb" | |
m.template 'plugin.rb', "#{plugin_path}/lib/#{file_name}.rb" | ||
m.template 'tasks.rake', "#{plugin_path}/tasks/#{file_name}_tasks.rake" | ||
m.template 'unit_test.rb', "#{plugin_path}/test/#{file_name}_test.rb" |
rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/plugin/templates/Rakefile:
prev. | current | |
Rake::RDocTask.new(:rdoc) do |rdoc| | ||
rdoc.rdoc_dir = 'rdoc' | ||
rdoc.title = '<%= class_name %>' | ||
19 | | |
19 | rdoc.options << '--line-numbers' << '--inline-source' | |
rdoc.rdoc_files.include('README') | ||
rdoc.rdoc_files.include('lib/**/*.rb') | ||
end |
rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb:
prev. | current | |
m.directory File.join('test/functional', controller_class_path) | ||
# Depend on model generator but skip if the model exists. | ||
76 | | |
76 | m.dependency 'model', [singular_name], :collision => :skip, :skip_migration => true | |
# Scaffolded forms. | ||
m.complex_template "form.rhtml", |
rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb:
prev. | current | |
end | ||
<% end -%> | ||
14 | # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html) | |
15 | verify :method => :post, :only => [ :destroy<%= suffix %>, :create<%= suffix %>, :update<%= suffix %> ], | |
16 | :redirect_to => { :action => :list<%= suffix %> } | |
17 | ||
def list<%= suffix %> | ||
@<%= singular_name %>_pages, @<%= plural_name %> = paginate :<%= plural_name %>, :per_page => 10 | ||
end |
rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/scaffold/templates/style.css:
prev. | current | |
display: table; | ||
} | ||
25 | ||
25 | #errorExplanation { | |
width: 400px; | ||
border: 2px solid red; | ||
padding: 7px; | ||
... | ... | |
background-color: #f0f0f0; | ||
} | ||
34 | ||
34 | #errorExplanation h2 { | |
text-align: left; | ||
font-weight: bold; | ||
padding: 5px 5px 5px 15px; | ||
... | ... | |
color: #fff; | ||
} | ||
44 | ||
44 | #errorExplanation p { | |
color: #333; | ||
margin-bottom: 0; | ||
padding: 5px; | ||
} | ||
50 | ||
50 | #errorExplanation ul li { | |
font-size: 12px; | ||
list-style: square; | ||
} |
rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml:
prev. | current | |
<%% end %> | ||
<td><%%= link_to 'Show', :action => 'show<%= suffix %>', :id => <%= singular_name %> %></td> | ||
<td><%%= link_to 'Edit', :action => 'edit<%= suffix %>', :id => <%= singular_name %> %></td> | ||
17 | | |
17 | <td><%%= link_to 'Destroy', { :action => 'destroy<%= suffix %>', :id => <%= singular_name %> }, :confirm => 'Are you sure?', :post => true %></td> | |
</tr> | ||
<%% end %> | ||
</table> |
rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/generators/components/session_migration/USAGE:
prev. | current | |
./script/generate session_migration AddSessionTable | ||
With 4 existing migrations, this will create an AddSessionTable migration in the | ||
15 | | |
16 | file db/migrate/005_add_session_table.rb | |
rool/rails/typo/trunk/vendor/rails/railties/lib/rails_generator/options.rb:
prev. | current | |
# Raise a usage error. Override usage_message to provide a blurb | ||
# after the option parser summary. | ||
99 | | |
100 | | |
99 | def usage(message = usage_message) | |
100 | raise UsageError, "#{@option_parser}\n#{message}" | |
end | ||
def usage_message |
rool/rails/typo/trunk/vendor/rails/railties/lib/tasks/databases.rake:
prev. | current | |
1 | ||
2 | ||
3 | | |
4 | | |
5 | ||
6 | ||
7 | ||
8 | ||
9 | | |
10 | | |
11 | | |
12 | | |
1 | namespace :db do | |
2 | desc "Migrate the database through scripts in db/migrate. Target specific version with VERSION=x" | |
3 | task :migrate => :environment do | |
4 | ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil) | |
5 | Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby | |
end | ||
14 | ||
16 | ||
17 | ||
18 | | |
19 | | |
20 | | |
21 | | |
22 | ||
8 | namespace :fixtures do | |
9 | desc "Load fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y" | |
10 | task :load => :environment do | |
11 | require 'active_record/fixtures' | |
12 | ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym) | |
13 | (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'test', 'fixtures', '*.{yml,csv}'))).each do |fixture_file| | |
14 | Fixtures.create_fixtures('test/fixtures', File.basename(fixture_file, '.*')) | |
15 | end | |
16 | end | |
17 | end | |
24 | ||
25 | ||
26 | | |
27 | | |
28 | ||
19 | namespace :schema do | |
20 | desc "Create a db/schema.rb file that can be portably used against any DB supported by AR" | |
21 | task :dump => :environment do | |
22 | require 'active_record/schema_dumper' | |
23 | File.open(ENV['SCHEMA'] || "db/schema.rb", "w") do |file| | |
24 | ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file) | |
25 | end | |
26 | end | |
30 | ||
31 | ||
32 | | |
33 | | |
34 | ||
35 | ||
36 | ||
37 | ||
38 | | |
39 | | |
40 | | |
41 | | |
42 | | |
43 | | |
44 | | |
45 | | |
46 | | |
47 | | |
48 | | |
49 | | |
50 | | |
51 | | |
52 | | |
53 | | |
54 | | |
55 | | |
56 | | |
57 | | |
28 | desc "Load a schema.rb file into the database" | |
29 | task :load => :environment do | |
30 | file = ENV['SCHEMA'] || "db/schema.rb" | |
31 | load(file) | |
32 | end | |
end | ||
60 | | |
61 | | |
62 | | |
63 | ||
35 | namespace :structure do | |
36 | desc "Dump the database structure to a SQL file" | |
37 | task :dump => :environment do | |
38 | abcs = ActiveRecord::Base.configurations | |
39 | case abcs[RAILS_ENV]["adapter"] | |
40 | when "mysql", "oci" | |
41 | ActiveRecord::Base.establish_connection(abcs[RAILS_ENV]) | |
42 | File.open("db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump } | |
43 | when "postgresql" | |
44 | ENV['PGHOST'] = abcs[RAILS_ENV]["host"] if abcs[RAILS_ENV]["host"] | |
45 | ENV['PGPORT'] = abcs[RAILS_ENV]["port"].to_s if abcs[RAILS_ENV]["port"] | |
46 | ENV['PGPASSWORD'] = abcs[RAILS_ENV]["password"].to_s if abcs[RAILS_ENV]["password"] | |
47 | search_path = abcs[RAILS_ENV]["schema_search_path"] | |
48 | search_path = "--schema=#{search_path}" if search_path | |
49 | `pg_dump -i -U "#{abcs[RAILS_ENV]["username"]}" -s -x -O -f db/#{RAILS_ENV}_structure.sql #{search_path} #{abcs[RAILS_ENV]["database"]}` | |
50 | raise "Error dumping database" if $?.exitstatus == 1 | |
51 | when "sqlite", "sqlite3" | |
52 | dbfile = abcs[RAILS_ENV]["database"] || abcs[RAILS_ENV]["dbfile"] | |
53 | `#{abcs[RAILS_ENV]["adapter"]} #{dbfile} .schema > db/#{RAILS_ENV}_structure.sql` | |
54 | when "sqlserver" | |
55 | `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /f db\\#{RAILS_ENV}_structure.sql /q /A /r` | |
56 | `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /F db\ /q /A /r` | |
57 | else | |
58 | raise "Task not supported by '#{abcs["test"]["adapter"]}'" | |
59 | end | |
65 | ||
66 | ||
67 | | |
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
73 | | |
61 | if ActiveRecord::Base.connection.supports_migrations? | |
62 | File.open("db/#{RAILS_ENV}_structure.sql", "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information } | |
end | ||
75 | | |
76 | | |
77 | | |
78 | | |
79 | | |
80 | | |
81 | | |
82 | | |
83 | | |
84 | | |
85 | | |
86 | | |
87 | | |
88 | | |
89 | | |
90 | | |
91 | | |
64 | end | |
end | ||
93 | ||
95 | ||
96 | ||
97 | | |
98 | | |
99 | | |
100 | | |
101 | | |
102 | | |
103 | | |
104 | | |
105 | | |
106 | | |
107 | | |
108 | | |
109 | | |
110 | | |
111 | | |
112 | | |
113 | | |
114 | | |
115 | | |
116 | | |
117 | | |
118 | | |
119 | | |
67 | namespace :test do | |
68 | desc "Recreate the test database from the current environment's database schema" | |
69 | task :clone => "db:schema:dump" do | |
70 | ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test']) | |
71 | ActiveRecord::Schema.verbose = false | |
72 | Rake::Task["db:schema:load"].invoke | |
73 | end | |
74 | ||
75 | ||
76 | desc "Recreate the test databases from the development structure" | |
77 | task :clone_structure => [ "db:structure:dump", "db:test:purge" ] do | |
78 | abcs = ActiveRecord::Base.configurations | |
79 | case abcs["test"]["adapter"] | |
80 | when "mysql" | |
81 | ActiveRecord::Base.establish_connection(:test) | |
82 | ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0') | |
83 | IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table| | |
84 | ActiveRecord::Base.connection.execute(table) | |
85 | end | |
86 | when "postgresql" | |
87 | ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"] | |
88 | ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"] | |
89 | ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"] | |
90 | `psql -U "#{abcs["test"]["username"]}" -f db/#{RAILS_ENV}_structure.sql #{abcs["test"]["database"]}` | |
91 | when "sqlite", "sqlite3" | |
92 | dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"] | |
93 | `#{abcs["test"]["adapter"]} #{dbfile} < db/#{RAILS_ENV}_structure.sql` | |
94 | when "sqlserver" | |
95 | `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql` | |
96 | when "oci" | |
97 | ActiveRecord::Base.establish_connection(:test) | |
98 | IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split(";\n\n").each do |ddl| | |
99 | ActiveRecord::Base.connection.execute(ddl) | |
100 | end | |
101 | else | |
102 | raise "Task not supported by '#{abcs["test"]["adapter"]}'" | |
end | ||
121 | | |
122 | | |
123 | | |
124 | ||
104 | end | |
126 | ||
127 | | |
128 | | |
129 | ||
106 | desc "Empty the test database" | |
107 | task :purge => :environment do | |
108 | abcs = ActiveRecord::Base.configurations | |
109 | case abcs["test"]["adapter"] | |
110 | when "mysql" | |
111 | ActiveRecord::Base.establish_connection(:test) | |
112 | ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"]) | |
113 | when "postgresql" | |
114 | ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"] | |
115 | ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"] | |
116 | ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"] | |
117 | enc_option = "-E #{abcs["test"]["encoding"]}" if abcs["test"]["encoding"] | |
118 | `dropdb -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}` | |
119 | `createdb #{enc_option} -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}` | |
120 | when "sqlite","sqlite3" | |
121 | dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"] | |
122 | File.delete(dbfile) if File.exist?(dbfile) | |
123 | when "sqlserver" | |
124 | dropfkscript = "#{abcs["test"]["host"]}.#{abcs["test"]["database"]}.DP1".gsub(/\\/,'-') | |
125 | `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{dropfkscript}` | |
126 | `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql` | |
127 | when "oci" | |
128 | ActiveRecord::Base.establish_connection(:test) | |
129 | ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl| | |
130 | ActiveRecord::Base.connection.execute(ddl) | |
131 | end | |
132 | else | |
133 | raise "Task not supported by '#{abcs["test"]["adapter"]}'" | |
134 | end | |
135 | end | |
131 | ||
132 | ||
133 | | |
134 | ||
137 | desc 'Prepare the test database and load the schema' | |
138 | task :prepare => :environment do | |
139 | Rake::Task[{ :sql => "db:test:clone_structure", :ruby => "db:test:clone" }[ActiveRecord::Base.schema_format]].invoke | |
140 | end | |
141 | end | |
136 | ||
137 | ||
138 | | |
143 | namespace :sessions do | |
144 | desc "Creates a sessions table for use with CGI::Session::ActiveRecordStore" | |
145 | task :create => :environment do | |
146 | raise "Task unavailable to this database (no migration support)" unless ActiveRecord::Base.connection.supports_migrations? | |
147 | require 'rails_generator' | |
148 | require 'rails_generator/scripts/generate' | |
149 | Rails::Generator::Scripts::Generate.new.run(["session_migration", ENV["MIGRATION"] || "AddSessions"]) | |
150 | end | |
140 | | |
141 | | |
142 | | |
143 | | |
152 | desc "Clear the sessions table" | |
153 | task :clear => :environment do | |
154 | ActiveRecord::Base.connection.execute "DELETE FROM sessions" | |
155 | end | |
end | ||
145 | | |
146 | | |
end | ||
149 | ||
150 | ||
151 | | |
152 | | |
153 | | |
159 | def session_table_name | |
160 | ActiveRecord::Base.pluralize_table_names ? :sessions : :session | |
end | ||
155 | ||
156 | ||
157 | ||
158 |
rool/rails/typo/trunk/vendor/rails/railties/lib/tasks/documentation.rake:
prev. | current | |
1 | ||
2 | ||
3 | | |
4 | | |
5 | | |
6 | | |
7 | | |
8 | ||
1 | namespace :doc do | |
2 | desc "Generate documentation for the application" | |
3 | Rake::RDocTask.new("app") { |rdoc| | |
4 | rdoc.rdoc_dir = 'doc/app' | |
5 | rdoc.title = "Rails Application Documentation" | |
6 | rdoc.options << '--line-numbers' << '--inline-source' | |
7 | rdoc.rdoc_files.include('doc/README_FOR_APP') | |
8 | rdoc.rdoc_files.include('app/**/*.rb') | |
9 | } | |
10 | ||
11 | ||
12 | ||
13 | | |
14 | | |
15 | | |
16 | | |
17 | | |
18 | | |
19 | | |
20 | | |
11 | desc "Generate documentation for the Rails framework" | |
12 | Rake::RDocTask.new("rails") { |rdoc| | |
13 | rdoc.rdoc_dir = 'doc/api' | |
14 | rdoc.template = "#{ENV['template']}.rb" if ENV['template'] | |
15 | rdoc.title = "Rails Framework Documentation" | |
16 | rdoc.options << '--line-numbers' << '--inline-source' | |
17 | rdoc.rdoc_files.include('README') | |
18 | rdoc.rdoc_files.include('vendor/rails/railties/CHANGELOG') | |
19 | rdoc.rdoc_files.include('vendor/rails/railties/MIT-LICENSE') | |
20 | rdoc.rdoc_files.include('vendor/rails/activerecord/README') | |
21 | rdoc.rdoc_files.include('vendor/rails/activerecord/CHANGELOG') | |
22 | rdoc.rdoc_files.include('vendor/rails/activerecord/lib/active_record/**/*.rb') | |
23 | rdoc.rdoc_files.exclude('vendor/rails/activerecord/lib/active_record/vendor/*') | |
24 | rdoc.rdoc_files.include('vendor/rails/actionpack/README') | |
25 | rdoc.rdoc_files.include('vendor/rails/actionpack/CHANGELOG') | |
26 | rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_controller/**/*.rb') | |
27 | rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_view/**/*.rb') | |
28 | rdoc.rdoc_files.include('vendor/rails/actionmailer/README') | |
29 | rdoc.rdoc_files.include('vendor/rails/actionmailer/CHANGELOG') | |
30 | rdoc.rdoc_files.include('vendor/rails/actionmailer/lib/action_mailer/base.rb') | |
31 | rdoc.rdoc_files.include('vendor/rails/actionwebservice/README') | |
32 | rdoc.rdoc_files.include('vendor/rails/actionwebservice/CHANGELOG') | |
33 | rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service.rb') | |
34 | rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/*.rb') | |
35 | rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/api/*.rb') | |
36 | rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/client/*.rb') | |
37 | rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/container/*.rb') | |
38 | rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/dispatcher/*.rb') | |
39 | rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/protocol/*.rb') | |
40 | rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/support/*.rb') | |
41 | rdoc.rdoc_files.include('vendor/rails/activesupport/README') | |
42 | rdoc.rdoc_files.include('vendor/rails/activesupport/CHANGELOG') | |
43 | rdoc.rdoc_files.include('vendor/rails/activesupport/lib/active_support/**/*.rb') | |
44 | } | |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
46 | plugins = FileList['vendor/plugins/**'].collect { |plugin| File.basename(plugin) } | |
29 | | |
48 | desc "Generate documation for all installed plugins" | |
49 | task :plugins => plugins.collect { |plugin| "doc:plugins:#{plugin}" } | |
31 | | |
51 | desc "Remove plugin documentation" | |
52 | task :clobber_plugins do | |
53 | rm_rf 'doc/plugins' rescue nil | |
end | ||
33 | ||
35 | ||
36 | ||
56 | namespace :plugins do | |
57 | # Define doc tasks for each plugin | |
58 | plugins.each do |plugin| | |
59 | task(plugin => :environment) do | |
60 | plugin_base = "vendor/plugins/#{plugin}" | |
61 | options = [] | |
62 | files = Rake::FileList.new | |
63 | options << "-o doc/plugins/#{plugin}" | |
64 | options << "--title '#{plugin.titlecase} Plugin Documentation'" | |
65 | options << '--line-numbers' << '--inline-source' | |
66 | options << '-T html' | |
38 | ||
39 | ||
40 | | |
41 | ||
68 | files.include("#{plugin_base}/lib/**/*.rb") | |
69 | if File.exists?("#{plugin_base}/README") | |
70 | files.include("#{plugin_base}/README") | |
71 | options << "--main '#{plugin_base}/README'" | |
72 | end | |
73 | files.include("#{plugin_base}/CHANGELOG") if File.exists?("#{plugin_base}/CHANGELOG") | |
43 | ||
44 | ||
45 | | |
46 | | |
47 | | |
48 | | |
49 | | |
50 | | |
51 | | |
52 | | |
53 | | |
54 | | |
55 | | |
56 | | |
57 | | |
58 | | |
59 | | |
60 | | |
61 | | |
62 | | |
63 | | |
64 | | |
65 | | |
66 | | |
67 | | |
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
73 | | |
74 | | |
75 | | |
76 | ||
75 | options << files.to_s | |
76 | ||
77 | sh %(rdoc #{options * ' '}) | |
78 | end | |
79 | end | |
80 | end | |
81 | end | |
rool/rails/typo/trunk/vendor/rails/railties/lib/tasks/framework.rake:
prev. | current | |
1 | ||
2 | ||
3 | | |
4 | | |
1 | namespace :rails do | |
2 | namespace :freeze do | |
3 | desc "Lock this application to the current gems (by unpacking them into vendor/rails)" | |
4 | task :gems do | |
5 | deps = %w(actionpack activerecord actionmailer activesupport actionwebservice) | |
6 | require 'rubygems' | |
7 | Gem.manage_gems | |
6 | | |
7 | | |
8 | | |
9 | | |
10 | | |
11 | | |
9 | rails = (version = ENV['VERSION']) ? | |
10 | Gem.cache.search('rails', "= #{version}").first : | |
11 | Gem.cache.search('rails').sort_by { |g| g.version }.last | |
13 | | |
14 | | |
15 | | |
16 | | |
13 | version ||= rails.version | |
18 | | |
19 | | |
20 | | |
15 | unless rails | |
16 | puts "No rails gem #{version} is installed. Do 'gem list rails' to see what you have available." | |
17 | exit | |
18 | end | |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | ||
20 | puts "Freezing to the gems for Rails #{rails.version}" | |
21 | rm_rf "vendor/rails" | |
22 | mkdir_p "vendor/rails" | |
30 | ||
31 | ||
32 | | |
33 | | |
34 | | |
35 | | |
36 | | |
37 | | |
24 | chdir("vendor/rails") do | |
25 | rails.dependencies.select { |g| deps.include? g.name }.each do |g| | |
26 | Gem::GemRunner.new.run(["unpack", "-v", "#{g.version_requirements}", "#{g.name}"]) | |
27 | mv(Dir.glob("#{g.name}*").first, g.name) | |
28 | end | |
39 | | |
40 | | |
30 | Gem::GemRunner.new.run(["unpack", "-v", "=#{version}", "rails"]) | |
31 | FileUtils.mv(Dir.glob("rails*").first, "railties") | |
32 | end | |
33 | end | |
42 | | |
43 | | |
44 | | |
45 | | |
35 | desc "Lock to latest Edge Rails or a specific revision with REVISION=X (ex: REVISION=4021) or a tag with TAG=Y (ex: TAG=rel_1-1-0)" | |
36 | task :edge do | |
37 | $verbose = false | |
38 | `svn --version` rescue nil | |
39 | unless !$?.nil? && $?.success? | |
40 | $stderr.puts "ERROR: Must have subversion (svn) available in the PATH to lock this application to Edge Rails" | |
41 | exit 1 | |
42 | end | |
43 | ||
44 | rm_rf "vendor/rails" | |
45 | mkdir_p "vendor/rails" | |
46 | ||
47 | svn_root = "http://dev.rubyonrails.org/svn/rails/" | |
48 | ||
49 | if ENV['TAG'] | |
50 | rails_svn = "#{svn_root}/tags/#{ENV['TAG']}" | |
51 | touch "vendor/rails/TAG_#{ENV['TAG']}" | |
52 | else | |
53 | rails_svn = "#{svn_root}/trunk" | |
54 | ||
55 | if ENV['REVISION'].nil? | |
56 | ENV['REVISION'] = /^r(\d+)/.match(%x{svn -qr HEAD log #{svn_root}})[1] | |
57 | puts "REVISION not set. Using HEAD, which is revision #{ENV['REVISION']}." | |
58 | end | |
59 | ||
60 | touch "vendor/rails/REVISION_#{ENV['REVISION']}" | |
61 | end | |
62 | ||
63 | for framework in %w( railties actionpack activerecord actionmailer activesupport actionwebservice ) | |
64 | system "svn export #{rails_svn}/#{framework} vendor/rails/#{framework}" + (ENV['REVISION'] ? " -r #{ENV['REVISION']}" : "") | |
65 | end | |
66 | end | |
end | ||
47 | ||
49 | ||
50 | ||
51 | | |
52 | ||
69 | desc "Unlock this application from freeze of gems or edge and return to a fluid use of system gems" | |
70 | task :unfreeze do | |
71 | rm_rf "vendor/rails" | |
72 | end | |
54 | ||
55 | ||
56 | | |
57 | | |
74 | desc "Update both configs, scripts and public/javascripts from Rails" | |
75 | task :update => [ "update:scripts", "update:javascripts", "update:configs" ] | |
59 | | |
60 | | |
77 | namespace :update do | |
78 | desc "Add new scripts to the application script/ directory" | |
79 | task :scripts do | |
80 | local_base = "script" | |
81 | edge_base = "#{File.dirname(__FILE__)}/../../bin" | |
82 | ||
83 | local = Dir["#{local_base}/**/*"].reject { |path| File.directory?(path) } | |
84 | edge = Dir["#{edge_base}/**/*"].reject { |path| File.directory?(path) } | |
62 | | |
63 | | |
64 | | |
65 | | |
66 | | |
67 | | |
86 | edge.each do |script| | |
87 | base_name = script[(edge_base.length+1)..-1] | |
88 | next if base_name == "rails" | |
89 | next if local.detect { |path| base_name == path[(local_base.length+1)..-1] } | |
90 | if !File.directory?("#{local_base}/#{File.dirname(base_name)}") | |
91 | mkdir_p "#{local_base}/#{File.dirname(base_name)}" | |
92 | end | |
93 | install script, "#{local_base}/#{base_name}", :mode => 0755 | |
94 | end | |
end | ||
69 | | |
96 | ||
97 | desc "Update your javascripts from your current rails install" | |
98 | task :javascripts do | |
99 | require 'railties_path' | |
100 | project_dir = RAILS_ROOT + '/public/javascripts/' | |
101 | scripts = Dir[RAILTIES_PATH + '/html/javascripts/*.js'] | |
102 | scripts.reject!{|s| File.basename(s) == 'application.js'} if File.exists?(project_dir + 'application.js') | |
103 | FileUtils.cp(scripts, project_dir) | |
104 | end | |
105 | ||
106 | desc "Update boot/config.rb from your current rails install" | |
107 | task :configs do | |
108 | require 'railties_path' | |
109 | project_dir = RAILS_ROOT + '/public/javascripts/' | |
110 | scripts = Dir[RAILTIES_PATH + '/html/javascripts/*.js'] | |
111 | FileUtils.cp(RAILTIES_PATH + '/environments/boot.rb', RAILS_ROOT + '/config/boot.rb') | |
112 | end | |
end | ||
end |
rool/rails/typo/trunk/vendor/rails/railties/lib/tasks/misc.rake:
prev. | current | |
1 | ||
2 | ||
3 | | |
4 | | |
5 | | |
6 | ||
7 | ||
1 | task :default => :test | |
task :environment do | ||
require(File.join(RAILS_ROOT, 'config', 'environment')) | ||
10 | ||
11 | ||
12 | ||
13 | ||
14 | ||
15 | | |
16 | | |
17 | | |
18 | | |
19 | ||
4 | end | |
rool/rails/typo/trunk/vendor/rails/railties/lib/tasks/statistics.rake:
prev. | current | |
STATS_DIRECTORIES = [ | ||
2 | | |
3 | | |
4 | | |
5 | | |
6 | | |
7 | | |
8 | | |
9 | | |
2 | %w(Helpers app/helpers), | |
3 | %w(Controllers app/controllers), | |
4 | %w(APIs app/apis), | |
5 | %w(Components components), | |
6 | %w(Functional\ tests test/functional), | |
7 | %w(Models app/models), | |
8 | %w(Unit\ tests test/unit), | |
9 | %w(Libraries lib/), | |
10 | %w(Integration\ tests test/integration) | |
].collect { |name, dir| [ name, "#{RAILS_ROOT}/#{dir}" ] }.select { |name, dir| File.directory?(dir) } | ||
desc "Report code statistics (KLOCs, etc) from the application" |
rool/rails/typo/trunk/vendor/rails/railties/lib/tasks/testing.rake:
prev. | current | |
end.compact | ||
end | ||
13 | ||
14 | ||
15 | | |
16 | | |
17 | | |
18 | | |
20 | | |
21 | | |
22 | | |
14 | # Recreated here from ActiveSupport because :uncommitted needs it before Rails is available | |
15 | module Kernel | |
16 | def silence_stderr | |
17 | old_stderr = STDERR.dup | |
18 | STDERR.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null') | |
19 | STDERR.sync = true | |
20 | yield | |
21 | ensure | |
22 | STDERR.reopen(old_stderr) | |
23 | end | |
end | ||
25 | ||
26 | ||
27 | | |
28 | | |
29 | | |
30 | ||
26 | desc 'Test all units and functionals' | |
27 | task :test do | |
28 | Rake::Task["test:units"].invoke rescue got_error = true | |
29 | Rake::Task["test:functionals"].invoke rescue got_error = true | |
30 | ||
31 | if File.exist?("test/integration") | |
32 | Rake::Task["test:integration"].invoke rescue got_error = true | |
33 | end | |
32 | ||
33 | ||
34 | | |
35 | | |
36 | | |
35 | raise "Test failures" if got_error | |
end | ||
39 | ||
40 | ||
41 | | |
38 | namespace :test do | |
39 | desc 'Test recent changes' | |
40 | Rake::TestTask.new(:recent => "db:test:prepare") do |t| | |
41 | since = TEST_CHANGES_SINCE | |
42 | touched = FileList['test/**/*_test.rb'].select { |path| File.mtime(path) > since } + | |
43 | recent_tests('app/models/*.rb', 'test/unit', since) + | |
44 | recent_tests('app/controllers/*.rb', 'test/functional', since) | |
45 | ||
46 | t.libs << 'test' | |
47 | t.verbose = true | |
48 | t.test_files = touched.uniq | |
49 | end | |
43 | | |
44 | | |
45 | | |
46 | | |
51 | desc 'Test changes since last checkin (only Subversion)' | |
52 | Rake::TestTask.new(:uncommitted => "db:test:prepare") do |t| | |
53 | def t.file_list | |
54 | changed_since_checkin = silence_stderr { `svn status` }.map { |path| path.chomp[7 .. -1] } | |
55 | ||
56 | models = changed_since_checkin.select { |path| path =~ /app\/models\/.*\.rb/ } | |
57 | controllers = changed_since_checkin.select { |path| path =~ /app\/controllers\/.*\.rb/ } | |
58 | ||
59 | unit_tests = models.map { |model| "test/unit/#{File.basename(model, '.rb')}_test.rb" } | |
60 | functional_tests = controllers.map { |controller| "test/functional/#{File.basename(controller, '.rb')}_test.rb" } | |
61 | ||
62 | unit_tests.uniq + functional_tests.uniq | |
63 | end | |
64 | ||
65 | t.libs << 'test' | |
66 | t.verbose = true | |
end | ||
49 | | |
69 | desc "Run the unit tests in test/unit" | |
70 | Rake::TestTask.new(:units => "db:test:prepare") do |t| | |
71 | t.libs << "test" | |
72 | t.pattern = 'test/unit/**/*_test.rb' | |
73 | t.verbose = true | |
74 | end | |
75 | ||
76 | desc "Run the functional tests in test/functional" | |
77 | Rake::TestTask.new(:functionals => "db:test:prepare") do |t| | |
78 | t.libs << "test" | |
79 | t.pattern = 'test/functional/**/*_test.rb' | |
80 | t.verbose = true | |
81 | end | |
82 | ||
83 | desc "Run the integration tests in test/integration" | |
84 | Rake::TestTask.new(:integration => "db:test:prepare") do |t| | |
85 | t.libs << "test" | |
86 | t.pattern = 'test/integration/**/*_test.rb' | |
87 | t.verbose = true | |
88 | end | |
89 | ||
90 | desc "Run the plugin tests in vendor/plugins/**/test (or specify with PLUGIN=name)" | |
91 | Rake::TestTask.new(:plugins => :environment) do |t| | |
92 | t.libs << "test" | |
93 | ||
94 | if ENV['PLUGIN'] | |
95 | t.pattern = "vendor/plugins/#{ENV['PLUGIN']}/test/**/*_test.rb" | |
96 | else | |
97 | t.pattern = 'vendor/plugins/**/test/**/*_test.rb' | |
98 | end | |
99 | ||
100 | t.verbose = true | |
101 | end | |
end |
rool/rails/typo/trunk/vendor/rails/railties/lib/test_help.rb:
prev. | current | |
require 'test/unit' | ||
require 'active_record/fixtures' | ||
require 'action_controller/test_process' | ||
10 | require 'action_controller/integration' | |
require 'action_web_service/test_invoke' | ||
require 'breakpoint' | ||
rool/rails/typo/trunk/vendor/rails/railties/lib/webrick_server.rb:
prev. | current | |
ABSOLUTE_RAILS_ROOT = File.expand_path(RAILS_ROOT) | ||
11 | ||
12 | ||
class CGI #:nodoc: | ||
def stdinput | ||
@stdin || $stdin | ||
... | ... | |
end | ||
def service(req, res) #:nodoc: | ||
80 | | |
81 | | |
78 | unless handle_file(req, res) | |
79 | begin | |
REQUEST_MUTEX.lock unless ActionController::Base.allow_concurrency | ||
unless handle_dispatch(req, res) | ||
raise WEBrick::HTTPStatus::NotFound, "`#{req.path}' not found." | ||
end | ||
84 | ensure | |
85 | unless ActionController::Base.allow_concurrency | |
86 | REQUEST_MUTEX.unlock if REQUEST_MUTEX.locked? | |
87 | end | |
end | ||
87 | | |
88 | | |
89 | | |
90 | | |
end | ||
end | ||
rool/rails/typo/trunk/vendor/rails/railties/test/dispatcher_test.rb:
prev. | current | |
def setup | ||
@output = StringIO.new | ||
ENV['REQUEST_METHOD'] = "GET" | ||
27 | | |
end | ||
def teardown | ||
ENV['REQUEST_METHOD'] = nil | ||
32 | | |
end | ||
def test_ac_subclasses_cleared_on_reset | ||
... | ... | |
def dispatch | ||
Dispatcher.dispatch(nil, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, @output) | ||
end | ||
94 | ||
95 | | |
96 | | |
97 | | |
98 | | |
99 | ||
100 | | |
101 | | |
102 | | |
end |
rool/rails/typo/trunk/vendor/rails/railties/test/rails_info_controller_test.rb:
prev. | current | |
$:.unshift File.dirname(__FILE__) + "/../lib" | ||
2 | ||
2 | $:.unshift File.dirname(__FILE__) + "/../builtin/rails_info" | |
$:.unshift File.dirname(__FILE__) + "/../../actionpack/lib" | ||
$:.unshift File.dirname(__FILE__) + "/../../activesupport/lib" | ||
require 'test/unit' | ||
require 'action_controller' | ||
require 'action_controller/test_process' | ||
9 | ||
11 | ||
12 | ||
13 | ||
10 | require_dependency 'rails/info_controller' | |
11 | class Rails::InfoController < ActionController::Base | |
@local_request = false | ||
class << self | ||
cattr_accessor :local_request | ||
end | ||
17 | # Re-raise errors caught by the controller. | |
18 | def rescue_action(e) raise e end; | |
19 | ||
protected | ||
def local_request? | ||
self.class.local_request | ||
... | ... | |
map.connect ':controller/:action/:id' | ||
end | ||
29 | ||
30 | ||
31 | ||
32 | ||
33 | ||
34 | ||
30 | class Rails::InfoControllerTest < Test::Unit::TestCase | |
def setup | ||
36 | | |
32 | @controller = Rails::InfoController.new | |
@request = ActionController::TestRequest.new | ||
@response = ActionController::TestResponse.new | ||
end | ||
def test_rails_info_properties_table_rendered_for_local_request | ||
42 | | |
38 | Rails::InfoController.local_request = true | |
get :properties | ||
assert_tag :tag => 'table' | ||
assert_response :success | ||
end | ||
def test_rails_info_properties_error_rendered_for_non_local_request | ||
49 | | |
45 | Rails::InfoController.local_request = false | |
get :properties | ||
assert_tag :tag => 'p' | ||
assert_response 500 |
rool/rails/typo/trunk/vendor/rails/release.rb:
prev. | current | |
#!/usr/local/bin/ruby | ||
3 | VERSION = ARGV.first | |
PACKAGES = %w( activesupport activerecord actionpack actionmailer actionwebservice ) | ||
5 | ||
6 | | |
7 | | |
8 | ||
9 | ||
# Checkout source | ||
11 | ||
7 | `rm -rf release && svn export http://dev.rubyonrails.org/svn/rails/trunk release` | |
# Create Rails packages | ||
`cd release/railties && rake template=jamis package` | ||
# Upload documentation | ||
17 | ||
18 | ||
19 | | |
20 | ||
13 | `cd release/rails/doc/api && scp -r * davidhh@wrath.rubyonrails.com:public_html/api` | |
# Upload packages | ||
(PACKAGES + %w(railties)).each do |p| | ||
24 | | |
17 | `cd release/#{p} && echo "Releasing #{p}" && rake release` | |
end | ||
# Upload rails tgz/zip | ||
21 | `rubyforge add_release rails rails 'REL #{VERSION}' rails-#{VERSION}.tgz` | |
22 | `rubyforge add_release rails rails 'REL #{VERSION}' rails-#{VERSION}.zip` | |
# Create SVN tag | ||
30 | ||
25 | puts "Remeber to create SVN tag" | |
rool/rails/typo/trunk/vendor/redcloth/bin/redcloth:
prev. | current | |
1 | ||
1 | #!/usr/bin/ruby18 | |
require 'redcloth' | ||
puts RedCloth.new( ARGF.read ).to_html |
rool/rails/typo/trunk/vendor/redcloth/doc/CHANGELOG:
prev. | current | |
--- %YAML:1.0 | ||
2 | - version: 3.0.4 | |
3 | date: 2005-02-18 | |
4 | changes: | |
5 | - The caps class doesn't swallow spaces. | |
6 | - Horizontal rules required to be on an empty line. | |
7 | - Hard breaks don't screw with Markdown headers any longer. | |
8 | - Fixed error triggered by complex lists. | |
9 | - Inline markups need to be butted up against enclosing text, no spaces. | |
10 | - Fixed problem with intermingled single and double quotes. | |
11 | - Brought back lite_mode. | |
12 | ||
- version: 3.0.3 | ||
date: 2005-02-06 | ||
changes: |
rool/rails/typo/trunk/vendor/redcloth/doc/README:
prev. | current | |
h4. Get RedCloth 3 | ||
7 | ||
7 | p(example1). *Stable version:* "3.0.3":http://rubyforge.org/frs/download.php/2896/RedCloth-3.0.3.tar.gz | |
9 | ||
10 | ||
Take a complete tour of Textile at "A Textile Reference":http://hobix.com/textile/. | ||
For fast syntax checking, try the "Quick Reference":http://hobix.com/textile/quick.html. | ||
... | ... | |
gem install RedCloth | ||
</pre> | ||
94 | ||
92 | Or "download RedCloth":http://rubyforge.org/frs/download.php/2896/RedCloth-3.0.3.tar.gz and simply run the install.rb like so: | |
<pre> | ||
ruby install.rb config |
rool/rails/typo/trunk/vendor/redcloth/doc/REFERENCE:
prev. | current | |
if it's found in a @pre@ or @code@ block. | ||
- !!example "I am <b>very</b> serious.\n\n<pre>\n I am <b>very</b> serious.\n</pre>" | ||
- h4. Line Breaks | ||
27 | | |
27 | - Line breaks are ignored. | |
- !!example "I spoke.\nAnd none replied." | ||
29 | | |
29 | - Line breaks can be converted to HTML breaks by setting @hard_breaks@. | |
- h4. Entities | ||
- Single- and double-quotes around words or phrases are converted to curly quotations, much easier on the eye. | ||
- !!example '"Observe!"' | ||
... | ... | |
- Pluses around a passage indicate its insertion. | ||
- !!example "You are a +pleasant+ child." | ||
- To superscript a phrase, surround with carets. | ||
81 | | |
81 | - !!example "a^2^ + b^2^ = c^2^" | |
- To subscript, surround with tildes. | ||
83 | | |
83 | - !!example "log~2~x" | |
- h4. HTML-Specific | ||
- Lastly, if you find yourself needing to customize the style of a passage, use percent symbols | ||
to translate the passage as an HTML span. |
rool/rails/typo/trunk/vendor/redcloth/lib/redcloth.rb:
prev. | current | |
class RedCloth < String | ||
169 | | |
169 | VERSION = '3.0.4' | |
DEFAULT_RULES = [:textile, :markdown] | ||
# | ||
... | ... | |
# | ||
attr_accessor :hard_breaks | ||
196 | # Accessor for toggling lite mode. | |
# | ||
198 | # In lite mode, block-level rules are ignored. This means | |
199 | # that tables, paragraphs, lists, and such aren't available. | |
200 | # Only the inline markup for bold, italics, entities and so on. | |
201 | # | |
202 | # r = RedCloth.new( "And then? She *fell*!", [:lite_mode] ) | |
203 | # r.to_html | |
204 | # #=> "And then? She <strong>fell</strong>!" | |
205 | # | |
206 | attr_accessor :lite_mode | |
207 | ||
208 | # | |
# Accessor for toggling span caps. | ||
# | ||
# Textile places `span' tags around capitalized | ||
... | ... | |
# inline_textile_image:: Textile inline images | ||
# inline_textile_link:: Textile inline links | ||
# inline_textile_span:: Textile inline spans | ||
222 | | |
234 | # glyphs_textile:: Textile entities (such as em-dashes and smart quotes) | |
# | ||
# == Markdown | ||
# | ||
... | ... | |
@shelf = [] | ||
textile_rules = [:refs_textile, :block_textile_table, :block_textile_lists, | ||
:block_textile_prefix, :inline_textile_image, :inline_textile_link, | ||
263 | | |
275 | :inline_textile_code, :inline_textile_span, :glyphs_textile] | |
markdown_rules = [:refs_markdown, :block_markdown_setext, :block_markdown_atx, :block_markdown_rule, | ||
:block_markdown_bq, :block_markdown_lists, | ||
:inline_markdown_reflink, :inline_markdown_link] | ||
... | ... | |
# standard clean up | ||
incoming_entities text | ||
clean_white_space text | ||
281 | | |
# start processor | ||
@pre_list = [] | ||
rip_offtags text | ||
286 | | |
287 | | |
288 | | |
297 | no_textile text | |
298 | hard_break text | |
299 | unless @lite_mode | |
300 | refs text | |
301 | blocks text | |
302 | end | |
inline text | ||
smooth_offtags text | ||
... | ... | |
C = "(?:#{C_CLAS}?#{C_STYL}?#{C_LNGE}?|#{C_STYL}?#{C_LNGE}?#{C_CLAS}?|#{C_LNGE}?#{C_STYL}?#{C_CLAS}?)" | ||
# PUNCT = Regexp::quote( '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~' ) | ||
PUNCT = Regexp::quote( '!"#$%&\'*+,-./:;=?@\\^_`|~' ) | ||
350 | PUNCT_NOQ = Regexp::quote( '!"#$&\',./:;=?@\\`|' ) | |
351 | PUNCT_Q = Regexp::quote( '*-_+^~%' ) | |
HYPERLINK = '(\S+?)([^\w\s/;=\?]*?)(?=\s|<|$)' | ||
# Text markup tags, don't conflict with block tags | ||
... | ... | |
'br', 'map', 'q', 'sub', 'sup', 'span', 'bdo' | ||
] | ||
345 | | |
346 | | |
347 | | |
348 | | |
349 | | |
350 | | |
351 | | |
352 | | |
353 | | |
354 | | |
355 | | |
356 | | |
357 | | |
358 | | |
359 | | |
360 | | |
361 | | |
362 | | |
363 | | |
364 | | |
365 | | |
366 | ||
367 | | |
368 | | |
369 | | |
370 | | |
371 | | |
372 | | |
373 | ||
374 | | |
375 | | |
376 | | |
377 | | |
378 | | |
379 | ||
QTAGS = [ | ||
['**', 'b'], | ||
['*', 'strong'], | ||
... | ... | |
(#{rcq}) | ||
(#{C}) | ||
(?::(\S+?))? | ||
401 | | |
382 | (\S.*?\S|\S) | |
#{rcq} | ||
(?=\W)/x | ||
else | ||
/(#{rcq}) | ||
(#{C}) | ||
407 | | |
408 | | |
388 | (?::(\S+))? | |
389 | (\S.*?\S|\S) | |
#{rcq}/xm | ||
end | ||
[rc, ht, re, rtype] | ||
end | ||
395 | # Elements to handle | |
396 | GLYPHS = [ | |
397 | # [ /([^\s\[{(>])?\'([dmst]\b|ll\b|ve\b|\s|:|$)/, '\1’\2' ], # single closing | |
398 | [ /([^\s\[{(>#{PUNCT_Q}][#{PUNCT_Q}]*)\'/, '\1’' ], # single closing | |
399 | [ /\'(?=[#{PUNCT_Q}]*(s\b|[\s#{PUNCT_NOQ}]))/, '’' ], # single closing | |
400 | [ /\'/, '‘' ], # single opening | |
401 | [ /</, '<' ], # less-than | |
402 | [ />/, '>' ], # greater-than | |
403 | # [ /([^\s\[{(])?"(\s|:|$)/, '\1”\2' ], # double closing | |
404 | [ /([^\s\[{(>#{PUNCT_Q}][#{PUNCT_Q}]*)"/, '\1”' ], # double closing | |
405 | [ /"(?=[#{PUNCT_Q}]*[\s#{PUNCT_NOQ}])/, '”' ], # double closing | |
406 | [ /"/, '“' ], # double opening | |
407 | [ /\b( )?\.{3}/, '\1…' ], # ellipsis | |
408 | [ /\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/, '<acronym title="\2">\1</acronym>' ], # 3+ uppercase acronym | |
409 | [ /(^|[^"][>\s])([A-Z][A-Z0-9 ]+[A-Z0-9])([^<A-Za-z0-9]|$)/, '\1<span class="caps">\2</span>\3', :no_span_caps ], # 3+ uppercase caps | |
410 | [ /(\.\s)?\s?--\s?/, '\1—' ], # em dash | |
411 | [ /\s->\s/, ' → ' ], # right arrow | |
412 | [ /\s-\s/, ' – ' ], # en dash | |
413 | [ /(\d+) ?x ?(\d+)/, '\1×\2' ], # dimension sign | |
414 | [ /\b ?[(\[]TM[\])]/i, '™' ], # trademark | |
415 | [ /\b ?[(\[]R[\])]/i, '®' ], # registered | |
416 | [ /\b ?[(\[]C[\])]/i, '©' ] # copyright | |
417 | ] | |
418 | ||
419 | H_ALGN_VALS = { | |
420 | '<' => 'left', | |
421 | '=' => 'center', | |
422 | '>' => 'right', | |
423 | '<>' => 'justify' | |
424 | } | |
425 | ||
426 | V_ALGN_VALS = { | |
427 | '^' => 'top', | |
428 | '-' => 'middle', | |
429 | '~' => 'bottom' | |
430 | } | |
431 | ||
# | ||
# Flexible HTML escaping | ||
# | ||
... | ... | |
depth.pop | ||
end | ||
end | ||
533 | | |
551 | if depth.last and depth.last.length == tl.length | |
lines[line_id - 1] << '</li>' | ||
end | ||
end | ||
... | ... | |
end | ||
def hard_break( text ) | ||
580 | | |
598 | text.gsub!( /(.)\n(?!\Z| *([#*=]+(\s|$)|[{|]))/, "\\1<br />" ) if hard_breaks | |
end | ||
BLOCKS_GROUP_RE = /\n{2,}(?! )/m | ||
... | ... | |
end | ||
end | ||
708 | | |
726 | MARKDOWN_RULE_RE = /^(#{ | |
['*', '-', '_'].collect { |ch| '( ?' + Regexp::quote( ch ) + ' ?){3,}' }.join( '|' ) | ||
710 | | |
728 | })$/ | |
def block_markdown_rule( text ) | ||
text.gsub!( MARKDOWN_RULE_RE ) do |blk| | ||
... | ... | |
def block_markdown_lists( text ) | ||
end | ||
722 | | |
723 | | |
724 | ||
def inline_textile_span( text ) | ||
QTAGS.each do |qtag_rc, ht, qtag_re, rtype| | ||
text.gsub!( qtag_re ) do |m| | ||
... | ... | |
def shelve( val ) | ||
@shelf << val | ||
906 | | |
921 | " :redsh##{ @shelf.length }:" | |
end | ||
def retrieve( text ) | ||
@shelf.each_with_index do |r, i| | ||
911 | | |
926 | text.gsub!( " :redsh##{ i + 1 }:", r ) | |
end | ||
end | ||
... | ... | |
HASTAG_MATCH = /(<\/?\w[^\n]*?>)/m | ||
ALLTAG_MATCH = /(<\/?\w[^\n]*?>)|.*?(?=<\/?\w[^\n]*?>|$)/m | ||
968 | | |
983 | def glyphs_textile( text, level = 0 ) | |
if text !~ HASTAG_MATCH | ||
pgl text | ||
footnote_ref text | ||
... | ... | |
codepre = 0 if codepre < 0 | ||
end | ||
elsif codepre.zero? | ||
984 | | |
999 | glyphs_textile( line, level + 1 ) | |
else | ||
htmlesc( line, :NoQuotes ) | ||
end | ||
988 | | |
1003 | # p [level, codepre, line] | |
line | ||
end | ||
... | ... | |
end | ||
def inline( text ) | ||
1036 | | |
1037 | | |
1051 | [/^inline_/, /^glyphs_/].each do |meth_re| | |
1052 | @rules.each do |rule_name| | |
1053 | method( rule_name ).call( text ) if rule_name.to_s.match( meth_re ) | |
1054 | end | |
end | ||
end | ||
... | ... | |
q2 = ( q != '' ? q : '\s' ) | ||
if raw[3] =~ /#{prop}\s*=\s*#{q}([^#{q2}]+)#{q}/i | ||
attrv = $1 | ||
1100 | | |
1117 | next if prop == 'src' and attrv =~ %r{^(?!http)\w+:} | |
pcs << "#{prop}=\"#{$1.gsub('"', '\\"')}\"" | ||
break | ||
end |
rool/rails/typo/trunk/vendor/redcloth/run-tests.rb:
prev. | current | |
Dir["tests/*.yml"].each do |testfile| | ||
YAML::load_documents( File.open( testfile ) ) do |doc| | ||
if doc['in'] and doc['out'] | ||
8 | | |
8 | opts = [] | |
9 | opts << :hard_breaks if testfile =~ /hard_breaks/ | |
10 | red = RedCloth.new( doc['in'], opts ) | |
html = if testfile =~ /markdown/ | ||
red.to_html( :markdown ) | ||
else |
rool/rails/typo/trunk/vendor/redcloth/tests/table.yml:
prev. | current | |
<td>11/18/04</td> | ||
<td>11/18/04</td> | ||
<td>070</td> | ||
42 | | |
42 | <td><span class="caps">XML</span> spec complete</td> | |
</tr> | ||
<tr> | ||
<td><img src="/i/g.gif" alt="" /></td> | ||
<td>11/29/04</td> | ||
<td>11/29/04</td> | ||
<td>011</td> | ||
49 | | |
49 | <td><span class="caps">XML</span> spec complete (KH is on schedule)</td> | |
</tr> | ||
<tr> | ||
<td><img src="/i/g.gif" alt="" /></td> | ||
<td>11/29/04</td> | ||
<td>11/29/04</td> | ||
<td>051</td> | ||
56 | | |
56 | <td><span class="caps">XML</span> spec complete (KH is on schedule)</td> | |
</tr> | ||
<tr> | ||
<td><img src="/i/g.gif" alt="" /></td> | ||
<td>11/29/04</td> | ||
<td>11/29/04</td> | ||
<td>081</td> | ||
63 | | |
63 | <td><span class="caps">XML</span> spec complete (KH is on schedule)</td> | |
</tr> | ||
<tr> | ||
<td><img src="/i/g.gif" alt="" /></td> |
rool/rails/typo/trunk/vendor/redcloth/tests/textism.yml:
prev. | current | |
in: '**a phrase**' | ||
out: <p><b>a phrase</b></p> | ||
--- | ||
74 | in: '*(a)* a' | |
75 | out: <p><strong>(a)</strong> a</p> | |
76 | --- | |
77 | in: '*(a)* *' | |
78 | out: <p><strong>(a)</strong> *</p> | |
79 | --- | |
in: Nabokov's ??Pnin?? | ||
out: <p>Nabokov’s <cite>Pnin</cite></p> | ||
--- | ||
... | ... | |
<li>We must act</li> | ||
</ul> | ||
404 | --- | |
405 | in: '"test":http://foo.com/b---ar' | |
406 | out: <p><a href="http://foo.com/b---ar">test</a></p> |