From 6fdd190a897dcc5bd959e9fdd265a68960cac1f8 Mon Sep 17 00:00:00 2001 From: Ryan Bates Date: Mon, 19 Sep 2011 16:25:08 -0700 Subject: [PATCH] adding episode 284 --- episode-284/README | 10 + episode-284/store-after/.gitignore | 5 + episode-284/store-after/Gemfile | 35 +++ episode-284/store-after/Gemfile.lock | 155 +++++++++++++ episode-284/store-after/README | 8 + episode-284/store-after/Rakefile | 7 + .../store-after/app/admin/dashboards.rb | 48 ++++ episode-284/store-after/app/admin/products.rb | 15 ++ .../store-after/app/assets/images/rails.png | Bin 0 -> 6646 bytes .../app/assets/javascripts/active_admin.js | 1 + .../app/assets/javascripts/application.js | 9 + .../app/assets/javascripts/products.js.coffee | 3 + .../assets/stylesheets/active_admin.css.scss | 10 + .../assets/stylesheets/application.css.scss | 82 +++++++ .../app/assets/stylesheets/products.css.scss | 3 + .../app/controllers/application_controller.rb | 3 + .../app/controllers/products_controller.rb | 9 + .../app/helpers/application_helper.rb | 2 + .../app/helpers/error_messages_helper.rb | 23 ++ .../store-after/app/helpers/layout_helper.rb | 18 ++ .../app/helpers/products_helper.rb | 2 + episode-284/store-after/app/mailers/.gitkeep | 0 episode-284/store-after/app/models/.gitkeep | 0 .../store-after/app/models/admin_user.rb | 9 + .../store-after/app/models/category.rb | 3 + episode-284/store-after/app/models/product.rb | 4 + .../app/views/layouts/application.html.erb | 19 ++ .../app/views/products/index.html.erb | 11 + .../app/views/products/show.html.erb | 21 ++ episode-284/store-after/config.ru | 4 + episode-284/store-after/config/application.rb | 48 ++++ episode-284/store-after/config/boot.rb | 6 + episode-284/store-after/config/database.yml | 25 +++ episode-284/store-after/config/environment.rb | 5 + .../config/environments/development.rb | 32 +++ .../config/environments/production.rb | 60 +++++ .../store-after/config/environments/test.rb | 42 ++++ .../config/initializers/active_admin.rb | 100 +++++++++ .../initializers/backtrace_silencers.rb | 7 + .../store-after/config/initializers/devise.rb | 211 ++++++++++++++++++ .../config/initializers/inflections.rb | 10 + .../config/initializers/mime_types.rb | 5 + .../config/initializers/secret_token.rb | 7 + .../config/initializers/session_store.rb | 8 + .../config/initializers/wrap_parameters.rb | 14 ++ .../store-after/config/locales/devise.en.yml | 58 +++++ episode-284/store-after/config/locales/en.yml | 5 + episode-284/store-after/config/routes.rb | 8 + .../20110919134727_create_admin_notes.rb | 16 ++ ...0919134728_move_admin_notes_to_comments.rb | 25 +++ .../migrate/20110919171838_create_products.rb | 11 + .../20110919174935_create_categories.rb | 9 + ...10919174955_add_category_id_to_products.rb | 5 + ...0110919204722_devise_create_admin_users.rb | 31 +++ episode-284/store-after/db/schema.rb | 64 ++++++ episode-284/store-after/db/seeds.rb | 7 + episode-284/store-after/doc/README_FOR_APP | 2 + episode-284/store-after/lib/assets/.gitkeep | 0 episode-284/store-after/lib/tasks/.gitkeep | 0 episode-284/store-after/log/.gitkeep | 0 episode-284/store-after/public/404.html | 26 +++ episode-284/store-after/public/422.html | 26 +++ episode-284/store-after/public/500.html | 26 +++ episode-284/store-after/public/favicon.ico | 0 episode-284/store-after/public/robots.txt | 5 + episode-284/store-after/script/rails | 6 + .../store-after/test/fixtures/.gitkeep | 0 .../store-after/test/fixtures/admin_users.yml | 10 + .../store-after/test/fixtures/categories.yml | 16 ++ .../store-after/test/fixtures/products.yml | 62 +++++ .../store-after/test/functional/.gitkeep | 0 .../functional/products_controller_test.rb | 49 ++++ .../store-after/test/integration/.gitkeep | 0 .../test/performance/browsing_test.rb | 12 + episode-284/store-after/test/test_helper.rb | 13 ++ episode-284/store-after/test/unit/.gitkeep | 0 .../store-after/test/unit/admin_user_test.rb | 7 + .../store-after/test/unit/category_test.rb | 7 + .../test/unit/helpers/products_helper_test.rb | 4 + .../store-after/test/unit/product_test.rb | 7 + .../vendor/assets/stylesheets/.gitkeep | 0 .../store-after/vendor/plugins/.gitkeep | 0 episode-284/store-before/.gitignore | 5 + episode-284/store-before/Gemfile | 33 +++ episode-284/store-before/Gemfile.lock | 119 ++++++++++ episode-284/store-before/README | 8 + episode-284/store-before/Rakefile | 7 + .../store-before/app/assets/images/rails.png | Bin 0 -> 6646 bytes .../app/assets/javascripts/application.js | 9 + .../app/assets/javascripts/products.js.coffee | 3 + .../app/assets/stylesheets/application.css | 88 ++++++++ .../app/assets/stylesheets/products.css.scss | 3 + .../app/controllers/application_controller.rb | 3 + .../app/controllers/products_controller.rb | 9 + .../app/helpers/application_helper.rb | 2 + .../app/helpers/error_messages_helper.rb | 23 ++ .../store-before/app/helpers/layout_helper.rb | 18 ++ .../app/helpers/products_helper.rb | 2 + episode-284/store-before/app/mailers/.gitkeep | 0 episode-284/store-before/app/models/.gitkeep | 0 .../store-before/app/models/category.rb | 3 + .../store-before/app/models/product.rb | 3 + .../app/views/layouts/application.html.erb | 19 ++ .../app/views/products/index.html.erb | 11 + .../app/views/products/show.html.erb | 21 ++ episode-284/store-before/config.ru | 4 + .../store-before/config/application.rb | 48 ++++ episode-284/store-before/config/boot.rb | 6 + episode-284/store-before/config/database.yml | 25 +++ .../store-before/config/environment.rb | 5 + .../config/environments/development.rb | 32 +++ .../config/environments/production.rb | 60 +++++ .../store-before/config/environments/test.rb | 42 ++++ .../initializers/backtrace_silencers.rb | 7 + .../config/initializers/inflections.rb | 10 + .../config/initializers/mime_types.rb | 5 + .../config/initializers/secret_token.rb | 7 + .../config/initializers/session_store.rb | 8 + .../config/initializers/wrap_parameters.rb | 14 ++ .../store-before/config/locales/en.yml | 5 + episode-284/store-before/config/routes.rb | 4 + .../migrate/20110919171838_create_products.rb | 11 + .../20110919174935_create_categories.rb | 9 + ...10919174955_add_category_id_to_products.rb | 5 + episode-284/store-before/db/schema.rb | 31 +++ episode-284/store-before/db/seeds.rb | 7 + episode-284/store-before/doc/README_FOR_APP | 2 + episode-284/store-before/lib/assets/.gitkeep | 0 episode-284/store-before/lib/tasks/.gitkeep | 0 episode-284/store-before/log/.gitkeep | 0 episode-284/store-before/public/404.html | 26 +++ episode-284/store-before/public/422.html | 26 +++ episode-284/store-before/public/500.html | 26 +++ episode-284/store-before/public/favicon.ico | 0 episode-284/store-before/public/robots.txt | 5 + episode-284/store-before/script/rails | 6 + .../store-before/test/fixtures/.gitkeep | 0 .../store-before/test/fixtures/categories.yml | 16 ++ .../store-before/test/fixtures/products.yml | 62 +++++ .../store-before/test/functional/.gitkeep | 0 .../functional/products_controller_test.rb | 49 ++++ .../store-before/test/integration/.gitkeep | 0 .../test/performance/browsing_test.rb | 12 + episode-284/store-before/test/test_helper.rb | 13 ++ episode-284/store-before/test/unit/.gitkeep | 0 .../store-before/test/unit/category_test.rb | 7 + .../test/unit/helpers/products_helper_test.rb | 4 + .../store-before/test/unit/product_test.rb | 7 + .../vendor/assets/stylesheets/.gitkeep | 0 .../store-before/vendor/plugins/.gitkeep | 0 150 files changed, 2611 insertions(+) create mode 100644 episode-284/README create mode 100644 episode-284/store-after/.gitignore create mode 100644 episode-284/store-after/Gemfile create mode 100644 episode-284/store-after/Gemfile.lock create mode 100644 episode-284/store-after/README create mode 100644 episode-284/store-after/Rakefile create mode 100644 episode-284/store-after/app/admin/dashboards.rb create mode 100644 episode-284/store-after/app/admin/products.rb create mode 100644 episode-284/store-after/app/assets/images/rails.png create mode 100644 episode-284/store-after/app/assets/javascripts/active_admin.js create mode 100644 episode-284/store-after/app/assets/javascripts/application.js create mode 100644 episode-284/store-after/app/assets/javascripts/products.js.coffee create mode 100644 episode-284/store-after/app/assets/stylesheets/active_admin.css.scss create mode 100644 episode-284/store-after/app/assets/stylesheets/application.css.scss create mode 100644 episode-284/store-after/app/assets/stylesheets/products.css.scss create mode 100644 episode-284/store-after/app/controllers/application_controller.rb create mode 100644 episode-284/store-after/app/controllers/products_controller.rb create mode 100644 episode-284/store-after/app/helpers/application_helper.rb create mode 100644 episode-284/store-after/app/helpers/error_messages_helper.rb create mode 100644 episode-284/store-after/app/helpers/layout_helper.rb create mode 100644 episode-284/store-after/app/helpers/products_helper.rb create mode 100644 episode-284/store-after/app/mailers/.gitkeep create mode 100644 episode-284/store-after/app/models/.gitkeep create mode 100644 episode-284/store-after/app/models/admin_user.rb create mode 100644 episode-284/store-after/app/models/category.rb create mode 100644 episode-284/store-after/app/models/product.rb create mode 100644 episode-284/store-after/app/views/layouts/application.html.erb create mode 100644 episode-284/store-after/app/views/products/index.html.erb create mode 100644 episode-284/store-after/app/views/products/show.html.erb create mode 100644 episode-284/store-after/config.ru create mode 100644 episode-284/store-after/config/application.rb create mode 100644 episode-284/store-after/config/boot.rb create mode 100644 episode-284/store-after/config/database.yml create mode 100644 episode-284/store-after/config/environment.rb create mode 100644 episode-284/store-after/config/environments/development.rb create mode 100644 episode-284/store-after/config/environments/production.rb create mode 100644 episode-284/store-after/config/environments/test.rb create mode 100644 episode-284/store-after/config/initializers/active_admin.rb create mode 100644 episode-284/store-after/config/initializers/backtrace_silencers.rb create mode 100644 episode-284/store-after/config/initializers/devise.rb create mode 100644 episode-284/store-after/config/initializers/inflections.rb create mode 100644 episode-284/store-after/config/initializers/mime_types.rb create mode 100644 episode-284/store-after/config/initializers/secret_token.rb create mode 100644 episode-284/store-after/config/initializers/session_store.rb create mode 100644 episode-284/store-after/config/initializers/wrap_parameters.rb create mode 100644 episode-284/store-after/config/locales/devise.en.yml create mode 100644 episode-284/store-after/config/locales/en.yml create mode 100644 episode-284/store-after/config/routes.rb create mode 100644 episode-284/store-after/db/migrate/20110919134727_create_admin_notes.rb create mode 100644 episode-284/store-after/db/migrate/20110919134728_move_admin_notes_to_comments.rb create mode 100644 episode-284/store-after/db/migrate/20110919171838_create_products.rb create mode 100644 episode-284/store-after/db/migrate/20110919174935_create_categories.rb create mode 100644 episode-284/store-after/db/migrate/20110919174955_add_category_id_to_products.rb create mode 100644 episode-284/store-after/db/migrate/20110919204722_devise_create_admin_users.rb create mode 100644 episode-284/store-after/db/schema.rb create mode 100644 episode-284/store-after/db/seeds.rb create mode 100644 episode-284/store-after/doc/README_FOR_APP create mode 100644 episode-284/store-after/lib/assets/.gitkeep create mode 100644 episode-284/store-after/lib/tasks/.gitkeep create mode 100644 episode-284/store-after/log/.gitkeep create mode 100644 episode-284/store-after/public/404.html create mode 100644 episode-284/store-after/public/422.html create mode 100644 episode-284/store-after/public/500.html create mode 100644 episode-284/store-after/public/favicon.ico create mode 100644 episode-284/store-after/public/robots.txt create mode 100755 episode-284/store-after/script/rails create mode 100644 episode-284/store-after/test/fixtures/.gitkeep create mode 100644 episode-284/store-after/test/fixtures/admin_users.yml create mode 100644 episode-284/store-after/test/fixtures/categories.yml create mode 100644 episode-284/store-after/test/fixtures/products.yml create mode 100644 episode-284/store-after/test/functional/.gitkeep create mode 100644 episode-284/store-after/test/functional/products_controller_test.rb create mode 100644 episode-284/store-after/test/integration/.gitkeep create mode 100644 episode-284/store-after/test/performance/browsing_test.rb create mode 100644 episode-284/store-after/test/test_helper.rb create mode 100644 episode-284/store-after/test/unit/.gitkeep create mode 100644 episode-284/store-after/test/unit/admin_user_test.rb create mode 100644 episode-284/store-after/test/unit/category_test.rb create mode 100644 episode-284/store-after/test/unit/helpers/products_helper_test.rb create mode 100644 episode-284/store-after/test/unit/product_test.rb create mode 100644 episode-284/store-after/vendor/assets/stylesheets/.gitkeep create mode 100644 episode-284/store-after/vendor/plugins/.gitkeep create mode 100644 episode-284/store-before/.gitignore create mode 100644 episode-284/store-before/Gemfile create mode 100644 episode-284/store-before/Gemfile.lock create mode 100644 episode-284/store-before/README create mode 100644 episode-284/store-before/Rakefile create mode 100644 episode-284/store-before/app/assets/images/rails.png create mode 100644 episode-284/store-before/app/assets/javascripts/application.js create mode 100644 episode-284/store-before/app/assets/javascripts/products.js.coffee create mode 100644 episode-284/store-before/app/assets/stylesheets/application.css create mode 100644 episode-284/store-before/app/assets/stylesheets/products.css.scss create mode 100644 episode-284/store-before/app/controllers/application_controller.rb create mode 100644 episode-284/store-before/app/controllers/products_controller.rb create mode 100644 episode-284/store-before/app/helpers/application_helper.rb create mode 100644 episode-284/store-before/app/helpers/error_messages_helper.rb create mode 100644 episode-284/store-before/app/helpers/layout_helper.rb create mode 100644 episode-284/store-before/app/helpers/products_helper.rb create mode 100644 episode-284/store-before/app/mailers/.gitkeep create mode 100644 episode-284/store-before/app/models/.gitkeep create mode 100644 episode-284/store-before/app/models/category.rb create mode 100644 episode-284/store-before/app/models/product.rb create mode 100644 episode-284/store-before/app/views/layouts/application.html.erb create mode 100644 episode-284/store-before/app/views/products/index.html.erb create mode 100644 episode-284/store-before/app/views/products/show.html.erb create mode 100644 episode-284/store-before/config.ru create mode 100644 episode-284/store-before/config/application.rb create mode 100644 episode-284/store-before/config/boot.rb create mode 100644 episode-284/store-before/config/database.yml create mode 100644 episode-284/store-before/config/environment.rb create mode 100644 episode-284/store-before/config/environments/development.rb create mode 100644 episode-284/store-before/config/environments/production.rb create mode 100644 episode-284/store-before/config/environments/test.rb create mode 100644 episode-284/store-before/config/initializers/backtrace_silencers.rb create mode 100644 episode-284/store-before/config/initializers/inflections.rb create mode 100644 episode-284/store-before/config/initializers/mime_types.rb create mode 100644 episode-284/store-before/config/initializers/secret_token.rb create mode 100644 episode-284/store-before/config/initializers/session_store.rb create mode 100644 episode-284/store-before/config/initializers/wrap_parameters.rb create mode 100644 episode-284/store-before/config/locales/en.yml create mode 100644 episode-284/store-before/config/routes.rb create mode 100644 episode-284/store-before/db/migrate/20110919171838_create_products.rb create mode 100644 episode-284/store-before/db/migrate/20110919174935_create_categories.rb create mode 100644 episode-284/store-before/db/migrate/20110919174955_add_category_id_to_products.rb create mode 100644 episode-284/store-before/db/schema.rb create mode 100644 episode-284/store-before/db/seeds.rb create mode 100644 episode-284/store-before/doc/README_FOR_APP create mode 100644 episode-284/store-before/lib/assets/.gitkeep create mode 100644 episode-284/store-before/lib/tasks/.gitkeep create mode 100644 episode-284/store-before/log/.gitkeep create mode 100644 episode-284/store-before/public/404.html create mode 100644 episode-284/store-before/public/422.html create mode 100644 episode-284/store-before/public/500.html create mode 100644 episode-284/store-before/public/favicon.ico create mode 100644 episode-284/store-before/public/robots.txt create mode 100755 episode-284/store-before/script/rails create mode 100644 episode-284/store-before/test/fixtures/.gitkeep create mode 100644 episode-284/store-before/test/fixtures/categories.yml create mode 100644 episode-284/store-before/test/fixtures/products.yml create mode 100644 episode-284/store-before/test/functional/.gitkeep create mode 100644 episode-284/store-before/test/functional/products_controller_test.rb create mode 100644 episode-284/store-before/test/integration/.gitkeep create mode 100644 episode-284/store-before/test/performance/browsing_test.rb create mode 100644 episode-284/store-before/test/test_helper.rb create mode 100644 episode-284/store-before/test/unit/.gitkeep create mode 100644 episode-284/store-before/test/unit/category_test.rb create mode 100644 episode-284/store-before/test/unit/helpers/products_helper_test.rb create mode 100644 episode-284/store-before/test/unit/product_test.rb create mode 100644 episode-284/store-before/vendor/assets/stylesheets/.gitkeep create mode 100644 episode-284/store-before/vendor/plugins/.gitkeep diff --git a/episode-284/README b/episode-284/README new file mode 100644 index 00000000..6a1f31b7 --- /dev/null +++ b/episode-284/README @@ -0,0 +1,10 @@ +RailsCasts Episode #284: Active Admin + +http://railscasts.com/episodes/284-active-admin + +Commands used in episode + + bundle + rails g active_admin:install + rake db:migrate + rails g active_admin:resource product diff --git a/episode-284/store-after/.gitignore b/episode-284/store-after/.gitignore new file mode 100644 index 00000000..923b6976 --- /dev/null +++ b/episode-284/store-after/.gitignore @@ -0,0 +1,5 @@ +.bundle +db/*.sqlite3 +log/*.log +tmp/ +.sass-cache/ diff --git a/episode-284/store-after/Gemfile b/episode-284/store-after/Gemfile new file mode 100644 index 00000000..f04af6ca --- /dev/null +++ b/episode-284/store-after/Gemfile @@ -0,0 +1,35 @@ +source 'http://rubygems.org' + +gem 'rails', '3.1.0' + +# Bundle edge Rails instead: +# gem 'rails', :git => 'git://github.com/rails/rails.git' + +gem 'sqlite3' + +gem 'activeadmin' + + +# Gems used only for assets and not required +# in production environments by default. +group :assets do + gem 'sass-rails', " ~> 3.1.0" + gem 'coffee-rails', "~> 3.1.0" + gem 'uglifier' +end + +gem 'jquery-rails' + +# Use unicorn as the web server +# gem 'unicorn' + +# Deploy with Capistrano +# gem 'capistrano' + +# To use debugger +# gem 'ruby-debug19', :require => 'ruby-debug' + +group :test do + # Pretty printed test output + gem 'turn', :require => false +end diff --git a/episode-284/store-after/Gemfile.lock b/episode-284/store-after/Gemfile.lock new file mode 100644 index 00000000..6e237b08 --- /dev/null +++ b/episode-284/store-after/Gemfile.lock @@ -0,0 +1,155 @@ +GEM + remote: http://rubygems.org/ + specs: + actionmailer (3.1.0) + actionpack (= 3.1.0) + mail (~> 2.3.0) + actionpack (3.1.0) + activemodel (= 3.1.0) + activesupport (= 3.1.0) + builder (~> 3.0.0) + erubis (~> 2.7.0) + i18n (~> 0.6) + rack (~> 1.3.2) + rack-cache (~> 1.0.3) + rack-mount (~> 0.8.2) + rack-test (~> 0.6.1) + sprockets (~> 2.0.0) + activeadmin (0.3.1) + devise (>= 1.1.2) + fastercsv + formtastic (>= 1.1.0) + inherited_resources (< 1.3.0) + kaminari (>= 0.12.4) + meta_search (>= 0.9.2) + rails (>= 3.0.0) + sass (>= 3.1.0) + activemodel (3.1.0) + activesupport (= 3.1.0) + bcrypt-ruby (~> 3.0.0) + builder (~> 3.0.0) + i18n (~> 0.6) + activerecord (3.1.0) + activemodel (= 3.1.0) + activesupport (= 3.1.0) + arel (~> 2.2.1) + tzinfo (~> 0.3.29) + activeresource (3.1.0) + activemodel (= 3.1.0) + activesupport (= 3.1.0) + activesupport (3.1.0) + multi_json (~> 1.0) + ansi (1.3.0) + arel (2.2.1) + bcrypt-ruby (3.0.1) + builder (3.0.0) + coffee-rails (3.1.1) + coffee-script (>= 2.2.0) + railties (~> 3.1.0) + coffee-script (2.2.0) + coffee-script-source + execjs + coffee-script-source (1.1.2) + devise (1.4.5) + bcrypt-ruby (~> 3.0) + orm_adapter (~> 0.0.3) + warden (~> 1.0.3) + erubis (2.7.0) + execjs (1.2.6) + multi_json (~> 1.0) + fastercsv (1.5.4) + formtastic (1.2.4) + actionpack (>= 2.3.7) + activesupport (>= 2.3.7) + i18n (~> 0.4) + has_scope (0.5.1) + hike (1.2.1) + i18n (0.6.0) + inherited_resources (1.2.2) + has_scope (~> 0.5.0) + responders (~> 0.6.0) + jquery-rails (1.0.14) + railties (~> 3.0) + thor (~> 0.14) + kaminari (0.12.4) + rails (>= 3.0.0) + mail (2.3.0) + i18n (>= 0.4.0) + mime-types (~> 1.16) + treetop (~> 1.4.8) + meta_search (1.1.1) + actionpack (~> 3.1.0) + activerecord (~> 3.1.0) + activesupport (~> 3.1.0) + polyamorous (~> 0.5.0) + mime-types (1.16) + multi_json (1.0.3) + orm_adapter (0.0.5) + polyamorous (0.5.0) + activerecord (~> 3.0) + polyglot (0.3.2) + rack (1.3.3) + rack-cache (1.0.3) + rack (>= 0.4) + rack-mount (0.8.3) + rack (>= 1.0.0) + rack-ssl (1.3.2) + rack + rack-test (0.6.1) + rack (>= 1.0) + rails (3.1.0) + actionmailer (= 3.1.0) + actionpack (= 3.1.0) + activerecord (= 3.1.0) + activeresource (= 3.1.0) + activesupport (= 3.1.0) + bundler (~> 1.0) + railties (= 3.1.0) + railties (3.1.0) + actionpack (= 3.1.0) + activesupport (= 3.1.0) + rack-ssl (~> 1.3.2) + rake (>= 0.8.7) + rdoc (~> 3.4) + thor (~> 0.14.6) + rake (0.9.2) + rdoc (3.9.4) + responders (0.6.4) + sass (3.1.7) + sass-rails (3.1.2) + actionpack (~> 3.1.0) + railties (~> 3.1.0) + sass (>= 3.1.4) + sprockets (~> 2.0.0) + tilt (~> 1.3.2) + sprockets (2.0.0) + hike (~> 1.2) + rack (~> 1.0) + tilt (!= 1.3.0, ~> 1.1) + sqlite3 (1.3.4) + thor (0.14.6) + tilt (1.3.3) + treetop (1.4.10) + polyglot + polyglot (>= 0.3.1) + turn (0.8.2) + ansi (>= 1.2.2) + tzinfo (0.3.29) + uglifier (1.0.3) + execjs (>= 0.3.0) + multi_json (>= 1.0.2) + warden (1.0.5) + rack (>= 1.0) + +PLATFORMS + ruby + +DEPENDENCIES + activeadmin + coffee-rails (~> 3.1.0) + jquery-rails + rails (= 3.1.0) + sass-rails (~> 3.1.0) + sqlite3 + turn + uglifier diff --git a/episode-284/store-after/README b/episode-284/store-after/README new file mode 100644 index 00000000..21d37ff8 --- /dev/null +++ b/episode-284/store-after/README @@ -0,0 +1,8 @@ += RailsCasts Example Application + +Run these commands to try it out. + + bundle + rake db:migrate + rake db:fixtures:load + rails s diff --git a/episode-284/store-after/Rakefile b/episode-284/store-after/Rakefile new file mode 100644 index 00000000..c43b4fc9 --- /dev/null +++ b/episode-284/store-after/Rakefile @@ -0,0 +1,7 @@ +#!/usr/bin/env rake +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require File.expand_path('../config/application', __FILE__) + +Store::Application.load_tasks diff --git a/episode-284/store-after/app/admin/dashboards.rb b/episode-284/store-after/app/admin/dashboards.rb new file mode 100644 index 00000000..dc85ab30 --- /dev/null +++ b/episode-284/store-after/app/admin/dashboards.rb @@ -0,0 +1,48 @@ +ActiveAdmin::Dashboards.build do + + section "Recent Products" do + table_for Product.order("released_at desc").limit(5) do + column :name do |product| + link_to product.name, [:admin, product] + end + column :released_at + end + strong { link_to "View All Products", admin_products_path } + end + + # Define your dashboard sections here. Each block will be + # rendered on the dashboard in the context of the view. So just + # return the content which you would like to display. + + # == Simple Dashboard Section + # Here is an example of a simple dashboard section + # + # section "Recent Posts" do + # ul do + # Post.recent(5).collect do |post| + # li link_to(post.title, admin_post_path(post)) + # end + # end + # end + + # == Render Partial Section + # The block is rendered within the context of the view, so you can + # easily render a partial rather than build content in ruby. + # + # section "Recent Posts" do + # div do + # render 'recent_posts' # => this will render /app/views/admin/dashboard/_recent_posts.html.erb + # end + # end + + # == Section Ordering + # The dashboard sections are ordered by a given priority from top left to + # bottom right. The default priority is 10. By giving a section numerically lower + # priority it will be sorted higher. For example: + # + # section "Recent Posts", :priority => 10 + # section "Recent User", :priority => 1 + # + # Will render the "Recent Users" then the "Recent Posts" sections on the dashboard. + +end diff --git a/episode-284/store-after/app/admin/products.rb b/episode-284/store-after/app/admin/products.rb new file mode 100644 index 00000000..8f9da410 --- /dev/null +++ b/episode-284/store-after/app/admin/products.rb @@ -0,0 +1,15 @@ +ActiveAdmin.register Product do + scope :unreleased + + index do + column :name + column :category + column "Release Date", :released_at + column :price, :sortable => :price do |product| + div :class => "price" do + number_to_currency product.price + end + end + default_actions + end +end diff --git a/episode-284/store-after/app/assets/images/rails.png b/episode-284/store-after/app/assets/images/rails.png new file mode 100644 index 0000000000000000000000000000000000000000..d5edc04e65f555e3ba4dcdaad39dc352e75b575e GIT binary patch literal 6646 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 AQ~&?~ literal 0 HcmV?d00001 diff --git a/episode-284/store-after/app/assets/javascripts/active_admin.js b/episode-284/store-after/app/assets/javascripts/active_admin.js new file mode 100644 index 00000000..d2b66c59 --- /dev/null +++ b/episode-284/store-after/app/assets/javascripts/active_admin.js @@ -0,0 +1 @@ +//= require active_admin/base diff --git a/episode-284/store-after/app/assets/javascripts/application.js b/episode-284/store-after/app/assets/javascripts/application.js new file mode 100644 index 00000000..37c7bfcd --- /dev/null +++ b/episode-284/store-after/app/assets/javascripts/application.js @@ -0,0 +1,9 @@ +// This is a manifest file that'll be compiled into including all the files listed below. +// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically +// be included in the compiled file accessible from http://example.com/assets/application.js +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// the compiled file. +// +//= require jquery +//= require jquery_ujs +//= require_tree . diff --git a/episode-284/store-after/app/assets/javascripts/products.js.coffee b/episode-284/store-after/app/assets/javascripts/products.js.coffee new file mode 100644 index 00000000..76156794 --- /dev/null +++ b/episode-284/store-after/app/assets/javascripts/products.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/episode-284/store-after/app/assets/stylesheets/active_admin.css.scss b/episode-284/store-after/app/assets/stylesheets/active_admin.css.scss new file mode 100644 index 00000000..5b90e47e --- /dev/null +++ b/episode-284/store-after/app/assets/stylesheets/active_admin.css.scss @@ -0,0 +1,10 @@ +// Active Admin CSS Styles +@import "active_admin/mixins"; +@import "active_admin/base"; + +// To customize the Active Admin interfaces, add your +// styles here: + +.price { + text-align: right; +} \ No newline at end of file diff --git a/episode-284/store-after/app/assets/stylesheets/application.css.scss b/episode-284/store-after/app/assets/stylesheets/application.css.scss new file mode 100644 index 00000000..e9640acc --- /dev/null +++ b/episode-284/store-after/app/assets/stylesheets/application.css.scss @@ -0,0 +1,82 @@ +html, body { + background-color: #4B7399; + font-family: Verdana, Helvetica, Arial; + font-size: 14px; +} + +a img { + border: none; +} + +a { + color: #0000FF; +} + +.clear { + clear: both; + height: 0; + overflow: hidden; +} + +#container { + width: 75%; + margin: 0 auto; + background-color: #FFF; + padding: 20px 40px; + border: solid 1px black; + margin-top: 20px; +} + +#flash_notice, #flash_error, #flash_alert { + padding: 5px 8px; + margin: 10px 0; +} + +#flash_notice { + background-color: #CFC; + border: solid 1px #6C6; +} + +#flash_error, #flash_alert { + background-color: #FCC; + border: solid 1px #C66; +} + +.fieldWithErrors { + display: inline; +} + +.error_messages { + width: 400px; + border: 2px solid #CF0000; + padding: 0px; + padding-bottom: 12px; + margin-bottom: 20px; + background-color: #f0f0f0; + font-size: 12px; +} + +.error_messages h2 { + text-align: left; + font-weight: bold; + padding: 5px 10px; + font-size: 12px; + margin: 0; + background-color: #c00; + color: #fff; +} + +.error_messages p { + margin: 8px 10px; +} + +.error_messages ul { + margin: 0; +} + +.product h2 { + font-size: 16px; + margin-bottom: 2px; +} + +@import "products"; diff --git a/episode-284/store-after/app/assets/stylesheets/products.css.scss b/episode-284/store-after/app/assets/stylesheets/products.css.scss new file mode 100644 index 00000000..89e2e8db --- /dev/null +++ b/episode-284/store-after/app/assets/stylesheets/products.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the products controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/episode-284/store-after/app/controllers/application_controller.rb b/episode-284/store-after/app/controllers/application_controller.rb new file mode 100644 index 00000000..e8065d95 --- /dev/null +++ b/episode-284/store-after/app/controllers/application_controller.rb @@ -0,0 +1,3 @@ +class ApplicationController < ActionController::Base + protect_from_forgery +end diff --git a/episode-284/store-after/app/controllers/products_controller.rb b/episode-284/store-after/app/controllers/products_controller.rb new file mode 100644 index 00000000..0528785d --- /dev/null +++ b/episode-284/store-after/app/controllers/products_controller.rb @@ -0,0 +1,9 @@ +class ProductsController < ApplicationController + def index + @products = Product.order("released_at desc") + end + + def show + @product = Product.find(params[:id]) + end +end diff --git a/episode-284/store-after/app/helpers/application_helper.rb b/episode-284/store-after/app/helpers/application_helper.rb new file mode 100644 index 00000000..de6be794 --- /dev/null +++ b/episode-284/store-after/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/episode-284/store-after/app/helpers/error_messages_helper.rb b/episode-284/store-after/app/helpers/error_messages_helper.rb new file mode 100644 index 00000000..92575730 --- /dev/null +++ b/episode-284/store-after/app/helpers/error_messages_helper.rb @@ -0,0 +1,23 @@ +module ErrorMessagesHelper + # Render error messages for the given objects. The :message and :header_message options are allowed. + def error_messages_for(*objects) + options = objects.extract_options! + options[:header_message] ||= "Invalid Fields" + options[:message] ||= "Correct the following errors and try again." + messages = objects.compact.map { |o| o.errors.full_messages }.flatten + unless messages.empty? + content_tag(:div, :class => "error_messages") do + list_items = messages.map { |msg| content_tag(:li, msg) } + content_tag(:h2, options[:header_message]) + content_tag(:p, options[:message]) + content_tag(:ul, list_items.join.html_safe) + end + end + end + + module FormBuilderAdditions + def error_messages(options = {}) + @template.error_messages_for(@object, options) + end + end +end + +ActionView::Helpers::FormBuilder.send(:include, ErrorMessagesHelper::FormBuilderAdditions) diff --git a/episode-284/store-after/app/helpers/layout_helper.rb b/episode-284/store-after/app/helpers/layout_helper.rb new file mode 100644 index 00000000..e995cba8 --- /dev/null +++ b/episode-284/store-after/app/helpers/layout_helper.rb @@ -0,0 +1,18 @@ +module LayoutHelper + def title(page_title, show_title = true) + content_for(:title) { h(page_title.to_s) } + @show_title = show_title + end + + def show_title? + @show_title + end + + def stylesheet(*args) + content_for(:head) { stylesheet_link_tag(*args) } + end + + def javascript(*args) + content_for(:head) { javascript_include_tag(*args) } + end +end diff --git a/episode-284/store-after/app/helpers/products_helper.rb b/episode-284/store-after/app/helpers/products_helper.rb new file mode 100644 index 00000000..ab5c42b3 --- /dev/null +++ b/episode-284/store-after/app/helpers/products_helper.rb @@ -0,0 +1,2 @@ +module ProductsHelper +end diff --git a/episode-284/store-after/app/mailers/.gitkeep b/episode-284/store-after/app/mailers/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-after/app/models/.gitkeep b/episode-284/store-after/app/models/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-after/app/models/admin_user.rb b/episode-284/store-after/app/models/admin_user.rb new file mode 100644 index 00000000..039464fa --- /dev/null +++ b/episode-284/store-after/app/models/admin_user.rb @@ -0,0 +1,9 @@ +class AdminUser < ActiveRecord::Base + # Include default devise modules. Others available are: + # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable + devise :database_authenticatable, + :recoverable, :rememberable, :trackable, :validatable + + # Setup accessible (or protected) attributes for your model + attr_accessible :email, :password, :password_confirmation, :remember_me +end diff --git a/episode-284/store-after/app/models/category.rb b/episode-284/store-after/app/models/category.rb new file mode 100644 index 00000000..e7d003bf --- /dev/null +++ b/episode-284/store-after/app/models/category.rb @@ -0,0 +1,3 @@ +class Category < ActiveRecord::Base + has_many :products +end diff --git a/episode-284/store-after/app/models/product.rb b/episode-284/store-after/app/models/product.rb new file mode 100644 index 00000000..d3f05819 --- /dev/null +++ b/episode-284/store-after/app/models/product.rb @@ -0,0 +1,4 @@ +class Product < ActiveRecord::Base + belongs_to :category + scope :unreleased, where(:released_at => nil) +end diff --git a/episode-284/store-after/app/views/layouts/application.html.erb b/episode-284/store-after/app/views/layouts/application.html.erb new file mode 100644 index 00000000..54476c83 --- /dev/null +++ b/episode-284/store-after/app/views/layouts/application.html.erb @@ -0,0 +1,19 @@ + + + + <%= content_for?(:title) ? yield(:title) : "Untitled" %> + <%= stylesheet_link_tag "application" %> + <%= javascript_include_tag "application" %> + <%= csrf_meta_tag %> + <%= yield(:head) %> + + +
+ <% flash.each do |name, msg| %> + <%= content_tag :div, raw(msg), :id => "flash_#{name}" %> + <% end %> + <%= content_tag :h1, yield(:title) if show_title? %> + <%= yield %> +
+ + diff --git a/episode-284/store-after/app/views/products/index.html.erb b/episode-284/store-after/app/views/products/index.html.erb new file mode 100644 index 00000000..c8dc2085 --- /dev/null +++ b/episode-284/store-after/app/views/products/index.html.erb @@ -0,0 +1,11 @@ +<% title "Products" %> + +<% for product in @products %> +
+

<%= link_to product.name, product %>

+
+ <%= number_to_currency(product.price) %> in + <%= product.category.name %> +
+
+<% end %> diff --git a/episode-284/store-after/app/views/products/show.html.erb b/episode-284/store-after/app/views/products/show.html.erb new file mode 100644 index 00000000..54e63189 --- /dev/null +++ b/episode-284/store-after/app/views/products/show.html.erb @@ -0,0 +1,21 @@ +

+ Name: + <%= @product.name %> +

+ +

+ Price: + <%= number_to_currency(@product.price) %> +

+ +

+ Released: + <%= @product.released_at.strftime("%B %e, %Y") %> +

+ +

+ Category: + <%= @product.category.name %> +

+ +<%= link_to 'View all products', products_path %> diff --git a/episode-284/store-after/config.ru b/episode-284/store-after/config.ru new file mode 100644 index 00000000..fdab6a6f --- /dev/null +++ b/episode-284/store-after/config.ru @@ -0,0 +1,4 @@ +# This file is used by Rack-based servers to start the application. + +require ::File.expand_path('../config/environment', __FILE__) +run Store::Application diff --git a/episode-284/store-after/config/application.rb b/episode-284/store-after/config/application.rb new file mode 100644 index 00000000..640d27f9 --- /dev/null +++ b/episode-284/store-after/config/application.rb @@ -0,0 +1,48 @@ +require File.expand_path('../boot', __FILE__) + +require 'rails/all' + +if defined?(Bundler) + # If you precompile assets before deploying to production, use this line + Bundler.require *Rails.groups(:assets => %w(development test)) + # If you want your assets lazily compiled in production, use this line + # Bundler.require(:default, :assets, Rails.env) +end + +module Store + class Application < Rails::Application + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + + # Custom directories with classes and modules you want to be autoloadable. + # config.autoload_paths += %W(#{config.root}/extras) + + # Only load the plugins named here, in the order given (default is alphabetical). + # :all can be used as a placeholder for all plugins not explicitly named. + # config.plugins = [ :exception_notification, :ssl_requirement, :all ] + + # Activate observers that should always be running. + # config.active_record.observers = :cacher, :garbage_collector, :forum_observer + + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. + # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. + # config.time_zone = 'Central Time (US & Canada)' + + # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. + # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] + # config.i18n.default_locale = :de + + # Configure the default encoding used in templates for Ruby 1.9. + config.encoding = "utf-8" + + # Configure sensitive parameters which will be filtered from the log file. + config.filter_parameters += [:password] + + # Enable the asset pipeline + config.assets.enabled = true + + # Version of your assets, change this if you want to expire all your assets + config.assets.version = '1.0' + end +end diff --git a/episode-284/store-after/config/boot.rb b/episode-284/store-after/config/boot.rb new file mode 100644 index 00000000..4489e586 --- /dev/null +++ b/episode-284/store-after/config/boot.rb @@ -0,0 +1,6 @@ +require 'rubygems' + +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) + +require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) diff --git a/episode-284/store-after/config/database.yml b/episode-284/store-after/config/database.yml new file mode 100644 index 00000000..51a4dd45 --- /dev/null +++ b/episode-284/store-after/config/database.yml @@ -0,0 +1,25 @@ +# SQLite version 3.x +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem 'sqlite3' +development: + adapter: sqlite3 + database: db/development.sqlite3 + pool: 5 + timeout: 5000 + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + adapter: sqlite3 + database: db/test.sqlite3 + pool: 5 + timeout: 5000 + +production: + adapter: sqlite3 + database: db/production.sqlite3 + pool: 5 + timeout: 5000 diff --git a/episode-284/store-after/config/environment.rb b/episode-284/store-after/config/environment.rb new file mode 100644 index 00000000..7be8e24c --- /dev/null +++ b/episode-284/store-after/config/environment.rb @@ -0,0 +1,5 @@ +# Load the rails application +require File.expand_path('../application', __FILE__) + +# Initialize the rails application +Store::Application.initialize! diff --git a/episode-284/store-after/config/environments/development.rb b/episode-284/store-after/config/environments/development.rb new file mode 100644 index 00000000..17c2ed4a --- /dev/null +++ b/episode-284/store-after/config/environments/development.rb @@ -0,0 +1,32 @@ +Store::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Don't care if the mailer can't send + config.action_mailer.raise_delivery_errors = false + + # Print deprecation notices to the Rails logger + config.active_support.deprecation = :log + + # Only use best-standards-support built into browsers + config.action_dispatch.best_standards_support = :builtin + + # Do not compress assets + config.assets.compress = false + + # Expands the lines which load the assets + config.assets.debug = true + + config.action_mailer.default_url_options = { :host => 'localhost:3000' } +end diff --git a/episode-284/store-after/config/environments/production.rb b/episode-284/store-after/config/environments/production.rb new file mode 100644 index 00000000..f3df992c --- /dev/null +++ b/episode-284/store-after/config/environments/production.rb @@ -0,0 +1,60 @@ +Store::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # Code is not reloaded between requests + config.cache_classes = true + + # Full error reports are disabled and caching is turned on + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Disable Rails's static asset server (Apache or nginx will already do this) + config.serve_static_assets = false + + # Compress JavaScripts and CSS + config.assets.compress = true + + # Don't fallback to assets pipeline if a precompiled asset is missed + config.assets.compile = false + + # Generate digests for assets URLs + config.assets.digest = true + + # Defaults to Rails.root.join("public/assets") + # config.assets.manifest = YOUR_PATH + + # Specifies the header that your server uses for sending files + # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # See everything in the log (default is :info) + # config.log_level = :debug + + # Use a different logger for distributed setups + # config.logger = SyslogLogger.new + + # Use a different cache store in production + # config.cache_store = :mem_cache_store + + # Enable serving of images, stylesheets, and JavaScripts from an asset server + # config.action_controller.asset_host = "http://assets.example.com" + + # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) + # config.assets.precompile += %w( search.js ) + + # Disable delivery errors, bad email addresses will be ignored + # config.action_mailer.raise_delivery_errors = false + + # Enable threaded mode + # config.threadsafe! + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation can not be found) + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners + config.active_support.deprecation = :notify +end diff --git a/episode-284/store-after/config/environments/test.rb b/episode-284/store-after/config/environments/test.rb new file mode 100644 index 00000000..b3d438d1 --- /dev/null +++ b/episode-284/store-after/config/environments/test.rb @@ -0,0 +1,42 @@ +Store::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Configure static asset server for tests with Cache-Control for performance + config.serve_static_assets = true + config.static_cache_control = "public, max-age=3600" + + # Log error messages when you accidentally call methods on nil + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment + config.action_controller.allow_forgery_protection = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Use SQL instead of Active Record's schema dumper when creating the test database. + # This is necessary if your schema can't be completely dumped by the schema dumper, + # like if you have constraints or database-specific column types + # config.active_record.schema_format = :sql + + # Print deprecation notices to the stderr + config.active_support.deprecation = :stderr + + # Allow pass debug_assets=true as a query parameter to load pages with unpackaged assets + config.assets.allow_debugging = true +end diff --git a/episode-284/store-after/config/initializers/active_admin.rb b/episode-284/store-after/config/initializers/active_admin.rb new file mode 100644 index 00000000..31a05a26 --- /dev/null +++ b/episode-284/store-after/config/initializers/active_admin.rb @@ -0,0 +1,100 @@ +ActiveAdmin.setup do |config| + + # == Site Title + # + # Set the title that is displayed on the main layout + # for each of the active admin pages. + # + config.site_title = "Ryan's Store" + + + # == Default Namespace + # + # Set the default namespace each administration resource + # will be added to. + # + # eg: + # config.default_namespace = :hello_world + # + # This will create resources in the HelloWorld module and + # will namespace routes to /hello_world/* + # + # To set no namespace by default, use: + # config.default_namespace = false + # + # Default: + # config.default_namespace = :admin + + + # == User Authentication + # + # Active Admin will automatically call an authentication + # method in a before filter of all controller actions to + # ensure that there is a currently logged in admin user. + # + # This setting changes the method which Active Admin calls + # within the controller. + config.authentication_method = :authenticate_admin_user! + + + # == Current User + # + # Active Admin will associate actions with the current + # user performing them. + # + # This setting changes the method which Active Admin calls + # to return the currently logged in user. + config.current_user_method = :current_admin_user + + + # == Logging Out + # + # Active Admin displays a logout link on each screen. These + # settings configure the location and method used for the link. + # + # This setting changes the path where the link points to. If it's + # a string, the strings is used as the path. If it's a Symbol, we + # will call the method to return the path. + # + # Default: + # config.logout_link_path = :destroy_admin_user_session_path + + # This setting changes the http method used when rendering the + # link. For example :get, :delete, :put, etc.. + # + # Default: + # config.logout_link_method = :get + + + # == Admin Comments + # + # Admin comments allow you to add comments to any model for admin use + # + # Admin comments are enabled by default in the default + # namespace only. You can turn them on in a namesapce + # by adding them to the comments array. + # + # Default: + # config.allow_comments_in = [:admin] + + + # == Controller Filters + # + # You can add before, after and around filters to all of your + # Active Admin resources from here. + # + # config.before_filter :do_something_awesome + + + # == Register Stylesheets & Javascripts + # + # We recommend using the built in Active Admin layout and loading + # up your own stylesheets / javascripts to customize the look + # and feel. + # + # To load a stylesheet: + # config.register_stylesheet 'my_stylesheet.css' + # + # To load a javascript file: + # config.register_javascript 'my_javascript.js' +end diff --git a/episode-284/store-after/config/initializers/backtrace_silencers.rb b/episode-284/store-after/config/initializers/backtrace_silencers.rb new file mode 100644 index 00000000..59385cdf --- /dev/null +++ b/episode-284/store-after/config/initializers/backtrace_silencers.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/episode-284/store-after/config/initializers/devise.rb b/episode-284/store-after/config/initializers/devise.rb new file mode 100644 index 00000000..b27a326d --- /dev/null +++ b/episode-284/store-after/config/initializers/devise.rb @@ -0,0 +1,211 @@ +# Use this hook to configure devise mailer, warden hooks and so forth. The first +# four configuration values can also be set straight in your models. +Devise.setup do |config| + # ==> Mailer Configuration + # Configure the e-mail address which will be shown in Devise::Mailer, + # note that it will be overwritten if you use your own mailer class with default "from" parameter. + config.mailer_sender = "please-change-me-at-config-initializers-devise@example.com" + + # Configure the class responsible to send e-mails. + # config.mailer = "Devise::Mailer" + + # ==> ORM configuration + # Load and configure the ORM. Supports :active_record (default) and + # :mongoid (bson_ext recommended) by default. Other ORMs may be + # available as additional gems. + require 'devise/orm/active_record' + + # ==> Configuration for any authentication mechanism + # Configure which keys are used when authenticating a user. The default is + # just :email. You can configure it to use [:username, :subdomain], so for + # authenticating a user, both parameters are required. Remember that those + # parameters are used only when authenticating and not when retrieving from + # session. If you need permissions, you should implement that in a before filter. + # You can also supply a hash where the value is a boolean determining whether + # or not authentication should be aborted when the value is not present. + # config.authentication_keys = [ :email ] + + # Configure parameters from the request object used for authentication. Each entry + # given should be a request method and it will automatically be passed to the + # find_for_authentication method and considered in your model lookup. For instance, + # if you set :request_keys to [:subdomain], :subdomain will be used on authentication. + # The same considerations mentioned for authentication_keys also apply to request_keys. + # config.request_keys = [] + + # Configure which authentication keys should be case-insensitive. + # These keys will be downcased upon creating or modifying a user and when used + # to authenticate or find a user. Default is :email. + config.case_insensitive_keys = [ :email ] + + # Configure which authentication keys should have whitespace stripped. + # These keys will have whitespace before and after removed upon creating or + # modifying a user and when used to authenticate or find a user. Default is :email. + config.strip_whitespace_keys = [ :email ] + + # Tell if authentication through request.params is enabled. True by default. + # config.params_authenticatable = true + + # Tell if authentication through HTTP Basic Auth is enabled. False by default. + # config.http_authenticatable = false + + # If http headers should be returned for AJAX requests. True by default. + # config.http_authenticatable_on_xhr = true + + # The realm used in Http Basic Authentication. "Application" by default. + # config.http_authentication_realm = "Application" + + # It will change confirmation, password recovery and other workflows + # to behave the same regardless if the e-mail provided was right or wrong. + # Does not affect registerable. + # config.paranoid = true + + # ==> Configuration for :database_authenticatable + # For bcrypt, this is the cost for hashing the password and defaults to 10. If + # using other encryptors, it sets how many times you want the password re-encrypted. + # + # Limiting the stretches to just one in testing will increase the performance of + # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use + # a value less than 10 in other environments. + config.stretches = Rails.env.test? ? 1 : 10 + + # Setup a pepper to generate the encrypted password. + # config.pepper = "0a6b61eb49db28c7560d069f21a1a4ace273af781a67d5647836fe21f34b2e34c9162ee5f883528f10f3335951c70eb4be9a89ec77b1b3156cfde374a631fb10" + + # ==> Configuration for :confirmable + # The time you want to give your user to confirm his account. During this time + # he will be able to access your application without confirming. Default is 0.days + # When confirm_within is zero, the user won't be able to sign in without confirming. + # You can use this to let your user access some features of your application + # without confirming the account, but blocking it after a certain period + # (ie 2 days). + # config.confirm_within = 2.days + + # Defines which key will be used when confirming an account + # config.confirmation_keys = [ :email ] + + # ==> Configuration for :rememberable + # The time the user will be remembered without asking for credentials again. + # config.remember_for = 2.weeks + + # If true, a valid remember token can be re-used between multiple browsers. + # config.remember_across_browsers = true + + # If true, extends the user's remember period when remembered via cookie. + # config.extend_remember_period = false + + # If true, uses the password salt as remember token. This should be turned + # to false if you are not using database authenticatable. + config.use_salt_as_remember_token = true + + # Options to be passed to the created cookie. For instance, you can set + # :secure => true in order to force SSL only cookies. + # config.cookie_options = {} + + # ==> Configuration for :validatable + # Range for password length. Default is 6..128. + # config.password_length = 6..128 + + # Email regex used to validate email formats. It simply asserts that + # an one (and only one) @ exists in the given string. This is mainly + # to give user feedback and not to assert the e-mail validity. + # config.email_regexp = /\A[^@]+@[^@]+\z/ + + # ==> Configuration for :timeoutable + # The time you want to timeout the user session without activity. After this + # time the user will be asked for credentials again. Default is 30 minutes. + # config.timeout_in = 30.minutes + + # ==> Configuration for :lockable + # Defines which strategy will be used to lock an account. + # :failed_attempts = Locks an account after a number of failed attempts to sign in. + # :none = No lock strategy. You should handle locking by yourself. + # config.lock_strategy = :failed_attempts + + # Defines which key will be used when locking and unlocking an account + # config.unlock_keys = [ :email ] + + # Defines which strategy will be used to unlock an account. + # :email = Sends an unlock link to the user email + # :time = Re-enables login after a certain amount of time (see :unlock_in below) + # :both = Enables both strategies + # :none = No unlock strategy. You should handle unlocking by yourself. + # config.unlock_strategy = :both + + # Number of authentication tries before locking an account if lock_strategy + # is failed attempts. + # config.maximum_attempts = 20 + + # Time interval to unlock the account if :time is enabled as unlock_strategy. + # config.unlock_in = 1.hour + + # ==> Configuration for :recoverable + # + # Defines which key will be used when recovering the password for an account + # config.reset_password_keys = [ :email ] + + # Time interval you can reset your password with a reset password key. + # Don't put a too small interval or your users won't have the time to + # change their passwords. + config.reset_password_within = 2.hours + + # ==> Configuration for :encryptable + # Allow you to use another encryption algorithm besides bcrypt (default). You can use + # :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1, + # :authlogic_sha512 (then you should set stretches above to 20 for default behavior) + # and :restful_authentication_sha1 (then you should set stretches to 10, and copy + # REST_AUTH_SITE_KEY to pepper) + # config.encryptor = :sha512 + + # ==> Configuration for :token_authenticatable + # Defines name of the authentication token params key + # config.token_authentication_key = :auth_token + + # If true, authentication through token does not store user in session and needs + # to be supplied on each request. Useful if you are using the token as API token. + # config.stateless_token = false + + # ==> Scopes configuration + # Turn scoped views on. Before rendering "sessions/new", it will first check for + # "users/sessions/new". It's turned off by default because it's slower if you + # are using only default views. + # config.scoped_views = false + + # Configure the default scope given to Warden. By default it's the first + # devise role declared in your routes (usually :user). + # config.default_scope = :user + + # Configure sign_out behavior. + # Sign_out action can be scoped (i.e. /users/sign_out affects only :user scope). + # The default is true, which means any logout action will sign out all active scopes. + # config.sign_out_all_scopes = true + + # ==> Navigation configuration + # Lists the formats that should be treated as navigational. Formats like + # :html, should redirect to the sign in page when the user does not have + # access, but formats like :xml or :json, should return 401. + # + # If you have any extra navigational formats, like :iphone or :mobile, you + # should add them to the navigational formats lists. + # + # The :"*/*" and "*/*" formats below is required to match Internet + # Explorer requests. + # config.navigational_formats = [:"*/*", "*/*", :html] + + # The default HTTP method used to sign out a resource. Default is :delete. + config.sign_out_via = :delete + + # ==> OmniAuth + # Add a new OmniAuth provider. Check the wiki for more information on setting + # up on your models and hooks. + # config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo' + + # ==> Warden configuration + # If you want to use other strategies, that are not supported by Devise, or + # change the failure app, you can configure them inside the config.warden block. + # + # config.warden do |manager| + # manager.failure_app = AnotherApp + # manager.intercept_401 = false + # manager.default_strategies(:scope => :user).unshift :some_external_strategy + # end +end diff --git a/episode-284/store-after/config/initializers/inflections.rb b/episode-284/store-after/config/initializers/inflections.rb new file mode 100644 index 00000000..9e8b0131 --- /dev/null +++ b/episode-284/store-after/config/initializers/inflections.rb @@ -0,0 +1,10 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format +# (all these examples are active by default): +# ActiveSupport::Inflector.inflections do |inflect| +# inflect.plural /^(ox)$/i, '\1en' +# inflect.singular /^(ox)en/i, '\1' +# inflect.irregular 'person', 'people' +# inflect.uncountable %w( fish sheep ) +# end diff --git a/episode-284/store-after/config/initializers/mime_types.rb b/episode-284/store-after/config/initializers/mime_types.rb new file mode 100644 index 00000000..72aca7e4 --- /dev/null +++ b/episode-284/store-after/config/initializers/mime_types.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf +# Mime::Type.register_alias "text/html", :iphone diff --git a/episode-284/store-after/config/initializers/secret_token.rb b/episode-284/store-after/config/initializers/secret_token.rb new file mode 100644 index 00000000..ddc57e75 --- /dev/null +++ b/episode-284/store-after/config/initializers/secret_token.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +Store::Application.config.secret_token = '913dc1a659fd2686a62b0d0284e92b601965038384c587a9edfccf213eb785f3991256b27d4de51c8d85ece2f0a896b902ed713fa581f0993f69ea732624f4e8' diff --git a/episode-284/store-after/config/initializers/session_store.rb b/episode-284/store-after/config/initializers/session_store.rb new file mode 100644 index 00000000..0b91f101 --- /dev/null +++ b/episode-284/store-after/config/initializers/session_store.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +Store::Application.config.session_store :cookie_store, key: '_store_session' + +# Use the database for sessions instead of the cookie-based default, +# which shouldn't be used to store highly confidential information +# (create the session table with "rails generate session_migration") +# Store::Application.config.session_store :active_record_store diff --git a/episode-284/store-after/config/initializers/wrap_parameters.rb b/episode-284/store-after/config/initializers/wrap_parameters.rb new file mode 100644 index 00000000..999df201 --- /dev/null +++ b/episode-284/store-after/config/initializers/wrap_parameters.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. +# +# This file contains settings for ActionController::ParamsWrapper which +# is enabled by default. + +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +ActiveSupport.on_load(:action_controller) do + wrap_parameters format: [:json] +end + +# Disable root element in JSON by default. +ActiveSupport.on_load(:active_record) do + self.include_root_in_json = false +end diff --git a/episode-284/store-after/config/locales/devise.en.yml b/episode-284/store-after/config/locales/devise.en.yml new file mode 100644 index 00000000..b1826351 --- /dev/null +++ b/episode-284/store-after/config/locales/devise.en.yml @@ -0,0 +1,58 @@ +# Additional translations at http://github.com/plataformatec/devise/wiki/I18n + +en: + errors: + messages: + expired: "has expired, please request a new one" + not_found: "not found" + already_confirmed: "was already confirmed, please try signing in" + not_locked: "was not locked" + not_saved: + one: "1 error prohibited this %{resource} from being saved:" + other: "%{count} errors prohibited this %{resource} from being saved:" + + devise: + failure: + already_authenticated: 'You are already signed in.' + unauthenticated: 'You need to sign in or sign up before continuing.' + unconfirmed: 'You have to confirm your account before continuing.' + locked: 'Your account is locked.' + invalid: 'Invalid email or password.' + invalid_token: 'Invalid authentication token.' + timeout: 'Your session expired, please sign in again to continue.' + inactive: 'Your account was not activated yet.' + sessions: + signed_in: 'Signed in successfully.' + signed_out: 'Signed out successfully.' + passwords: + send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.' + updated: 'Your password was changed successfully. You are now signed in.' + updated_not_active: 'Your password was changed successfully.' + send_paranoid_instructions: "If your e-mail exists on our database, you will receive a password recovery link on your e-mail" + confirmations: + send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.' + send_paranoid_instructions: 'If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes.' + confirmed: 'Your account was successfully confirmed. You are now signed in.' + registrations: + signed_up: 'Welcome! You have signed up successfully.' + inactive_signed_up: 'You have signed up successfully. However, we could not sign you in because your account is %{reason}.' + updated: 'You updated your account successfully.' + destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.' + reasons: + inactive: 'inactive' + unconfirmed: 'unconfirmed' + locked: 'locked' + unlocks: + send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.' + unlocked: 'Your account was successfully unlocked. You are now signed in.' + send_paranoid_instructions: 'If your account exists, you will receive an email with instructions about how to unlock it in a few minutes.' + omniauth_callbacks: + success: 'Successfully authorized from %{kind} account.' + failure: 'Could not authorize you from %{kind} because "%{reason}".' + mailer: + confirmation_instructions: + subject: 'Confirmation instructions' + reset_password_instructions: + subject: 'Reset password instructions' + unlock_instructions: + subject: 'Unlock Instructions' diff --git a/episode-284/store-after/config/locales/en.yml b/episode-284/store-after/config/locales/en.yml new file mode 100644 index 00000000..179c14ca --- /dev/null +++ b/episode-284/store-after/config/locales/en.yml @@ -0,0 +1,5 @@ +# Sample localization file for English. Add more files in this directory for other locales. +# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. + +en: + hello: "Hello world" diff --git a/episode-284/store-after/config/routes.rb b/episode-284/store-after/config/routes.rb new file mode 100644 index 00000000..4c964618 --- /dev/null +++ b/episode-284/store-after/config/routes.rb @@ -0,0 +1,8 @@ +Store::Application.routes.draw do + ActiveAdmin.routes(self) + + devise_for :admin_users, ActiveAdmin::Devise.config + + root :to => 'products#index' + resources :products +end diff --git a/episode-284/store-after/db/migrate/20110919134727_create_admin_notes.rb b/episode-284/store-after/db/migrate/20110919134727_create_admin_notes.rb new file mode 100644 index 00000000..a2d3247e --- /dev/null +++ b/episode-284/store-after/db/migrate/20110919134727_create_admin_notes.rb @@ -0,0 +1,16 @@ +class CreateAdminNotes < ActiveRecord::Migration + def self.up + create_table :admin_notes do |t| + t.references :resource, :polymorphic => true, :null => false + t.references :admin_user, :polymorphic => true + t.text :body + t.timestamps + end + add_index :admin_notes, [:resource_type, :resource_id] + add_index :admin_notes, [:admin_user_type, :admin_user_id] + end + + def self.down + drop_table :admin_notes + end +end diff --git a/episode-284/store-after/db/migrate/20110919134728_move_admin_notes_to_comments.rb b/episode-284/store-after/db/migrate/20110919134728_move_admin_notes_to_comments.rb new file mode 100644 index 00000000..296aa43f --- /dev/null +++ b/episode-284/store-after/db/migrate/20110919134728_move_admin_notes_to_comments.rb @@ -0,0 +1,25 @@ +class MoveAdminNotesToComments < ActiveRecord::Migration + def self.up + remove_index :admin_notes, [:admin_user_type, :admin_user_id] + rename_table :admin_notes, :active_admin_comments + rename_column :active_admin_comments, :admin_user_type, :author_type + rename_column :active_admin_comments, :admin_user_id, :author_id + add_column :active_admin_comments, :namespace, :string + add_index :active_admin_comments, [:namespace] + add_index :active_admin_comments, [:author_type, :author_id] + + # Update all the existing comments to the default namespace + say "Updating any existing comments to the #{ActiveAdmin.application.default_namespace} namespace." + execute "UPDATE active_admin_comments SET namespace='#{ActiveAdmin.application.default_namespace}'" + end + + def self.down + remove_index :active_admin_comments, :column => [:author_type, :author_id] + remove_index :active_admin_comments, :column => [:namespace] + remove_column :active_admin_comments, :namespace + rename_column :active_admin_comments, :author_id, :admin_user_id + rename_column :active_admin_comments, :author_type, :admin_user_type + rename_table :active_admin_comments, :admin_notes + add_index :admin_notes, [:admin_user_type, :admin_user_id] + end +end diff --git a/episode-284/store-after/db/migrate/20110919171838_create_products.rb b/episode-284/store-after/db/migrate/20110919171838_create_products.rb new file mode 100644 index 00000000..8e2b24c6 --- /dev/null +++ b/episode-284/store-after/db/migrate/20110919171838_create_products.rb @@ -0,0 +1,11 @@ +class CreateProducts < ActiveRecord::Migration + def change + create_table :products do |t| + t.string :name + t.decimal :price + t.datetime :released_at + + t.timestamps + end + end +end diff --git a/episode-284/store-after/db/migrate/20110919174935_create_categories.rb b/episode-284/store-after/db/migrate/20110919174935_create_categories.rb new file mode 100644 index 00000000..97606840 --- /dev/null +++ b/episode-284/store-after/db/migrate/20110919174935_create_categories.rb @@ -0,0 +1,9 @@ +class CreateCategories < ActiveRecord::Migration + def change + create_table :categories do |t| + t.string :name + + t.timestamps + end + end +end diff --git a/episode-284/store-after/db/migrate/20110919174955_add_category_id_to_products.rb b/episode-284/store-after/db/migrate/20110919174955_add_category_id_to_products.rb new file mode 100644 index 00000000..fa902b6c --- /dev/null +++ b/episode-284/store-after/db/migrate/20110919174955_add_category_id_to_products.rb @@ -0,0 +1,5 @@ +class AddCategoryIdToProducts < ActiveRecord::Migration + def change + add_column :products, :category_id, :integer + end +end diff --git a/episode-284/store-after/db/migrate/20110919204722_devise_create_admin_users.rb b/episode-284/store-after/db/migrate/20110919204722_devise_create_admin_users.rb new file mode 100644 index 00000000..9074d3c7 --- /dev/null +++ b/episode-284/store-after/db/migrate/20110919204722_devise_create_admin_users.rb @@ -0,0 +1,31 @@ +class DeviseCreateAdminUsers < ActiveRecord::Migration + def self.up + create_table(:admin_users) do |t| + t.database_authenticatable :null => false + t.recoverable + t.rememberable + t.trackable + + # t.encryptable + # t.confirmable + # t.lockable :lock_strategy => :failed_attempts, :unlock_strategy => :both + # t.token_authenticatable + + + t.timestamps + end + + # Create a default user + AdminUser.create!(:email => 'admin@example.com', :password => 'password', :password_confirmation => 'password') + + add_index :admin_users, :email, :unique => true + add_index :admin_users, :reset_password_token, :unique => true + # add_index :admin_users, :confirmation_token, :unique => true + # add_index :admin_users, :unlock_token, :unique => true + # add_index :admin_users, :authentication_token, :unique => true + end + + def self.down + drop_table :admin_users + end +end diff --git a/episode-284/store-after/db/schema.rb b/episode-284/store-after/db/schema.rb new file mode 100644 index 00000000..60ad08d9 --- /dev/null +++ b/episode-284/store-after/db/schema.rb @@ -0,0 +1,64 @@ +# encoding: UTF-8 +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended to check this file into your version control system. + +ActiveRecord::Schema.define(:version => 20110919204722) do + + create_table "active_admin_comments", :force => true do |t| + t.integer "resource_id", :null => false + t.string "resource_type", :null => false + t.integer "author_id" + t.string "author_type" + t.text "body" + t.datetime "created_at" + t.datetime "updated_at" + t.string "namespace" + end + + add_index "active_admin_comments", ["author_type", "author_id"], :name => "index_active_admin_comments_on_author_type_and_author_id" + add_index "active_admin_comments", ["namespace"], :name => "index_active_admin_comments_on_namespace" + add_index "active_admin_comments", ["resource_type", "resource_id"], :name => "index_admin_notes_on_resource_type_and_resource_id" + + create_table "admin_users", :force => true do |t| + t.string "email", :default => "", :null => false + t.string "encrypted_password", :limit => 128, :default => "", :null => false + t.string "reset_password_token" + t.datetime "reset_password_sent_at" + t.datetime "remember_created_at" + t.integer "sign_in_count", :default => 0 + t.datetime "current_sign_in_at" + t.datetime "last_sign_in_at" + t.string "current_sign_in_ip" + t.string "last_sign_in_ip" + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "admin_users", ["email"], :name => "index_admin_users_on_email", :unique => true + add_index "admin_users", ["reset_password_token"], :name => "index_admin_users_on_reset_password_token", :unique => true + + create_table "categories", :force => true do |t| + t.string "name" + t.datetime "created_at" + t.datetime "updated_at" + end + + create_table "products", :force => true do |t| + t.string "name" + t.decimal "price" + t.datetime "released_at" + t.datetime "created_at" + t.datetime "updated_at" + t.integer "category_id" + end + +end diff --git a/episode-284/store-after/db/seeds.rb b/episode-284/store-after/db/seeds.rb new file mode 100644 index 00000000..4edb1e85 --- /dev/null +++ b/episode-284/store-after/db/seeds.rb @@ -0,0 +1,7 @@ +# This file should contain all the record creation needed to seed the database with its default values. +# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). +# +# Examples: +# +# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) +# Mayor.create(name: 'Emanuel', city: cities.first) diff --git a/episode-284/store-after/doc/README_FOR_APP b/episode-284/store-after/doc/README_FOR_APP new file mode 100644 index 00000000..fe41f5cc --- /dev/null +++ b/episode-284/store-after/doc/README_FOR_APP @@ -0,0 +1,2 @@ +Use this README file to introduce your application and point to useful places in the API for learning more. +Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries. diff --git a/episode-284/store-after/lib/assets/.gitkeep b/episode-284/store-after/lib/assets/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-after/lib/tasks/.gitkeep b/episode-284/store-after/lib/tasks/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-after/log/.gitkeep b/episode-284/store-after/log/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-after/public/404.html b/episode-284/store-after/public/404.html new file mode 100644 index 00000000..9a48320a --- /dev/null +++ b/episode-284/store-after/public/404.html @@ -0,0 +1,26 @@ + + + + The page you were looking for doesn't exist (404) + + + + + +
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+ + diff --git a/episode-284/store-after/public/422.html b/episode-284/store-after/public/422.html new file mode 100644 index 00000000..83660ab1 --- /dev/null +++ b/episode-284/store-after/public/422.html @@ -0,0 +1,26 @@ + + + + The change you wanted was rejected (422) + + + + + +
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+ + diff --git a/episode-284/store-after/public/500.html b/episode-284/store-after/public/500.html new file mode 100644 index 00000000..b80307fc --- /dev/null +++ b/episode-284/store-after/public/500.html @@ -0,0 +1,26 @@ + + + + We're sorry, but something went wrong (500) + + + + + +
+

We're sorry, but something went wrong.

+

We've been notified about this issue and we'll take a look at it shortly.

+
+ + diff --git a/episode-284/store-after/public/favicon.ico b/episode-284/store-after/public/favicon.ico new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-after/public/robots.txt b/episode-284/store-after/public/robots.txt new file mode 100644 index 00000000..085187fa --- /dev/null +++ b/episode-284/store-after/public/robots.txt @@ -0,0 +1,5 @@ +# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file +# +# To ban all spiders from the entire site uncomment the next two lines: +# User-Agent: * +# Disallow: / diff --git a/episode-284/store-after/script/rails b/episode-284/store-after/script/rails new file mode 100755 index 00000000..f8da2cff --- /dev/null +++ b/episode-284/store-after/script/rails @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. + +APP_PATH = File.expand_path('../../config/application', __FILE__) +require File.expand_path('../../config/boot', __FILE__) +require 'rails/commands' diff --git a/episode-284/store-after/test/fixtures/.gitkeep b/episode-284/store-after/test/fixtures/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-after/test/fixtures/admin_users.yml b/episode-284/store-after/test/fixtures/admin_users.yml new file mode 100644 index 00000000..a53d4f26 --- /dev/null +++ b/episode-284/store-after/test/fixtures/admin_users.yml @@ -0,0 +1,10 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/Fixtures.html + +# This model initially had no columns defined. If you add columns to the +# model remove the '{}' from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +# column: value diff --git a/episode-284/store-after/test/fixtures/categories.yml b/episode-284/store-after/test/fixtures/categories.yml new file mode 100644 index 00000000..5d87c1df --- /dev/null +++ b/episode-284/store-after/test/fixtures/categories.yml @@ -0,0 +1,16 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/Fixtures.html + +electronics: + name: Electronics + +clothing: + name: Clothing + +groceries: + name: Groceries + +toys: + name: "Toys & Games" + +furniture: + name: Furniture diff --git a/episode-284/store-after/test/fixtures/products.yml b/episode-284/store-after/test/fixtures/products.yml new file mode 100644 index 00000000..40a5d212 --- /dev/null +++ b/episode-284/store-after/test/fixtures/products.yml @@ -0,0 +1,62 @@ +product_1: + id: 1 + category: toys + name: Settlers of Catan + price: 29.95 + released_at: 2011-08-22 00:00:00 + +product_2: + id: 2 + category: electronics + name: DVD Player + price: 79.99 + released_at: + +product_3: + id: 3 + category: clothing + name: Red T-Shirt + price: 12.49 + released_at: 2011-05-20 00:00:00 + +product_4: + id: 4 + category: furniture + name: Black Leather Couch + price: 399.99 + released_at: 2011-07-20 00:00:00 + +product_5: + id: 5 + category: furniture + name: Oak Coffee Table + price: 223.99 + released_at: + +product_6: + id: 6 + category: groceries + name: 1 Gallon Milk + price: 2.99 + released_at: 2011-06-07 00:00:00 + +product_7: + id: 7 + category: groceries + name: Oh's Cereal + price: 3.95 + released_at: 2011-05-15 00:00:00 + +product_8: + id: 8 + category: electronics + name: Video Game Console + price: 299.95 + released_at: 2011-06-20 00:00:00 + +product_9: + id: 9 + category: electronics + name: Video Game + price: 29.95 + released_at: 2011-07-24 00:00:00 diff --git a/episode-284/store-after/test/functional/.gitkeep b/episode-284/store-after/test/functional/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-after/test/functional/products_controller_test.rb b/episode-284/store-after/test/functional/products_controller_test.rb new file mode 100644 index 00000000..145d1761 --- /dev/null +++ b/episode-284/store-after/test/functional/products_controller_test.rb @@ -0,0 +1,49 @@ +require 'test_helper' + +class ProductsControllerTest < ActionController::TestCase + setup do + @product = products(:one) + end + + test "should get index" do + get :index + assert_response :success + assert_not_nil assigns(:products) + end + + test "should get new" do + get :new + assert_response :success + end + + test "should create product" do + assert_difference('Product.count') do + post :create, product: @product.attributes + end + + assert_redirected_to product_path(assigns(:product)) + end + + test "should show product" do + get :show, id: @product.to_param + assert_response :success + end + + test "should get edit" do + get :edit, id: @product.to_param + assert_response :success + end + + test "should update product" do + put :update, id: @product.to_param, product: @product.attributes + assert_redirected_to product_path(assigns(:product)) + end + + test "should destroy product" do + assert_difference('Product.count', -1) do + delete :destroy, id: @product.to_param + end + + assert_redirected_to products_path + end +end diff --git a/episode-284/store-after/test/integration/.gitkeep b/episode-284/store-after/test/integration/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-after/test/performance/browsing_test.rb b/episode-284/store-after/test/performance/browsing_test.rb new file mode 100644 index 00000000..3fea27b9 --- /dev/null +++ b/episode-284/store-after/test/performance/browsing_test.rb @@ -0,0 +1,12 @@ +require 'test_helper' +require 'rails/performance_test_help' + +class BrowsingTest < ActionDispatch::PerformanceTest + # Refer to the documentation for all available options + # self.profile_options = { :runs => 5, :metrics => [:wall_time, :memory] + # :output => 'tmp/performance', :formats => [:flat] } + + def test_homepage + get '/' + end +end diff --git a/episode-284/store-after/test/test_helper.rb b/episode-284/store-after/test/test_helper.rb new file mode 100644 index 00000000..8bf1192f --- /dev/null +++ b/episode-284/store-after/test/test_helper.rb @@ -0,0 +1,13 @@ +ENV["RAILS_ENV"] = "test" +require File.expand_path('../../config/environment', __FILE__) +require 'rails/test_help' + +class ActiveSupport::TestCase + # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order. + # + # Note: You'll currently still have to declare fixtures explicitly in integration tests + # -- they do not yet inherit this setting + fixtures :all + + # Add more helper methods to be used by all tests here... +end diff --git a/episode-284/store-after/test/unit/.gitkeep b/episode-284/store-after/test/unit/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-after/test/unit/admin_user_test.rb b/episode-284/store-after/test/unit/admin_user_test.rb new file mode 100644 index 00000000..6215c049 --- /dev/null +++ b/episode-284/store-after/test/unit/admin_user_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class AdminUserTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/episode-284/store-after/test/unit/category_test.rb b/episode-284/store-after/test/unit/category_test.rb new file mode 100644 index 00000000..47335415 --- /dev/null +++ b/episode-284/store-after/test/unit/category_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class CategoryTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/episode-284/store-after/test/unit/helpers/products_helper_test.rb b/episode-284/store-after/test/unit/helpers/products_helper_test.rb new file mode 100644 index 00000000..0f5beab7 --- /dev/null +++ b/episode-284/store-after/test/unit/helpers/products_helper_test.rb @@ -0,0 +1,4 @@ +require 'test_helper' + +class ProductsHelperTest < ActionView::TestCase +end diff --git a/episode-284/store-after/test/unit/product_test.rb b/episode-284/store-after/test/unit/product_test.rb new file mode 100644 index 00000000..211cdd0b --- /dev/null +++ b/episode-284/store-after/test/unit/product_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class ProductTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/episode-284/store-after/vendor/assets/stylesheets/.gitkeep b/episode-284/store-after/vendor/assets/stylesheets/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-after/vendor/plugins/.gitkeep b/episode-284/store-after/vendor/plugins/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-before/.gitignore b/episode-284/store-before/.gitignore new file mode 100644 index 00000000..923b6976 --- /dev/null +++ b/episode-284/store-before/.gitignore @@ -0,0 +1,5 @@ +.bundle +db/*.sqlite3 +log/*.log +tmp/ +.sass-cache/ diff --git a/episode-284/store-before/Gemfile b/episode-284/store-before/Gemfile new file mode 100644 index 00000000..a3456964 --- /dev/null +++ b/episode-284/store-before/Gemfile @@ -0,0 +1,33 @@ +source 'http://rubygems.org' + +gem 'rails', '3.1.0' + +# Bundle edge Rails instead: +# gem 'rails', :git => 'git://github.com/rails/rails.git' + +gem 'sqlite3' + + +# Gems used only for assets and not required +# in production environments by default. +group :assets do + gem 'sass-rails', " ~> 3.1.0" + gem 'coffee-rails', "~> 3.1.0" + gem 'uglifier' +end + +gem 'jquery-rails' + +# Use unicorn as the web server +# gem 'unicorn' + +# Deploy with Capistrano +# gem 'capistrano' + +# To use debugger +# gem 'ruby-debug19', :require => 'ruby-debug' + +group :test do + # Pretty printed test output + gem 'turn', :require => false +end diff --git a/episode-284/store-before/Gemfile.lock b/episode-284/store-before/Gemfile.lock new file mode 100644 index 00000000..625d18cd --- /dev/null +++ b/episode-284/store-before/Gemfile.lock @@ -0,0 +1,119 @@ +GEM + remote: http://rubygems.org/ + specs: + actionmailer (3.1.0) + actionpack (= 3.1.0) + mail (~> 2.3.0) + actionpack (3.1.0) + activemodel (= 3.1.0) + activesupport (= 3.1.0) + builder (~> 3.0.0) + erubis (~> 2.7.0) + i18n (~> 0.6) + rack (~> 1.3.2) + rack-cache (~> 1.0.3) + rack-mount (~> 0.8.2) + rack-test (~> 0.6.1) + sprockets (~> 2.0.0) + activemodel (3.1.0) + activesupport (= 3.1.0) + bcrypt-ruby (~> 3.0.0) + builder (~> 3.0.0) + i18n (~> 0.6) + activerecord (3.1.0) + activemodel (= 3.1.0) + activesupport (= 3.1.0) + arel (~> 2.2.1) + tzinfo (~> 0.3.29) + activeresource (3.1.0) + activemodel (= 3.1.0) + activesupport (= 3.1.0) + activesupport (3.1.0) + multi_json (~> 1.0) + ansi (1.3.0) + arel (2.2.1) + bcrypt-ruby (3.0.1) + builder (3.0.0) + coffee-rails (3.1.1) + coffee-script (>= 2.2.0) + railties (~> 3.1.0) + coffee-script (2.2.0) + coffee-script-source + execjs + coffee-script-source (1.1.2) + erubis (2.7.0) + execjs (1.2.6) + multi_json (~> 1.0) + hike (1.2.1) + i18n (0.6.0) + jquery-rails (1.0.14) + railties (~> 3.0) + thor (~> 0.14) + mail (2.3.0) + i18n (>= 0.4.0) + mime-types (~> 1.16) + treetop (~> 1.4.8) + mime-types (1.16) + multi_json (1.0.3) + polyglot (0.3.2) + rack (1.3.3) + rack-cache (1.0.3) + rack (>= 0.4) + rack-mount (0.8.3) + rack (>= 1.0.0) + rack-ssl (1.3.2) + rack + rack-test (0.6.1) + rack (>= 1.0) + rails (3.1.0) + actionmailer (= 3.1.0) + actionpack (= 3.1.0) + activerecord (= 3.1.0) + activeresource (= 3.1.0) + activesupport (= 3.1.0) + bundler (~> 1.0) + railties (= 3.1.0) + railties (3.1.0) + actionpack (= 3.1.0) + activesupport (= 3.1.0) + rack-ssl (~> 1.3.2) + rake (>= 0.8.7) + rdoc (~> 3.4) + thor (~> 0.14.6) + rake (0.9.2) + rdoc (3.9.4) + sass (3.1.7) + sass-rails (3.1.2) + actionpack (~> 3.1.0) + railties (~> 3.1.0) + sass (>= 3.1.4) + sprockets (~> 2.0.0) + tilt (~> 1.3.2) + sprockets (2.0.0) + hike (~> 1.2) + rack (~> 1.0) + tilt (!= 1.3.0, ~> 1.1) + sqlite3 (1.3.4) + thor (0.14.6) + tilt (1.3.3) + treetop (1.4.10) + polyglot + polyglot (>= 0.3.1) + turn (0.8.2) + ansi (>= 1.2.2) + tzinfo (0.3.29) + uglifier (1.0.3) + execjs (>= 0.3.0) + multi_json (>= 1.0.2) + +PLATFORMS + ruby + +DEPENDENCIES + coffee-rails (~> 3.1.0) + jquery-rails + rails (= 3.1.0) + sass-rails (~> 3.1.0) + sqlite3 + turn + uglifier diff --git a/episode-284/store-before/README b/episode-284/store-before/README new file mode 100644 index 00000000..21d37ff8 --- /dev/null +++ b/episode-284/store-before/README @@ -0,0 +1,8 @@ += RailsCasts Example Application + +Run these commands to try it out. + + bundle + rake db:migrate + rake db:fixtures:load + rails s diff --git a/episode-284/store-before/Rakefile b/episode-284/store-before/Rakefile new file mode 100644 index 00000000..c43b4fc9 --- /dev/null +++ b/episode-284/store-before/Rakefile @@ -0,0 +1,7 @@ +#!/usr/bin/env rake +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require File.expand_path('../config/application', __FILE__) + +Store::Application.load_tasks diff --git a/episode-284/store-before/app/assets/images/rails.png b/episode-284/store-before/app/assets/images/rails.png new file mode 100644 index 0000000000000000000000000000000000000000..d5edc04e65f555e3ba4dcdaad39dc352e75b575e GIT binary patch literal 6646 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 AQ~&?~ literal 0 HcmV?d00001 diff --git a/episode-284/store-before/app/assets/javascripts/application.js b/episode-284/store-before/app/assets/javascripts/application.js new file mode 100644 index 00000000..37c7bfcd --- /dev/null +++ b/episode-284/store-before/app/assets/javascripts/application.js @@ -0,0 +1,9 @@ +// This is a manifest file that'll be compiled into including all the files listed below. +// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically +// be included in the compiled file accessible from http://example.com/assets/application.js +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// the compiled file. +// +//= require jquery +//= require jquery_ujs +//= require_tree . diff --git a/episode-284/store-before/app/assets/javascripts/products.js.coffee b/episode-284/store-before/app/assets/javascripts/products.js.coffee new file mode 100644 index 00000000..76156794 --- /dev/null +++ b/episode-284/store-before/app/assets/javascripts/products.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/episode-284/store-before/app/assets/stylesheets/application.css b/episode-284/store-before/app/assets/stylesheets/application.css new file mode 100644 index 00000000..9f0680dc --- /dev/null +++ b/episode-284/store-before/app/assets/stylesheets/application.css @@ -0,0 +1,88 @@ +/* + * This is a manifest file that'll automatically include all the stylesheets available in this directory + * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at + * the top of the compiled file, but it's generally better to create a new file per style scope. + *= require_self + *= require_tree . +*/ + +html, body { + background-color: #4B7399; + font-family: Verdana, Helvetica, Arial; + font-size: 14px; +} + +a img { + border: none; +} + +a { + color: #0000FF; +} + +.clear { + clear: both; + height: 0; + overflow: hidden; +} + +#container { + width: 75%; + margin: 0 auto; + background-color: #FFF; + padding: 20px 40px; + border: solid 1px black; + margin-top: 20px; +} + +#flash_notice, #flash_error, #flash_alert { + padding: 5px 8px; + margin: 10px 0; +} + +#flash_notice { + background-color: #CFC; + border: solid 1px #6C6; +} + +#flash_error, #flash_alert { + background-color: #FCC; + border: solid 1px #C66; +} + +.fieldWithErrors { + display: inline; +} + +.error_messages { + width: 400px; + border: 2px solid #CF0000; + padding: 0px; + padding-bottom: 12px; + margin-bottom: 20px; + background-color: #f0f0f0; + font-size: 12px; +} + +.error_messages h2 { + text-align: left; + font-weight: bold; + padding: 5px 10px; + font-size: 12px; + margin: 0; + background-color: #c00; + color: #fff; +} + +.error_messages p { + margin: 8px 10px; +} + +.error_messages ul { + margin: 0; +} + +.product h2 { + font-size: 16px; + margin-bottom: 2px; +} diff --git a/episode-284/store-before/app/assets/stylesheets/products.css.scss b/episode-284/store-before/app/assets/stylesheets/products.css.scss new file mode 100644 index 00000000..89e2e8db --- /dev/null +++ b/episode-284/store-before/app/assets/stylesheets/products.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the products controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/episode-284/store-before/app/controllers/application_controller.rb b/episode-284/store-before/app/controllers/application_controller.rb new file mode 100644 index 00000000..e8065d95 --- /dev/null +++ b/episode-284/store-before/app/controllers/application_controller.rb @@ -0,0 +1,3 @@ +class ApplicationController < ActionController::Base + protect_from_forgery +end diff --git a/episode-284/store-before/app/controllers/products_controller.rb b/episode-284/store-before/app/controllers/products_controller.rb new file mode 100644 index 00000000..0528785d --- /dev/null +++ b/episode-284/store-before/app/controllers/products_controller.rb @@ -0,0 +1,9 @@ +class ProductsController < ApplicationController + def index + @products = Product.order("released_at desc") + end + + def show + @product = Product.find(params[:id]) + end +end diff --git a/episode-284/store-before/app/helpers/application_helper.rb b/episode-284/store-before/app/helpers/application_helper.rb new file mode 100644 index 00000000..de6be794 --- /dev/null +++ b/episode-284/store-before/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/episode-284/store-before/app/helpers/error_messages_helper.rb b/episode-284/store-before/app/helpers/error_messages_helper.rb new file mode 100644 index 00000000..92575730 --- /dev/null +++ b/episode-284/store-before/app/helpers/error_messages_helper.rb @@ -0,0 +1,23 @@ +module ErrorMessagesHelper + # Render error messages for the given objects. The :message and :header_message options are allowed. + def error_messages_for(*objects) + options = objects.extract_options! + options[:header_message] ||= "Invalid Fields" + options[:message] ||= "Correct the following errors and try again." + messages = objects.compact.map { |o| o.errors.full_messages }.flatten + unless messages.empty? + content_tag(:div, :class => "error_messages") do + list_items = messages.map { |msg| content_tag(:li, msg) } + content_tag(:h2, options[:header_message]) + content_tag(:p, options[:message]) + content_tag(:ul, list_items.join.html_safe) + end + end + end + + module FormBuilderAdditions + def error_messages(options = {}) + @template.error_messages_for(@object, options) + end + end +end + +ActionView::Helpers::FormBuilder.send(:include, ErrorMessagesHelper::FormBuilderAdditions) diff --git a/episode-284/store-before/app/helpers/layout_helper.rb b/episode-284/store-before/app/helpers/layout_helper.rb new file mode 100644 index 00000000..e995cba8 --- /dev/null +++ b/episode-284/store-before/app/helpers/layout_helper.rb @@ -0,0 +1,18 @@ +module LayoutHelper + def title(page_title, show_title = true) + content_for(:title) { h(page_title.to_s) } + @show_title = show_title + end + + def show_title? + @show_title + end + + def stylesheet(*args) + content_for(:head) { stylesheet_link_tag(*args) } + end + + def javascript(*args) + content_for(:head) { javascript_include_tag(*args) } + end +end diff --git a/episode-284/store-before/app/helpers/products_helper.rb b/episode-284/store-before/app/helpers/products_helper.rb new file mode 100644 index 00000000..ab5c42b3 --- /dev/null +++ b/episode-284/store-before/app/helpers/products_helper.rb @@ -0,0 +1,2 @@ +module ProductsHelper +end diff --git a/episode-284/store-before/app/mailers/.gitkeep b/episode-284/store-before/app/mailers/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-before/app/models/.gitkeep b/episode-284/store-before/app/models/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-before/app/models/category.rb b/episode-284/store-before/app/models/category.rb new file mode 100644 index 00000000..e7d003bf --- /dev/null +++ b/episode-284/store-before/app/models/category.rb @@ -0,0 +1,3 @@ +class Category < ActiveRecord::Base + has_many :products +end diff --git a/episode-284/store-before/app/models/product.rb b/episode-284/store-before/app/models/product.rb new file mode 100644 index 00000000..456f3e1d --- /dev/null +++ b/episode-284/store-before/app/models/product.rb @@ -0,0 +1,3 @@ +class Product < ActiveRecord::Base + belongs_to :category +end diff --git a/episode-284/store-before/app/views/layouts/application.html.erb b/episode-284/store-before/app/views/layouts/application.html.erb new file mode 100644 index 00000000..54476c83 --- /dev/null +++ b/episode-284/store-before/app/views/layouts/application.html.erb @@ -0,0 +1,19 @@ + + + + <%= content_for?(:title) ? yield(:title) : "Untitled" %> + <%= stylesheet_link_tag "application" %> + <%= javascript_include_tag "application" %> + <%= csrf_meta_tag %> + <%= yield(:head) %> + + +
+ <% flash.each do |name, msg| %> + <%= content_tag :div, raw(msg), :id => "flash_#{name}" %> + <% end %> + <%= content_tag :h1, yield(:title) if show_title? %> + <%= yield %> +
+ + diff --git a/episode-284/store-before/app/views/products/index.html.erb b/episode-284/store-before/app/views/products/index.html.erb new file mode 100644 index 00000000..c8dc2085 --- /dev/null +++ b/episode-284/store-before/app/views/products/index.html.erb @@ -0,0 +1,11 @@ +<% title "Products" %> + +<% for product in @products %> +
+

<%= link_to product.name, product %>

+
+ <%= number_to_currency(product.price) %> in + <%= product.category.name %> +
+
+<% end %> diff --git a/episode-284/store-before/app/views/products/show.html.erb b/episode-284/store-before/app/views/products/show.html.erb new file mode 100644 index 00000000..54e63189 --- /dev/null +++ b/episode-284/store-before/app/views/products/show.html.erb @@ -0,0 +1,21 @@ +

+ Name: + <%= @product.name %> +

+ +

+ Price: + <%= number_to_currency(@product.price) %> +

+ +

+ Released: + <%= @product.released_at.strftime("%B %e, %Y") %> +

+ +

+ Category: + <%= @product.category.name %> +

+ +<%= link_to 'View all products', products_path %> diff --git a/episode-284/store-before/config.ru b/episode-284/store-before/config.ru new file mode 100644 index 00000000..fdab6a6f --- /dev/null +++ b/episode-284/store-before/config.ru @@ -0,0 +1,4 @@ +# This file is used by Rack-based servers to start the application. + +require ::File.expand_path('../config/environment', __FILE__) +run Store::Application diff --git a/episode-284/store-before/config/application.rb b/episode-284/store-before/config/application.rb new file mode 100644 index 00000000..640d27f9 --- /dev/null +++ b/episode-284/store-before/config/application.rb @@ -0,0 +1,48 @@ +require File.expand_path('../boot', __FILE__) + +require 'rails/all' + +if defined?(Bundler) + # If you precompile assets before deploying to production, use this line + Bundler.require *Rails.groups(:assets => %w(development test)) + # If you want your assets lazily compiled in production, use this line + # Bundler.require(:default, :assets, Rails.env) +end + +module Store + class Application < Rails::Application + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + + # Custom directories with classes and modules you want to be autoloadable. + # config.autoload_paths += %W(#{config.root}/extras) + + # Only load the plugins named here, in the order given (default is alphabetical). + # :all can be used as a placeholder for all plugins not explicitly named. + # config.plugins = [ :exception_notification, :ssl_requirement, :all ] + + # Activate observers that should always be running. + # config.active_record.observers = :cacher, :garbage_collector, :forum_observer + + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. + # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. + # config.time_zone = 'Central Time (US & Canada)' + + # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. + # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] + # config.i18n.default_locale = :de + + # Configure the default encoding used in templates for Ruby 1.9. + config.encoding = "utf-8" + + # Configure sensitive parameters which will be filtered from the log file. + config.filter_parameters += [:password] + + # Enable the asset pipeline + config.assets.enabled = true + + # Version of your assets, change this if you want to expire all your assets + config.assets.version = '1.0' + end +end diff --git a/episode-284/store-before/config/boot.rb b/episode-284/store-before/config/boot.rb new file mode 100644 index 00000000..4489e586 --- /dev/null +++ b/episode-284/store-before/config/boot.rb @@ -0,0 +1,6 @@ +require 'rubygems' + +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) + +require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) diff --git a/episode-284/store-before/config/database.yml b/episode-284/store-before/config/database.yml new file mode 100644 index 00000000..51a4dd45 --- /dev/null +++ b/episode-284/store-before/config/database.yml @@ -0,0 +1,25 @@ +# SQLite version 3.x +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem 'sqlite3' +development: + adapter: sqlite3 + database: db/development.sqlite3 + pool: 5 + timeout: 5000 + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + adapter: sqlite3 + database: db/test.sqlite3 + pool: 5 + timeout: 5000 + +production: + adapter: sqlite3 + database: db/production.sqlite3 + pool: 5 + timeout: 5000 diff --git a/episode-284/store-before/config/environment.rb b/episode-284/store-before/config/environment.rb new file mode 100644 index 00000000..7be8e24c --- /dev/null +++ b/episode-284/store-before/config/environment.rb @@ -0,0 +1,5 @@ +# Load the rails application +require File.expand_path('../application', __FILE__) + +# Initialize the rails application +Store::Application.initialize! diff --git a/episode-284/store-before/config/environments/development.rb b/episode-284/store-before/config/environments/development.rb new file mode 100644 index 00000000..17c2ed4a --- /dev/null +++ b/episode-284/store-before/config/environments/development.rb @@ -0,0 +1,32 @@ +Store::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Don't care if the mailer can't send + config.action_mailer.raise_delivery_errors = false + + # Print deprecation notices to the Rails logger + config.active_support.deprecation = :log + + # Only use best-standards-support built into browsers + config.action_dispatch.best_standards_support = :builtin + + # Do not compress assets + config.assets.compress = false + + # Expands the lines which load the assets + config.assets.debug = true + + config.action_mailer.default_url_options = { :host => 'localhost:3000' } +end diff --git a/episode-284/store-before/config/environments/production.rb b/episode-284/store-before/config/environments/production.rb new file mode 100644 index 00000000..f3df992c --- /dev/null +++ b/episode-284/store-before/config/environments/production.rb @@ -0,0 +1,60 @@ +Store::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # Code is not reloaded between requests + config.cache_classes = true + + # Full error reports are disabled and caching is turned on + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Disable Rails's static asset server (Apache or nginx will already do this) + config.serve_static_assets = false + + # Compress JavaScripts and CSS + config.assets.compress = true + + # Don't fallback to assets pipeline if a precompiled asset is missed + config.assets.compile = false + + # Generate digests for assets URLs + config.assets.digest = true + + # Defaults to Rails.root.join("public/assets") + # config.assets.manifest = YOUR_PATH + + # Specifies the header that your server uses for sending files + # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # See everything in the log (default is :info) + # config.log_level = :debug + + # Use a different logger for distributed setups + # config.logger = SyslogLogger.new + + # Use a different cache store in production + # config.cache_store = :mem_cache_store + + # Enable serving of images, stylesheets, and JavaScripts from an asset server + # config.action_controller.asset_host = "http://assets.example.com" + + # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) + # config.assets.precompile += %w( search.js ) + + # Disable delivery errors, bad email addresses will be ignored + # config.action_mailer.raise_delivery_errors = false + + # Enable threaded mode + # config.threadsafe! + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation can not be found) + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners + config.active_support.deprecation = :notify +end diff --git a/episode-284/store-before/config/environments/test.rb b/episode-284/store-before/config/environments/test.rb new file mode 100644 index 00000000..b3d438d1 --- /dev/null +++ b/episode-284/store-before/config/environments/test.rb @@ -0,0 +1,42 @@ +Store::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Configure static asset server for tests with Cache-Control for performance + config.serve_static_assets = true + config.static_cache_control = "public, max-age=3600" + + # Log error messages when you accidentally call methods on nil + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment + config.action_controller.allow_forgery_protection = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Use SQL instead of Active Record's schema dumper when creating the test database. + # This is necessary if your schema can't be completely dumped by the schema dumper, + # like if you have constraints or database-specific column types + # config.active_record.schema_format = :sql + + # Print deprecation notices to the stderr + config.active_support.deprecation = :stderr + + # Allow pass debug_assets=true as a query parameter to load pages with unpackaged assets + config.assets.allow_debugging = true +end diff --git a/episode-284/store-before/config/initializers/backtrace_silencers.rb b/episode-284/store-before/config/initializers/backtrace_silencers.rb new file mode 100644 index 00000000..59385cdf --- /dev/null +++ b/episode-284/store-before/config/initializers/backtrace_silencers.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/episode-284/store-before/config/initializers/inflections.rb b/episode-284/store-before/config/initializers/inflections.rb new file mode 100644 index 00000000..9e8b0131 --- /dev/null +++ b/episode-284/store-before/config/initializers/inflections.rb @@ -0,0 +1,10 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format +# (all these examples are active by default): +# ActiveSupport::Inflector.inflections do |inflect| +# inflect.plural /^(ox)$/i, '\1en' +# inflect.singular /^(ox)en/i, '\1' +# inflect.irregular 'person', 'people' +# inflect.uncountable %w( fish sheep ) +# end diff --git a/episode-284/store-before/config/initializers/mime_types.rb b/episode-284/store-before/config/initializers/mime_types.rb new file mode 100644 index 00000000..72aca7e4 --- /dev/null +++ b/episode-284/store-before/config/initializers/mime_types.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf +# Mime::Type.register_alias "text/html", :iphone diff --git a/episode-284/store-before/config/initializers/secret_token.rb b/episode-284/store-before/config/initializers/secret_token.rb new file mode 100644 index 00000000..ddc57e75 --- /dev/null +++ b/episode-284/store-before/config/initializers/secret_token.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +Store::Application.config.secret_token = '913dc1a659fd2686a62b0d0284e92b601965038384c587a9edfccf213eb785f3991256b27d4de51c8d85ece2f0a896b902ed713fa581f0993f69ea732624f4e8' diff --git a/episode-284/store-before/config/initializers/session_store.rb b/episode-284/store-before/config/initializers/session_store.rb new file mode 100644 index 00000000..0b91f101 --- /dev/null +++ b/episode-284/store-before/config/initializers/session_store.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +Store::Application.config.session_store :cookie_store, key: '_store_session' + +# Use the database for sessions instead of the cookie-based default, +# which shouldn't be used to store highly confidential information +# (create the session table with "rails generate session_migration") +# Store::Application.config.session_store :active_record_store diff --git a/episode-284/store-before/config/initializers/wrap_parameters.rb b/episode-284/store-before/config/initializers/wrap_parameters.rb new file mode 100644 index 00000000..999df201 --- /dev/null +++ b/episode-284/store-before/config/initializers/wrap_parameters.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. +# +# This file contains settings for ActionController::ParamsWrapper which +# is enabled by default. + +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +ActiveSupport.on_load(:action_controller) do + wrap_parameters format: [:json] +end + +# Disable root element in JSON by default. +ActiveSupport.on_load(:active_record) do + self.include_root_in_json = false +end diff --git a/episode-284/store-before/config/locales/en.yml b/episode-284/store-before/config/locales/en.yml new file mode 100644 index 00000000..179c14ca --- /dev/null +++ b/episode-284/store-before/config/locales/en.yml @@ -0,0 +1,5 @@ +# Sample localization file for English. Add more files in this directory for other locales. +# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. + +en: + hello: "Hello world" diff --git a/episode-284/store-before/config/routes.rb b/episode-284/store-before/config/routes.rb new file mode 100644 index 00000000..0fbcfdc9 --- /dev/null +++ b/episode-284/store-before/config/routes.rb @@ -0,0 +1,4 @@ +Store::Application.routes.draw do + root :to => 'products#index' + resources :products +end diff --git a/episode-284/store-before/db/migrate/20110919171838_create_products.rb b/episode-284/store-before/db/migrate/20110919171838_create_products.rb new file mode 100644 index 00000000..8e2b24c6 --- /dev/null +++ b/episode-284/store-before/db/migrate/20110919171838_create_products.rb @@ -0,0 +1,11 @@ +class CreateProducts < ActiveRecord::Migration + def change + create_table :products do |t| + t.string :name + t.decimal :price + t.datetime :released_at + + t.timestamps + end + end +end diff --git a/episode-284/store-before/db/migrate/20110919174935_create_categories.rb b/episode-284/store-before/db/migrate/20110919174935_create_categories.rb new file mode 100644 index 00000000..97606840 --- /dev/null +++ b/episode-284/store-before/db/migrate/20110919174935_create_categories.rb @@ -0,0 +1,9 @@ +class CreateCategories < ActiveRecord::Migration + def change + create_table :categories do |t| + t.string :name + + t.timestamps + end + end +end diff --git a/episode-284/store-before/db/migrate/20110919174955_add_category_id_to_products.rb b/episode-284/store-before/db/migrate/20110919174955_add_category_id_to_products.rb new file mode 100644 index 00000000..fa902b6c --- /dev/null +++ b/episode-284/store-before/db/migrate/20110919174955_add_category_id_to_products.rb @@ -0,0 +1,5 @@ +class AddCategoryIdToProducts < ActiveRecord::Migration + def change + add_column :products, :category_id, :integer + end +end diff --git a/episode-284/store-before/db/schema.rb b/episode-284/store-before/db/schema.rb new file mode 100644 index 00000000..8f62ff18 --- /dev/null +++ b/episode-284/store-before/db/schema.rb @@ -0,0 +1,31 @@ +# encoding: UTF-8 +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended to check this file into your version control system. + +ActiveRecord::Schema.define(:version => 20110919174955) do + + create_table "categories", :force => true do |t| + t.string "name" + t.datetime "created_at" + t.datetime "updated_at" + end + + create_table "products", :force => true do |t| + t.string "name" + t.decimal "price" + t.datetime "released_at" + t.datetime "created_at" + t.datetime "updated_at" + t.integer "category_id" + end + +end diff --git a/episode-284/store-before/db/seeds.rb b/episode-284/store-before/db/seeds.rb new file mode 100644 index 00000000..4edb1e85 --- /dev/null +++ b/episode-284/store-before/db/seeds.rb @@ -0,0 +1,7 @@ +# This file should contain all the record creation needed to seed the database with its default values. +# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). +# +# Examples: +# +# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) +# Mayor.create(name: 'Emanuel', city: cities.first) diff --git a/episode-284/store-before/doc/README_FOR_APP b/episode-284/store-before/doc/README_FOR_APP new file mode 100644 index 00000000..fe41f5cc --- /dev/null +++ b/episode-284/store-before/doc/README_FOR_APP @@ -0,0 +1,2 @@ +Use this README file to introduce your application and point to useful places in the API for learning more. +Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries. diff --git a/episode-284/store-before/lib/assets/.gitkeep b/episode-284/store-before/lib/assets/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-before/lib/tasks/.gitkeep b/episode-284/store-before/lib/tasks/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-before/log/.gitkeep b/episode-284/store-before/log/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-before/public/404.html b/episode-284/store-before/public/404.html new file mode 100644 index 00000000..9a48320a --- /dev/null +++ b/episode-284/store-before/public/404.html @@ -0,0 +1,26 @@ + + + + The page you were looking for doesn't exist (404) + + + + + +
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+ + diff --git a/episode-284/store-before/public/422.html b/episode-284/store-before/public/422.html new file mode 100644 index 00000000..83660ab1 --- /dev/null +++ b/episode-284/store-before/public/422.html @@ -0,0 +1,26 @@ + + + + The change you wanted was rejected (422) + + + + + +
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+ + diff --git a/episode-284/store-before/public/500.html b/episode-284/store-before/public/500.html new file mode 100644 index 00000000..b80307fc --- /dev/null +++ b/episode-284/store-before/public/500.html @@ -0,0 +1,26 @@ + + + + We're sorry, but something went wrong (500) + + + + + +
+

We're sorry, but something went wrong.

+

We've been notified about this issue and we'll take a look at it shortly.

+
+ + diff --git a/episode-284/store-before/public/favicon.ico b/episode-284/store-before/public/favicon.ico new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-before/public/robots.txt b/episode-284/store-before/public/robots.txt new file mode 100644 index 00000000..085187fa --- /dev/null +++ b/episode-284/store-before/public/robots.txt @@ -0,0 +1,5 @@ +# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file +# +# To ban all spiders from the entire site uncomment the next two lines: +# User-Agent: * +# Disallow: / diff --git a/episode-284/store-before/script/rails b/episode-284/store-before/script/rails new file mode 100755 index 00000000..f8da2cff --- /dev/null +++ b/episode-284/store-before/script/rails @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. + +APP_PATH = File.expand_path('../../config/application', __FILE__) +require File.expand_path('../../config/boot', __FILE__) +require 'rails/commands' diff --git a/episode-284/store-before/test/fixtures/.gitkeep b/episode-284/store-before/test/fixtures/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-before/test/fixtures/categories.yml b/episode-284/store-before/test/fixtures/categories.yml new file mode 100644 index 00000000..5d87c1df --- /dev/null +++ b/episode-284/store-before/test/fixtures/categories.yml @@ -0,0 +1,16 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/Fixtures.html + +electronics: + name: Electronics + +clothing: + name: Clothing + +groceries: + name: Groceries + +toys: + name: "Toys & Games" + +furniture: + name: Furniture diff --git a/episode-284/store-before/test/fixtures/products.yml b/episode-284/store-before/test/fixtures/products.yml new file mode 100644 index 00000000..3030c4a7 --- /dev/null +++ b/episode-284/store-before/test/fixtures/products.yml @@ -0,0 +1,62 @@ +product_1: + id: 1 + category: toys + name: Settlers of Catan + price: 29.95 + released_at: 2011-08-22 00:00:00 + +product_2: + id: 2 + category: electronics + name: DVD Player + price: 79.99 + released_at: 2011-07-07 00:00:00 + +product_3: + id: 3 + category: clothing + name: Red T-Shirt + price: 12.49 + released_at: 2011-05-20 00:00:00 + +product_4: + id: 4 + category: furniture + name: Black Leather Couch + price: 399.99 + released_at: 2011-07-20 00:00:00 + +product_5: + id: 5 + category: furniture + name: Oak Coffee Table + price: 223.99 + released_at: 2011-08-14 00:00:00 + +product_6: + id: 6 + category: groceries + name: 1 Gallon Milk + price: 2.99 + released_at: 2011-06-07 00:00:00 + +product_7: + id: 7 + category: groceries + name: Oh's Cereal + price: 3.95 + released_at: 2011-05-15 00:00:00 + +product_8: + id: 8 + category: electronics + name: Video Game Console + price: 299.95 + released_at: 2011-06-20 00:00:00 + +product_9: + id: 9 + category: electronics + name: Video Game + price: 29.95 + released_at: 2011-07-24 00:00:00 diff --git a/episode-284/store-before/test/functional/.gitkeep b/episode-284/store-before/test/functional/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-before/test/functional/products_controller_test.rb b/episode-284/store-before/test/functional/products_controller_test.rb new file mode 100644 index 00000000..145d1761 --- /dev/null +++ b/episode-284/store-before/test/functional/products_controller_test.rb @@ -0,0 +1,49 @@ +require 'test_helper' + +class ProductsControllerTest < ActionController::TestCase + setup do + @product = products(:one) + end + + test "should get index" do + get :index + assert_response :success + assert_not_nil assigns(:products) + end + + test "should get new" do + get :new + assert_response :success + end + + test "should create product" do + assert_difference('Product.count') do + post :create, product: @product.attributes + end + + assert_redirected_to product_path(assigns(:product)) + end + + test "should show product" do + get :show, id: @product.to_param + assert_response :success + end + + test "should get edit" do + get :edit, id: @product.to_param + assert_response :success + end + + test "should update product" do + put :update, id: @product.to_param, product: @product.attributes + assert_redirected_to product_path(assigns(:product)) + end + + test "should destroy product" do + assert_difference('Product.count', -1) do + delete :destroy, id: @product.to_param + end + + assert_redirected_to products_path + end +end diff --git a/episode-284/store-before/test/integration/.gitkeep b/episode-284/store-before/test/integration/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-before/test/performance/browsing_test.rb b/episode-284/store-before/test/performance/browsing_test.rb new file mode 100644 index 00000000..3fea27b9 --- /dev/null +++ b/episode-284/store-before/test/performance/browsing_test.rb @@ -0,0 +1,12 @@ +require 'test_helper' +require 'rails/performance_test_help' + +class BrowsingTest < ActionDispatch::PerformanceTest + # Refer to the documentation for all available options + # self.profile_options = { :runs => 5, :metrics => [:wall_time, :memory] + # :output => 'tmp/performance', :formats => [:flat] } + + def test_homepage + get '/' + end +end diff --git a/episode-284/store-before/test/test_helper.rb b/episode-284/store-before/test/test_helper.rb new file mode 100644 index 00000000..8bf1192f --- /dev/null +++ b/episode-284/store-before/test/test_helper.rb @@ -0,0 +1,13 @@ +ENV["RAILS_ENV"] = "test" +require File.expand_path('../../config/environment', __FILE__) +require 'rails/test_help' + +class ActiveSupport::TestCase + # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order. + # + # Note: You'll currently still have to declare fixtures explicitly in integration tests + # -- they do not yet inherit this setting + fixtures :all + + # Add more helper methods to be used by all tests here... +end diff --git a/episode-284/store-before/test/unit/.gitkeep b/episode-284/store-before/test/unit/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-before/test/unit/category_test.rb b/episode-284/store-before/test/unit/category_test.rb new file mode 100644 index 00000000..47335415 --- /dev/null +++ b/episode-284/store-before/test/unit/category_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class CategoryTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/episode-284/store-before/test/unit/helpers/products_helper_test.rb b/episode-284/store-before/test/unit/helpers/products_helper_test.rb new file mode 100644 index 00000000..0f5beab7 --- /dev/null +++ b/episode-284/store-before/test/unit/helpers/products_helper_test.rb @@ -0,0 +1,4 @@ +require 'test_helper' + +class ProductsHelperTest < ActionView::TestCase +end diff --git a/episode-284/store-before/test/unit/product_test.rb b/episode-284/store-before/test/unit/product_test.rb new file mode 100644 index 00000000..211cdd0b --- /dev/null +++ b/episode-284/store-before/test/unit/product_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class ProductTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/episode-284/store-before/vendor/assets/stylesheets/.gitkeep b/episode-284/store-before/vendor/assets/stylesheets/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/episode-284/store-before/vendor/plugins/.gitkeep b/episode-284/store-before/vendor/plugins/.gitkeep new file mode 100644 index 00000000..e69de29b