├── .github └── workflows │ └── tests.yml ├── .gitignore ├── .standard.yml ├── CHANGELOG.md ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── config.ru ├── devise-guests.gemspec ├── lib ├── devise-guests.rb ├── devise-guests │ ├── controllers │ │ ├── helpers.rb │ │ └── url_helpers.rb │ ├── engine.rb │ └── version.rb ├── generators │ ├── active_record │ │ ├── devise_guests_generator.rb │ │ └── templates │ │ │ └── migration_existing.rb │ └── devise_guests │ │ └── devise_guests_generator.rb └── railties │ └── devise_guests.rake └── spec ├── controllers └── application_controller_spec.rb ├── helpers └── devise_guests_helpers_spec.rb ├── integration └── simple_integration_spec.rb ├── internal ├── app │ ├── assets │ │ └── config │ │ │ └── manifest.js │ ├── controllers │ │ └── application_controller.rb │ └── models │ │ └── user.rb ├── config │ ├── database.yml │ ├── initializers │ │ └── devise.rb │ ├── routes.rb │ └── storage.yml ├── db │ └── schema.rb ├── log │ └── .gitignore └── public │ └── favicon.ico └── spec_helper.rb /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake 6 | # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby 7 | 8 | name: Tests 9 | 10 | on: 11 | push: 12 | branches: [ master ] 13 | pull_request: 14 | branches: [ master ] 15 | types: 16 | - opened 17 | - synchronize 18 | - reopened 19 | - ready_for_review 20 | - labeled 21 | - unlabeled 22 | 23 | jobs: 24 | changelog: 25 | runs-on: ubuntu-latest 26 | steps: 27 | - uses: actions/checkout@v4 28 | - id: read-version 29 | run: | 30 | echo "::set-output name=VERSION::`cat lib/devise-guests/version.rb | grep -i version | awk '{ print $3 }' | sed -e 's/\"//g'`" 31 | - uses: dangoslen/changelog-enforcer@v3 32 | with: 33 | skipLabels: 'skip-changelog' 34 | expectedLatestVersion: ${{ steps.read-version.outputs.VERSION }} 35 | lint: 36 | runs-on: ubuntu-latest 37 | steps: 38 | - uses: actions/checkout@v4 39 | - uses: ruby/setup-ruby@v1 40 | with: 41 | ruby-version: '3.3' 42 | bundler-cache: true 43 | cache-version: 1 44 | - run: bundle exec standardrb 45 | test: 46 | needs: 47 | - changelog 48 | - lint 49 | runs-on: ubuntu-latest 50 | strategy: 51 | matrix: 52 | ruby: ['3.0', '3.1', '3.2', '3.3'] 53 | 54 | steps: 55 | - uses: actions/checkout@v4 56 | - name: Set up Ruby 57 | uses: ruby/setup-ruby@v1 58 | with: 59 | ruby-version: ${{ matrix.ruby }} 60 | bundler-cache: true # runs 'bundle install' and caches installed gems automatically 61 | cache-version: 1 62 | - name: Run tests 63 | run: bundle exec rspec 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /spec/internal/db/*.sqlite 10 | /tmp/ 11 | *.bundle 12 | *.so 13 | *.o 14 | *.a 15 | mkmf.log 16 | -------------------------------------------------------------------------------- /.standard.yml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - "lib/generators/active_record/templates/migration_existing.rb" 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [0.8.3] - 2024-04-26 8 | - Fix issue with passing batch_size to delete_old_guest_users task ([#52](https://github.com/cbeer/devise-guests/pull/52)) by [@whereismyjetpack](https://github.com/whereismyjetpack) 9 | 10 | ## [0.8.2] - 2023-12-24 11 | ### Fixed 12 | - Prevent crashing processes due to loading all guest users in memory during delete_old_guest_users task ([#42](https://github.com/cbeer/devise-guests/pull/42)) by [@hackartisan](https://github.com/hackartisan) 13 | 14 | ### Changed 15 | - Update README with better detail around data migration ([#49](https://github.com/cbeer/devise-guests/pull/49)) by [@joshmenden](https://github.com/joshmenden) 16 | - Update supported ruby versions ([#50](https://github.com/cbeer/devise-guests/pull/50)) by [@pacso](https://github.com/pacso) 17 | 18 | ## [0.8.1] - 2021-10-26 19 | ### Changed 20 | - Simplify guest transfer ([#38](https://github.com/cbeer/devise-guests/pull/38)) 21 | 22 | ## [0.8.0] - 2021-10-25 23 | ### Added 24 | - Allow setting of custom params on guest model ([#31](https://github.com/cbeer/devise-guests/pull/31)) by [@pacso](https://github.com/pacso) 25 | - Allow deletion of guest records to optionally be skipped ([#32](https://github.com/cbeer/devise-guests/pull/32)) by [@pacso](https://github.com/pacso) 26 | 27 | ### Changed 28 | - Switch to SecureRandom.uuid for guest_user_unique_suffix ([#28](https://github.com/cbeer/devise-guests/pull/28)) by [@notch8](https://github.com/notch8) 29 | - Update combustion gem ([#29](https://github.com/cbeer/devise-guests/pull/29)) by [@notch8](https://github.com/notch8) 30 | 31 | ### Fixed 32 | - Defining the logging_in callback when the controller loads ([#34](https://github.com/cbeer/devise-guests/pull/34)) by [@davidkuz](https://github.com/davidkuz) 33 | 34 | [Unreleased]: https://github.com/cbeer/devise-guests/compare/v0.8.1...HEAD 35 | [0.8.1]: https://github.com/cbeer/devise-guests/compare/v0.8.0...v0.8.1 36 | [0.8.0]: https://github.com/cbeer/devise-guests/compare/v0.7.0...v0.8.0 37 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec 4 | 5 | gem "sqlite3", "~> 1.4" 6 | 7 | group :test do 8 | gem "activerecord" 9 | gem "actionmailer" 10 | end 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2012-2013 Chris Beer 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Devise Guests 2 | [![Gem Version](https://badge.fury.io/rb/devise-guests.svg)](https://badge.fury.io/rb/devise-guests) 3 | [![Tests](https://github.com/cbeer/devise-guests/actions/workflows/tests.yml/badge.svg)](https://github.com/cbeer/devise-guests/actions/workflows/tests.yml) 4 | [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard) 5 | 6 | A drop-in guest user implementation for devise 7 | 8 | (I'm using "user" to mean my devise model, but you should be able to use any model you want, just like devise) 9 | 10 | ## Installation 11 | 12 | ```ruby 13 | # install devise first 14 | # gem install devise 15 | # rails g devise:install 16 | # rails g devise User 17 | 18 | gem install devise-guests 19 | rails g devise_guests User 20 | ``` 21 | 22 | ## Usage 23 | 24 | ```ruby 25 | # Where you might use current_user; now you can use 26 | 27 | current_or_guest_user 28 | 29 | # which returns 30 | 31 | current_user # (for logged in users) 32 | 33 | => User 34 | # or 35 | 36 | guest_user # ( for anonymous users) 37 | 38 | => User 39 | 40 | ``` 41 | 42 | ### Transferring Guest to User on Login 43 | 44 | During the login process you may want to transfer things from your guest user to the account they logged into. 45 | To do so, add the following method to your ApplicationController: 46 | 47 | ```ruby 48 | private 49 | def transfer_guest_to_user 50 | # At this point you have access to: 51 | # * current_user - the user they've just logged in as 52 | # * guest_user - the guest user they were previously identified by 53 | # 54 | # After this block runs, the guest_user will be destroyed! 55 | 56 | if current_user.cart 57 | guest_user.cart.line_items.update_all(cart_id: current_user.cart.id) 58 | else 59 | guest_user.cart.update!(user: current_user) 60 | end 61 | 62 | # In this example we've moved `LineItem` records from the guest 63 | # user's cart to the logged-in user's cart. 64 | # 65 | # To prevent these being deleted when the guest user & cart are 66 | # destroyed, we need to reload the guest record: 67 | guest_user.reload 68 | end 69 | ``` 70 | 71 | ### Custom attribute 72 | 73 | If you have added additional authentication_keys, or have other attributes on your Devise model that you need to set 74 | when creating a guest user, you can do so by overriding the set_guest_user_params method in your ApplicationController: 75 | 76 | ```ruby 77 | private 78 | def guest_user_params 79 | { site_id: current_site.id } 80 | end 81 | ``` 82 | 83 | ### Non-standard authentication keys 84 | 85 | By default Devise will use `:email` as the authentication key for your model. If for some reason you have modified your 86 | Devise config to use an alternative attribute (such as `:phone_number`) you will need to provide a method to generate 87 | the value of this attribute for any guest users which are created. 88 | 89 | Sticking with the `:phone_number` example, you should define the following method in your `application_controller.rb`: 90 | 91 | ```ruby 92 | private 93 | def guest_phone_number_authentication_key(key) 94 | key &&= nil unless key.to_s.match(/^guest/) 95 | key ||= "guest_447" + 9.times.map { SecureRandom.rand(0..9) }.join 96 | end 97 | ``` 98 | 99 | Validations are skipped when creating guest users, but if you need to rely on future modifications to the guest record 100 | passing validations, then you should ensure that this default value for guests is generated in such a way as to be 101 | valid. 102 | 103 | ### Prevent deletion of guest records 104 | 105 | By default, when signing in from a guest account to an authenticated account, the guest user is destroyed. You have an 106 | opportunity through the `logging_in_user` callback (or `logging_in_MODEL` if you're not using `User`) to transfer data 107 | from the guest to the main account before destruction occurs. 108 | 109 | However, for some situations such as guest-checkout, you may desire that any guest account which makes a purchase does 110 | not get destroyed. In that case you can use the `skip_destroy_guest_user` method to identify when to skip deleting these 111 | records. By default this method returns `false`, indicating that every record is acceptable for destruction, but you 112 | could use something like the following to optionally prevent it: 113 | 114 | ```ruby 115 | def skip_destroy_guest_user 116 | guest_user.orders.any? 117 | end 118 | ``` 119 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "rubygems" 2 | require "bundler" 3 | require "bundler/gem_tasks" 4 | require "standard/rake" 5 | 6 | begin 7 | Bundler.setup(:default, :development) 8 | rescue Bundler::BundlerError => e 9 | warn e.message 10 | warn "Run `bundle install` to install missing gems" 11 | exit e.status_code 12 | end 13 | 14 | task default: :ci 15 | 16 | require "rspec/core/rake_task" 17 | desc "Run specs" 18 | RSpec::Core::RakeTask.new do |t| 19 | if ENV["COVERAGE"] && RUBY_VERSION =~ (/^1.8/) 20 | t.rcov = true 21 | t.rcov_opts = %w[--exclude spec\/*,gems\/*,ruby\/* --aggregate coverage.data] 22 | end 23 | end 24 | 25 | require "yard" 26 | YARD::Rake::YardocTask.new do |t| 27 | t.options = ["--readme", "README.md"] 28 | end 29 | 30 | desc "Continuous Integration build" 31 | task :ci do 32 | Rake::Task["spec"].invoke 33 | Rake::Task["yard"].invoke 34 | end 35 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rubygems" 4 | require "bundler" 5 | 6 | Bundler.require :default, :development 7 | 8 | Combustion.initialize! :all 9 | run Combustion::Application 10 | -------------------------------------------------------------------------------- /devise-guests.gemspec: -------------------------------------------------------------------------------- 1 | $:.push File.expand_path("../lib", __FILE__) 2 | require "devise-guests/version" 3 | 4 | Gem::Specification.new do |s| 5 | s.name = "devise-guests" 6 | s.version = DeviseGuests::VERSION 7 | s.platform = Gem::Platform::RUBY 8 | s.authors = ["Chris Beer"] 9 | s.email = "chris@cbeer.info" 10 | s.homepage = "http://github.com/cbeer/devise-guests" 11 | s.summary = " Guest user implementation for devise " 12 | s.description = " Guest user implementation for devise " 13 | s.license = "MIT" 14 | 15 | s.add_dependency "devise" 16 | 17 | s.add_development_dependency "rspec", "~> 3.0" 18 | s.add_development_dependency "rake" 19 | s.add_development_dependency "combustion", "~> 1.3" 20 | s.add_development_dependency "rspec-rails" 21 | s.add_development_dependency "capybara" 22 | s.add_development_dependency "standard" 23 | s.add_development_dependency "yard" 24 | 25 | s.files = `git ls-files`.split("\n") 26 | s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) } 27 | s.extra_rdoc_files = [ 28 | "LICENSE", 29 | "README.md" 30 | ] 31 | 32 | s.require_paths = ["lib"] 33 | end 34 | -------------------------------------------------------------------------------- /lib/devise-guests.rb: -------------------------------------------------------------------------------- 1 | require "devise" 2 | 3 | module DeviseGuests 4 | require "devise-guests/version" 5 | 6 | module Controllers 7 | autoload :Helpers, "devise-guests/controllers/helpers" 8 | autoload :UrlHelpers, "devise-guests/controllers/url_helpers" 9 | end 10 | 11 | require "devise-guests/engine" 12 | end 13 | -------------------------------------------------------------------------------- /lib/devise-guests/controllers/helpers.rb: -------------------------------------------------------------------------------- 1 | module DeviseGuests::Controllers 2 | module Helpers 3 | extend ActiveSupport::Concern 4 | 5 | included do 6 | include ActiveSupport::Callbacks 7 | end 8 | 9 | module ClassMethods 10 | end 11 | 12 | def self.define_helpers(mapping) # :nodoc: 13 | class_name = mapping.class_name 14 | mapping = mapping.name 15 | 16 | class_eval <<-METHODS, __FILE__, __LINE__ + 1 17 | def guest_#{mapping} 18 | return @guest_#{mapping} if @guest_#{mapping} 19 | 20 | if session[:guest_#{mapping}_id] 21 | @guest_#{mapping} = #{class_name}.find_by(#{class_name}.authentication_keys.first => session[:guest_#{mapping}_id]) rescue nil 22 | @guest_#{mapping} = nil if @guest_#{mapping}.respond_to? :guest and !@guest_#{mapping}.guest 23 | end 24 | 25 | @guest_#{mapping} ||= begin 26 | u = create_guest_#{mapping}(session[:guest_#{mapping}_id]) 27 | session[:guest_#{mapping}_id] = u.send(#{class_name}.authentication_keys.first) 28 | u 29 | end 30 | 31 | @guest_#{mapping} 32 | end 33 | 34 | def current_or_guest_#{mapping} 35 | if current_#{mapping} 36 | if session[:guest_#{mapping}_id] 37 | run_callbacks :logging_in_#{mapping} do 38 | guest_#{mapping}.destroy unless send(:"skip_destroy_guest_#{mapping}") 39 | session[:guest_#{mapping}_id] = nil 40 | end 41 | end 42 | current_#{mapping} 43 | else 44 | guest_#{mapping} 45 | end 46 | end 47 | 48 | private 49 | def create_guest_#{mapping} key = nil 50 | auth_key = #{class_name}.authentication_keys.first 51 | #{class_name}.new do |g| 52 | g.send("\#{auth_key}=", send(:"guest_\#{auth_key}_authentication_key", key)) 53 | g.assign_attributes(send(:"guest_#{mapping}_params")) 54 | g.guest = true if g.respond_to? :guest 55 | g.skip_confirmation! if g.respond_to?(:skip_confirmation!) 56 | g.save(validate: false) 57 | end 58 | end 59 | 60 | def guest_email_authentication_key key 61 | key &&= nil unless key.to_s.match(/^guest/) 62 | key ||= "guest_" + guest_#{mapping}_unique_suffix + "@example.com" 63 | end 64 | 65 | def guest_#{mapping}_params 66 | {} 67 | end 68 | 69 | def guest_#{mapping}_unique_suffix 70 | SecureRandom.uuid 71 | end 72 | 73 | def skip_destroy_guest_#{mapping} 74 | false 75 | end 76 | 77 | def transfer_guest_to_#{mapping} 78 | end 79 | 80 | METHODS 81 | 82 | ActiveSupport.on_load(:action_controller) do 83 | if respond_to?(:helper_method) 84 | helper_method "guest_#{mapping}", "current_or_guest_#{mapping}" 85 | end 86 | define_callbacks "logging_in_#{mapping}" 87 | set_callback :"logging_in_#{mapping}", :"transfer_guest_to_#{mapping}" 88 | end 89 | end 90 | end 91 | end 92 | -------------------------------------------------------------------------------- /lib/devise-guests/controllers/url_helpers.rb: -------------------------------------------------------------------------------- 1 | module DeviseGuests::Controllers 2 | module UrlHelpers 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /lib/devise-guests/engine.rb: -------------------------------------------------------------------------------- 1 | require "rails" 2 | require "devise" 3 | 4 | module DeviseGuests 5 | class Engine < ::Rails::Engine 6 | initializer "devise_guests.add_helpers" do 7 | Devise.include_helpers(DeviseGuests::Controllers) 8 | Devise.helpers << DeviseGuests::Controllers::Helpers 9 | end 10 | 11 | # This makes our rake tasks visible. 12 | rake_tasks do 13 | Dir.chdir(File.expand_path(File.join(File.dirname(__FILE__), ".."))) do 14 | Dir.glob(File.join("railties", "*.rake")).each do |railtie| 15 | load railtie 16 | end 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/devise-guests/version.rb: -------------------------------------------------------------------------------- 1 | module DeviseGuests 2 | VERSION = "0.8.3" 3 | end 4 | -------------------------------------------------------------------------------- /lib/generators/active_record/devise_guests_generator.rb: -------------------------------------------------------------------------------- 1 | require "rails/generators/active_record" 2 | require "generators/devise/orm_helpers" 3 | 4 | module ActiveRecord 5 | module Generators 6 | class DeviseGuestsGenerator < ActiveRecord::Generators::Base 7 | include Devise::Generators::OrmHelpers 8 | source_root File.expand_path("../templates", __FILE__) 9 | 10 | def copy_devise_migration 11 | migration_template "migration_existing.rb", 12 | "db/migrate/add_devise_guests_to_#{table_name}.rb", 13 | migration_version: migration_version 14 | end 15 | 16 | def migration_data 17 | < false 20 | RUBY 21 | end 22 | 23 | def rails4? 24 | Rails.version.start_with? "4" 25 | end 26 | 27 | def migration_version 28 | return if rails4? 29 | "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]" 30 | end 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/generators/active_record/templates/migration_existing.rb: -------------------------------------------------------------------------------- 1 | class AddDeviseGuestsTo<%= table_name.camelize %> < ActiveRecord::Migration<%= migration_version %> 2 | def self.up 3 | change_table(:<%= table_name %>) do |t| 4 | <%= migration_data -%> 5 | end 6 | 7 | end 8 | 9 | def self.down 10 | # By default, we don't want to make any assumption about how to roll back a migration when your 11 | # model already existed. Please edit below which fields you would like to remove in this migration. 12 | raise ActiveRecord::IrreversibleMigration 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/generators/devise_guests/devise_guests_generator.rb: -------------------------------------------------------------------------------- 1 | module DeviseGuests 2 | module Generators 3 | class DeviseGuestsGenerator < Rails::Generators::NamedBase 4 | include Rails::Generators::ResourceHelpers 5 | 6 | namespace "devise_guests" 7 | source_root File.expand_path("../templates", __FILE__) 8 | 9 | desc "Generates devise guests attributes into a model with the given NAME" 10 | 11 | hook_for :orm 12 | 13 | def do_nothing 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/railties/devise_guests.rake: -------------------------------------------------------------------------------- 1 | namespace :devise_guests do 2 | # task to clean out old guest users 3 | # rake devise_guests:delete_old_guest_users[days_old] 4 | # example cron entry to delete users older than 7 days at 2:00 AM every day: 5 | # 0 2 * * * cd /path/to/your/app && /path/to/rake devise_guests:delete_old_guest_users[7] RAILS_ENV=your_env 6 | desc "Removes entries in the users table for guest users that are older than the number of days given." 7 | task :delete_old_guest_users, [:days_old, :batch_size] => [:environment] do |t, args| 8 | args.with_defaults(days_old: 7, batch_size: 1000) 9 | User 10 | .where("guest = ? and updated_at < ?", true, Time.now - args[:days_old].to_i.days) 11 | .find_each(batch_size: args[:batch_size], &:destroy) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/controllers/application_controller_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | require "ostruct" 3 | 4 | describe ApplicationController, type: :controller do 5 | controller do 6 | end 7 | 8 | before(:each) do 9 | @mock_warden = OpenStruct.new 10 | @controller.request.env["warden"] = @mock_warden 11 | end 12 | 13 | it "should create an anonymous user for a guest" do 14 | allow(@mock_warden).to receive(:authenticate).with(anything).and_return(false) 15 | 16 | expect(@controller.current_or_guest_user.email).to match(/guest/) 17 | end 18 | 19 | it "should use the current user when available" do 20 | m = double 21 | allow(@mock_warden).to receive(:authenticate).with(anything).and_return(m) 22 | 23 | expect(@controller.current_or_guest_user).to eq(m) 24 | end 25 | 26 | it "should run the 'logging_in' callbacks" do 27 | # A user is logged in 28 | current_user = double 29 | allow(@controller).to receive(:current_user) { current_user } 30 | 31 | # There is a guest user instance 32 | guest_user = double 33 | allow(guest_user).to receive(:destroy) 34 | allow(@controller).to receive(:guest_user) { guest_user } 35 | allow(@controller).to receive(:session) { {guest_user_id: 123} } 36 | 37 | expect(@controller).to receive(:run_callbacks).with(:logging_in_user).and_call_original 38 | expect(@controller).to receive(:transfer_guest_to_user).and_call_original 39 | 40 | @controller.current_or_guest_user 41 | end 42 | 43 | it "should define a 'logging_in' callback" do 44 | expect(@controller).to respond_to(:_logging_in_user_callbacks) 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /spec/helpers/devise_guests_helpers_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe "devise guest helpers", type: :helper do 4 | end 5 | -------------------------------------------------------------------------------- /spec/integration/simple_integration_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe "Simple Integration", type: :request do 4 | it "should work" do 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /spec/internal/app/assets/config/manifest.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbeer/devise-guests/374375109f748c499acae99081de31080dcbc05f/spec/internal/app/assets/config/manifest.js -------------------------------------------------------------------------------- /spec/internal/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | end 3 | -------------------------------------------------------------------------------- /spec/internal/app/models/user.rb: -------------------------------------------------------------------------------- 1 | class User < ActiveRecord::Base 2 | # Include default devise modules. Others available are: 3 | # :token_authenticatable, :confirmable, 4 | # :lockable, :timeoutable and :omniauthable 5 | devise :database_authenticatable, :registerable, 6 | :recoverable, :rememberable, :trackable, :validatable 7 | end 8 | -------------------------------------------------------------------------------- /spec/internal/config/database.yml: -------------------------------------------------------------------------------- 1 | test: 2 | adapter: sqlite3 3 | database: db/combustion_test.sqlite 4 | -------------------------------------------------------------------------------- /spec/internal/config/initializers/devise.rb: -------------------------------------------------------------------------------- 1 | Devise.setup do |config| 2 | require "devise/orm/active_record" 3 | require "devise-guests" 4 | 5 | config.helpers << DeviseGuests::Controllers::Helpers 6 | config.secret_key = "71da52cff5ef1a77c9ccdc5153993e0e58054c288c86e005d9f7eca6ac7a9279825c7903f1de5960e900543ab0cf7f85b6d307c43b53719bebcdb9cdcfe8b7e7" 7 | end 8 | -------------------------------------------------------------------------------- /spec/internal/config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | devise_for :users 3 | end 4 | -------------------------------------------------------------------------------- /spec/internal/config/storage.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: ./tmp/storage 4 | -------------------------------------------------------------------------------- /spec/internal/db/schema.rb: -------------------------------------------------------------------------------- 1 | ActiveRecord::Schema.define do 2 | create_table "users", force: true do |t| 3 | t.string "email", default: "", null: false 4 | t.string "encrypted_password", default: "", null: false 5 | t.string "reset_password_token" 6 | t.datetime "reset_password_sent_at" 7 | t.datetime "remember_created_at" 8 | t.integer "sign_in_count", default: 0 9 | t.datetime "current_sign_in_at" 10 | t.datetime "last_sign_in_at" 11 | t.string "current_sign_in_ip" 12 | t.string "last_sign_in_ip" 13 | t.datetime "created_at", null: false 14 | t.datetime "updated_at", null: false 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /spec/internal/log/.gitignore: -------------------------------------------------------------------------------- 1 | *.log -------------------------------------------------------------------------------- /spec/internal/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbeer/devise-guests/374375109f748c499acae99081de31080dcbc05f/spec/internal/public/favicon.ico -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require "rubygems" 2 | require "bundler/setup" 3 | 4 | require "combustion" 5 | require "capybara/rspec" 6 | 7 | require "devise" 8 | require "devise-guests" 9 | Combustion.initialize!(:active_record, :action_mailer) 10 | 11 | require "rspec/rails" 12 | require "capybara/rails" 13 | 14 | RSpec.configure do |config| 15 | config.infer_spec_type_from_file_location! 16 | end 17 | --------------------------------------------------------------------------------