redcrumbs 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +1 -0
- data/.travis.yml +33 -0
- data/Gemfile +6 -0
- data/LICENSE +21 -0
- data/README.md +140 -105
- data/gemfiles/Gemfile.rails-3.1.x +12 -0
- data/gemfiles/Gemfile.rails-3.2.x +12 -0
- data/gemfiles/Gemfile.rails-4.0.x +12 -0
- data/gemfiles/Gemfile.rails-4.1.x +12 -0
- data/lib/generators/redcrumbs/templates/initializer.rb +9 -26
- data/lib/redcrumbs.rb +12 -7
- data/lib/redcrumbs/config.rb +55 -5
- data/lib/redcrumbs/creation.rb +60 -47
- data/lib/redcrumbs/crumb.rb +100 -0
- data/lib/redcrumbs/options.rb +8 -3
- data/lib/redcrumbs/serializable_association.rb +193 -0
- data/lib/redcrumbs/users.rb +27 -37
- data/lib/redcrumbs/version.rb +1 -1
- data/redcrumbs.gemspec +11 -9
- data/spec/redcrumbs/config_spec.rb +168 -0
- data/spec/redcrumbs/creation_spec.rb +271 -0
- data/spec/redcrumbs/crumb_spec.rb +254 -0
- data/spec/redcrumbs/options_spec.rb +70 -0
- data/spec/redcrumbs/serializable_association_spec.rb +101 -0
- data/spec/redcrumbs/users_spec.rb +55 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/support/models.rb +34 -0
- data/spec/support/schema.rb +26 -0
- metadata +106 -34
- data/app/models/redcrumbs/crumb.rb +0 -68
- data/app/models/redcrumbs/crumb/expiry.rb +0 -23
- data/app/models/redcrumbs/crumb/getters.rb +0 -74
- data/app/models/redcrumbs/crumb/setters.rb +0 -28
- data/lib/redcrumbs/engine.rb +0 -8
| @@ -0,0 +1,193 @@ | |
| 1 | 
            +
            require 'dm-core'
         | 
| 2 | 
            +
            require 'dm-types'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module Redcrumbs
         | 
| 5 | 
            +
              module SerializableAssociation
         | 
| 6 | 
            +
                def self.included(base)
         | 
| 7 | 
            +
                  base.extend(ClassMethods)
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  base.class_eval do
         | 
| 10 | 
            +
                    include DataMapper::Resource unless self < DataMapper::Resource
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                module ClassMethods
         | 
| 15 | 
            +
                  def serializable_association(name)
         | 
| 16 | 
            +
                    raise ArgumentError unless name and [:creator, :target, :subject].include?(name)
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    property "stored_#{name}".to_sym, DataMapper::Property::Json, :lazy => false
         | 
| 19 | 
            +
                    property "#{name}_id".to_sym, DataMapper::Property::Integer, :index => true, :lazy => false
         | 
| 20 | 
            +
                    property "#{name}_type".to_sym, DataMapper::Property::String, :index => true, :lazy => false
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    define_setter_for(name)
         | 
| 23 | 
            +
                    define_getter_for(name)
         | 
| 24 | 
            +
                    define_loader_for(name)
         | 
| 25 | 
            +
                    define_load_state_getter(name)
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    self
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  private
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  # Define a setter, e.g. object.creator=
         | 
| 33 | 
            +
                  #
         | 
| 34 | 
            +
                  def define_setter_for(name)
         | 
| 35 | 
            +
                    define_method("#{name}=") do |associated|
         | 
| 36 | 
            +
                      instance_variable_set("@#{name}".to_sym, associated)
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                      assign_id_for(name, associated)
         | 
| 39 | 
            +
                      assign_type_for(name, associated)
         | 
| 40 | 
            +
                      assign_serialized_attributes(name, associated)
         | 
| 41 | 
            +
                    end
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
             | 
| 45 | 
            +
                  # Define a getter, e.g. object.creator
         | 
| 46 | 
            +
                  #
         | 
| 47 | 
            +
                  def define_getter_for(name)
         | 
| 48 | 
            +
                    define_method("#{name}") do
         | 
| 49 | 
            +
                      instance_variable_get("@#{name}") or
         | 
| 50 | 
            +
                      instance_variable_set("@#{name}", deserialize(name)) or
         | 
| 51 | 
            +
                      instance_variable_set("@#{name}", load_associated(name))
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
             | 
| 56 | 
            +
                  # Define method to force a load of the association from
         | 
| 57 | 
            +
                  # the database or return it if already loaded.
         | 
| 58 | 
            +
                  #
         | 
| 59 | 
            +
                  def define_loader_for(name)
         | 
| 60 | 
            +
                    define_method("full_#{name}") do
         | 
| 61 | 
            +
                      if send("has_loaded_#{name}?")
         | 
| 62 | 
            +
                        instance_variable_get("@#{name}")
         | 
| 63 | 
            +
                      else
         | 
| 64 | 
            +
                        instance_variable_set("@#{name}_load_state", true)
         | 
| 65 | 
            +
                        instance_variable_set("@#{name}", load_associated(name))
         | 
| 66 | 
            +
                      end
         | 
| 67 | 
            +
                    end
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
             | 
| 71 | 
            +
                  # Define method to check if association has been fully loaded
         | 
| 72 | 
            +
                  # from the database.
         | 
| 73 | 
            +
                  #
         | 
| 74 | 
            +
                  def define_load_state_getter(name)
         | 
| 75 | 
            +
                    instance_variable_set("@#{name}_load_state", false)
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                    define_method("has_loaded_#{name}?") do
         | 
| 78 | 
            +
                      instance_variable_get("@#{name}_load_state")
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
                  end
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
             | 
| 84 | 
            +
                # Load the association from the database.
         | 
| 85 | 
            +
                #
         | 
| 86 | 
            +
                def load_associated(name)
         | 
| 87 | 
            +
                  return nil unless association_id = send("#{name}_id")
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                  class_name = send("#{name}_type") || config_class_name_for(name)
         | 
| 90 | 
            +
                  klass = class_name.classify.constantize
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                  primary_key = config_primary_key_for(name) || klass.primary_key
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                  klass.where(primary_key => association_id).first
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                private
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                # Assign the association id based on default primary key
         | 
| 100 | 
            +
                #
         | 
| 101 | 
            +
                def assign_id_for(name, associated)
         | 
| 102 | 
            +
                  id = if associated
         | 
| 103 | 
            +
                    primary_key = config_primary_key_for(name) or associated.class.primary_key
         | 
| 104 | 
            +
                    associated[primary_key]
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  send("#{name}_id=", id)
         | 
| 108 | 
            +
                end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
             | 
| 111 | 
            +
                # Assign the association type based on default primary key
         | 
| 112 | 
            +
                #
         | 
| 113 | 
            +
                def assign_type_for(name, associated)
         | 
| 114 | 
            +
                  type = associated ? associated.class.name : nil
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                  send("#{name}_type=", type)
         | 
| 117 | 
            +
                end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
             | 
| 120 | 
            +
                # Serialize and assign the association
         | 
| 121 | 
            +
                #
         | 
| 122 | 
            +
                def assign_serialized_attributes(name, associated)
         | 
| 123 | 
            +
                  serialized = associated ? serialize(name, associated) : {}
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                  send("stored_#{name}=", serialized)
         | 
| 126 | 
            +
                end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
             | 
| 129 | 
            +
                # Get the class name from the config options, e.g.
         | 
| 130 | 
            +
                # Redcrumbs.creator_class_sym
         | 
| 131 | 
            +
                #
         | 
| 132 | 
            +
                def config_class_name_for(name)
         | 
| 133 | 
            +
                  Redcrumbs.send("#{name}_class_sym").to_s
         | 
| 134 | 
            +
                end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
             | 
| 137 | 
            +
                # Get the expected primary key for the association from
         | 
| 138 | 
            +
                # the config options.
         | 
| 139 | 
            +
                #
         | 
| 140 | 
            +
                def config_primary_key_for(name)
         | 
| 141 | 
            +
                  Redcrumbs.send("#{name}_primary_key")
         | 
| 142 | 
            +
                rescue NoMethodError
         | 
| 143 | 
            +
                  nil
         | 
| 144 | 
            +
                end
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                # Serializes a given object by looking for its configuration options
         | 
| 147 | 
            +
                # or calling serialization method.
         | 
| 148 | 
            +
                #
         | 
| 149 | 
            +
                def serialize(name, associated)
         | 
| 150 | 
            +
                  if name == :subject
         | 
| 151 | 
            +
                    associated.serialized_as_redcrumbs_subject
         | 
| 152 | 
            +
                  else
         | 
| 153 | 
            +
                    keys = Redcrumbs.send("store_#{name}_attributes").dup
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                    associated.attributes.select {|k,v| keys.include?(k.to_sym)}
         | 
| 156 | 
            +
                  end
         | 
| 157 | 
            +
                end
         | 
| 158 | 
            +
             | 
| 159 | 
            +
             | 
| 160 | 
            +
                # Returns a new instance of the associated object based on the
         | 
| 161 | 
            +
                # serialized attributes only.
         | 
| 162 | 
            +
                #
         | 
| 163 | 
            +
                def deserialize(name)
         | 
| 164 | 
            +
                  properties = send("stored_#{name}")
         | 
| 165 | 
            +
                  associated_id = send("#{name}_id")
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                  return nil unless properties.present? and associated_id
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                  class_name = send("#{name}_type")
         | 
| 170 | 
            +
                  class_name ||= config_class_name_for(name) unless name == :subject
         | 
| 171 | 
            +
             | 
| 172 | 
            +
                  instantiate_with_id(class_name, properties, associated_id)
         | 
| 173 | 
            +
                end
         | 
| 174 | 
            +
                
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                # Return a properties hash that corresponds to the given class's
         | 
| 177 | 
            +
                # column names.
         | 
| 178 | 
            +
                #
         | 
| 179 | 
            +
                def clean_properties(klass, properties)
         | 
| 180 | 
            +
                  properties.select {|k,v| klass.column_names.include?(k.to_s)}
         | 
| 181 | 
            +
                end
         | 
| 182 | 
            +
             | 
| 183 | 
            +
             | 
| 184 | 
            +
                def instantiate_with_id(class_name, properties, associated_id)
         | 
| 185 | 
            +
                  klass = class_name.classify.constantize
         | 
| 186 | 
            +
                  properties = clean_properties(klass, properties)
         | 
| 187 | 
            +
             | 
| 188 | 
            +
                  associated = klass.new(properties, :without_protection => true)
         | 
| 189 | 
            +
                  associated.id = associated_id
         | 
| 190 | 
            +
                  associated
         | 
| 191 | 
            +
                end
         | 
| 192 | 
            +
              end
         | 
| 193 | 
            +
            end
         | 
    
        data/lib/redcrumbs/users.rb
    CHANGED
    
    | @@ -1,45 +1,35 @@ | |
| 1 1 | 
             
            module Redcrumbs
         | 
| 2 2 | 
             
            # Provides methods for giving user context to crumbs. Retrieves crumbs created by a user (creator) or
         | 
| 3 3 | 
             
            # affecting a user (target)
         | 
| 4 | 
            -
             | 
| 4 | 
            +
              module Users
         | 
| 5 5 | 
             
                extend ActiveSupport::Concern
         | 
| 6 | 
            -
                
         | 
| 7 | 
            -
                module InstanceMethods
         | 
| 8 | 
            -
                  # Retrieves crumbs related to the user
         | 
| 9 | 
            -
                  def crumbs_for
         | 
| 10 | 
            -
                    crumb_or_custom_class.all(:target_id => self[Redcrumbs.target_primary_key], :order => [:created_at.desc])
         | 
| 11 | 
            -
                  end
         | 
| 12 6 |  | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
                   | 
| 17 | 
            -
             | 
| 18 | 
            -
                   | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
                  
         | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
                  
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                  
         | 
| 36 | 
            -
                   | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
                     else
         | 
| 40 | 
            -
                       Crumb
         | 
| 41 | 
            -
                     end
         | 
| 42 | 
            -
                  end
         | 
| 7 | 
            +
                # Retrieves crumbs related to the user
         | 
| 8 | 
            +
                #
         | 
| 9 | 
            +
                def crumbs_for(opts = {})
         | 
| 10 | 
            +
                  klass = Redcrumbs.crumb_class
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  klass.targetted_by(self).all(opts)
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                # Retrieves crumbs created by the user
         | 
| 16 | 
            +
                #
         | 
| 17 | 
            +
                def crumbs_by(opts = {})
         | 
| 18 | 
            +
                  klass = Redcrumbs.crumb_class
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  klass.created_by(self).all(opts)
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                # Or queries don't seem to be working with dm-redis-adapter. This
         | 
| 24 | 
            +
                # is a temporary workaround.
         | 
| 25 | 
            +
                #
         | 
| 26 | 
            +
                def crumbs_as_user(opts = {})
         | 
| 27 | 
            +
                  opts[:limit] ||= 100
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  arr = crumbs_by.to_a + crumbs_for.to_a
         | 
| 30 | 
            +
                  arr.uniq!
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  arr.sort_by! {|c| [c.created_at, c.id]}.reverse
         | 
| 43 33 | 
             
                end
         | 
| 44 34 | 
             
              end
         | 
| 45 35 | 
             
            end
         | 
    
        data/lib/redcrumbs/version.rb
    CHANGED
    
    
    
        data/redcrumbs.gemspec
    CHANGED
    
    | @@ -6,20 +6,22 @@ Gem::Specification.new do |s| | |
| 6 6 | 
             
              s.name        = "redcrumbs"
         | 
| 7 7 | 
             
              s.version     = Redcrumbs::VERSION
         | 
| 8 8 | 
             
              s.authors     = ["John Hope"]
         | 
| 9 | 
            -
              s.email       = [" | 
| 10 | 
            -
              s.homepage    = "https://github.com/ | 
| 9 | 
            +
              s.email       = ["john@shiftdock.com"]
         | 
| 10 | 
            +
              s.homepage    = "https://github.com/JonMidhir/Redcrumbs"
         | 
| 11 11 | 
             
              s.summary     = %q{Fast and unobtrusive activity tracking of ActiveRecord models using DataMapper and Redis}
         | 
| 12 12 | 
             
              s.description = %q{Fast and unobtrusive activity tracking of ActiveRecord models using DataMapper and Redis}
         | 
| 13 | 
            +
              s.license     = 'MIT'
         | 
| 13 14 |  | 
| 14 15 | 
             
              s.rubyforge_project = "redcrumbs"
         | 
| 16 | 
            +
              
         | 
| 17 | 
            +
              s.add_dependency 'data_mapper', '>= 1.2.0'
         | 
| 18 | 
            +
              s.add_dependency 'redis', '>= 2.2.2'
         | 
| 19 | 
            +
              s.add_dependency 'dm-redis-adapter', '>= 0.6.2'
         | 
| 20 | 
            +
              s.add_dependency 'redis-namespace', '>= 1.3.0'
         | 
| 21 | 
            +
              s.add_dependency 'activerecord', '>= 3.1', '< 5'
         | 
| 22 | 
            +
              s.add_dependency 'activesupport', '>= 3.1', '< 5'
         | 
| 15 23 |  | 
| 16 24 | 
             
              s.files         = `git ls-files`.split("\n")
         | 
| 17 | 
            -
              s.test_files    =  | 
| 18 | 
            -
              s.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
         | 
| 25 | 
            +
              s.test_files    = s.files.grep(/^spec/)
         | 
| 19 26 | 
             
              s.require_paths = ["lib"]
         | 
| 20 | 
            -
              
         | 
| 21 | 
            -
              s.add_dependency 'data_mapper', '>= 1.2.0'
         | 
| 22 | 
            -
              s.add_dependency 'dm-redis-adapter', '~> 0.6.2'
         | 
| 23 | 
            -
              s.add_dependency 'redis', '~> 2.2.2'
         | 
| 24 | 
            -
              s.add_dependency 'redis-namespace', '>= 1.1.0'
         | 
| 25 27 | 
             
            end
         | 
| @@ -0,0 +1,168 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Redcrumbs do
         | 
| 4 | 
            +
              describe '.creator_class_sym' do
         | 
| 5 | 
            +
                subject { Redcrumbs.creator_class_sym }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                context 'when unchanged' do
         | 
| 8 | 
            +
                  it { is_expected.to eq(:user) }
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                context 'when changed to :game' do
         | 
| 12 | 
            +
                  before { Redcrumbs.creator_class_sym = :game }
         | 
| 13 | 
            +
                  after  { Redcrumbs.creator_class_sym = :user }
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  it { is_expected.to eq(:game)}
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
             | 
| 20 | 
            +
              describe '.creator_primary_key' do
         | 
| 21 | 
            +
                subject { Redcrumbs.creator_primary_key }
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                context 'when unchanged' do
         | 
| 24 | 
            +
                  it { is_expected.to eq('id') }
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                context 'when changed to :name' do
         | 
| 28 | 
            +
                  before { Redcrumbs.creator_primary_key = :name }
         | 
| 29 | 
            +
                  after  { Redcrumbs.creator_primary_key = :id }
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  it { is_expected.to eq(:name)}
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
             | 
| 36 | 
            +
              describe '.target_class_sym' do
         | 
| 37 | 
            +
                subject { Redcrumbs.target_class_sym }
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                context 'when unchanged' do
         | 
| 40 | 
            +
                  it { is_expected.to eq(:user) }
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                context 'when changed to :game' do
         | 
| 44 | 
            +
                  before { Redcrumbs.target_class_sym = :game }
         | 
| 45 | 
            +
                  after  { Redcrumbs.target_class_sym = :user }
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  it { is_expected.to eq(:game)}
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
             | 
| 52 | 
            +
              describe '.target_primary_key' do
         | 
| 53 | 
            +
                subject { Redcrumbs.target_primary_key }
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                context 'when unchanged' do
         | 
| 56 | 
            +
                  it { is_expected.to eq('id') }
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                context 'when changed to :name' do
         | 
| 60 | 
            +
                  before { Redcrumbs.target_primary_key = :name }
         | 
| 61 | 
            +
                  after  { Redcrumbs.target_primary_key = :id }
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  it { is_expected.to eq(:name)}
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
              end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
             | 
| 68 | 
            +
              describe '.store_creator_attributes' do
         | 
| 69 | 
            +
                subject { Redcrumbs.store_creator_attributes }
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                context 'when unchanged' do
         | 
| 72 | 
            +
                  it { is_expected.to eq([]) }
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                context 'when given attribute keys' do
         | 
| 76 | 
            +
                  before { Redcrumbs.store_creator_attributes = [:id, :name] }
         | 
| 77 | 
            +
                  after  { Redcrumbs.store_creator_attributes = [] }
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  it { is_expected.to eq([:id, :name])}
         | 
| 80 | 
            +
                end
         | 
| 81 | 
            +
              end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
             | 
| 84 | 
            +
              describe '.store_target_attributes' do
         | 
| 85 | 
            +
                subject { Redcrumbs.store_target_attributes }
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                context 'when unchanged' do
         | 
| 88 | 
            +
                  it { is_expected.to eq([]) }
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                context 'when given attribute keys' do
         | 
| 92 | 
            +
                  before { Redcrumbs.store_target_attributes = [:id, :name] }
         | 
| 93 | 
            +
                  after  { Redcrumbs.store_target_attributes = [] }
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                  it { is_expected.to eq([:id, :name])}
         | 
| 96 | 
            +
                end
         | 
| 97 | 
            +
              end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
             | 
| 100 | 
            +
              describe '.redis' do
         | 
| 101 | 
            +
                let!(:default_redis) { Redcrumbs.redis }
         | 
| 102 | 
            +
                subject { Redcrumbs.redis }
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                context 'when given a URL string with port and scheme' do
         | 
| 105 | 
            +
                  before { Redcrumbs.redis = 'redis://localhost:6379' }
         | 
| 106 | 
            +
                  after { Redcrumbs.redis = default_redis }
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                  it { expect(subject.namespace).to eq(:redcrumbs) }
         | 
| 109 | 
            +
                  it { expect(subject.client.host).to eq('localhost') }
         | 
| 110 | 
            +
                  it { expect(subject.client.port).to eq(6379) }
         | 
| 111 | 
            +
                end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                context 'when given a URL string without scheme' do
         | 
| 114 | 
            +
                  before { Redcrumbs.redis = 'localhost:6379' }
         | 
| 115 | 
            +
                  after { Redcrumbs.redis = default_redis }
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                  it { expect(subject.namespace).to eq(:redcrumbs) }
         | 
| 118 | 
            +
                  it { expect(subject.client.host).to eq('localhost') }
         | 
| 119 | 
            +
                  it { expect(subject.client.port).to eq(6379) }
         | 
| 120 | 
            +
                end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                context 'when given a URL string with namespace' do
         | 
| 123 | 
            +
                  before { Redcrumbs.redis = 'localhost:6379/some_namespace' }
         | 
| 124 | 
            +
                  after { Redcrumbs.redis = default_redis }
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                  it { expect(subject.namespace).to eq('some_namespace') }
         | 
| 127 | 
            +
                end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                context 'when given an existing redis client' do
         | 
| 130 | 
            +
                  let(:redis) { Redis.new }
         | 
| 131 | 
            +
                  before { Redcrumbs.redis = redis }
         | 
| 132 | 
            +
                  after { Redcrumbs.redis = default_redis }
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                  it { expect(subject.redis).to eq(redis) }
         | 
| 135 | 
            +
                end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                context 'when given an existing redis namespace' do
         | 
| 138 | 
            +
                  let(:redis) { Redis::Namespace.new('some_namespace') }
         | 
| 139 | 
            +
                  before { Redcrumbs.redis = redis }
         | 
| 140 | 
            +
                  after { Redcrumbs.redis = default_redis }
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                  it { is_expected.to eq(redis) }
         | 
| 143 | 
            +
                end
         | 
| 144 | 
            +
              end
         | 
| 145 | 
            +
             | 
| 146 | 
            +
             | 
| 147 | 
            +
              describe '.crumb_class' do
         | 
| 148 | 
            +
                subject { Redcrumbs.crumb_class }
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                context 'when class_name unchanged' do
         | 
| 151 | 
            +
                  it { is_expected.to be(Redcrumbs::Crumb) }
         | 
| 152 | 
            +
                end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                context 'when class_name set to unknown class' do
         | 
| 155 | 
            +
                  before { Redcrumbs.class_name = :foo }
         | 
| 156 | 
            +
                  after  { Redcrumbs.class_name = nil }
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                  it { is_expected.to be(Redcrumbs::Crumb) }
         | 
| 159 | 
            +
                end
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                context 'when class doesnt inherit from Crumb' do
         | 
| 162 | 
            +
                  before { Redcrumbs.class_name = :game }
         | 
| 163 | 
            +
                  after  { Redcrumbs.class_name = nil }
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                  it { expect { subject }.to raise_error(ArgumentError) }
         | 
| 166 | 
            +
                end
         | 
| 167 | 
            +
              end
         | 
| 168 | 
            +
            end
         |