diff --git a/README b/README index 655fb96..60cd8d7 100644 --- a/README +++ b/README @@ -1,4 +1,63 @@ -RECIPES -["analytics", "core", "deployment", "devise", "email", "extras", "frontend", "gems", "git", "init", "learn_rails", "locale", "omniauth", "pages", "rails_bootstrap", "rails_devise", "rails_devise_pundit", "rails_devise_roles", "rails_foundation", "rails_mailinglist_activejob", "rails_omniauth", "rails_signup_download", "rails_stripe_checkout", "railsapps", "readme", "roles", "setup", "tests"] -PREFERENCES -{:git=>true, :apps4=>"rails-signup-download", :announcements=>"none", :authentication=>"devise", :authorization=>"roles", :better_errors=>true, :devise_modules=>false, :form_builder=>false, :local_env_file=>false, :pry=>false, :quiet_assets=>true, :secrets=>["mailchimp_list_id", "mailchimp_api_key"], :pages=>"users", :locale=>"none", :rubocop=>false, :dev_webserver=>"webrick", :prod_webserver=>"webrick", :database=>"sqlite", :templates=>"erb", :tests=>"rspec", :continuous_testing=>"none", :frontend=>"bootstrap3", :email=>"gmail", :dashboard=>"none"} \ No newline at end of file +Rails Stripe Coupons +================ + +Rails Composer, open source, supported by subscribers. +Please join RailsApps to support development of Rails Composer. +Need help? Ask on Stack Overflow with the tag 'railsapps.' +Problems? Submit an issue: https://github.com/RailsApps/rails_apps_composer/issues +Your application contains diagnostics in this README file. +Please provide a copy of this README file when reporting any issues. + + +option Build a starter application? +choose Enter your selection: [rails-signup-download] +option Get on the mailing list for Rails Composer news? +choose Enter your selection: [none] +option Web server for development? +choose Enter your selection: [webrick] +option Web server for production? +choose Enter your selection: [webrick] +option Database used in development? +choose Enter your selection: [sqlite] +option Template engine? +choose Enter your selection: [erb] +option Test framework? +choose Enter your selection: [rspec] +option Continuous testing? +choose Enter your selection: [none] +option Front-end framework? +choose Enter your selection: [bootstrap3] +option Add support for sending email? +choose Enter your selection: [gmail] +option Authentication? +choose Enter your selection: [devise] +option Devise modules? +choose Enter your selection: [false] +option OmniAuth provider? +choose Enter your selection: [] +option Authorization? +choose Enter your selection: [roles] +option Use a form builder gem? +choose Enter your selection: [false] +option Add pages? +choose Enter your selection: [users] +option Set a locale? +choose Enter your selection: [none] +option Install page-view analytics? +choose Enter your selection: [none] +option Add a deployment mechanism? +choose Enter your selection: [none] +option Set a robots.txt file to ban spiders? +choose Enter your selection: [] +option Create a GitHub repository? (y/n) +choose Enter your selection: [] +option Add gem and file for environment variables? +choose Enter your selection: [false] +option Reduce assets logger noise during development? +choose Enter your selection: [true] +option Improve error reporting with 'better_errors' during development? +choose Enter your selection: [true] +option Use 'pry' as console replacement during development and test? +choose Enter your selection: [false] +option Use or create a project-specific rvm gemset? +choose Enter your selection: [true] diff --git a/README.md b/README.md new file mode 100644 index 0000000..ab4daae --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +Rails Stripe Coupons +================ + +This application was generated with the [rails_apps_composer](https://github.com/RailsApps/rails_apps_composer) gem +provided by the [RailsApps Project](http://railsapps.github.io/). + +Rails Composer is open source and supported by subscribers. Please join RailsApps to support development of Rails Composer. + +Problems? Issues? +----------- + +Need help? Ask on Stack Overflow with the tag 'railsapps.' + +Your application contains diagnostics in the README file. Please provide a copy of the README file when reporting any issues. + +If the application doesn't work as expected, please [report an issue](https://github.com/RailsApps/rails_apps_composer/issues) +and include the diagnostics. + +Ruby on Rails +------------- + +This application requires: + +- Ruby 2.2.0 +- Rails 4.2.0 + +Learn more about [Installing Rails](http://railsapps.github.io/installing-rails.html). + +Getting Started +--------------- + +Documentation and Support +------------------------- + +Issues +------------- + +Similar Projects +---------------- + +Contributing +------------ + +Credits +------- + +License +------- diff --git a/README.rdoc b/README.rdoc deleted file mode 100644 index dd4e97e..0000000 --- a/README.rdoc +++ /dev/null @@ -1,28 +0,0 @@ -== README - -This README would normally document whatever steps are necessary to get the -application up and running. - -Things you may want to cover: - -* Ruby version - -* System dependencies - -* Configuration - -* Database creation - -* Database initialization - -* How to run the test suite - -* Services (job queues, cache servers, search engines, etc.) - -* Deployment instructions - -* ... - - -Please feel free to use a different markup language if you do not plan to run -rake doc:app. diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb new file mode 100644 index 0000000..d807090 --- /dev/null +++ b/app/controllers/products_controller.rb @@ -0,0 +1,28 @@ +class ProductsController < ApplicationController + before_filter :authenticate_user! + before_filter :identify_product + + def show + send_file @path, :disposition => "attachment; filename=#{@file}" + end + + private + def identify_product + valid_characters = "^[0-9a-zA-Z]*$".freeze + unless params[:id].blank? + @product_id = params[:id] + @product_id = @product_id.tr("^#{valid_characters}", '') + else + raise "Filename missing" + end + unless params[:format].blank? + @format = params[:format] + @format = @format.tr("^#{valid_characters}", '') + else + raise "File extension missing" + end + @path = "app/views/products/#{@product_id}.#{@format}" + @file = "#{@product_id}.#{@format}" + end + +end diff --git a/app/jobs/mailing_list_signup_job.rb b/app/jobs/mailing_list_signup_job.rb new file mode 100644 index 0000000..5ae4a96 --- /dev/null +++ b/app/jobs/mailing_list_signup_job.rb @@ -0,0 +1,8 @@ +class MailingListSignupJob < ActiveJob::Base + + def perform(user) + logger.info "signing up #{user.email}" + user.subscribe + end + +end diff --git a/app/models/user.rb b/app/models/user.rb index 9e36969..9498f1a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,6 +1,7 @@ class User < ActiveRecord::Base enum role: [:user, :vip, :admin] after_initialize :set_default_role, :if => :new_record? + after_create :sign_up_for_mailing_list def set_default_role self.role ||= :user @@ -10,4 +11,21 @@ def set_default_role # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable + + def sign_up_for_mailing_list + MailingListSignupJob.perform_later(self) + end + + def subscribe + mailchimp = Gibbon::API.new(Rails.application.secrets.mailchimp_api_key) + result = mailchimp.lists.subscribe({ + :id => Rails.application.secrets.mailchimp_list_id, + :email => {:email => self.email}, + :double_optin => false, + :update_existing => true, + :send_welcome => true + }) + Rails.logger.info("Subscribed #{self.email} to MailChimp") if result + end + end diff --git a/app/views/products/product.pdf b/app/views/products/product.pdf new file mode 100644 index 0000000..dc92b8d Binary files /dev/null and b/app/views/products/product.pdf differ diff --git a/app/views/visitors/index.html.erb b/app/views/visitors/index.html.erb index 5854d00..38d0b7f 100644 --- a/app/views/visitors/index.html.erb +++ b/app/views/visitors/index.html.erb @@ -1,2 +1,13 @@

Welcome

-

<%= link_to 'Users:', users_path %> <%= User.count %> registered

+<% if user_signed_in? %> + <% if current_user.admin? %> +

Admin

+

<%= link_to 'User count:', users_path %> <%= User.count %>

+ <% else %> +

You've signed up. Download a free book.

+ <%= link_to 'Download PDF', products_path('product.pdf'), :class => 'btn btn-success btn-large' %> + <% end %> +<% else %> +

Sign up and download a free book.

+ <%= link_to 'Sign up', new_user_registration_path, :class => 'btn btn-primary btn-large' %> +<% end %> diff --git a/config/initializers/active_job.rb b/config/initializers/active_job.rb new file mode 100644 index 0000000..e10a7f1 --- /dev/null +++ b/config/initializers/active_job.rb @@ -0,0 +1,2 @@ +# ActiveJob::Base.queue_adapter = :inline +ActiveJob::Base.queue_adapter = :sucker_punch diff --git a/config/routes.rb b/config/routes.rb index 7466adb..cdacac2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,59 +1,6 @@ Rails.application.routes.draw do root to: 'visitors#index' + get 'products/:id', to: 'products#show', :as => :products devise_for :users resources :users - # The priority is based upon order of creation: first created -> highest priority. - # See how all your routes lay out with "rake routes". - - # You can have the root of your site routed with "root" - # root 'welcome#index' - - # Example of regular route: - # get 'products/:id' => 'catalog#view' - - # Example of named route that can be invoked with purchase_url(id: product.id) - # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase - - # Example resource route (maps HTTP verbs to controller actions automatically): - # resources :products - - # Example resource route with options: - # resources :products do - # member do - # get 'short' - # post 'toggle' - # end - # - # collection do - # get 'sold' - # end - # end - - # Example resource route with sub-resources: - # resources :products do - # resources :comments, :sales - # resource :seller - # end - - # Example resource route with more complex sub-resources: - # resources :products do - # resources :comments - # resources :sales do - # get 'recent', on: :collection - # end - # end - - # Example resource route with concerns: - # concern :toggleable do - # post 'toggle' - # end - # resources :posts, concerns: :toggleable - # resources :photos, concerns: :toggleable - - # Example resource route within a namespace: - # namespace :admin do - # # Directs /admin/products/* to Admin::ProductsController - # # (app/controllers/admin/products_controller.rb) - # resources :products - # end end diff --git a/public/humans.txt b/public/humans.txt new file mode 100644 index 0000000..d3deaf9 --- /dev/null +++ b/public/humans.txt @@ -0,0 +1,20 @@ +/* the humans responsible & colophon */ +/* humanstxt.org */ + + +/* TEAM */ + : + Site: + Twitter: + Location: + +/* THANKS */ + Daniel Kehoe (@rails_apps) for the RailsApps project + +/* SITE */ + Standards: HTML5, CSS3 + Components: jQuery + Software: Ruby on Rails + +/* GENERATED BY */ +Rails Composer: http://railscomposer.com/ diff --git a/spec/controllers/products_controller_spec.rb b/spec/controllers/products_controller_spec.rb new file mode 100644 index 0000000..81861f2 --- /dev/null +++ b/spec/controllers/products_controller_spec.rb @@ -0,0 +1,12 @@ +describe ProductsController do + + describe 'GET #show' do + + it "returns a PDF file" do + get :show, id: 'product', format: 'pdf' + expect(response.headers['Content-Type']).to have_content 'application/pdf' + end + + end + +end diff --git a/spec/features/users/product_acquisition_spec.rb b/spec/features/users/product_acquisition_spec.rb new file mode 100644 index 0000000..931f407 --- /dev/null +++ b/spec/features/users/product_acquisition_spec.rb @@ -0,0 +1,27 @@ +include Warden::Test::Helpers +Warden.test_mode! + +# Feature: Product acquisition +# As a user +# I want to download the product +# So I can complete my acquisition +feature 'Product acquisition' do + + after(:each) do + Warden.test_reset! + end + + # Scenario: Download the product + # Given I am a user + # When I click the 'Download' button + # Then I should receive a PDF file + scenario 'Download the product' do + user = FactoryGirl.create(:user) + login_as(user, scope: :user) + visit root_path + expect(page).to have_content 'Download a free book' + click_link_or_button 'Download PDF' + expect(page.response_headers['Content-Type']).to have_content 'application/pdf' + end + +end