proclaim 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG +6 -0
- data/Gemfile +14 -0
- data/LICENSE +674 -0
- data/README.md +137 -0
- data/Rakefile +65 -0
- data/VERSION +1 -0
- data/app/assets/images/ajax_loader.gif +0 -0
- data/app/assets/javascripts/proclaim.js +18 -0
- data/app/assets/javascripts/proclaim/comments_handler.js.coffee +192 -0
- data/app/assets/javascripts/proclaim/editor.js.coffee +50 -0
- data/app/assets/javascripts/proclaim/images.js.coffee +3 -0
- data/app/assets/javascripts/proclaim/subscriptions.js.coffee +3 -0
- data/app/assets/stylesheets/proclaim.css.scss +28 -0
- data/app/assets/stylesheets/proclaim/comments.css.scss +14 -0
- data/app/assets/stylesheets/proclaim/images.scss +3 -0
- data/app/assets/stylesheets/proclaim/posts.css.scss +77 -0
- data/app/assets/stylesheets/proclaim/subscriptions.css.scss +3 -0
- data/app/controllers/proclaim/application_controller.rb +44 -0
- data/app/controllers/proclaim/comments_controller.rb +128 -0
- data/app/controllers/proclaim/images_controller.rb +108 -0
- data/app/controllers/proclaim/posts_controller.rb +131 -0
- data/app/controllers/proclaim/subscriptions_controller.rb +67 -0
- data/app/helpers/proclaim/application_helper.rb +34 -0
- data/app/helpers/proclaim/comments_helper.rb +4 -0
- data/app/helpers/proclaim/images_helper.rb +4 -0
- data/app/helpers/proclaim/posts_helper.rb +4 -0
- data/app/helpers/proclaim/subscriptions_helper.rb +4 -0
- data/app/mailers/proclaim/subscription_mailer.rb +43 -0
- data/app/models/proclaim/comment.rb +35 -0
- data/app/models/proclaim/image.rb +19 -0
- data/app/models/proclaim/post.rb +133 -0
- data/app/models/proclaim/subscription.rb +63 -0
- data/app/policies/application_policy.rb +53 -0
- data/app/policies/proclaim/comment_policy.rb +27 -0
- data/app/policies/proclaim/image_policy.rb +29 -0
- data/app/policies/proclaim/post_policy.rb +38 -0
- data/app/policies/proclaim/subscription_policy.rb +32 -0
- data/app/uploaders/proclaim/image_uploader.rb +82 -0
- data/app/views/layouts/proclaim/subscription_mailer.html.erb +133 -0
- data/app/views/proclaim/comments/_comment.html.erb +33 -0
- data/app/views/proclaim/comments/_form.html.erb +51 -0
- data/app/views/proclaim/posts/_form.html.erb +67 -0
- data/app/views/proclaim/posts/edit.html.erb +3 -0
- data/app/views/proclaim/posts/index.html.erb +30 -0
- data/app/views/proclaim/posts/new.html.erb +3 -0
- data/app/views/proclaim/posts/show.html.erb +46 -0
- data/app/views/proclaim/subscription_mailer/new_comment_notification_email.html.erb +11 -0
- data/app/views/proclaim/subscription_mailer/new_post_notification_email.html.erb +15 -0
- data/app/views/proclaim/subscription_mailer/welcome_email.html.erb +25 -0
- data/app/views/proclaim/subscriptions/_form.html.erb +32 -0
- data/app/views/proclaim/subscriptions/new.html.erb +8 -0
- data/app/views/proclaim/subscriptions/subscribed.html.erb +7 -0
- data/app/views/proclaim/subscriptions/unsubscribe.html.erb +7 -0
- data/app/views/proclaim/subscriptions/unsubscribed.html.erb +3 -0
- data/config/routes.rb +18 -0
- data/db/migrate/20141108222616_create_proclaim_posts.rb +15 -0
- data/db/migrate/20141114235359_create_proclaim_comments.rb +15 -0
- data/db/migrate/20141115022230_create_proclaim_comment_hierarchies.rb +26 -0
- data/db/migrate/20141210234057_create_proclaim_subscriptions.rb +17 -0
- data/db/migrate/20141222224905_create_proclaim_images.rb +12 -0
- data/lib/generators/proclaim/install_generator.rb +23 -0
- data/lib/generators/proclaim/templates/README +27 -0
- data/lib/generators/proclaim/templates/initialize_proclaim.rb +22 -0
- data/lib/generators/proclaim/views_generator.rb +24 -0
- data/lib/proclaim.rb +22 -0
- data/lib/proclaim/engine.rb +39 -0
- data/lib/proclaim/version.rb +3 -0
- data/lib/tasks/proclaim_tasks.rake +4 -0
- data/proclaim.gemspec +46 -0
- data/test/controllers/proclaim/comments_controller_test.rb +228 -0
- data/test/controllers/proclaim/images_controller_test.rb +123 -0
- data/test/controllers/proclaim/posts_controller_test.rb +303 -0
- data/test/controllers/proclaim/subscriptions_controller_test.rb +93 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +14 -0
- data/test/dummy/app/assets/stylesheets/application.css +16 -0
- data/test/dummy/app/controllers/application_controller.rb +15 -0
- data/test/dummy/app/helpers/application_helper.rb +28 -0
- data/test/dummy/app/models/user.rb +7 -0
- data/test/dummy/app/views/layouts/application.html.erb +16 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +24 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +45 -0
- data/test/dummy/config/environments/production.rb +80 -0
- data/test/dummy/config/environments/test.rb +49 -0
- data/test/dummy/config/initializers/assets.rb +8 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +5 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/db/migrate/20141117214323_create_users.rb +10 -0
- data/test/dummy/db/schema.rb +75 -0
- data/test/dummy/log/development.log +131 -0
- data/test/dummy/log/test.log +25961 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/tmp/cache/assets/test/sass/0b69f7cc441d56def3a51688e6a7a8474dc476d1/proclaim.css.scssc +0 -0
- data/test/dummy/tmp/cache/assets/test/sass/12a97df611d5fb0e395afda829edf8b9372acde7/comments.css.scssc +0 -0
- data/test/dummy/tmp/cache/assets/test/sass/12a97df611d5fb0e395afda829edf8b9372acde7/images.scssc +0 -0
- data/test/dummy/tmp/cache/assets/test/sass/12a97df611d5fb0e395afda829edf8b9372acde7/posts.css.scssc +0 -0
- data/test/dummy/tmp/cache/assets/test/sass/12a97df611d5fb0e395afda829edf8b9372acde7/subscriptions.css.scssc +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/04adcece63bc645379e6de797e7998f8 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/06620fc450f0a9b4a482a7bc08387711 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/076dd0d567a92c34163b3b98af1d48ba +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/09fc2eadf6d6062b2cc135a44e4e73db +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/09fe8c62e8ae706e01058b4b4d056c8e +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/142fd040033525acb73ad2ccf1406aea +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/1762aeeaf38da3b8d989a5b66b088004 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/194ac1a695334e303516614579b3926d +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/197ea008934db3e7ea8045302d206b92 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/19eba2635fec0895379c3e38f81ada84 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/1c2ebe72fcd7ff1379a561552ca30f85 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/1f42c80faacb651f670ec2b0998e49dc +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/2243230e778a749ecbf0415a52e75be0 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/23ad87e715c70312aa61dde4fbb4bfe1 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/245b8735db4ea90bcaa91c011a1f447e +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/26a42dac0cec64483f4126d2de4b0c9e +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/30151c8f6d93717f06fa12774612ddf4 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/3c623d200214a5334aaf170537db087f +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/3ec36650a50759fd4b75794cb253936f +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/40431cdcc10c75ba1f275ecfe42623d3 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/4226218a4b06608115b21063353370ea +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/437901953eb8707af6c27ca59cf65d91 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/461885b8ad31ef6a94c9a4f2e332b7eb +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/4792f46317cda92ccd5b278ec61f9ac5 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/4dcb3434b91b1c62f897a1741c6d398b +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/5101cda93cf70f0fc0837713be587780 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/52d8c61de0703e0d7cf97d0f7b0cca7a +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/57f3d19a9bd484ac68c46f962a8684b2 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/587e7c1332c8d8b69746dd85164e2cef +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/5934d5d0d1ac6657842708e85c73cf51 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/5af081799d7da2f04ead6a516c6015ad +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/69ee5af8d9a655898a67bc538ca1c7e7 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/6d1c56259648b0383bc438c875a448c3 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/6e7de35055967df848aa490830043e51 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/70bc59560ee544af7bb2f727247db307 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/728cb566999910549092ff0a98e2853b +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/72b5f0d35e9d69b744a156edad98f983 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/72ffa34d552e3fd02f28a6f845a5ac5b +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/7369d324e84bc872c42b3e717ff4ad6c +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/749a8b0e45b11df748a256dd04ceb1f7 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/77fb9f62552d9b786f9407ef11cc9a09 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/797823842565e01fc989ad8df0bd4254 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/7c139afa2296ac17483520109aecd449 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/7fb99e2b35af65c4f58bfb92dd4185b4 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/819de31c63b704f9ddf4865587a91d41 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/8604b464bf846e5223da37ef2f29b524 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/88fc815613b473e98e9307b1d423918d +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/8bc4341aa4060b8646e8134722cf3b11 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/8cf8fd5ff8eae12211a88f971af30236 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/8da3b4a9f17aafff49eb263bdb758f44 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/9168e513bae02f041dbb806d6dbe94ac +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/920c1322be1212a54b7c4f2751d5e7bf +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/92205679a36afd387a2ba5c585a5a62c +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/940566ebcae2d4e5c56a881ab66f2cf0 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/976967e07e2944a7ecc7403667f1f96b +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/99bdde70cefa71745279232be575f14e +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/9a8e402a7e32063e46647403b43553a5 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/9b09ad72f8cc33503878b01c713d92d0 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/a20dbdfebf37fe50e832a6273c972553 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/a3c6189fad6cb9ae955f6d5a43a61d51 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/abb54e11ff057a3e22a5a97d27cc4fa3 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/ad18e3875541d4298b1df133d494b93f +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/b9b7c575c22943d49734d52381c5ee16 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/ba269a52f100d3d6cffda81e82e1ed49 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/bc7a0846b4881b0832d41de2b1724dba +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/bcb2df87f9611d3cc3ef8a5575e54fb8 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/bcf33791d3286af3ba2cdf6a6756c89e +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/be32d0a530ce861537d6abfa41333df9 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/c8270a6f07dccc5f00e6b2b43f10efd2 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/cd82cd410a50bffcfb6e21e3c49a85c9 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/ce4ccaa06bdee6426486224bc7e54187 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/d0bdb8592e4eed80aa2341e37f20dbc9 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/d4b784b16fa1b1dfcca6590689a8c157 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/d968bd38a69bbf5c0065e2df3d30cfd3 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/daa4d4b8a5ce46d6c4ecf031e0c61cfe +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/dc2effd195334219a7e4acfdc7ec7974 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/de36ab6c3b1a9b62a586d98373dd569c +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/e3aec457d5c753090d6521f2bb2d91b6 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/e8d6158b1fed2f574242b55856a3953d +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/ea82f6aececcf81eef3e2e15a9225e66 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/ed9f5c17f71ec75de10b1bb029ebd7a2 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/f2984adaeaa5322e3a040705c6d40622 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/f62fd0cf9f5e7e077ec9c4daeccb06ae +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/f78ea69bdbba5738c052e9eb04e6c208 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/f864e553f706456dbdf168319970ec2e +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/fb0f641bfcbb0101c040da9ff736447b +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/fe426a44cf23cf82032091cbffff898c +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/ff732ea47a86c449582b2a81ef2930da +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/ffc4980851addaacf12abeebfa63e07f +0 -0
- data/test/dummy/tmp/generators/config/initializers/proclaim.rb +22 -0
- data/test/factories/proclaim/comment.rb +11 -0
- data/test/factories/proclaim/image.rb +6 -0
- data/test/factories/proclaim/post.rb +14 -0
- data/test/factories/proclaim/subscription.rb +13 -0
- data/test/factories/user.rb +6 -0
- data/test/helpers/proclaim/comments_helper_test.rb +6 -0
- data/test/helpers/proclaim/posts_helper_test.rb +6 -0
- data/test/helpers/proclaim/subscriptions_helper_test.rb +6 -0
- data/test/integration/with_javascript/comment_test.rb +353 -0
- data/test/integration/with_javascript/post_form_test.rb +179 -0
- data/test/integration/with_javascript/post_subscription_test.rb +273 -0
- data/test/integration/without_javascript/blog_subscription_test.rb +87 -0
- data/test/integration/without_javascript/post_test.rb +140 -0
- data/test/integration/without_javascript/subscription_email_test.rb +95 -0
- data/test/integration/without_javascript/unsubscribe_test.rb +32 -0
- data/test/mailers/previews/proclaim/subscription_mailer_preview.rb +22 -0
- data/test/mailers/proclaim/subscription_mailer_test.rb +87 -0
- data/test/models/proclaim/comment_test.rb +41 -0
- data/test/models/proclaim/image_test.rb +70 -0
- data/test/models/proclaim/post_test.rb +127 -0
- data/test/models/proclaim/subscription_test.rb +66 -0
- data/test/policies/proclaim/comment_policy_test.rb +71 -0
- data/test/policies/proclaim/post_policy_test.rb +87 -0
- data/test/policies/proclaim/subscription_policy_test.rb +91 -0
- data/test/proclaim_test.rb +7 -0
- data/test/support/images/test.jpg +0 -0
- data/test/support/pages/posts/edit_page.rb +5 -0
- data/test/support/pages/posts/show_page.rb +47 -0
- data/test/support/wait_for_ajax.rb +11 -0
- data/test/test_helper.rb +56 -0
- data/vendor/assets/images/link.png +0 -0
- data/vendor/assets/images/remove.png +0 -0
- data/vendor/assets/images/resize-bigger.png +0 -0
- data/vendor/assets/images/resize-smaller.png +0 -0
- data/vendor/assets/images/unlink.png +0 -0
- data/vendor/assets/javascripts/addons/medium-editor-insert-embeds.js +197 -0
- data/vendor/assets/javascripts/addons/medium-editor-insert-embeds.min.js +10 -0
- data/vendor/assets/javascripts/addons/medium-editor-insert-images.js +572 -0
- data/vendor/assets/javascripts/addons/medium-editor-insert-images.min.js +10 -0
- data/vendor/assets/javascripts/addons/medium-editor-insert-maps.js +50 -0
- data/vendor/assets/javascripts/addons/medium-editor-insert-maps.min.js +10 -0
- data/vendor/assets/javascripts/addons/medium-editor-insert-plugin.js +496 -0
- data/vendor/assets/javascripts/addons/medium-editor-insert-plugin.min.js +10 -0
- data/vendor/assets/javascripts/addons/medium-editor-insert-tables.js +132 -0
- data/vendor/assets/javascripts/addons/medium-editor-insert-tables.min.js +10 -0
- data/vendor/assets/javascripts/medium-editor-insert-plugin.all.js +1415 -0
- data/vendor/assets/javascripts/medium-editor-insert-plugin.all.min.js +10 -0
- data/vendor/assets/stylesheets/medium-editor-insert-plugin-frontend.css +55 -0
- data/vendor/assets/stylesheets/medium-editor-insert-plugin-frontend.min.css +10 -0
- data/vendor/assets/stylesheets/medium-editor-insert-plugin.css +277 -0
- data/vendor/assets/stylesheets/medium-editor-insert-plugin.min.css +10 -0
- metadata +791 -0
data/README.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Proclaim
|
|
2
|
+
|
|
3
|
+
Most Rails blogging tools include everything you could ever want, including
|
|
4
|
+
things you don't. Proclaim tries to provide the simplest (yet beautiful)
|
|
5
|
+
implementation of a blog you could want-- posts, comments, and subscriptions.
|
|
6
|
+
It's not meant to *be* your entire website-- it's a mountable engine. Mount it
|
|
7
|
+
where you want it, configure it, and you have a blog. It otherwise stays out of
|
|
8
|
+
your way.
|
|
9
|
+
|
|
10
|
+
## Getting Started
|
|
11
|
+
|
|
12
|
+
### Get Proclaim
|
|
13
|
+
|
|
14
|
+
Proclaim 0.1 works with Rails 4.2 and on. Add it to your Gemfile with:
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
gem 'proclaim', "~> 0.1.0"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Run `bundle install` to install it.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Install Proclaim
|
|
24
|
+
|
|
25
|
+
After you've added Proclaim to your gemfile, you can install it with:
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
rails generate proclaim:install
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The generator will install an initializer which describes all of Proclaim's
|
|
32
|
+
configuration options. You should check those out, and change them if necessary.
|
|
33
|
+
It will also mount Proclaim in your `config/routes.rb` at the path `/blog`.
|
|
34
|
+
|
|
35
|
+
Now run `rake db:migrate`
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
### Setup Assets
|
|
39
|
+
|
|
40
|
+
Include Proclaim in Javascript manifest file:
|
|
41
|
+
|
|
42
|
+
```javascript
|
|
43
|
+
//= require proclaim
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Include Proclaim in Stylesheet manifest file:
|
|
47
|
+
|
|
48
|
+
```scss
|
|
49
|
+
*= require proclaim
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### Setup Mailer and Root Route
|
|
54
|
+
|
|
55
|
+
Proclaim sends emails when:
|
|
56
|
+
|
|
57
|
+
- A new subscription is added (A welcome email)
|
|
58
|
+
- A new comment is made on a post to which subscriptions exist
|
|
59
|
+
- A new post is made and subscriptions exist on the blog itself
|
|
60
|
+
|
|
61
|
+
Because of this, ensure that the mailer has default URL options in each
|
|
62
|
+
environment. Here is a possible configuration for
|
|
63
|
+
`config/environments/development.rb`:
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
A default root path must also be defined in the application's routes:
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
root to: "home#index"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
### Engine Configuration Options
|
|
77
|
+
|
|
78
|
+
The Proclaim engine has a number of configurable parameters that mostly relate
|
|
79
|
+
to tying the engine in with the rest of the site. Proclaim tries to be as
|
|
80
|
+
unobtrusive as possible-- it doesn't provide users or authentication. It does,
|
|
81
|
+
however, require some concept of authors, expecting that they authenticate
|
|
82
|
+
somehow, and posts will belong to whichever author publishes them.
|
|
83
|
+
|
|
84
|
+
All configuration items (and their defaults) follow:
|
|
85
|
+
|
|
86
|
+
```ruby
|
|
87
|
+
Proclaim.author_class = "User"
|
|
88
|
+
Proclaim.author_name_method = :name
|
|
89
|
+
Proclaim.current_author_method = :current_user
|
|
90
|
+
Proclaim.authentication_method = :authenticate_user!
|
|
91
|
+
Proclaim.excerpt_length = 500
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
- **Proclaim.author_class**
|
|
95
|
+
|
|
96
|
+
The class to which posts belong. Changing this also changes the default
|
|
97
|
+
`Proclaim.current_author_method` and `Proclaim.authentication_method`. For
|
|
98
|
+
example, setting `author_class = "Admin"` changes the default
|
|
99
|
+
`current_author_method` to be `:current_admin`, etc.
|
|
100
|
+
|
|
101
|
+
- **Proclaim.author_name_method**
|
|
102
|
+
|
|
103
|
+
Method to obtain the name of the author. This should be a method on the author
|
|
104
|
+
class.
|
|
105
|
+
|
|
106
|
+
- **Proclaim.current_author_method**
|
|
107
|
+
|
|
108
|
+
Method to obtain the currently-authenticated user. Should return nil if no
|
|
109
|
+
user is currently authenticated.
|
|
110
|
+
|
|
111
|
+
- **Proclaim.authentication_method**
|
|
112
|
+
|
|
113
|
+
Method to verify that a user is authenticated, and if not, will redirect to
|
|
114
|
+
some sort of authentication page.
|
|
115
|
+
|
|
116
|
+
- **Proclaim.excerpt_length**
|
|
117
|
+
|
|
118
|
+
Maximum length for the excerpts shown on the posts index. The excerpts may be
|
|
119
|
+
less than this, but will never exceed it.
|
|
120
|
+
|
|
121
|
+
Astute readers may note that the defaults corresponds to defaults from Devise (on
|
|
122
|
+
the User class). If that's not your setup, all of these options can be changed
|
|
123
|
+
in the initializer installed by `rails generate proclaim:install`.
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
## Customizations
|
|
127
|
+
|
|
128
|
+
Proclaim was built to help you quickly develop an application that includes a
|
|
129
|
+
blog. However, it shouldn't be in your way when you need to customize it. Since
|
|
130
|
+
Proclaim is an engine, all of its views are packaged inside the gem. These views
|
|
131
|
+
will get you started, and you can always implement new styles via CSS, but you
|
|
132
|
+
may wish to change them completely. You can simply copy them into your
|
|
133
|
+
application and alter them by using the generator:
|
|
134
|
+
|
|
135
|
+
```ruby
|
|
136
|
+
rails generate proclaim:views
|
|
137
|
+
```
|
data/Rakefile
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
require 'rdoc/task'
|
|
8
|
+
|
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
11
|
+
rdoc.title = 'Proclaim'
|
|
12
|
+
rdoc.options << '--line-numbers'
|
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
|
18
|
+
load 'rails/tasks/engine.rake'
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
Bundler::GemHelper.install_tasks
|
|
23
|
+
|
|
24
|
+
require 'rake/testtask'
|
|
25
|
+
|
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
|
27
|
+
t.libs << 'lib'
|
|
28
|
+
t.libs << 'test'
|
|
29
|
+
t.verbose = false
|
|
30
|
+
if ENV["TEST"].nil?
|
|
31
|
+
t.pattern = 'test/**/*_test.rb'
|
|
32
|
+
else
|
|
33
|
+
t.pattern = ENV["TEST"]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
namespace :test do
|
|
38
|
+
Rails::TestTask.new(:generators) do |t|
|
|
39
|
+
t.pattern = "test/lib/generators/**/*_test.rb"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
Rails::TestTask.new(:units) do |t|
|
|
43
|
+
t.pattern = 'test/{models,helpers,unit}/**/*_test.rb'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
Rails::TestTask.new(:functionals) do |t|
|
|
47
|
+
t.pattern = 'test/{controllers,mailers,functional}/**/*_test.rb'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
Rails::TestTask.new(:integration) do |t|
|
|
51
|
+
t.pattern = 'test/integration/**/*_test.rb'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
namespace :integration do
|
|
55
|
+
Rails::TestTask.new(:js) do |t|
|
|
56
|
+
t.pattern = 'test/integration/with_javascript/**/*_test.rb'
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
Rails::TestTask.new(:no_js) do |t|
|
|
60
|
+
t.pattern = 'test/integration/without_javascript/**/*_test.rb'
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
task default: :test
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.1.0
|
|
Binary file
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
|
2
|
+
// listed below.
|
|
3
|
+
//
|
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
|
6
|
+
//
|
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
|
8
|
+
// compiled file.
|
|
9
|
+
//
|
|
10
|
+
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
|
11
|
+
// about supported directives.
|
|
12
|
+
//
|
|
13
|
+
//= require jquery
|
|
14
|
+
//= require jquery_ujs
|
|
15
|
+
//= require medium-editor
|
|
16
|
+
//= require medium-editor-insert-plugin.all.min
|
|
17
|
+
//= require rails-timeago
|
|
18
|
+
//= require_tree .
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
class CommentsHandler
|
|
2
|
+
constructor: (@discussionClass, @commentClass, @commentFormClass,
|
|
3
|
+
@mainCommentFormClass, @cancelCommentButtonClass,
|
|
4
|
+
@replyLinkClass, @updateLinkClass, @deleteLinkClass,
|
|
5
|
+
@subscribeCheckboxClass, @subscribeEmailClass) ->
|
|
6
|
+
if (@discussionClass.length > 0) and
|
|
7
|
+
(@commentClass.length > 0) and
|
|
8
|
+
(@commentFormClass.length > 0) and
|
|
9
|
+
(@mainCommentFormClass.length > 0) and
|
|
10
|
+
(@cancelCommentButtonClass.length > 0) and
|
|
11
|
+
(@replyLinkClass.length > 0) and
|
|
12
|
+
(@updateLinkClass.length > 0) and
|
|
13
|
+
(@deleteLinkClass.length > 0) and
|
|
14
|
+
(@subscribeCheckboxClass.length > 0) and
|
|
15
|
+
(@subscribeEmailClass.length > 0)
|
|
16
|
+
@cleanBindings()
|
|
17
|
+
@addBindings()
|
|
18
|
+
else
|
|
19
|
+
console.error("Invalid length for comment classes!")
|
|
20
|
+
|
|
21
|
+
addBindings: ->
|
|
22
|
+
$(document).on "click", @replyLinkClass, @showNewCommentForm
|
|
23
|
+
$(document).on "click", @updateLinkClass, @showUpdateCommentForm
|
|
24
|
+
$(document).on "click", @cancelCommentButtonClass, @cancelComment
|
|
25
|
+
|
|
26
|
+
$(document).on "ajax:beforeSend", @commentFormClass, @handleCommentStarted
|
|
27
|
+
$(document).on "ajax:complete", @commentFormClass, @handleCommentFinished
|
|
28
|
+
|
|
29
|
+
$(document).on "ajax:success", @commentFormClass, @handleCommentSuccess
|
|
30
|
+
$(document).on "ajax:error", @commentFormClass, @handleCommentFailure
|
|
31
|
+
|
|
32
|
+
$(document).on "ajax:success", @deleteLinkClass, @handleDeleteCommentSuccess
|
|
33
|
+
$(document).on "ajax:error", @deleteLinkClass, @handleDeleteCommentFailure
|
|
34
|
+
|
|
35
|
+
$(document).on "change", @subscribeCheckboxClass, @handleSubscribeCheckbox
|
|
36
|
+
|
|
37
|
+
cleanBindings: ->
|
|
38
|
+
$(document).off "click", @replyLinkClass
|
|
39
|
+
$(document).off "click", @updateLinkClass
|
|
40
|
+
$(document).off "click", @cancelCommentButtonClass
|
|
41
|
+
|
|
42
|
+
$(document).off "ajax:beforeSend", @commentFormClass
|
|
43
|
+
$(document).off "ajax:complete", @commentFormClass
|
|
44
|
+
|
|
45
|
+
$(document).off "ajax:success", @commentFormClass
|
|
46
|
+
$(document).off "ajax:error", @commentFormClass
|
|
47
|
+
|
|
48
|
+
$(document).off "ajax:success", @deleteLinkClass
|
|
49
|
+
$(document).off "ajax:error", @deleteLinkClass
|
|
50
|
+
|
|
51
|
+
$(document).off "change", @subscribeCheckboxClass
|
|
52
|
+
|
|
53
|
+
# Disable the form until the new comment has been processed
|
|
54
|
+
handleCommentStarted: (event, xhr, settings) =>
|
|
55
|
+
form = $(event.target)
|
|
56
|
+
form.find(":input").prop("disabled", true);
|
|
57
|
+
form.before('<div class = "loading" style = "width: 100px;"></div>')
|
|
58
|
+
|
|
59
|
+
handleCommentFinished: (event, xhr, status) =>
|
|
60
|
+
form = $(event.target)
|
|
61
|
+
target = $(form.data("target"))
|
|
62
|
+
form.find(":input").prop("disabled", false);
|
|
63
|
+
form.siblings('div.loading').remove()
|
|
64
|
+
|
|
65
|
+
if status == "success"
|
|
66
|
+
@removeForm form
|
|
67
|
+
|
|
68
|
+
handleCommentSuccess: (event, data, status, xhr) =>
|
|
69
|
+
if data.html.length == 0
|
|
70
|
+
console.error("Invalid comment HTML!")
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
form = $(event.target)
|
|
74
|
+
|
|
75
|
+
if form.hasClass("edit_comment")
|
|
76
|
+
form.closest(@discussionClass).replaceWith(data.html)
|
|
77
|
+
else
|
|
78
|
+
target = $(form.data("target"))
|
|
79
|
+
if target.length == 1
|
|
80
|
+
target.append(data.html)
|
|
81
|
+
else
|
|
82
|
+
console.error("Invalid comment target!")
|
|
83
|
+
return
|
|
84
|
+
|
|
85
|
+
# Hide form, but don't remove so events can still be emitted
|
|
86
|
+
@removeForm form, true
|
|
87
|
+
|
|
88
|
+
handleCommentFailure: (event, xhr, status, error) =>
|
|
89
|
+
$(event.target).siblings("div.error").remove()
|
|
90
|
+
errorMessage = "<div class='error'>"
|
|
91
|
+
errorMessage += "<strong>The following errors have prevented this comment from being saved:</strong>"
|
|
92
|
+
errorMessage += "<ul>"
|
|
93
|
+
for error in $.parseJSON(xhr.responseText)
|
|
94
|
+
errorMessage += "<li>" + error + "</li>"
|
|
95
|
+
errorMessage += "</ul>"
|
|
96
|
+
errorMessage += "</div>"
|
|
97
|
+
$(event.target).before(errorMessage)
|
|
98
|
+
|
|
99
|
+
handleDeleteCommentSuccess: (event, data, status, xhr) =>
|
|
100
|
+
commentContainer = $(event.target).closest(@discussionClass)
|
|
101
|
+
if commentContainer.length == 1
|
|
102
|
+
commentContainer.fadeOut ->
|
|
103
|
+
commentContainer.remove()
|
|
104
|
+
else
|
|
105
|
+
console.error("No comment container for removal!")
|
|
106
|
+
|
|
107
|
+
handleDeleteCommentFailure: (event, xhr, status, error) =>
|
|
108
|
+
console.error("Unable to delete comment!")
|
|
109
|
+
|
|
110
|
+
showNewCommentForm: (event) =>
|
|
111
|
+
event.preventDefault()
|
|
112
|
+
|
|
113
|
+
target = $($(event.target).data("target"))
|
|
114
|
+
if target.length != 1
|
|
115
|
+
console.error("Invalid comment target data!")
|
|
116
|
+
return
|
|
117
|
+
|
|
118
|
+
# Ensure form isn't already shown. If it is, don't show it again
|
|
119
|
+
if target.children(@commentFormClass).length == 0
|
|
120
|
+
form = $(event.target).data("form")
|
|
121
|
+
if form.length == 0
|
|
122
|
+
console.error("Invalid comment form data!")
|
|
123
|
+
return
|
|
124
|
+
|
|
125
|
+
# Remove all other non-main forms-- make this form exclusive
|
|
126
|
+
other_forms = $(document).find(@commentFormClass).not(@mainCommentFormClass)
|
|
127
|
+
if other_forms.length > 0
|
|
128
|
+
@removeForm other_forms
|
|
129
|
+
|
|
130
|
+
target.append(form)
|
|
131
|
+
form = target.children(@commentFormClass)
|
|
132
|
+
form.addClass("new_comment")
|
|
133
|
+
|
|
134
|
+
form.children(@cancelCommentButtonClass).focus();
|
|
135
|
+
form.children("input:text:visible:first").focus();
|
|
136
|
+
|
|
137
|
+
showUpdateCommentForm: (event) =>
|
|
138
|
+
event.preventDefault()
|
|
139
|
+
|
|
140
|
+
target = $(event.target)
|
|
141
|
+
|
|
142
|
+
form = target.data("form")
|
|
143
|
+
if form.length == 0
|
|
144
|
+
console.error("Invalid comment form data!")
|
|
145
|
+
return
|
|
146
|
+
|
|
147
|
+
discussion = target.closest(@discussionClass)
|
|
148
|
+
target.closest(@commentClass).hide()
|
|
149
|
+
discussion.prepend(form)
|
|
150
|
+
form = discussion.children(@commentFormClass)
|
|
151
|
+
form.addClass("edit_comment")
|
|
152
|
+
form.children(@cancelCommentButtonClass).focus();
|
|
153
|
+
form.children("input:text:visible:first").focus();
|
|
154
|
+
|
|
155
|
+
cancelComment: (event) =>
|
|
156
|
+
event.preventDefault()
|
|
157
|
+
|
|
158
|
+
form = $(event.target).closest(@commentFormClass)
|
|
159
|
+
if form.hasClass("edit_comment")
|
|
160
|
+
form.siblings(@commentClass).show()
|
|
161
|
+
|
|
162
|
+
$(event.target).siblings(@subscribeEmailClass).hide()
|
|
163
|
+
@removeForm form
|
|
164
|
+
|
|
165
|
+
handleSubscribeCheckbox: (event) =>
|
|
166
|
+
if event.target.checked
|
|
167
|
+
$(event.target).siblings(@subscribeEmailClass).show()
|
|
168
|
+
else
|
|
169
|
+
$(event.target).siblings(@subscribeEmailClass).val("")
|
|
170
|
+
$(event.target).siblings(@subscribeEmailClass).hide()
|
|
171
|
+
|
|
172
|
+
removeForm: (form, hideInsteadOfRemove = false) ->
|
|
173
|
+
if form.length == 0
|
|
174
|
+
console.error("Invalid comment form length for removal!")
|
|
175
|
+
return
|
|
176
|
+
|
|
177
|
+
form.siblings("div.error").remove() # If any
|
|
178
|
+
|
|
179
|
+
form.each (index, element) =>
|
|
180
|
+
thisForm = $(element)
|
|
181
|
+
|
|
182
|
+
# Don't remove the main comment form-- just clear it
|
|
183
|
+
if thisForm.is(@mainCommentFormClass)
|
|
184
|
+
element.reset()
|
|
185
|
+
else
|
|
186
|
+
if (hideInsteadOfRemove)
|
|
187
|
+
thisForm.hide()
|
|
188
|
+
else
|
|
189
|
+
thisForm.remove()
|
|
190
|
+
|
|
191
|
+
# Make available to other scripts
|
|
192
|
+
@CommentsHandler = CommentsHandler
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
class Editor
|
|
2
|
+
constructor: (@form, @titleFormField, @titleEditableItem,
|
|
3
|
+
@bodyFormField, @bodyEditableItem) ->
|
|
4
|
+
if (@form.length == 1) and (@titleFormField.length == 1) and
|
|
5
|
+
(@titleEditableItem.length == 1) and (@bodyFormField.length == 1) and
|
|
6
|
+
(@bodyEditableItem.length == 1)
|
|
7
|
+
imageUploadPath = @bodyEditableItem.data("image-upload-path")
|
|
8
|
+
imageDeletePath = @bodyEditableItem.data("image-delete-path")
|
|
9
|
+
|
|
10
|
+
if (imageUploadPath.length > 0) and (imageDeletePath.length > 0)
|
|
11
|
+
@bodyEditor = new MediumEditor(@bodyEditableItem,
|
|
12
|
+
{buttonLabels: 'fontawesome'})
|
|
13
|
+
|
|
14
|
+
@titleEditor = new MediumEditor(@titleEditableItem)
|
|
15
|
+
|
|
16
|
+
@bodyEditableItem.mediumInsert({
|
|
17
|
+
editor: @bodyEditor,
|
|
18
|
+
addons: {
|
|
19
|
+
images: {
|
|
20
|
+
imagesUploadScript: imageUploadPath,
|
|
21
|
+
imagesDeleteScript: imageDeletePath,
|
|
22
|
+
deleteFile: (file, that) =>
|
|
23
|
+
$.post that.options.imagesDeleteScript, {file: file}, (data, status, jqxhr) =>
|
|
24
|
+
if data.id
|
|
25
|
+
@form.append('<input type="hidden" name="post[images_attributes][' + data.id + '][id]" value="' + data.id + '" />')
|
|
26
|
+
@form.append('<input type="hidden" name="post[images_attributes][' + data.id + '][_destroy]" value="true" />')
|
|
27
|
+
, "json"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
@cleanBindings()
|
|
33
|
+
@addBindings()
|
|
34
|
+
else
|
|
35
|
+
console.error("Missing image upload and/or image delete paths for body editor!")
|
|
36
|
+
else
|
|
37
|
+
console.error("Invalid length for editable items or form fields!")
|
|
38
|
+
|
|
39
|
+
addBindings: ->
|
|
40
|
+
@form.on "submit", @updateFormFields
|
|
41
|
+
|
|
42
|
+
cleanBindings: ->
|
|
43
|
+
@form.off "submit"
|
|
44
|
+
|
|
45
|
+
updateFormFields: (event) =>
|
|
46
|
+
@titleFormField.val(@titleEditor.serialize()["element-0"].value)
|
|
47
|
+
@bodyFormField.val(@bodyEditor.serialize()["element-0"].value)
|
|
48
|
+
|
|
49
|
+
# Make available to other scripts
|
|
50
|
+
@Editor = Editor
|