writefully 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +31 -0
- data/Rakefile +22 -0
- data/app/assets/javascripts/writefully/authorships.js +2 -0
- data/app/assets/javascripts/writefully/sessions.js +2 -0
- data/app/assets/javascripts/writefully/writefully/initializers/boot.coffee +6 -0
- data/app/assets/javascripts/writefully/writefully/initializers/manifest.coffee +28 -0
- data/app/assets/javascripts/writefully/writefully/initializers/setup.coffee +4 -0
- data/app/assets/javascripts/writefully/writefully/loader.coffee +6 -0
- data/app/assets/javascripts/writefully/writefully.coffee +8 -0
- data/app/assets/stylesheets/writefully/base.sass +23 -0
- data/app/assets/stylesheets/writefully/sessions.sass +9 -0
- data/app/assets/stylesheets/writefully/sites.sass +33 -0
- data/app/assets/stylesheets/writefully/writefully.sass +4 -0
- data/app/controllers/writefully/application_controller.rb +28 -0
- data/app/controllers/writefully/authorships_controller.rb +8 -0
- data/app/controllers/writefully/hooks_controller.rb +51 -0
- data/app/controllers/writefully/posts_controller.rb +21 -0
- data/app/controllers/writefully/sessions_controller.rb +47 -0
- data/app/controllers/writefully/sites_controller.rb +51 -0
- data/app/helpers/writefully/application_helper.rb +15 -0
- data/app/helpers/writefully/flash_helper.rb +31 -0
- data/app/helpers/writefully/posts_helper.rb +8 -0
- data/app/helpers/writefully/sites_helper.rb +21 -0
- data/app/models/writefully/authorship.rb +34 -0
- data/app/models/writefully/post.rb +23 -0
- data/app/models/writefully/site.rb +30 -0
- data/app/models/writefully/tag.rb +15 -0
- data/app/models/writefully/tagging.rb +6 -0
- data/app/views/layouts/writefully/application.html.erb +16 -0
- data/app/views/layouts/writefully/sessions.html.erb +16 -0
- data/app/views/writefully/application/_activeable_link_to.html.erb +5 -0
- data/app/views/writefully/application/_flash.html.erb +5 -0
- data/app/views/writefully/application/_navigation.html.erb +23 -0
- data/app/views/writefully/application/flash/_owner_exists.html.erb +0 -0
- data/app/views/writefully/application/flash/_signed_in.html.erb +0 -0
- data/app/views/writefully/application/flash/_signed_out.html.erb +0 -0
- data/app/views/writefully/posts/_not_published.html.erb +1 -0
- data/app/views/writefully/posts/_post.html.erb +14 -0
- data/app/views/writefully/posts/_published.html.erb +1 -0
- data/app/views/writefully/posts/index.html.erb +7 -0
- data/app/views/writefully/posts/show.html.erb +0 -0
- data/app/views/writefully/sessions/new.html.erb +7 -0
- data/app/views/writefully/sites/_empty.html.erb +0 -0
- data/app/views/writefully/sites/_form.html.erb +15 -0
- data/app/views/writefully/sites/_site.html.erb +16 -0
- data/app/views/writefully/sites/edit.html.erb +0 -0
- data/app/views/writefully/sites/flash/create/_error.html.erb +0 -0
- data/app/views/writefully/sites/flash/create/_success.html.erb +2 -0
- data/app/views/writefully/sites/healthy/_no.html.erb +3 -0
- data/app/views/writefully/sites/healthy/_yes.html.erb +3 -0
- data/app/views/writefully/sites/index.html.erb +14 -0
- data/app/views/writefully/sites/new.html.erb +7 -0
- data/app/views/writefully/sites/processing/_no.html.erb +3 -0
- data/app/views/writefully/sites/processing/_yes.html.erb +3 -0
- data/app/views/writefully/sites/show/_errors.html.erb +0 -0
- data/app/views/writefully/sites/show/_heading.html.erb +6 -0
- data/app/views/writefully/sites/show/_processing.html.erb +0 -0
- data/app/views/writefully/sites/show/_tabs.html.erb +5 -0
- data/app/views/writefully/sites/show.html.erb +3 -0
- data/bin/rails +12 -0
- data/bin/writefully +7 -0
- data/config/routes.rb +16 -0
- data/db/migrate/20140402091204_create_writefully_posts.rb +22 -0
- data/db/migrate/20140402091244_create_writefully_tags.rb +14 -0
- data/db/migrate/20140402091415_create_writefully_taggings.rb +10 -0
- data/db/migrate/20140402200330_create_writefully_authorships.rb +12 -0
- data/db/migrate/20140403181629_create_writefully_sites.rb +20 -0
- data/lib/sample/README.md +26 -0
- data/lib/sample/meta.yml +7 -0
- data/lib/sample/writefully.png +0 -0
- data/lib/tasks/writefully_tasks.rake +9 -0
- data/lib/writefully/asset.rb +33 -0
- data/lib/writefully/cli.rb +57 -0
- data/lib/writefully/content.rb +31 -0
- data/lib/writefully/engine.rb +25 -0
- data/lib/writefully/indices.rb +21 -0
- data/lib/writefully/news_agency.rb +8 -0
- data/lib/writefully/postable.rb +57 -0
- data/lib/writefully/process.rb +84 -0
- data/lib/writefully/source.rb +52 -0
- data/lib/writefully/storage.rb +33 -0
- data/lib/writefully/taxon.rb +28 -0
- data/lib/writefully/tools/dispatcher.rb +59 -0
- data/lib/writefully/tools/eraser.rb +0 -0
- data/lib/writefully/tools/hammer.rb +41 -0
- data/lib/writefully/tools/initializer.rb +38 -0
- data/lib/writefully/tools/pencil.rb +71 -0
- data/lib/writefully/tools/pigeon.rb +19 -0
- data/lib/writefully/tools/synchronizer.rb +24 -0
- data/lib/writefully/tools.rb +13 -0
- data/lib/writefully/version.rb +3 -0
- data/lib/writefully/workers/base_worker.rb +25 -0
- data/lib/writefully/workers/handyman.rb +44 -0
- data/lib/writefully/workers/helpers/handyman/builder.rb +17 -0
- data/lib/writefully/workers/helpers.rb +8 -0
- data/lib/writefully/workers/journalist.rb +23 -0
- data/lib/writefully/workers.rb +9 -0
- data/lib/writefully/workers_helpers.rb +7 -0
- data/lib/writefully.rb +77 -0
- data/scripts/initialize.sh +30 -0
- data/scripts/sync.sh +17 -0
- data/spec/controllers/writefully/hooks_controller_spec.rb +35 -0
- data/spec/controllers/writefully/posts_controller_spec.rb +46 -0
- data/spec/controllers/writefully/sites_controller_spec.rb +91 -0
- data/spec/dummy/Rakefile +8 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/models/playlist.rb +3 -0
- data/spec/dummy/app/models/post.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config/application.rb +22 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +29 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +36 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/writefully.yml +9 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/content/codemy-net/posts/1-hash-selector-pattern/README.md +119 -0
- data/spec/dummy/content/codemy-net/posts/1-hash-selector-pattern/assets/hash-selector-cover.png +0 -0
- data/spec/dummy/content/codemy-net/posts/1-hash-selector-pattern/assets/hash-selector-icon.png +0 -0
- data/spec/dummy/content/codemy-net/posts/1-hash-selector-pattern/benchmark/selector.rb +77 -0
- data/spec/dummy/content/codemy-net/posts/1-hash-selector-pattern/meta.yml +7 -0
- data/spec/dummy/content/codemy-net/posts/2-rails-flash-partials/README.md +171 -0
- data/spec/dummy/content/codemy-net/posts/2-rails-flash-partials/assets/cover.png +0 -0
- data/spec/dummy/content/codemy-net/posts/2-rails-flash-partials/meta.yml +7 -0
- data/spec/dummy/db/schema.rb +89 -0
- data/spec/dummy/log/development.log +13946 -0
- data/spec/dummy/log/test.log +100164 -0
- data/spec/dummy/tmp/cache/assets/development/sass/77bc3b7f842c905df4dddb7e3ac7b7cf15d9035b/application.sassc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/77bc3b7f842c905df4dddb7e3ac7b7cf15d9035b/bootstrap.cssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/77bc3b7f842c905df4dddb7e3ac7b7cf15d9035b/setups.sassc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/77bc3b7f842c905df4dddb7e3ac7b7cf15d9035b/writefully.sassc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/04641fdb653c0ff3c557033d87eb6a16 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/064b3076e29f54ea572ca43d6c5950cc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/0d2e79f7f8c9026d7d8a7f6dc63fb4a8 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/0f1c342384786865a6200cc3ed6234a3 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/13c3568b2854b103512b2658e6507d4b +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/18eb9f12c7e8971e0e2fad29c85a8b8e +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/18f8d9596e0fba3397539181f63befe1 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/1977498f5af78beca26942a7c812b294 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/1ae121eed970dfdb5f4f09953ade4de2 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/1b5404b64386f619af12582a1a634574 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/22b701cb6ffd8eac83ec1bfc563b54cb +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2d27da60cfa2f1952c3aadd169ea2570 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2e33b23d27ad5b8771d09ed8a1435cf6 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3063f229c5edc0e8a3d82d7bf78024de +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/31c84f37a0c92c38be6459f19997c981 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/320d61138ae0221b11c7e4ea0f3d53d3 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3355368d663ec5236287158290d6c297 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3df2d5c2f4f6b6d502c017346b915051 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/4596b288fc67fdb9037e06897d416879 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/47381977da0f1b2165bdbb09480ccff3 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/4aab863b927c65a4b9e70c43e4e6d482 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/4c0271d24537b8a24979e07bbd75956c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/4c16c5c88ae074d893e1de2ad787b031 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/51610d35f263eb68b1cf73737045113d +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/5af65427549750bdf60b3f06ce273b41 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/63958de32a7352bcfb139639ba2d4209 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/63f349e6a646ae0252d46e1816064e0c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/67ae1c504593279ebd6da7b6fdbe99b7 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/68e61e8d5ac667de89a4bf1e732cde0a +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/69dfb59cc80e2c111bfbfc108371b27b +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6d0103100e416966beba1039661e234e +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/71ea75f9945cdb543e0dc44527fcd926 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/7556620a4f8405144dca74330e54608c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/76598a5aebf24a1b763f5b10ae223c15 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/7af8770b019b471931e4f6cb86027307 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/7b696db3b421aeaa1afd210b07db8aae +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/7ff072db2442371da6ee49c9b279efdc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/82b92bb7c88523dc617b3c0c877aeade +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/8c388cf0035e064a06ae30a03d96b51b +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/95703f30550e80a229dd0ec4a6ddc85c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/98ccb36ebbfc6f6ac684a05ad8543c01 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/9ad5688a6dad8d54658f492eb1fa07d6 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/9b9ee2a899dd8b3bfa592fba44ebf8d2 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/9c48c31b831040e919db903d9edef2ab +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/9f9f72b9edf89242aada0d52dbc57635 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a0e14dd5894f94a561a349d40037db07 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a125c2261ecc9d800e450373950ea433 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a3999d8baf1b9ed61d91ea6bd5e42951 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a8b93e1f061f64547b92633c5bde6b13 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ad8f1428d5543a9fc4ed7a9e9526e40a +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/adae8faa21b116471ec4285998d3f3cf +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/aea01e6a7f75a01b9f61f7e0430bd61b +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/b690c630e4500da8d405b10c5d827ac9 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/b83537e814e13cf03642ccc3d90fda13 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ba4f054949cb1c1bea0fd796890fcb11 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/bccc085acd77705bf4cd104dbd5dbec3 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/c0c44ab8b0b90fb0287ca1400731f920 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/c1208bf8d0e9714161d8e6ae61781efc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/c6dae51db325ad18ac445895075e66b5 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ca8c11b2ed33b38e8b65858a2ba66d6f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ce5a98586efc888dc74dff9380760c33 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d0e440792b09f3cc258704d7850f0652 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d0e6d527077e64dc87dfa25abccd4dd3 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d10e06dee94ddaa562f7df319407bf18 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d1238ae38ca7b9522d86d67ee367223e +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d2c2fff5893ce8979ca48bab1c6f1c3a +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/e1a679a58449aa2ee72eb4341d85b5d6 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/e8fafe37de58ddbf16ebaf5cdc988320 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f15276b8745ef08f03a61f6fabe0001f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f79e04c0583c4be5f17610f948bc7436 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f966462e6d5e859d5be8f52161d2f53b +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f977be4be94ab364314f054e18c53742 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/23cfae14a65dc753e1ade92b6095067a45aad26f/bootstrap.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_alerts.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_badges.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_breadcrumbs.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_button-groups.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_buttons.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_carousel.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_close.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_code.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_component-animations.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_dropdowns.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_forms.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_glyphicons.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_grid.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_input-groups.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_jumbotron.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_labels.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_list-group.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_media.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_mixins.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_modals.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_navbar.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_navs.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_normalize.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_pager.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_pagination.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_panels.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_popovers.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_print.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_progress-bars.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_responsive-utilities.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_scaffolding.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_tables.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_thumbnails.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_tooltip.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_type.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_utilities.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_variables.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/6cd443894d18a18028b11ff7afc2188b8e6a0c6d/_wells.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/77bc3b7f842c905df4dddb7e3ac7b7cf15d9035b/base.sassc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/77bc3b7f842c905df4dddb7e3ac7b7cf15d9035b/sessions.sassc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/77bc3b7f842c905df4dddb7e3ac7b7cf15d9035b/sites.sassc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/77bc3b7f842c905df4dddb7e3ac7b7cf15d9035b/writefully.sassc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/064b3076e29f54ea572ca43d6c5950cc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/0d2e79f7f8c9026d7d8a7f6dc63fb4a8 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/18eb9f12c7e8971e0e2fad29c85a8b8e +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/1977498f5af78beca26942a7c812b294 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/2d27da60cfa2f1952c3aadd169ea2570 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/2e33b23d27ad5b8771d09ed8a1435cf6 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/3063f229c5edc0e8a3d82d7bf78024de +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/31c84f37a0c92c38be6459f19997c981 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/3df2d5c2f4f6b6d502c017346b915051 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/4aab863b927c65a4b9e70c43e4e6d482 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/4c0271d24537b8a24979e07bbd75956c +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/4c16c5c88ae074d893e1de2ad787b031 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/63f349e6a646ae0252d46e1816064e0c +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/67ae1c504593279ebd6da7b6fdbe99b7 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/68e61e8d5ac667de89a4bf1e732cde0a +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/6cf5095a6f2a3e346267010d81431898 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/71ea75f9945cdb543e0dc44527fcd926 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/74d56087624f43b73234c3691a21203b +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/76598a5aebf24a1b763f5b10ae223c15 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/7af8770b019b471931e4f6cb86027307 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/7ff072db2442371da6ee49c9b279efdc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/82b92bb7c88523dc617b3c0c877aeade +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/8789652d56b500257c05b6b3370096a2 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/95703f30550e80a229dd0ec4a6ddc85c +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/98ccb36ebbfc6f6ac684a05ad8543c01 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/9ad5688a6dad8d54658f492eb1fa07d6 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/9b9ee2a899dd8b3bfa592fba44ebf8d2 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/9c48c31b831040e919db903d9edef2ab +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/9f9f72b9edf89242aada0d52dbc57635 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/a2398b853766dfb3e66e6709e65e0fe8 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/a8b93e1f061f64547b92633c5bde6b13 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/adae8faa21b116471ec4285998d3f3cf +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/b776b64154999147a7219e7ab2ec18c5 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/b83537e814e13cf03642ccc3d90fda13 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/bccc085acd77705bf4cd104dbd5dbec3 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/c1208bf8d0e9714161d8e6ae61781efc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/d0e6d527077e64dc87dfa25abccd4dd3 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/d10e06dee94ddaa562f7df319407bf18 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/d1238ae38ca7b9522d86d67ee367223e +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/d2c2fff5893ce8979ca48bab1c6f1c3a +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/d743017d31a484ac9254192a452e4619 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/e1c18951e718ae5b0d527ddf0099a3b0 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/e1eb88bc099cda2e70c0a0ebc1e99665 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/e8fafe37de58ddbf16ebaf5cdc988320 +0 -0
- data/spec/features/writefully/sites_feature_spec.rb +27 -0
- data/spec/fixtures/writefully/authorships.yml +11 -0
- data/spec/fixtures/writefully/github_hook_test.json +4 -0
- data/spec/fixtures/writefully/github_member_add_hook.json +127 -0
- data/spec/fixtures/writefully/github_push_hook.json +94 -0
- data/spec/fixtures/writefully/posts.yml +14 -0
- data/spec/fixtures/writefully/sites.yml +10 -0
- data/spec/lib/writefully/asset_spec.rb +22 -0
- data/spec/lib/writefully/content_spec.rb +22 -0
- data/spec/lib/writefully/indices_spec.rb +17 -0
- data/spec/lib/writefully/postable_spec.rb +27 -0
- data/spec/lib/writefully/source_spec.rb +23 -0
- data/spec/lib/writefully/taxon_spec.rb +27 -0
- data/spec/lib/writefully/tools/dispatcher_spec.rb +75 -0
- data/spec/lib/writefully/tools/hammer_spec.rb +78 -0
- data/spec/lib/writefully/tools/initializer_spec.rb +18 -0
- data/spec/lib/writefully/tools/pencil_spec.rb +72 -0
- data/spec/lib/writefully/tools/synchronizer_spec.rb +17 -0
- data/spec/lib/writefully/workers/handyman_spec.rb +50 -0
- data/spec/lib/writefully/workers/journalist_spec.rb +30 -0
- data/spec/spec_helper.rb +56 -0
- metadata +903 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'listen'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
require 'celluloid'
|
5
|
+
|
6
|
+
require 'active_record'
|
7
|
+
require 'writefully'
|
8
|
+
require 'redis'
|
9
|
+
require 'redis-namespace'
|
10
|
+
|
11
|
+
%w(tag post site tagging authorship).each do |model|
|
12
|
+
require File.dirname(__FILE__) + "/../../app/models/writefully/#{model}"
|
13
|
+
end
|
14
|
+
|
15
|
+
Writefully::Source.to_load.each do |model|
|
16
|
+
require File.join(Writefully.options[:app_directory], 'app', 'models', model)
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'github_api'
|
20
|
+
|
21
|
+
require 'writefully/tools'
|
22
|
+
require 'writefully/workers'
|
23
|
+
require 'writefully/news_agency'
|
24
|
+
|
25
|
+
module Writefully
|
26
|
+
Process = Struct.new(:config) do
|
27
|
+
|
28
|
+
def listen
|
29
|
+
log_start
|
30
|
+
connect_to_database!
|
31
|
+
start_news_agency!
|
32
|
+
start_dispatcher!
|
33
|
+
boot_listener!
|
34
|
+
end
|
35
|
+
|
36
|
+
# connect to db
|
37
|
+
def connect_to_database!
|
38
|
+
ActiveRecord::Base.establish_connection(Writefully.db_config)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Dispatcher monitors job queue and throws job at workers
|
42
|
+
def start_dispatcher!
|
43
|
+
Tools::Dispatcher.supervise_as :dispatch
|
44
|
+
end
|
45
|
+
|
46
|
+
# Supervises the actors that manage all the work with converting content
|
47
|
+
# and sorting it into its place
|
48
|
+
def start_news_agency!
|
49
|
+
NewsAgency.run!
|
50
|
+
end
|
51
|
+
|
52
|
+
def log_start
|
53
|
+
Writefully.logger.info("This is doctor Frasier Crane. I'm listening...")
|
54
|
+
end
|
55
|
+
|
56
|
+
def process_message
|
57
|
+
Proc.new do |modified, added, removed|
|
58
|
+
queue_jobs(Indices.build_from(modified), :write)
|
59
|
+
queue_jobs(Indices.build_from(added), :write)
|
60
|
+
queue_jobs(Indices.build_from(removed), :remove)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# this listener listens to the specified content folder
|
65
|
+
# queues the changes detected into the job queue
|
66
|
+
def boot_listener!
|
67
|
+
listener = Listen.to config[:content], wait_for_delay: 2, &process_message
|
68
|
+
listener.start
|
69
|
+
while listener.listen?
|
70
|
+
sleep 0.5
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
JOBS = {
|
75
|
+
write: -> (index) { Writefully.add_job :journalists, index.merge({task: :publish}) },
|
76
|
+
remove: -> (index) { Wrotefully.add_job :journalists, index.merge({task: :remove}) }
|
77
|
+
}
|
78
|
+
|
79
|
+
def queue_jobs indices, action
|
80
|
+
indices.uniq.each { |index| JOBS[action].call(index) if Source.valid_resources.include?(index[:resource]) }
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module Writefully
|
4
|
+
module Source
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def content_path
|
8
|
+
Writefully.options[:content]
|
9
|
+
end
|
10
|
+
|
11
|
+
def models_path
|
12
|
+
File.join(Writefully.options[:app_directory], 'app', 'models')
|
13
|
+
end
|
14
|
+
|
15
|
+
def sample_content file
|
16
|
+
open(File.dirname(__FILE__) + "/../sample/#{file}").read
|
17
|
+
end
|
18
|
+
|
19
|
+
def sample_content_paths
|
20
|
+
valid_resources.map do |resource|
|
21
|
+
["#{resource}/1-change-me/README.md",
|
22
|
+
"#{resource}/1-change-me/meta.yml",
|
23
|
+
"#{resource}/1-change-me/assets/writefully.png"]
|
24
|
+
end.flatten
|
25
|
+
end
|
26
|
+
|
27
|
+
def sample_content_properties file
|
28
|
+
{
|
29
|
+
path: file,
|
30
|
+
content: sample_content(file),
|
31
|
+
message: "added sample #{file}"
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def valid_resources
|
36
|
+
skim_for(::Regexp.new('Writefully::Post')).map { |r| r.pluralize }
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_load
|
40
|
+
skim_for ::Regexp.new('Writefully')
|
41
|
+
end
|
42
|
+
|
43
|
+
def skim_for matcher
|
44
|
+
Dir.chdir(models_path) do
|
45
|
+
Dir.glob('*').select do |file|
|
46
|
+
open(File.join(models_path, file)).read.strip.match(matcher) if File.file?(file)
|
47
|
+
end.collect { |file| file.split('.')[0] }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Writefully
|
2
|
+
module Storage
|
3
|
+
class << self
|
4
|
+
def directory
|
5
|
+
@directory ||= connection.directories.get(Writefully.options[:storage_folder])
|
6
|
+
end
|
7
|
+
|
8
|
+
def store_file(path, body)
|
9
|
+
directory.files.create({
|
10
|
+
key: path,
|
11
|
+
body: body,
|
12
|
+
public: true
|
13
|
+
})
|
14
|
+
end
|
15
|
+
|
16
|
+
def endpoint
|
17
|
+
provider_endpoints[Writefully.options[:storage_provider].downcase.to_sym]
|
18
|
+
end
|
19
|
+
|
20
|
+
def provider_endpoints
|
21
|
+
{ aws: "https://#{Writefully.options[:storage_folder]}.s3.amazonaws.com"}
|
22
|
+
end
|
23
|
+
|
24
|
+
def connection
|
25
|
+
@connection ||= Fog::Storage.new({
|
26
|
+
provider: Writefully.options[:storage_provider],
|
27
|
+
aws_access_key_id: Writefully.options[:storage_key],
|
28
|
+
aws_secret_access_key: Writefully.options[:storage_secret]
|
29
|
+
})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Writefully
|
2
|
+
Taxon = Struct.new(:incoming, :existing, :type) do
|
3
|
+
def non_existing
|
4
|
+
get_difference.map { |token| Tag.new(build_attributes(token)) }
|
5
|
+
end
|
6
|
+
|
7
|
+
def selector
|
8
|
+
@selector ||= type.underscore.to_sym
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_difference
|
12
|
+
(parameterized(incoming) - parameterized(existing)).map { |t| t.titleize }
|
13
|
+
end
|
14
|
+
|
15
|
+
def type_attribute
|
16
|
+
selector == :'writefully/tag' ? { type: nil } : { type: selector.to_s.classify }
|
17
|
+
end
|
18
|
+
|
19
|
+
def build_attributes token
|
20
|
+
type_attribute
|
21
|
+
.merge({ name: token, slug: token.parameterize })
|
22
|
+
end
|
23
|
+
|
24
|
+
def parameterized items
|
25
|
+
items.map { |t| t.parameterize }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Writefully
|
2
|
+
module Tools
|
3
|
+
class Dispatcher
|
4
|
+
include Celluloid
|
5
|
+
|
6
|
+
attr_reader :job
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
every 1.second do
|
10
|
+
async.heartbeat
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_job_data
|
15
|
+
Writefully.redis.with { |c| c.spop 'jobs' }
|
16
|
+
end
|
17
|
+
|
18
|
+
def heartbeat
|
19
|
+
@job = Marshal.load(get_job_data)
|
20
|
+
run_job if is_job?
|
21
|
+
end
|
22
|
+
|
23
|
+
def run_job
|
24
|
+
if is_retry? and retry_valid? then retry_job
|
25
|
+
elsif is_job? and job_valid? then dispatch
|
26
|
+
else mark_as_failed end
|
27
|
+
end
|
28
|
+
|
29
|
+
def dispatch
|
30
|
+
Celluloid::Actor[job[:worker]].perform(job[:message])
|
31
|
+
end
|
32
|
+
|
33
|
+
def retry_job
|
34
|
+
after((job[:tries] * job[:tries]).seconds) { dispatch(job) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def mark_as_failed
|
38
|
+
Writefully.redis.with { |c| c.sadd 'failed', Marshal.dump(job) }
|
39
|
+
end
|
40
|
+
|
41
|
+
def is_job?
|
42
|
+
job.has_key?(:worker) and job.has_key?(:message)
|
43
|
+
end
|
44
|
+
|
45
|
+
def is_retry?
|
46
|
+
is_job? and job.has_key?(:tries)
|
47
|
+
end
|
48
|
+
|
49
|
+
def job_valid?
|
50
|
+
job.keys.count == 2
|
51
|
+
end
|
52
|
+
|
53
|
+
def retry_valid?
|
54
|
+
job[:tries] <= 5
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
File without changes
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Writefully
|
2
|
+
module Tools
|
3
|
+
class Hammer
|
4
|
+
include Celluloid
|
5
|
+
|
6
|
+
attr_reader :api, :message
|
7
|
+
|
8
|
+
def initialize message
|
9
|
+
@message = message
|
10
|
+
@api = Github.new oauth_token: message[:auth_token]
|
11
|
+
end
|
12
|
+
|
13
|
+
def hook_config
|
14
|
+
{ name: 'web',
|
15
|
+
events: ["push", "member"],
|
16
|
+
active: true,
|
17
|
+
config: {
|
18
|
+
url: "#{message[:domain]}/writefully/hook",
|
19
|
+
content_type: 'json',
|
20
|
+
secret: Writefully.options[:hook_secret]
|
21
|
+
}
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
def forge
|
26
|
+
Writefully.logger.info "Forging #{message[:site_slug]}"
|
27
|
+
api.repos.create name: message[:site_slug], auto_init: true
|
28
|
+
rescue Exception => e
|
29
|
+
raise e
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_hook_for repo_name
|
33
|
+
Writefully.logger.info "Adding hook for #{message[:site_slug]}"
|
34
|
+
api.repos.hooks.create message[:user_name], repo_name, hook_config
|
35
|
+
rescue Exception => e
|
36
|
+
raise e
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Writefully
|
2
|
+
module Tools
|
3
|
+
class Initializer
|
4
|
+
include Celluloid
|
5
|
+
|
6
|
+
INITIALIZE_SCRIPT = File.dirname(__FILE__) + "/../../../scripts/initialize.sh"
|
7
|
+
|
8
|
+
attr_reader :message, :api
|
9
|
+
|
10
|
+
def initialize message
|
11
|
+
@message = message
|
12
|
+
@api = Github.new oauth_token: message[:auth_token]
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_sample_content
|
16
|
+
Writefully.logger.info "Adding Sample content #{message[:site_slug]}"
|
17
|
+
Source.sample_content_paths.map do |path|
|
18
|
+
api.repos.contents.create message[:user_name],
|
19
|
+
message[:site_slug],
|
20
|
+
path, sample_content_for(path.split('/').last)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def build_content_folder
|
25
|
+
Writefully.logger.info "Creating content folder #{message[:site_slug]}"
|
26
|
+
system(content_folder_setup_command)
|
27
|
+
end
|
28
|
+
|
29
|
+
def content_folder_setup_command
|
30
|
+
['bash', INITIALIZE_SCRIPT, Writefully.options[:content], message[:site_slug], message[:ssh_url]].join(' ')
|
31
|
+
end
|
32
|
+
|
33
|
+
def sample_content_for file_name
|
34
|
+
Source.sample_content_properties(file_name)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Writefully
|
2
|
+
module Tools
|
3
|
+
class Pencil
|
4
|
+
include Celluloid
|
5
|
+
|
6
|
+
attr_reader :resource, :content, :asset, :index, :site_id, :asset
|
7
|
+
|
8
|
+
class ContentModelNotFound < StandardError; end
|
9
|
+
class SomeAssetsNotUploaded < StandardError; end
|
10
|
+
|
11
|
+
def initialize(index)
|
12
|
+
@site_id = Site.where(slug: index[:site]).first.id
|
13
|
+
@index = index
|
14
|
+
@content = Content.new(index)
|
15
|
+
@asset = Asset.new(index)
|
16
|
+
end
|
17
|
+
|
18
|
+
def perform
|
19
|
+
assets_uploaded = upload_assets.map(&:value).compact
|
20
|
+
written_to_db = future.write if can_update_db?(assets_uploaded)
|
21
|
+
terminate if written_to_db.value
|
22
|
+
end
|
23
|
+
|
24
|
+
def computed_attributes
|
25
|
+
content.meta.merge({
|
26
|
+
"content" => asset.convert_for(content.body),
|
27
|
+
"details" => asset.convert_for(content.details)
|
28
|
+
})
|
29
|
+
end
|
30
|
+
|
31
|
+
def write
|
32
|
+
compute_type.by_site(site_id).where(slug: content.slug)
|
33
|
+
.first_or_initialize
|
34
|
+
.update_attributes(computed_attributes)
|
35
|
+
ensure
|
36
|
+
::ActiveRecord::Base.clear_active_connections! if defined?(::ActiveRecord)
|
37
|
+
end
|
38
|
+
|
39
|
+
def upload_assets
|
40
|
+
asset.names.map do |name|
|
41
|
+
Celluloid::Actor[:pigeons].future.upload(asset.endpoint, asset.path, name)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def can_update_db? uploaded
|
46
|
+
if asset.names.count == uploaded.count
|
47
|
+
true
|
48
|
+
else
|
49
|
+
raise SomeAssetsNotUploaded, "Some assets was not uploaded"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def compute_type
|
56
|
+
index[:resource].classify.constantize
|
57
|
+
rescue NameError
|
58
|
+
fallback_type
|
59
|
+
end
|
60
|
+
|
61
|
+
def fallback_type
|
62
|
+
if index[:resource] == "posts"
|
63
|
+
"Writefully::Post".constantize
|
64
|
+
else
|
65
|
+
raise ContentModelNotFound, "Model #{index[:resource].classify} was not found"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Writefully
|
2
|
+
module Tools
|
3
|
+
class Pigeon
|
4
|
+
include Celluloid
|
5
|
+
|
6
|
+
def upload endpoint, path, name
|
7
|
+
file = File.open(File.join(path, name))
|
8
|
+
Writefully::Storage.store_file(File.join(endpoint, name), file)
|
9
|
+
true
|
10
|
+
rescue Exception => e
|
11
|
+
nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def remove endpoint, path, name
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Writefully
|
2
|
+
module Tools
|
3
|
+
class Synchronizer
|
4
|
+
include Celluloid
|
5
|
+
|
6
|
+
SYNC_SCRIPT = File.dirname(__FILE__) + "/../../../scripts/sync.sh"
|
7
|
+
|
8
|
+
attr_reader :message
|
9
|
+
|
10
|
+
def initialize message
|
11
|
+
@message = message
|
12
|
+
end
|
13
|
+
|
14
|
+
def sync
|
15
|
+
Writefully.logger.info "Synchronizing #{message[:site_slug]}"
|
16
|
+
system(sync_command)
|
17
|
+
end
|
18
|
+
|
19
|
+
def sync_command
|
20
|
+
['bash', SYNC_SCRIPT, Writefully.options[:content], message[:site_slug]].join(' ')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Writefully
|
2
|
+
module Tools
|
3
|
+
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'writefully/tools/eraser'
|
8
|
+
require 'writefully/tools/pencil'
|
9
|
+
require 'writefully/tools/pigeon'
|
10
|
+
require 'writefully/tools/hammer'
|
11
|
+
require 'writefully/tools/dispatcher'
|
12
|
+
require 'writefully/tools/initializer'
|
13
|
+
require 'writefully/tools/synchronizer'
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Writefully
|
2
|
+
module Workers
|
3
|
+
class BaseWorker
|
4
|
+
include Celluloid
|
5
|
+
|
6
|
+
trap_exit :actor_died
|
7
|
+
|
8
|
+
attr_reader :message
|
9
|
+
|
10
|
+
def perform(message)
|
11
|
+
@message = message
|
12
|
+
self.__send__ message[:task]
|
13
|
+
end
|
14
|
+
|
15
|
+
def close_db_connection!
|
16
|
+
::ActiveRecord::Base.clear_active_connections! if defined?(::ActiveRecord)
|
17
|
+
end
|
18
|
+
|
19
|
+
def actor_died(actor, reason)
|
20
|
+
Writefully.logger.error "An error occured #{reason.message}"
|
21
|
+
on_death(actor, reason) if self.respond_to?(:on_death)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Writefully
|
2
|
+
module Workers
|
3
|
+
class Handyman < BaseWorker
|
4
|
+
include Helpers::Handyman::Builder
|
5
|
+
|
6
|
+
attr_reader :site
|
7
|
+
|
8
|
+
def build
|
9
|
+
@site = Site.where(id: message[:site_id]).first
|
10
|
+
@hammer = Tools::Hammer.new_link(message.merge({ domain: site.domain }))
|
11
|
+
# create the repository
|
12
|
+
repo = @hammer.future.forge
|
13
|
+
|
14
|
+
# add sample content
|
15
|
+
@initializer = Tools::Initializer.new_link(message.merge({ ssh_url: repo.value.ssh_url }))
|
16
|
+
initialize_sample_content
|
17
|
+
|
18
|
+
# add web hook
|
19
|
+
hook = @hammer.future.add_hook_for(repo.value.name)
|
20
|
+
complete_site_setup(repo.value, hook.value)
|
21
|
+
ensure
|
22
|
+
@hammer.terminate
|
23
|
+
@initializer.terminate
|
24
|
+
close_db_connection!
|
25
|
+
end
|
26
|
+
|
27
|
+
def synchronize
|
28
|
+
@synchronizer = Tools::Synchronizer.new_link(message)
|
29
|
+
synced = @synchronizer.future.sync
|
30
|
+
Writefully.logger.info "Synchronized #{message[:site_slug]}" if synced.value
|
31
|
+
ensure
|
32
|
+
@synchronizer.terminate
|
33
|
+
end
|
34
|
+
|
35
|
+
def on_death actor, reason
|
36
|
+
if site
|
37
|
+
Writefully.redis.with { |c| s.sadd "site:#{site.id}:errors", reason.message }
|
38
|
+
site.update_attributes(processing: false, healty: false)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Writefully::Workers::Helpers::Handyman
|
2
|
+
module Builder
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def complete_site_setup repo, hook
|
6
|
+
site_repository = { name: repo.name, id: repo.id, hook_id: hook.id }
|
7
|
+
site.update_attributes(repository: site_repository, processing: false, healthy: true)
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize_sample_content
|
11
|
+
added_sample_content = @initializer.add_sample_content
|
12
|
+
created_directory = @initializer.build_content_folder
|
13
|
+
|
14
|
+
[added_sample_content, created_directory]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Writefully
|
2
|
+
module Workers
|
3
|
+
class Journalist < BaseWorker
|
4
|
+
def publish
|
5
|
+
Writefully.logger.info "Publishing #{message[:resource]} #{message[:slug]}"
|
6
|
+
pencil = Tools::Pencil.new_link(message)
|
7
|
+
pencil.perform
|
8
|
+
end
|
9
|
+
|
10
|
+
def remove
|
11
|
+
Writefully.logger.info "Removing #{message[:resource]} #{message[:slug]}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def message_with_tries
|
15
|
+
message.merge({ tries: (message[:tries] || 1) + 1 })
|
16
|
+
end
|
17
|
+
|
18
|
+
def on_death actor, reason
|
19
|
+
Writefully.add_job :journalists, message_with_tries
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|