The change you wanted was rejected.
28 |Maybe you tried to change something you didn't have access to.
29 | 30 |├── lib ├── tasks │ ├── .gitkeep │ ├── rubocop.rake │ ├── cache_cooker.rake │ ├── mailchimp.rake │ ├── import.rake │ ├── travis.rake │ ├── stripe.rake │ └── setup.rake ├── null_object.rb ├── md_mentions.rb ├── rake_exception_notification.rb ├── mail_chimp │ └── web_hooks.rb └── cache_cooker.rb ├── vendor ├── plugins │ └── .gitkeep └── assets │ ├── images │ ├── .gitkeep │ └── facebox │ │ ├── loading.gif │ │ └── closelabel.png │ ├── javascripts │ └── .gitkeep │ └── stylesheets │ ├── .gitkeep │ └── facebox.css ├── app ├── views │ ├── shared │ │ ├── _branded_footer.html.haml │ │ ├── _ios_icon.html.haml │ │ ├── _flash.html.haml │ │ ├── _sad_pinkie.html.haml │ │ ├── _broadcasts.html.haml │ │ ├── _navigation.html.haml │ │ └── _credit_card.html.haml │ ├── comments │ │ ├── update.text.erb │ │ ├── destroy.js.erb │ │ └── _show.html.haml │ ├── announcements │ │ ├── dismiss.js.erb │ │ ├── show.html.haml │ │ ├── index.html.haml │ │ └── _announcement.html.haml │ ├── user_email │ │ ├── dismiss_warning.js.coffee │ │ ├── update.js.coffee │ │ ├── _warning.html.haml │ │ └── change.html.haml │ ├── articles │ │ ├── _comments.html.haml │ │ ├── _explore_article.html.haml │ │ ├── _subway.html.haml │ │ ├── index.html.haml │ │ ├── _footer.html.haml │ │ ├── _header.html.haml │ │ ├── _archives.html.haml │ │ ├── shared.html.haml │ │ └── show.haml │ ├── broadcast_mailer │ │ └── broadcast.text.erb │ ├── admin │ │ ├── articles │ │ │ ├── new.html.haml │ │ │ ├── edit.html.haml │ │ │ ├── index.html.haml │ │ │ └── _form.html.haml │ │ ├── announcements │ │ │ ├── new.html.haml │ │ │ ├── edit.html.haml │ │ │ ├── _form.html.haml │ │ │ └── index.html.haml │ │ ├── reports │ │ │ └── index.html.haml │ │ └── broadcasts │ │ │ └── new.html.haml │ ├── users │ │ ├── mailchimp_yearly_billing.js.coffee │ │ ├── current_credit_card.html.haml │ │ ├── _sidebar.html.haml │ │ ├── destroy.html.haml │ │ ├── show.html.haml │ │ ├── edit.html.haml │ │ ├── _settings_page.html.haml │ │ ├── _form.html.haml │ │ ├── profile.html.haml │ │ ├── notifications.html.haml │ │ └── billing.html.haml │ ├── account_mailer │ │ ├── canceled.text.erb │ │ ├── mailchimp_yearly_billing.text.erb │ │ ├── payment_created.text.erb │ │ ├── card_expiring.text.erb │ │ ├── failed_payment.text.erb │ │ └── unsubscribed.text.erb │ ├── conversation_mailer │ │ ├── mentioned.text.erb │ │ ├── comment_made.text.erb │ │ └── started.text.erb │ ├── registration_mailer │ │ └── email_confirmation.text.erb │ ├── home │ │ ├── public_archives.html.haml │ │ ├── chat.html.haml │ │ ├── contact.html.haml │ │ ├── about.html.haml │ │ └── open_source.html.haml │ ├── layouts │ │ ├── landing.html.haml │ │ ├── application.html.haml │ │ └── maintenance.html.erb │ ├── sessions │ │ ├── expired_link.html.haml │ │ ├── failure.html.haml │ │ └── problems.html.haml │ └── subscriptions │ │ ├── _thanks.html.haml │ │ ├── new.html.haml │ │ └── redirect.html.haml ├── models │ ├── payment.rb │ ├── payment_log.rb │ ├── collection.rb │ ├── article_visit.rb │ ├── volume.rb │ ├── announcement.rb │ ├── payment_gateway.rb │ ├── secret_generator.rb │ ├── authorization.rb │ ├── credit_card.rb │ ├── payment_gateway │ │ └── mail_chimp.rb │ ├── shared_article.rb │ ├── subscription.rb │ ├── card_expirer.rb │ ├── broadcaster.rb │ ├── article_link.rb │ ├── comment.rb │ ├── authorization_link.rb │ ├── reports.rb │ ├── user_manager.rb │ ├── article.rb │ └── conversation_notifier.rb ├── assets │ ├── images │ │ ├── avatar.png │ │ ├── contact.jpg │ │ ├── divider.png │ │ ├── preview.png │ │ ├── santa.jpg │ │ ├── ecc_logo.png │ │ ├── tinyrobo.png │ │ ├── announcement.png │ │ ├── beta_badge.png │ │ ├── icons │ │ │ ├── chess.png │ │ │ ├── heart.png │ │ │ ├── ruby.png │ │ │ ├── tower.png │ │ │ ├── question.png │ │ │ ├── experiments.png │ │ │ └── nuts_bolts.png │ │ ├── logo │ │ │ ├── large.png │ │ │ └── ios-icon.png │ │ ├── payment │ │ │ ├── cvc.gif │ │ │ └── dolla_billz.jpg │ │ ├── ruby-divider.png │ │ ├── sad_pinkie.png │ │ ├── controls │ │ │ ├── close.png │ │ │ ├── next.png │ │ │ └── previous.png │ │ ├── ecc_logo_black.png │ │ ├── pr-subscribers.pdf │ │ ├── cross_scratches.png │ │ └── backgrounds │ │ │ └── clean_textile.png │ ├── javascripts │ │ ├── pjax.coffee │ │ ├── pr.toggle.js.coffee │ │ ├── github_redirect_warning.js.coffee │ │ ├── application.js │ │ └── save.js │ └── stylesheets │ │ ├── partials │ │ ├── _contact.sass │ │ ├── _chat.sass │ │ ├── _mobile.sass │ │ ├── _open_source.sass │ │ ├── _email_confirmation_warning.sass │ │ ├── _broadcasts.sass │ │ ├── _flash.sass │ │ ├── _announcements.sass │ │ ├── _sharebox.sass │ │ ├── _admin.sass │ │ ├── _payments.sass │ │ ├── _navigation.sass │ │ ├── _fonts.sass │ │ ├── _landing.sass │ │ ├── _archives.sass │ │ ├── _library.sass │ │ ├── _form.sass │ │ ├── _subscribe.sass │ │ ├── _layout.sass │ │ └── _articles.sass │ │ └── application.css.sass ├── controllers │ ├── admin │ │ ├── reports_controller.rb │ │ ├── magic_controller.rb │ │ ├── broadcasts_controller.rb │ │ ├── articles_controller.rb │ │ └── announcements_controller.rb │ ├── hooks_controller.rb │ ├── announcements_controller.rb │ ├── home_controller.rb │ ├── user_email_controller.rb │ ├── sessions_controller.rb │ ├── subscriptions_controller.rb │ └── comments_controller.rb ├── mailers │ ├── registration_mailer.rb │ ├── broadcast_mailer.rb │ ├── conversation_mailer.rb │ └── account_mailer.rb ├── helpers │ ├── article_helper.rb │ └── application_helper.rb └── decorators │ ├── collection_decorator.rb │ ├── volume_decorator.rb │ ├── comment_decorator.rb │ ├── article_decorator.rb │ ├── user_decorator.rb │ └── subscription_decorator.rb ├── .rvmrc.example ├── doc └── header.png ├── Procfile ├── db ├── dump.sql.bz2 ├── migrate │ ├── 20130816174433_add_slug_to_articles.rb │ ├── 20130809174926_add_summary_to_articles.rb │ ├── 20120803001039_add_url_to_announcements.rb │ ├── 20120831192230_add_access_token_to_user.rb │ ├── 20120801233245_add_position_to_collections.rb │ ├── 20150821164859_add_discourse_url_to_articles.rb │ ├── 20121011002134_add_coupon_code_to_subscriptions.rb │ ├── 20130820143254_add_share_token_to_user.rb │ ├── 20120319214410_add_beta_tester_field_to_users.rb │ ├── 20120328151105_add_volume_id_to_articles.rb │ ├── 20120406161709_add_account_disabled_field_to_user.rb │ ├── 20120831190102_add_status_to_users.rb │ ├── 20120914175304_add_notify_updates_to_users.rb │ ├── 20120407205455_add_collection_id_to_articles.rb │ ├── 20130920195554_add_recommended_to_articles.rb │ ├── 20111108180149_add_notify_comment_made_to_users.rb │ ├── 20120516152433_add_notifications_enabled_to_users.rb │ ├── 20120626145819_add_queue_to_delayed_jobs.rb │ ├── 20110912175336_add_issue_number_to_articles.rb │ ├── 20131114225709_add_interval_to_subscriptions.rb │ ├── 20111206143647_add_broadcast_columns_to_announcements.rb │ ├── 20120328150809_create_volumes.rb │ ├── 20120112195907_create_article_visits.rb │ ├── 20110830041617_add_admin_field_to_user.rb │ ├── 20110829215505_create_authorizations.rb │ ├── 20110829230541_add_github_nickname_to_user.rb │ ├── 20120407204814_create_collections.rb │ ├── 20110820183757_create_users.rb │ ├── 20110909193908_create_announcements.rb │ ├── 20131204201817_add_email_confirmed_to_users.rb │ ├── 20121019183135_create_credit_cards.rb │ ├── 20110830162757_create_shared_articles.rb │ ├── 20110901130928_create_comments.rb │ ├── 20110829215511_create_authorization_links.rb │ ├── 20110821020718_create_articles.rb │ ├── 20130215174537_create_payments.rb │ ├── 20110912173127_add_email_preferences_to_users.rb │ ├── 20110916140124_change_mail_columns_to_text.rb │ ├── 20110916131749_create_emails.rb │ ├── 20110916132222_create_delayed_jobs.rb │ └── 20120927154744_add_payment_models.rb └── seeds.rb ├── config ├── initializers │ ├── chat.rb │ ├── mailhopper.rb │ ├── secret_token.rb │ ├── domain_settings.rb │ ├── mailchimp_settings.rb │ ├── stripe.rb │ ├── cache_cooker_settings.rb │ ├── mime_types.rb │ ├── omniauth.rb │ ├── inflections.rb │ ├── backtrace_silencers.rb │ ├── session_store.rb │ ├── rails_security_workarounds.rb │ ├── exception_notifier.rb │ ├── mail_settings.rb │ ├── markdown.rb │ └── stripe_webhooks.rb ├── environment.rb ├── deploy │ ├── production.rb │ ├── old_production.rb │ └── vagrant.rb ├── boot.rb ├── locales │ └── en.yml ├── schedule.rb ├── database.yml.example ├── environments │ ├── development.rb │ ├── test.rb │ └── production.rb └── delayed_job.god ├── public ├── favicon.ico ├── fonts │ ├── folks-light.eot │ ├── folks-light.ttf │ ├── folks-light.woff │ ├── folks-normal.eot │ ├── folks-normal.ttf │ ├── inconsolata.eot │ ├── inconsolata.ttf │ ├── inconsolata.woff │ └── folks-normal.woff ├── robots.txt ├── 422.html ├── 404.html └── 500.html ├── config.ru ├── test ├── factories │ ├── authorization_factory.rb │ ├── credit_card.rb │ ├── comment_factory.rb │ ├── announcement_factory.rb │ ├── stripe.rb │ ├── article_factory.rb │ └── user_factory.rb ├── integration │ ├── authorization_failure_test.rb │ ├── account_cancelation_test.rb │ ├── profile_test.rb │ ├── edit_article_test.rb │ ├── disabled_accounts_test.rb │ ├── article_routing_test.rb │ ├── article_footnote_test.rb │ ├── confirm_user_email_test.rb │ ├── credit_card_expiration_test.rb │ ├── change_billing_interval_test.rb │ ├── broadcast_test.rb │ └── shared_article_test.rb ├── support │ ├── stripe │ │ └── invoice.rb │ ├── outbox.rb │ └── mini_contest.rb └── unit │ ├── mailers │ ├── account_mailer_test.rb │ └── broadcast_mailer_test.rb │ ├── user_manager_test.rb │ ├── decorators │ └── comment_decorator_test.rb │ ├── user_test.rb │ └── card_expirer_test.rb ├── script ├── delayed_job └── rails ├── .gitignore ├── .travis.yml ├── .rubocop.yml ├── Capfile ├── Rakefile ├── .env.example └── Gemfile /lib/tasks/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/plugins/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/assets/images/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/assets/stylesheets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/views/shared/_branded_footer.html.haml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.rvmrc.example: -------------------------------------------------------------------------------- 1 | rvm 1.9.2@practicing-ruby-web 2 | -------------------------------------------------------------------------------- /app/views/comments/update.text.erb: -------------------------------------------------------------------------------- 1 | <%= @comment.content %> -------------------------------------------------------------------------------- /app/views/announcements/dismiss.js.erb: -------------------------------------------------------------------------------- 1 | $('#broadcasts').slideUp(); -------------------------------------------------------------------------------- /app/views/comments/destroy.js.erb: -------------------------------------------------------------------------------- 1 | $('.comment[data-id=<%= @comment.id %>]').remove(); -------------------------------------------------------------------------------- /app/models/payment.rb: -------------------------------------------------------------------------------- 1 | class Payment < ActiveRecord::Base 2 | belongs_to :user 3 | end 4 | -------------------------------------------------------------------------------- /app/models/payment_log.rb: -------------------------------------------------------------------------------- 1 | class PaymentLog < ActiveRecord::Base 2 | belongs_to :user 3 | end -------------------------------------------------------------------------------- /app/views/user_email/dismiss_warning.js.coffee: -------------------------------------------------------------------------------- 1 | $("#email-confirmation-warning").fadeOut() 2 | -------------------------------------------------------------------------------- /app/models/collection.rb: -------------------------------------------------------------------------------- 1 | class Collection < ActiveRecord::Base 2 | has_many :articles 3 | end 4 | -------------------------------------------------------------------------------- /doc/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/doc/header.png -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: script/rails s 2 | worker: bundle exec rake jobs:work 3 | mail: bundle exec mailcatcher -f 4 | -------------------------------------------------------------------------------- /db/dump.sql.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/db/dump.sql.bz2 -------------------------------------------------------------------------------- /config/initializers/chat.rb: -------------------------------------------------------------------------------- 1 | CHAT_GUEST_URL = ENV["CHAT_GUEST_URL"] 2 | CHAT_LOGIN_URL = ENV["CHAT_LOGIN_URL"] 3 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /app/views/shared/_ios_icon.html.haml: -------------------------------------------------------------------------------- 1 | %link{ :rel => 'apple-touch-icon', :href => image_path('logo/ios-icon.png') } 2 | -------------------------------------------------------------------------------- /config/initializers/mailhopper.rb: -------------------------------------------------------------------------------- 1 | Mailhopper::Base.setup do |config| 2 | config.default_delivery_method = :smtp 3 | end -------------------------------------------------------------------------------- /app/assets/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/avatar.png -------------------------------------------------------------------------------- /app/assets/images/contact.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/contact.jpg -------------------------------------------------------------------------------- /app/assets/images/divider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/divider.png -------------------------------------------------------------------------------- /app/assets/images/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/preview.png -------------------------------------------------------------------------------- /app/assets/images/santa.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/santa.jpg -------------------------------------------------------------------------------- /lib/null_object.rb: -------------------------------------------------------------------------------- 1 | class << (NullObject = Object.new) 2 | def method_missing(id, *a, &b) 3 | NullObject 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /public/fonts/folks-light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/public/fonts/folks-light.eot -------------------------------------------------------------------------------- /public/fonts/folks-light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/public/fonts/folks-light.ttf -------------------------------------------------------------------------------- /public/fonts/folks-light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/public/fonts/folks-light.woff -------------------------------------------------------------------------------- /public/fonts/folks-normal.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/public/fonts/folks-normal.eot -------------------------------------------------------------------------------- /public/fonts/folks-normal.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/public/fonts/folks-normal.ttf -------------------------------------------------------------------------------- /public/fonts/inconsolata.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/public/fonts/inconsolata.eot -------------------------------------------------------------------------------- /public/fonts/inconsolata.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/public/fonts/inconsolata.ttf -------------------------------------------------------------------------------- /public/fonts/inconsolata.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/public/fonts/inconsolata.woff -------------------------------------------------------------------------------- /app/assets/images/ecc_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/ecc_logo.png -------------------------------------------------------------------------------- /app/assets/images/tinyrobo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/tinyrobo.png -------------------------------------------------------------------------------- /public/fonts/folks-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/public/fonts/folks-normal.woff -------------------------------------------------------------------------------- /app/assets/images/announcement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/announcement.png -------------------------------------------------------------------------------- /app/assets/images/beta_badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/beta_badge.png -------------------------------------------------------------------------------- /app/assets/images/icons/chess.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/icons/chess.png -------------------------------------------------------------------------------- /app/assets/images/icons/heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/icons/heart.png -------------------------------------------------------------------------------- /app/assets/images/icons/ruby.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/icons/ruby.png -------------------------------------------------------------------------------- /app/assets/images/icons/tower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/icons/tower.png -------------------------------------------------------------------------------- /app/assets/images/logo/large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/logo/large.png -------------------------------------------------------------------------------- /app/assets/images/payment/cvc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/payment/cvc.gif -------------------------------------------------------------------------------- /app/assets/images/ruby-divider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/ruby-divider.png -------------------------------------------------------------------------------- /app/assets/images/sad_pinkie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/sad_pinkie.png -------------------------------------------------------------------------------- /app/assets/images/controls/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/controls/close.png -------------------------------------------------------------------------------- /app/assets/images/controls/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/controls/next.png -------------------------------------------------------------------------------- /app/assets/images/ecc_logo_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/ecc_logo_black.png -------------------------------------------------------------------------------- /app/assets/images/icons/question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/icons/question.png -------------------------------------------------------------------------------- /app/assets/images/logo/ios-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/logo/ios-icon.png -------------------------------------------------------------------------------- /app/assets/images/pr-subscribers.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/pr-subscribers.pdf -------------------------------------------------------------------------------- /app/assets/images/controls/previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/controls/previous.png -------------------------------------------------------------------------------- /app/assets/images/cross_scratches.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/cross_scratches.png -------------------------------------------------------------------------------- /app/assets/images/icons/experiments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/icons/experiments.png -------------------------------------------------------------------------------- /app/assets/images/icons/nuts_bolts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/icons/nuts_bolts.png -------------------------------------------------------------------------------- /app/models/article_visit.rb: -------------------------------------------------------------------------------- 1 | # DEPRECATED 2 | # 3 | class ArticleVisit < ActiveRecord::Base 4 | belongs_to :user 5 | belongs_to :article 6 | end 7 | -------------------------------------------------------------------------------- /app/models/volume.rb: -------------------------------------------------------------------------------- 1 | class Volume < ActiveRecord::Base 2 | has_many :articles 3 | 4 | def name 5 | "Volume #{number}" 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/assets/images/payment/dolla_billz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/payment/dolla_billz.jpg -------------------------------------------------------------------------------- /vendor/assets/images/facebox/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/vendor/assets/images/facebox/loading.gif -------------------------------------------------------------------------------- /vendor/assets/images/facebox/closelabel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/vendor/assets/images/facebox/closelabel.png -------------------------------------------------------------------------------- /app/controllers/admin/reports_controller.rb: -------------------------------------------------------------------------------- 1 | module Admin 2 | class ReportsController < ApplicationController 3 | before_filter :admin_only 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/assets/images/backgrounds/clean_textile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-city-craftworks/practicing-ruby-web/HEAD/app/assets/images/backgrounds/clean_textile.png -------------------------------------------------------------------------------- /app/assets/javascripts/pjax.coffee: -------------------------------------------------------------------------------- 1 | jQuery -> 2 | $('.paginated-list .controls a').pjax('[data-pjax-container]') 3 | $('#settings-sidebar a').pjax('[data-pjax-container]') -------------------------------------------------------------------------------- /app/views/articles/_comments.html.haml: -------------------------------------------------------------------------------- 1 | - if @article.discourse_url.present? 2 | #comments 3 | = link_to "Discuss this article on discourse", @article.discourse_url 4 | -------------------------------------------------------------------------------- /config/initializers/secret_token.rb: -------------------------------------------------------------------------------- 1 | token = Rails.env.production? ? ENV["SECRET_TOKEN"] : ('x' * 30) 2 | 3 | PracticingRubyWeb::Application.config.secret_token = token 4 | -------------------------------------------------------------------------------- /app/models/announcement.rb: -------------------------------------------------------------------------------- 1 | class Announcement < ActiveRecord::Base 2 | belongs_to :author, :class_name => "User" 3 | 4 | scope :broadcasts, where(:broadcast => true) 5 | end 6 | -------------------------------------------------------------------------------- /app/models/payment_gateway.rb: -------------------------------------------------------------------------------- 1 | module PaymentGateway 2 | 3 | # TODO Enable MailChimp 4 | def self.for_user(user) 5 | PaymentGateway::Stripe.new(user) 6 | end 7 | 8 | end -------------------------------------------------------------------------------- /app/models/secret_generator.rb: -------------------------------------------------------------------------------- 1 | module SecretGenerator 2 | extend self 3 | 4 | def generate(length=30) 5 | (0...length).map{ ('a'..'z').to_a[rand(26)] }.join 6 | end 7 | end -------------------------------------------------------------------------------- /db/migrate/20130816174433_add_slug_to_articles.rb: -------------------------------------------------------------------------------- 1 | class AddSlugToArticles < ActiveRecord::Migration 2 | def change 3 | add_column :articles, :slug, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/assets/stylesheets/partials/_contact.sass: -------------------------------------------------------------------------------- 1 | #contact 2 | font-family: sans-serif 3 | img 4 | box-sizing: border-box 5 | +image-box 6 | margin: 0 auto 7 | width: 100% 8 | -------------------------------------------------------------------------------- /app/models/authorization.rb: -------------------------------------------------------------------------------- 1 | class Authorization < ActiveRecord::Base 2 | has_one :authorization_link 3 | belongs_to :user 4 | 5 | def confirmed? 6 | !!user 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/views/broadcast_mailer/broadcast.text.erb: -------------------------------------------------------------------------------- 1 | <%= @body.html_safe %> 2 | 3 | ---- 4 | 5 | You can customize your notification settings via the link below: 6 | 7 | <%= profile_settings_url %> -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run PracticingRubyWeb::Application 5 | -------------------------------------------------------------------------------- /db/migrate/20130809174926_add_summary_to_articles.rb: -------------------------------------------------------------------------------- 1 | class AddSummaryToArticles < ActiveRecord::Migration 2 | def change 3 | add_column :articles, :summary, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20120803001039_add_url_to_announcements.rb: -------------------------------------------------------------------------------- 1 | class AddUrlToAnnouncements < ActiveRecord::Migration 2 | def change 3 | add_column :announcements, :url, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20120831192230_add_access_token_to_user.rb: -------------------------------------------------------------------------------- 1 | class AddAccessTokenToUser < ActiveRecord::Migration 2 | def change 3 | add_column :users, :access_token, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /test/factories/authorization_factory.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | factory :authorization do |a| 3 | a.github_uid(12345) 4 | a.association(:user, :factory => :user) 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the rails application 2 | require File.expand_path('../application', __FILE__) 3 | 4 | # Initialize the rails application 5 | PracticingRubyWeb::Application.initialize! 6 | -------------------------------------------------------------------------------- /app/models/credit_card.rb: -------------------------------------------------------------------------------- 1 | class CreditCard < ActiveRecord::Base 2 | belongs_to :user 3 | 4 | def description 5 | "XXXX-XXXX-XXXX-#{last_four} #{expiration_month}/#{expiration_year}" 6 | end 7 | end -------------------------------------------------------------------------------- /db/migrate/20120801233245_add_position_to_collections.rb: -------------------------------------------------------------------------------- 1 | class AddPositionToCollections < ActiveRecord::Migration 2 | def change 3 | add_column :collections, :position, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/views/admin/articles/new.html.haml: -------------------------------------------------------------------------------- 1 | = form_for @article, :url => admin_articles_path, 2 | :html => { :'data-track-changes' => true } do |f| 3 | = render :partial => "form", :locals => {:f => f} 4 | 5 | -------------------------------------------------------------------------------- /app/views/user_email/update.js.coffee: -------------------------------------------------------------------------------- 1 | unless <%= @user.errors.any? %> 2 | $.facebox "
Email updated and confirmation sent. Thanks!
" 3 | else 4 | alert "<%= @user.errors.full_messages.join(', ') %>" 5 | -------------------------------------------------------------------------------- /config/deploy/production.rb: -------------------------------------------------------------------------------- 1 | set :deploy_to, "/home/deploy" 2 | set :user, "deploy" 3 | 4 | server "practicingruby.com", :app, :web, :db, :primary => true 5 | 6 | after 'deploy:restart', 'unicorn:restart' 7 | -------------------------------------------------------------------------------- /config/initializers/domain_settings.rb: -------------------------------------------------------------------------------- 1 | url_options = { :host => ENV["HOST"] } 2 | 3 | ActionMailer::Base.default_url_options = url_options 4 | Rails.application.routes.default_url_options = url_options 5 | -------------------------------------------------------------------------------- /db/migrate/20150821164859_add_discourse_url_to_articles.rb: -------------------------------------------------------------------------------- 1 | class AddDiscourseUrlToArticles < ActiveRecord::Migration 2 | def change 3 | add_column :articles, :discourse_url, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /script/delayed_job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment')) 4 | require 'delayed/command' 5 | Delayed::Command.new(ARGV).daemonize 6 | -------------------------------------------------------------------------------- /app/controllers/hooks_controller.rb: -------------------------------------------------------------------------------- 1 | class HooksController < ApplicationController 2 | def receive 3 | webhooks = MailChimp::WebHooks.new(params) 4 | 5 | render :text => webhooks.process 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20121011002134_add_coupon_code_to_subscriptions.rb: -------------------------------------------------------------------------------- 1 | class AddCouponCodeToSubscriptions < ActiveRecord::Migration 2 | def change 3 | add_column :subscriptions, :coupon_code, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/views/users/mailchimp_yearly_billing.js.coffee: -------------------------------------------------------------------------------- 1 | $.facebox "Thanks for switching to yearly billing! We've recieved your request 2 | and will be in touch shortly to finish up the process.", 'confirm-interval-change' 3 | -------------------------------------------------------------------------------- /db/migrate/20130820143254_add_share_token_to_user.rb: -------------------------------------------------------------------------------- 1 | class AddShareTokenToUser < ActiveRecord::Migration 2 | def change 3 | change_table :users do |t| 4 | t.string :share_token 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .bundle 2 | db/*.sqlite3 3 | log/*.log 4 | tmp/ 5 | .rvmrc 6 | config/database.yml 7 | lib/development_mail_interceptor.rb 8 | .sass-cache/ 9 | public/assets 10 | coverage 11 | .kick 12 | .pow* 13 | .env 14 | -------------------------------------------------------------------------------- /app/assets/javascripts/pr.toggle.js.coffee: -------------------------------------------------------------------------------- 1 | $(document).on 'click', 'a[data-toggle]', (e) -> 2 | target = $(this).data('toggle') 3 | $(target).toggleClass('visible') 4 | $.post '/toggle_nav' 5 | e.preventDefault() 6 | -------------------------------------------------------------------------------- /config/initializers/mailchimp_settings.rb: -------------------------------------------------------------------------------- 1 | MailChimpSettings = { 2 | :list_id => ENV["MAILCHIMP_LIST_ID"], 3 | :api_key => ENV["MAILCHIMP_API_KEY"], 4 | :webhook_key => ENV["MAILCHIMP_WEBHOOK_KEY"] 5 | } 6 | -------------------------------------------------------------------------------- /config/initializers/stripe.rb: -------------------------------------------------------------------------------- 1 | STRIPE_SECRET_KEY = ENV["STRIPE_SECRET_KEY"] 2 | STRIPE_PUBLISHABLE_KEY = ENV["STRIPE_PUBLISHABLE_KEY"] 3 | STRIPE_WEBHOOK_PATH = ENV["TRAVIS"] ? "a/b/c/d" : ENV["STRIPE_WEBHOOK_PATH"] 4 | -------------------------------------------------------------------------------- /db/migrate/20120319214410_add_beta_tester_field_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddBetaTesterFieldToUsers < ActiveRecord::Migration 2 | def change 3 | add_column :users, :beta_tester, :boolean, :default => false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20120328151105_add_volume_id_to_articles.rb: -------------------------------------------------------------------------------- 1 | class AddVolumeIdToArticles < ActiveRecord::Migration 2 | def change 3 | change_table :articles do |t| 4 | t.belongs_to :volume 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | 3 | # Set up gems listed in the Gemfile. 4 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 5 | 6 | require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) 7 | -------------------------------------------------------------------------------- /app/assets/stylesheets/partials/_chat.sass: -------------------------------------------------------------------------------- 1 | #chat 2 | text-align: center 3 | font-family: sans-serif 4 | 5 | a.btn 6 | margin: 10px 0 7 | width: 300px 8 | p 9 | font-size: 14px 10 | text-align: center 11 | -------------------------------------------------------------------------------- /db/migrate/20120406161709_add_account_disabled_field_to_user.rb: -------------------------------------------------------------------------------- 1 | class AddAccountDisabledFieldToUser < ActiveRecord::Migration 2 | def change 3 | add_column :users, :account_disabled, :boolean, :default => false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20120831190102_add_status_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddStatusToUsers < ActiveRecord::Migration 2 | def change 3 | add_column :users, :status, :string 4 | add_column :users, :contact_email, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20120914175304_add_notify_updates_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddNotifyUpdatesToUsers < ActiveRecord::Migration 2 | def change 3 | add_column :users, :notify_updates, :boolean, :default => true, :null => false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/views/shared/_flash.html.haml: -------------------------------------------------------------------------------- 1 | #flash 2 | - flash.each do |flashtype, message| 3 | %div{:class => "flash #{flashtype}", :id => "flash-#{flashtype}"}= message 4 | :javascript 5 | setTimeout("$('#flash').slideUp()", 4000); 6 | -------------------------------------------------------------------------------- /config/initializers/cache_cooker_settings.rb: -------------------------------------------------------------------------------- 1 | CacheCooker.base_uri ENV["CACHE_COOKER_URI"] 2 | CacheCooker.digest_auth ENV["CACHE_COOKER_USERNAME"], ENV["CACHE_COOKER_PASSWORD"] 3 | CacheCooker.realm ENV["CACHE_COOKER_REALM"] 4 | -------------------------------------------------------------------------------- /db/migrate/20120407205455_add_collection_id_to_articles.rb: -------------------------------------------------------------------------------- 1 | class AddCollectionIdToArticles < ActiveRecord::Migration 2 | def change 3 | change_table :articles do |t| 4 | t.belongs_to :collection 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20130920195554_add_recommended_to_articles.rb: -------------------------------------------------------------------------------- 1 | class AddRecommendedToArticles < ActiveRecord::Migration 2 | def change 3 | add_column :articles, :recommended, :boolean, :default => false, :null => false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-Agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /test/factories/credit_card.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | factory :credit_card do |c| 3 | c.last_four("1234") 4 | c.expiration_month { Date.today.month } 5 | c.expiration_year { Date.today.year } 6 | c.user 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20111108180149_add_notify_comment_made_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddNotifyCommentMadeToUsers < ActiveRecord::Migration 2 | def change 3 | add_column :users, :notify_comment_made, :boolean, :default => false, :null => false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/views/articles/_explore_article.html.haml: -------------------------------------------------------------------------------- 1 | %div{class: "row_#{index}"} 2 | = link_to article_path(article) do 3 | %strong= article.list_title 4 | .description 5 | #{article.issue_number}, #{article.published_time.strftime("%B %Y")} 6 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | # Mime::Type.register_alias "text/html", :iphone 6 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Sample localization file for English. Add more files in this directory for other locales. 2 | # See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. 3 | 4 | en: 5 | hello: "Hello world" 6 | -------------------------------------------------------------------------------- /test/integration/authorization_failure_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class AuthorizationFailureTest < ActionDispatch::IntegrationTest 4 | test "auth failure page should load successfully" do 5 | visit auth_failure_path 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20120516152433_add_notifications_enabled_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddNotificationsEnabledToUsers < ActiveRecord::Migration 2 | def change 3 | add_column :users, :notifications_enabled, :boolean, :null => false, :default => false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/assets/javascripts/github_redirect_warning.js.coffee: -------------------------------------------------------------------------------- 1 | $(document).on 'click', 2 | "a[href='/subscriptions/new'][data-redirect-warning='true']", 3 | (e) -> 4 | e.preventDefault() 5 | $.facebox {ajax: '/subscriptions/redirect'}, 'redirect-warning' 6 | -------------------------------------------------------------------------------- /app/mailers/registration_mailer.rb: -------------------------------------------------------------------------------- 1 | class RegistrationMailer < ActionMailer::Base 2 | def email_confirmation(user) 3 | @user = user 4 | mail(:to => @user.contact_email, 5 | :subject => "Confirm your Practicing Ruby subscription") 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/models/payment_gateway/mail_chimp.rb: -------------------------------------------------------------------------------- 1 | module PaymentGateway 2 | class MailChimp 3 | 4 | def initialize(user) 5 | @user = user 6 | end 7 | 8 | def subscribe(params = {}) 9 | raise NotImplementedError 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /app/views/admin/announcements/new.html.haml: -------------------------------------------------------------------------------- 1 | - content_for(:header) { "New Announcement" } 2 | 3 | = form_for @announcement, :url => admin_announcements_path, 4 | :html => { :'data-track-changes' => true } do |f| 5 | = render :partial => "form", :locals => {:f => f} -------------------------------------------------------------------------------- /app/models/shared_article.rb: -------------------------------------------------------------------------------- 1 | class SharedArticle < ActiveRecord::Base 2 | before_create do 3 | write_attribute(:secret, SecretGenerator.generate(12)) 4 | write_attribute(:views, 0) 5 | end 6 | 7 | belongs_to :user 8 | belongs_to :article 9 | end 10 | -------------------------------------------------------------------------------- /app/views/account_mailer/canceled.text.erb: -------------------------------------------------------------------------------- 1 | Name: <%= @user.name || 'Unknown' %> 2 | Github: <%= @user.github_nickname %> 3 | Email: <%= @user.contact_email %> 4 | Payment Provider: <%= @user.payment_provider || 'None' %> 5 | Provider Id: <%= @user.payment_provider_id || "N/A" %> 6 | -------------------------------------------------------------------------------- /app/views/shared/_sad_pinkie.html.haml: -------------------------------------------------------------------------------- 1 | = image_tag "sad_pinkie.png", :class => "sad_pinkie", 2 | :title => "Sad Pinkie: http://regolithx.deviantart.com/art/Sad-Pinkie-Pie-Vector-285845297" 3 | // Image Credit: http://regolithx.deviantart.com/art/Sad-Pinkie-Pie-Vector-285845297 4 | -------------------------------------------------------------------------------- /app/views/admin/announcements/edit.html.haml: -------------------------------------------------------------------------------- 1 | - content_for(:header) { "Edit Announcement" } 2 | 3 | = form_for @announcement, :url => admin_announcement_path(@announcement), 4 | :html => { :'data-track-changes' => true } do |f| 5 | = render :partial => "form", :locals => {:f => f} -------------------------------------------------------------------------------- /app/views/announcements/show.html.haml: -------------------------------------------------------------------------------- 1 | - content_for(:title) { @announcement.title } 2 | 3 | #announcements 4 | = render :partial => "announcement", 5 | :locals => {:announcement => @announcement} 6 | 7 | %p= link_to "← back to announcements".html_safe, announcements_path -------------------------------------------------------------------------------- /db/migrate/20120626145819_add_queue_to_delayed_jobs.rb: -------------------------------------------------------------------------------- 1 | class AddQueueToDelayedJobs < ActiveRecord::Migration 2 | def self.up 3 | add_column :delayed_jobs, :queue, :string 4 | end 5 | 6 | def self.down 7 | remove_column :delayed_jobs, :queue 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.0.0 4 | before_script: 5 | - bundle exec rake travis:setup 6 | - export DISPLAY=:99.0 7 | - sh -e /etc/init.d/xvfb start 8 | notifications: 9 | email: 10 | - jordan.byron@gmail.com 11 | - gregory.t.brown@gmail.com 12 | -------------------------------------------------------------------------------- /app/assets/stylesheets/partials/_mobile.sass: -------------------------------------------------------------------------------- 1 | @media only screen and (max-device-width: 480px) 2 | // TODO Re-evaluate font size in mobile safari 3 | // body 4 | // font-size: 25px 5 | pre 6 | overflow: scroll 7 | -webkit-overflow-scrolling: touch 8 | font-size: 0.75em -------------------------------------------------------------------------------- /app/views/user_email/_warning.html.haml: -------------------------------------------------------------------------------- 1 | - if show_email_warning? 2 | #email-confirmation-warning 3 | Your email address isn't verified yet. Please check your inbox, or 4 | = link_to "update your contact info", change_email_path, 5 | :rel => "facebox" 6 | to try again. 7 | -------------------------------------------------------------------------------- /db/migrate/20110912175336_add_issue_number_to_articles.rb: -------------------------------------------------------------------------------- 1 | class AddIssueNumberToArticles < ActiveRecord::Migration 2 | def self.up 3 | add_column :articles, :issue_number, :text 4 | end 5 | 6 | def self.down 7 | remove_column :articles, :issue_number 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/views/account_mailer/mailchimp_yearly_billing.text.erb: -------------------------------------------------------------------------------- 1 | Name: <%= @user.name || 'Unknown' %> 2 | Github: <%= @user.github_nickname %> 3 | Email: <%= @user.contact_email %> 4 | Payment Provider: <%= @user.payment_provider || 'None' %> 5 | Provider Id: <%= @user.payment_provider_id || "N/A" %> 6 | -------------------------------------------------------------------------------- /db/migrate/20131114225709_add_interval_to_subscriptions.rb: -------------------------------------------------------------------------------- 1 | class AddIntervalToSubscriptions < ActiveRecord::Migration 2 | def change 3 | add_column :subscriptions, :interval, :string, default: 'month' 4 | rename_column :subscriptions, :monthly_rate_cents, :rate_cents 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /test/factories/comment_factory.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | sequence(:comment_body) { |n| "Comment #{n}" } 3 | 4 | factory :comment do |c| 5 | c.body { |_| FactoryGirl.generate(:comment_body) } 6 | c.commentable { FactoryGirl.create(:article) } 7 | c.association :user 8 | end 9 | end -------------------------------------------------------------------------------- /app/assets/stylesheets/partials/_open_source.sass: -------------------------------------------------------------------------------- 1 | body.home-open_source 2 | font-family: sans-serif 3 | header h1 4 | font-size: 27px 5 | font-weight: bold 6 | h3 7 | font-size: 1.5em 8 | li 9 | list-style-type: circle 10 | margin-bottom: 10px 11 | text-align: justify 12 | 13 | -------------------------------------------------------------------------------- /app/views/articles/_subway.html.haml: -------------------------------------------------------------------------------- 1 | #subway 2 | - @collections.each do |collection| 3 | = link_to collection.icon, collection.path, :rel => "tooltip", 4 | :title => collection.name 5 | - @volumes.each do |volume| 6 | = link_to volume.icon, volume.path, :rel => "tooltip", 7 | :title => volume.name -------------------------------------------------------------------------------- /app/views/conversation_mailer/mentioned.text.erb: -------------------------------------------------------------------------------- 1 | You can see what was said and share your own thoughts via the link below: 2 | 3 | <%= article_url(@article, :anchor => "comments") %> 4 | 5 | ---- 6 | 7 | You can customize your notification settings via the link below: 8 | 9 | <%= profile_settings_url %> 10 | -------------------------------------------------------------------------------- /app/views/users/current_credit_card.html.haml: -------------------------------------------------------------------------------- 1 | %h1 Current credit card 2 | %hr 3 | 4 | %p 5 | %strong Card #: 6 | ************#{@card.last4} 7 | 8 | %p 9 | %strong Expiration: 10 | #{@card.exp_month}/#{@card.exp_year} 11 | 12 | %hr 13 | = link_to "Change your credit card", '#', :class => "btn update-cc" -------------------------------------------------------------------------------- /config/deploy/old_production.rb: -------------------------------------------------------------------------------- 1 | set :user, "git" 2 | set :deploy_to, "/var/rapp/#{application}" 3 | 4 | server "173.246.46.66", :app, :web, :db, :primary => true 5 | 6 | namespace :deploy do 7 | task :restart, :roles => :app do 8 | run "touch #{current_path}/tmp/restart.txt" 9 | end 10 | end 11 | 12 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: rubocop-todo.yml 2 | 3 | HashSyntax: 4 | Enabled: false 5 | IfUnlessModifier: 6 | Enabled: false 7 | SignalException: 8 | Enabled: false 9 | StringLiterals: 10 | Enabled: false 11 | ClassLength: 12 | Enabled: false 13 | 14 | AllCops: 15 | Excludes: 16 | - vendor/** 17 | -------------------------------------------------------------------------------- /db/migrate/20111206143647_add_broadcast_columns_to_announcements.rb: -------------------------------------------------------------------------------- 1 | class AddBroadcastColumnsToAnnouncements < ActiveRecord::Migration 2 | def change 3 | add_column :announcements, :broadcast, :boolean, :default => false, :null => false 4 | add_column :announcements, :broadcast_message, :text 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /test/integration/account_cancelation_test.rb: -------------------------------------------------------------------------------- 1 | require_relative '../test_helper' 2 | 3 | class AccountCancelationTest < ActionDispatch::IntegrationTest 4 | test "user account is disabled" do 5 | simulated_user 6 | .register(Support::SimulatedUser.default) 7 | .cancel_account 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/views/admin/articles/edit.html.haml: -------------------------------------------------------------------------------- 1 | - if @article.published? 2 | = javascript_tag "alert('Be careful buddy, this is a published article!!!')" 3 | 4 | = form_for @article, :url => admin_article_path(@article), 5 | :html => { :'data-track-changes' => true } do |f| 6 | = render :partial => "form", :locals => {:f => f} 7 | -------------------------------------------------------------------------------- /app/views/conversation_mailer/comment_made.text.erb: -------------------------------------------------------------------------------- 1 | You can see what has been said and share your own thoughts via the link below: 2 | 3 | <%= article_url(@article, :anchor => "comments") %> 4 | 5 | ---- 6 | 7 | You can customize your notification settings via the link below: 8 | 9 | <%= profile_settings_url %> 10 | -------------------------------------------------------------------------------- /app/views/conversation_mailer/started.text.erb: -------------------------------------------------------------------------------- 1 | You can see what people are saying and share your own thoughts via the link below: 2 | 3 | <%= article_url(@article, :anchor => "comments") %> 4 | 5 | ---- 6 | 7 | You can customize your notification settings via the link below: 8 | 9 | <%= profile_settings_url %> 10 | -------------------------------------------------------------------------------- /app/views/registration_mailer/email_confirmation.text.erb: -------------------------------------------------------------------------------- 1 | Hello, 2 | 3 | To confirm your Practicing Ruby email, click the link below. 4 | 5 | <%= confirm_email_url(:secret => @user.access_token) %> 6 | 7 | If you run into problems, don't hesitate to contact gregory@practicingruby.com 8 | 9 | Thanks! 10 | -greg 11 | -------------------------------------------------------------------------------- /script/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. 3 | 4 | APP_PATH = File.expand_path('../../config/application', __FILE__) 5 | require File.expand_path('../../config/boot', __FILE__) 6 | require 'rails/commands' 7 | -------------------------------------------------------------------------------- /app/views/announcements/index.html.haml: -------------------------------------------------------------------------------- 1 | - content_for(:title) { "Announcements" } 2 | 3 | - if current_user.admin? 4 | #admin 5 | = button_to "New announcement", new_admin_announcement_path, :method => :get 6 | .clear 7 | 8 | #announcements 9 | 10 | = render :partial => "announcement", :collection => @announcements -------------------------------------------------------------------------------- /config/initializers/omniauth.rb: -------------------------------------------------------------------------------- 1 | Rails.application.config.middleware.use OmniAuth::Builder do 2 | case ENV["AUTH_MODE"] 3 | when "developer" 4 | provider :developer, :fields => [:nickname], :uid_field => :nickname 5 | when "github" 6 | provider :github, ENV["GITHUB_CLIENT_KEY"], ENV["GITHUB_SECRET"] 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /config/schedule.rb: -------------------------------------------------------------------------------- 1 | set :output, "/home/deploy/current/log/cron_log.log" 2 | 3 | # Make sure +bundle exec+ is used when executing rake tasks 4 | # 5 | job_type :rake, "cd :path && RAILS_ENV=:environment bundle exec rake :task --silent :output" 6 | 7 | every 1.month do 8 | rake "stripe:card_exipration_notice" 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20120328150809_create_volumes.rb: -------------------------------------------------------------------------------- 1 | class CreateVolumes < ActiveRecord::Migration 2 | def change 3 | create_table :volumes do |t| 4 | t.integer :number 5 | t.text :description 6 | t.date :start_date 7 | t.date :finish_date 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/views/announcements/_announcement.html.haml: -------------------------------------------------------------------------------- 1 | .announcement 2 | .title 3 | = link_to announcement.title, announcement_path(announcement) 4 | .on= announcement.created_at.to_date 5 | - if current_user.admin? 6 | .right 7 | = link_to "Edit", edit_admin_announcement_path(announcement) 8 | 9 | = md(announcement.body) -------------------------------------------------------------------------------- /db/migrate/20120112195907_create_article_visits.rb: -------------------------------------------------------------------------------- 1 | class CreateArticleVisits < ActiveRecord::Migration 2 | def change 3 | create_table :article_visits do |t| 4 | t.belongs_to :user 5 | t.belongs_to :article 6 | t.integer :views, :default => 1 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /Capfile: -------------------------------------------------------------------------------- 1 | load 'deploy' if respond_to?(:namespace) # cap2 differentiator 2 | 3 | # Uncomment if you are using Rails' asset pipeline 4 | # load 'deploy/assets' 5 | 6 | Dir['vendor/gems/*/recipes/*.rb','vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) } 7 | 8 | load 'config/deploy' # remove this line to skip loading any of the default tasks -------------------------------------------------------------------------------- /app/views/home/public_archives.html.haml: -------------------------------------------------------------------------------- 1 | - content_for(:title) { "Delightful lessons for dedicated programmers - Practicing Ruby" } 2 | - content_for :header do 3 | %h1 Practicing Ruby 4 | %h2 Delightful lessons for dedicated programmers 5 | 6 | = image_tag "ruby-divider.png" 7 | 8 | #archives 9 | = render 'articles/archives' 10 | -------------------------------------------------------------------------------- /db/migrate/20110830041617_add_admin_field_to_user.rb: -------------------------------------------------------------------------------- 1 | class AddAdminFieldToUser < ActiveRecord::Migration 2 | def self.up 3 | change_table :users do |t| 4 | t.boolean :admin, :default => false 5 | end 6 | end 7 | 8 | def self.down 9 | change_table :users do |t| 10 | t.remove :admin 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20110829215505_create_authorizations.rb: -------------------------------------------------------------------------------- 1 | class CreateAuthorizations < ActiveRecord::Migration 2 | def self.up 3 | create_table :authorizations do |t| 4 | t.text :github_uid 5 | t.belongs_to :user 6 | t.timestamps 7 | end 8 | end 9 | 10 | def self.down 11 | drop_table :authorizations 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20110829230541_add_github_nickname_to_user.rb: -------------------------------------------------------------------------------- 1 | class AddGithubNicknameToUser < ActiveRecord::Migration 2 | def self.up 3 | change_table :users do |t| 4 | t.text :github_nickname 5 | end 6 | end 7 | 8 | def self.down 9 | change_table :users do |t| 10 | t.remove :github_nickname 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/tasks/rubocop.rake: -------------------------------------------------------------------------------- 1 | unless Rails.env.production? 2 | require "rubocop/rake_task" 3 | 4 | namespace :test do 5 | desc "Run RuboCop style and lint checks" 6 | Rubocop::RakeTask.new(:rubocop) do |t| 7 | t.options = ["--rails"] 8 | end 9 | end 10 | 11 | Rake::Task[:test].enhance { Rake::Task["test:rubocop"].invoke } 12 | end 13 | -------------------------------------------------------------------------------- /app/models/subscription.rb: -------------------------------------------------------------------------------- 1 | class Subscription < ActiveRecord::Base 2 | belongs_to :user 3 | 4 | def self.active 5 | where(:finish_date => nil).first 6 | end 7 | 8 | def self.cancel_account 9 | active.update_attributes(:finish_date => Date.today) if active 10 | end 11 | 12 | def active? 13 | finish_date.blank? 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/views/users/_sidebar.html.haml: -------------------------------------------------------------------------------- 1 | #settings-sidebar 2 | = link_to "Profile", profile_settings_path, 3 | class: ('active' if current == 'profile') 4 | = link_to "Notifications", notification_settings_path, 5 | class: ('active' if current == 'notifications') 6 | = link_to "Billing", billing_settings_path, 7 | class: ('active' if current == 'billing') 8 | -------------------------------------------------------------------------------- /db/migrate/20120407204814_create_collections.rb: -------------------------------------------------------------------------------- 1 | class CreateCollections < ActiveRecord::Migration 2 | def change 3 | create_table :collections do |t| 4 | t.integer :id 5 | t.string :name 6 | t.text :description 7 | t.string :image_file_name 8 | t.string :slug 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/models/card_expirer.rb: -------------------------------------------------------------------------------- 1 | CardExpirer = ->(date) { 2 | cards = CreditCard.includes(:user) 3 | .where(:expiration_year => date.year, 4 | :expiration_month => date.month, 5 | "users.status" => "active") 6 | cards.each do |card| 7 | AccountMailer.card_expiring(card) 8 | end 9 | } 10 | -------------------------------------------------------------------------------- /app/views/users/destroy.html.haml: -------------------------------------------------------------------------------- 1 | - content_for(:title) { "Sorry to see you go"} 2 | - content_for(:header) { "Sorry to see you go" } 3 | 4 | %h3 5 | Please feel free to email #{mail_to "gregory@practicingruby.com"} with 6 | feedback. 7 | %p 8 | And remember it may take up to 24 hours before your account is fully cancelled. 9 | 10 | = render "shared/sad_pinkie" -------------------------------------------------------------------------------- /test/factories/announcement_factory.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | sequence(:announcement_title) { |n| "Announcement #{n}" } 3 | 4 | factory :announcement do |a| 5 | a.title { |_| FactoryGirl.generate(:announcement_title) } 6 | a.body "Announcement Body" 7 | a.broadcast_message { |announcement| announcement.title } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('../config/application', __FILE__) 5 | require 'rake' 6 | require File.expand_path('../lib/rake_exception_notification', __FILE__) 7 | 8 | PracticingRubyWeb::Application.load_tasks 9 | -------------------------------------------------------------------------------- /app/views/shared/_broadcasts.html.haml: -------------------------------------------------------------------------------- 1 | - if active_broadcasts.any? && current_user.try(:status) == "active" 2 | #top-bar 3 | #broadcasts 4 | = link_to "Dismiss", dismiss_broadcasts_path, :class => "dismiss", 5 | :remote => true 6 | - active_broadcasts.each do |broadcast| 7 | .broadcast 8 | = link_to broadcast.broadcast_message, broadcast.url 9 | -------------------------------------------------------------------------------- /db/migrate/20110820183757_create_users.rb: -------------------------------------------------------------------------------- 1 | class CreateUsers < ActiveRecord::Migration 2 | def self.up 3 | create_table :users do |t| 4 | t.text :first_name 5 | t.text :last_name 6 | t.text :email 7 | t.text :mailchimp_web_id 8 | 9 | t.timestamps 10 | end 11 | end 12 | 13 | def self.down 14 | drop_table :users 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/views/users/show.html.haml: -------------------------------------------------------------------------------- 1 | #profile 2 | .header 3 | .avatar= @user.icon(100) 4 | 5 | %h1= @user.github_nickname 6 | 7 | .info 8 | = "Member since #{@user.member_since}" 9 | 10 | - if @user.comments.any? 11 | %br 12 | = "#{@user.comments.count} comments made" 13 | 14 | - #TODO Add website link 15 | - #TODO Display comments made by user -------------------------------------------------------------------------------- /db/migrate/20110909193908_create_announcements.rb: -------------------------------------------------------------------------------- 1 | class CreateAnnouncements < ActiveRecord::Migration 2 | def self.up 3 | create_table :announcements do |t| 4 | t.text :title 5 | t.text :body 6 | t.belongs_to :author 7 | 8 | t.timestamps 9 | end 10 | end 11 | 12 | def self.down 13 | drop_table :announcements 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /test/integration/profile_test.rb: -------------------------------------------------------------------------------- 1 | require_relative "../test_helper" 2 | 3 | class ProfileTest < ActionDispatch::IntegrationTest 4 | test "contact email is validated" do 5 | simulated_user 6 | .register(Support::SimulatedUser.default) 7 | .edit_profile(:email => "jordan byron at gmail dot com") 8 | 9 | assert_content "Contact email is invalid" 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/controllers/announcements_controller.rb: -------------------------------------------------------------------------------- 1 | class AnnouncementsController < ApplicationController 2 | def index 3 | redirect_to "http://elmcitycraftworks.org/" 4 | end 5 | 6 | def show 7 | redirect_to "http://elmcitycraftworks.org/" 8 | end 9 | 10 | def dismiss 11 | ids = active_broadcasts.map(&:id) 12 | session[:dismissed_broadcasts] += ids 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/views/layouts/landing.html.haml: -------------------------------------------------------------------------------- 1 | !!! 5 2 | %html{:lang => 'en'} 3 | %head 4 | %title Practicing Ruby | A unique journal curated by Gregory Brown 5 | 6 | = stylesheet_link_tag 'application' 7 | = javascript_include_tag 'application' 8 | = csrf_meta_tag 9 | 10 | = render :partial => "shared/ios_icon" 11 | 12 | = yield(:header_bottom) 13 | 14 | %body.landing= yield 15 | -------------------------------------------------------------------------------- /app/views/account_mailer/payment_created.text.erb: -------------------------------------------------------------------------------- 1 | Hi there! 2 | 3 | On <%= @payment.invoice_date %>, we charged your card ending in <%= @payment.credit_card_last_four %> a total of <%= number_to_currency @payment.amount %> 4 | for your Practicing Ruby subscription. Please hang on to this email as 5 | proof of payment, and let us know if you have any questions! 6 | 7 | Thanks, 8 | Gregory Brown (practicingruby.com) 9 | -------------------------------------------------------------------------------- /app/views/articles/index.html.haml: -------------------------------------------------------------------------------- 1 | - content_for(:title) { "Articles" } 2 | - if params[:new_subscription] 3 | :coffeescript 4 | $.facebox '#{escape_javascript render('subscriptions/thanks')}', 'thanks-box' 5 | - content_for(:header) do 6 | %h1 Practicing Ruby 7 | %h2 Delightful lessons for dedicated programmers 8 | = image_tag "ruby-divider.png" 9 | 10 | #archives 11 | = render 'archives' 12 | -------------------------------------------------------------------------------- /app/assets/stylesheets/partials/_email_confirmation_warning.sass: -------------------------------------------------------------------------------- 1 | #email-confirmation-warning 2 | width: 750px 3 | font-family: Helvetica, sans-serif 4 | @extend #share-alert 5 | box-sizing: border-box 6 | a.dismiss 7 | float: right 8 | color: #fff 9 | font-size: 0.75em 10 | line-height: 3em 11 | strong 12 | display: block 13 | font-weight: bold 14 | margin-bottom: 0.5em 15 | -------------------------------------------------------------------------------- /db/migrate/20131204201817_add_email_confirmed_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddEmailConfirmedToUsers < ActiveRecord::Migration 2 | def change 3 | add_column :users, :email_confirmed, :boolean, :default => false, 4 | :null => false 5 | execute %{update users set email_confirmed = true where status in 6 | ('active', 'confirmed', 'payment_pending')} 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20121019183135_create_credit_cards.rb: -------------------------------------------------------------------------------- 1 | class CreateCreditCards < ActiveRecord::Migration 2 | def up 3 | create_table :credit_cards do |t| 4 | t.belongs_to :user 5 | t.string :last_four 6 | t.integer :expiration_month 7 | t.integer :expiration_year 8 | t.timestamps 9 | end 10 | end 11 | 12 | def down 13 | drop_table :credit_cards 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20110830162757_create_shared_articles.rb: -------------------------------------------------------------------------------- 1 | class CreateSharedArticles < ActiveRecord::Migration 2 | def self.up 3 | create_table :shared_articles do |t| 4 | t.belongs_to :user 5 | t.belongs_to :article 6 | t.text :secret 7 | t.integer :views 8 | 9 | t.timestamps 10 | end 11 | end 12 | 13 | def self.down 14 | drop_table :shared_articles 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /db/migrate/20110901130928_create_comments.rb: -------------------------------------------------------------------------------- 1 | class CreateComments < ActiveRecord::Migration 2 | def self.up 3 | create_table :comments do |t| 4 | t.integer :commentable_id 5 | t.string :commentable_type 6 | 7 | t.belongs_to :user 8 | 9 | t.text :body 10 | 11 | t.timestamps 12 | end 13 | end 14 | 15 | def self.down 16 | drop_table :comments 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /test/support/stripe/invoice.rb: -------------------------------------------------------------------------------- 1 | module Support 2 | module Stripe 3 | class Invoice 4 | attr_accessor :id, :customer, :period_start, :date, :total, :paid, 5 | :invoice_items, :closed 6 | 7 | Lines = Struct.new(:invoiceitems) 8 | 9 | def lines 10 | Lines.new(invoice_items) 11 | end 12 | 13 | def save 14 | # noop 15 | end 16 | end 17 | end 18 | end -------------------------------------------------------------------------------- /app/views/articles/_footer.html.haml: -------------------------------------------------------------------------------- 1 | #article-footer 2 | %h3 If you enjoyed this issue of Practicing Ruby, please share it! 3 | 4 | %p 5 | Copy-and-paste the link below to give your friends free access to 6 | this article: 7 | 8 | = text_field_tag :share_link, article_url(@article), :size => 80 9 | 10 | %p 11 | We believe that sharing is caring, so feel free to post this link anywhere 12 | you'd like! 13 | -------------------------------------------------------------------------------- /app/views/sessions/expired_link.html.haml: -------------------------------------------------------------------------------- 1 | - content_for(:header) { "Drat!" } 2 | 3 | %h3 The confirmation link you've clicked on is either expired or invalid. 4 | 5 | %p 6 | If you have already confirmed your email address, you can try 7 | #{link_to 'logging in', login_path}, but if that doesn't work 8 | just send an email to #{mail_to "support@elmcitycraftworks.org"} 9 | and I will help you resolve this issue. 10 | 11 | -------------------------------------------------------------------------------- /db/migrate/20110829215511_create_authorization_links.rb: -------------------------------------------------------------------------------- 1 | class CreateAuthorizationLinks < ActiveRecord::Migration 2 | def self.up 3 | create_table :authorization_links do |t| 4 | t.text :mailchimp_email 5 | t.text :github_nickname 6 | t.text :secret 7 | t.belongs_to :authorization 8 | t.timestamps 9 | end 10 | end 11 | 12 | def self.down 13 | drop_table :authorization_links 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format 4 | # (all these examples are active by default): 5 | # ActiveSupport::Inflector.inflections do |inflect| 6 | # inflect.plural /^(ox)$/i, '\1en' 7 | # inflect.singular /^(ox)en/i, '\1' 8 | # inflect.irregular 'person', 'people' 9 | # inflect.uncountable %w( fish sheep ) 10 | # end 11 | -------------------------------------------------------------------------------- /db/migrate/20110821020718_create_articles.rb: -------------------------------------------------------------------------------- 1 | class CreateArticles < ActiveRecord::Migration 2 | def self.up 3 | create_table :articles do |t| 4 | t.text :subject 5 | t.text :body 6 | t.text :status, :default => "draft" 7 | t.text :mailchimp_campaign_id 8 | t.datetime :published_time 9 | 10 | t.timestamps 11 | end 12 | end 13 | 14 | def self.down 15 | drop_table :articles 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/helpers/article_helper.rb: -------------------------------------------------------------------------------- 1 | module ArticleHelper 2 | def article_url(article, params={}) 3 | return super unless current_user && current_user.active? 4 | 5 | ArticleLink.new(article, params).url(current_user.share_token) 6 | end 7 | 8 | def article_path(article, params={}) 9 | return super unless current_user && current_user.active? 10 | 11 | ArticleLink.new(article, params).path(current_user.share_token) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /db/migrate/20130215174537_create_payments.rb: -------------------------------------------------------------------------------- 1 | class CreatePayments < ActiveRecord::Migration 2 | def change 3 | create_table :payments do |t| 4 | t.belongs_to :user 5 | t.date :invoice_date 6 | t.decimal :amount 7 | t.string :stripe_invoice_id 8 | t.string :credit_card_last_four 9 | t.boolean :email_sent, :default => false, :null => false 10 | 11 | t.timestamps 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/tasks/cache_cooker.rake: -------------------------------------------------------------------------------- 1 | # Rake tasks to bake caches 2 | # 3 | namespace :bake do 4 | desc 'Refresh the articles cache' 5 | task :articles => :environment do 6 | puts "Fire up the oven. It's time to start cookin!" 7 | 8 | Article.order("published_time DESC").each do |article| 9 | CacheCooker.delay.bake("/articles/#{article.id}") 10 | end 11 | 12 | puts "#{Article.count} articles baked and ready to serve :)" 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20110912173127_add_email_preferences_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddEmailPreferencesToUsers < ActiveRecord::Migration 2 | def self.up 3 | add_column :users, :notify_conversations, :boolean, :default => true, :null => false 4 | add_column :users, :notify_mentions, :boolean, :default => true, :null => false 5 | end 6 | 7 | def self.down 8 | remove_column :users, :notify_conversations 9 | remove_column :users, :notify_mentions 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20110916140124_change_mail_columns_to_text.rb: -------------------------------------------------------------------------------- 1 | class ChangeMailColumnsToText < ActiveRecord::Migration 2 | COLUMNS = [ :to_address, :cc_address, :bcc_address, :reply_to_address, 3 | :subject ] 4 | 5 | def up 6 | COLUMNS.each do |column| 7 | change_column :emails, column, :text 8 | end 9 | end 10 | 11 | def down 12 | COLUMNS.each do |column| 13 | change_column :emails, column, :string 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/models/broadcaster.rb: -------------------------------------------------------------------------------- 1 | class Broadcaster 2 | def self.notify_subscribers(params) 3 | BroadcastMailer.recipients.each do |subscriber| 4 | BroadcastMailer.broadcast(params, subscriber).deliver 5 | end 6 | end 7 | 8 | def self.notify_testers(params) 9 | subscriber = Struct.new(:contact_email, :share_token) 10 | .new(params[:to], "testtoken") 11 | 12 | BroadcastMailer.broadcast(params, subscriber).deliver 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/views/articles/_header.html.haml: -------------------------------------------------------------------------------- 1 | - content_for(:title) do 2 | #{@article.subject} - #{@article.issue_number} 3 | - content_for(:description) do 4 | #{@article.summary} 5 | - content_for(:header) do 6 | %div{:style => "text-align: center; margin: 20 px"} 7 | = link_to root_path do 8 | = image_tag "//i.imgur.com/hYoGfNJ.png", :width => "75%" 9 | .bigtext{style: 'text-align: center;'} 10 | %div{:style => "padding-top: 40px;"} 11 | = @article.subject 12 | -------------------------------------------------------------------------------- /lib/tasks/mailchimp.rake: -------------------------------------------------------------------------------- 1 | include ActionView::Helpers::TextHelper 2 | include RakeExceptionNotification 3 | 4 | namespace :mailchimp do 5 | desc 'Disable accounts which have been unsubscribed in mailchimp' 6 | task :disable_unsubscribed => :environment do 7 | 8 | puts "# Running mailchip:disable_unsubscribed at #{Time.now}" 9 | 10 | exception_notify do 11 | user_manager = UserManager.new 12 | user_manager.disable_unsubscribed_users 13 | end 14 | end 15 | end -------------------------------------------------------------------------------- /app/assets/stylesheets/partials/_broadcasts.sass: -------------------------------------------------------------------------------- 1 | #top-bar 2 | background-color: darken(#f0f1f4, 10%) 3 | 4 | #broadcasts 5 | width: $page-width 6 | margin: 0 auto 7 | text-align: center 8 | font-family: sans-serif 9 | a.dismiss 10 | float: right 11 | color: #1b1b1b 12 | font-size: 0.75em 13 | line-height: 3em 14 | text-decoration: none 15 | .broadcast 16 | display: block 17 | text-align: center 18 | padding: 7px 0 19 | a 20 | color: $red 21 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | PracticingRubyWeb::Application.config.session_store :cookie_store, :key => '_practicing-ruby-web_session' 4 | 5 | # Use the database for sessions instead of the cookie-based default, 6 | # which shouldn't be used to store highly confidential information 7 | # (create the session table with "rails generate session_migration") 8 | # PracticingRubyWeb::Application.config.session_store :active_record_store 9 | -------------------------------------------------------------------------------- /app/assets/stylesheets/partials/_flash.sass: -------------------------------------------------------------------------------- 1 | #flash 2 | width: $page-width 3 | margin: 0 auto 4 | text-align: center 5 | font-family: 'Helvetica', sans-serif 6 | .flash 7 | text-align: center 8 | padding: 0.5em 1em 9 | margin: 0.5em 10 | display: inline-block 11 | +border-radius(2px) 12 | background-color: #FAFAE2 13 | 14 | &.notice 15 | background-color: #8c8 16 | color: #252 17 | 18 | &.error 19 | background-color: #c88 20 | color: #522 21 | -------------------------------------------------------------------------------- /config/initializers/rails_security_workarounds.rb: -------------------------------------------------------------------------------- 1 | # https://groups.google.com/forum/#!topic/rubyonrails-security/bahr2JLnxvk 2 | 3 | ActiveSupport::XmlMini.backend = 'Nokogiri' 4 | 5 | # https://groups.google.com/forum/#!topic/rubyonrails-security/7VlB_pck3hU 6 | # 7 | module ActiveSupport 8 | module JSON 9 | module Encoding 10 | 11 | private 12 | 13 | class EscapedString 14 | def to_s 15 | self 16 | end 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /app/views/home/chat.html.haml: -------------------------------------------------------------------------------- 1 | #chat 2 | %p 3 | Get in touch with your fellow Practicing Rubyists! 4 | 5 | = link_to "Chat with a guest account", CHAT_GUEST_URL, 6 | :class => "btn" 7 | = link_to "Chat with your Campfire account", CHAT_LOGIN_URL, 8 | :class => "btn" 9 | %p 10 | You can log in as a guest without any extra setup. 11 | %br 12 | For transcripts, you need a (free) Campfire account. 13 | 14 | %p 15 | Email #{mail_to "gregory@practicingruby.com"} for an invite. 16 | 17 | -------------------------------------------------------------------------------- /app/views/comments/_show.html.haml: -------------------------------------------------------------------------------- 1 | .comment{:data => { :id => comment.id, 2 | :editable => (comment.editable_by?(current_user)).inspect }} 3 | .header 4 | = comment.user.icon(32) 5 | = link_to comment.user.github_nickname, 6 | user_path(comment.user.github_nickname), :class => "user-profile" 7 | .controls= comment.controls 8 | .on 9 | = comment.time_ago 10 | ago 11 | .clear 12 | .content 13 | - cache("comment_body_#{comment.id}") do 14 | = comment.content 15 | -------------------------------------------------------------------------------- /app/views/subscriptions/_thanks.html.haml: -------------------------------------------------------------------------------- 1 | %h1 You're awesome. Thanks for subscribing! 2 | 3 | %p.image= image_tag "payment/dolla_billz.jpg" 4 | 5 | %p 6 | Your account is now set up, which means that you can enjoy everything that 7 | Practicing Ruby has to offer. You can start by 8 | #{link_to 'browsing through our library', articles_path} or reading a 9 | #{link_to 'randomly selected article', random_article_path}. 10 | If you have any questions, please send an email to 11 | #{mail_to 'gregory@practicingruby.com'}. 12 | -------------------------------------------------------------------------------- /app/views/user_email/change.html.haml: -------------------------------------------------------------------------------- 1 | #change-email 2 | = form_for @user, :remote => true, :url => update_email_path, 3 | :html => {'parsley-validate' => ''} do |f| 4 | = error_messages_for(@user) 5 | .field 6 | = f.label :contact_email, "Email Address" 7 | = f.email_field :contact_email, :required => true, 8 | 'parsley-remote' => email_unique_users_path 9 | .field 10 | = f.submit "Send confirmation email", :class => 'btn-small' 11 | :coffeescript 12 | $('#edit_user_#{@user.id}').parsley() 13 | -------------------------------------------------------------------------------- /app/assets/stylesheets/partials/_announcements.sass: -------------------------------------------------------------------------------- 1 | #announcements 2 | .announcement 3 | margin: 1em 0 4 | font-family: 'Helvetica', sans-serif 5 | +markdown 6 | .title 7 | font-size: 1.1em 8 | font-weight: bold 9 | padding: 0.5em 10 | background-color: #eee 11 | .right 12 | float: right 13 | margin-right: 0.5em 14 | .on 15 | display: inline-block 16 | float: right 17 | color: #555 18 | font-weight: normal 19 | a 20 | color: #000 -------------------------------------------------------------------------------- /lib/md_mentions.rb: -------------------------------------------------------------------------------- 1 | module MdMentions 2 | class Render < MdEmoji::Render 3 | def paragraph(text) 4 | mentioned_text = text.gsub(/@([a-z\d-]+)(\.[a-z]{3})?/i) do |mention| 5 | github = $1 6 | user = User.where("LOWER(github_nickname) = ?", github.downcase).exists? 7 | 8 | if user && $2.blank? 9 | %{@#{github}} 10 | else 11 | mention 12 | end 13 | end 14 | 15 | super mentioned_text 16 | end 17 | end 18 | end -------------------------------------------------------------------------------- /app/models/article_link.rb: -------------------------------------------------------------------------------- 1 | class ArticleLink 2 | include Rails.application.routes.url_helpers 3 | 4 | def initialize(article, params={}) 5 | self.article = article 6 | self.params = params 7 | end 8 | 9 | def path(token) 10 | article_path(article, params_with_token(token)) 11 | end 12 | 13 | def url(token) 14 | article_url(article, params_with_token(token)) 15 | end 16 | 17 | private 18 | 19 | attr_accessor :params, :article 20 | 21 | def params_with_token(token) 22 | {:u => token}.merge(params) 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /config/initializers/exception_notifier.rb: -------------------------------------------------------------------------------- 1 | if Rails.env.production? 2 | PracticingRubyWeb::Application.config.middleware.use ExceptionNotification::Rack, 3 | :email => { 4 | :email_prefix => "[Practicing Ruby] ", 5 | :sender_address => %{"Exception Notifier"Maybe you tried to change something you didn't have access to.
29 | 30 |You may have mistyped the address or the page may have moved.
29 | 30 |Please let us know about it: support@elmcitycraftworks.org
29 | 30 |42 | Hi Folks! We are down for <%= reason ? reason : "maintenance" %> 43 | as of <%= Time.now.utc.strftime("%H:%M %Z") %>. 44 |
45 |46 | We will be back <%= deadline ? deadline : "shortly" %>. 47 | Thanks for visiting! 48 |
49 |