toystore 0.13.1 → 0.13.2
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.
- data/Changelog.md +5 -3
 - data/Gemfile +3 -1
 - data/README.md +29 -1
 - data/gemfiles/rails_3_0.gemfile +2 -0
 - data/gemfiles/rails_3_1.gemfile +2 -0
 - data/lib/toy.rb +10 -13
 - data/lib/toy/callbacks.rb +1 -1
 - data/lib/toy/dirty_store.rb +2 -2
 - data/lib/toy/identity_map.rb +2 -2
 - data/lib/toy/instrumentation/active_support_notifications.rb +5 -0
 - data/lib/toy/instrumentation/log_subscriber.rb +49 -0
 - data/lib/toy/instrumentation/metriks.rb +5 -0
 - data/lib/toy/instrumentation/metriks_subscriber.rb +16 -0
 - data/lib/toy/instrumentation/statsd.rb +5 -0
 - data/lib/toy/instrumentation/statsd_subscriber.rb +22 -0
 - data/lib/toy/instrumentation/subscriber.rb +38 -0
 - data/lib/toy/instrumenters/memory.rb +27 -0
 - data/lib/toy/instrumenters/noop.rb +9 -0
 - data/lib/toy/middleware/identity_map.rb +10 -21
 - data/lib/toy/object.rb +0 -1
 - data/lib/toy/persistence.rb +22 -4
 - data/lib/toy/querying.rb +46 -18
 - data/lib/toy/version.rb +1 -1
 - data/perf/reads.rb +1 -4
 - data/perf/writes.rb +0 -3
 - data/spec/helper.rb +4 -12
 - data/spec/support/fake_udp_socket.rb +27 -0
 - data/spec/support/instrumenter_helpers.rb +14 -0
 - data/spec/toy/instrumentation/log_subscriber_spec.rb +85 -0
 - data/spec/toy/instrumentation/metriks_subscriber_spec.rb +37 -0
 - data/spec/toy/instrumentation/statsd_subscriber_spec.rb +47 -0
 - data/spec/toy/instrumenters/memory_spec.rb +26 -0
 - data/spec/toy/instrumenters/noop_spec.rb +22 -0
 - data/spec/toy/persistence_spec.rb +45 -3
 - data/spec/toy/querying_spec.rb +121 -36
 - data/spec/toy_spec.rb +14 -16
 - metadata +27 -7
 - data/lib/toy/logger.rb +0 -15
 - data/spec/toy/logger_spec.rb +0 -21
 
    
        data/Changelog.md
    CHANGED
    
    | 
         @@ -2,12 +2,14 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            I will do my best to keep this up to date with significant changes here, starting in 0.8.3.
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
            ##  
     | 
| 
      
 5 
     | 
    
         
            +
            ## 0.13.2
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
            *  
     | 
| 
      
 7 
     | 
    
         
            +
            * Added instrumentation and log subscriber
         
     | 
| 
      
 8 
     | 
    
         
            +
            * Removed Toy.logger, Toy.logger? and Toy.logger=. All logging is now through log_subscriber. See the README.
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
            ## 0. 
     | 
| 
      
 10 
     | 
    
         
            +
            ## 0.13.1
         
     | 
| 
       10 
11 
     | 
    
         | 
| 
      
 12 
     | 
    
         
            +
            * No longer defaulting uuid to new instance, use :default instead. This allows for nil values for attributes of uuid type.
         
     | 
| 
       11 
13 
     | 
    
         
             
            * No longer persisting nil attributes
         
     | 
| 
       12 
14 
     | 
    
         
             
            * Added Toy::Types::JSON for storing serialized JSON as an attribute value
         
     | 
| 
       13 
15 
     | 
    
         
             
            * Added #persisted_id and made it public so people can override confidently. It is now used in adapter.write and adapter.delete.
         
     | 
    
        data/Gemfile
    CHANGED
    
    | 
         @@ -1,4 +1,4 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            source  
     | 
| 
      
 1 
     | 
    
         
            +
            source "https://rubygems.org"
         
     | 
| 
       2 
2 
     | 
    
         
             
            gemspec
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            gem 'activesupport', '~> 3.2.0'
         
     | 
| 
         @@ -6,6 +6,8 @@ gem 'activemodel',   '~> 3.2.0' 
     | 
|
| 
       6 
6 
     | 
    
         
             
            gem 'rake',          '~> 0.9.0'
         
     | 
| 
       7 
7 
     | 
    
         
             
            gem 'oj',            '~> 1.0.0'
         
     | 
| 
       8 
8 
     | 
    
         
             
            gem 'multi_json',    '~> 1.3.2'
         
     | 
| 
      
 9 
     | 
    
         
            +
            gem 'metriks', :require => false
         
     | 
| 
      
 10 
     | 
    
         
            +
            gem 'statsd-ruby', :require => false
         
     | 
| 
       9 
11 
     | 
    
         | 
| 
       10 
12 
     | 
    
         
             
            group(:guard) do
         
     | 
| 
       11 
13 
     | 
    
         
             
              gem 'guard',          '~> 1.0.0'
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,4 +1,4 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # Toystore 
     | 
| 
      
 1 
     | 
    
         
            +
            # Toystore
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            An object mapper for any [adapter](https://github.com/jnunemaker/adapter) that can read, write, delete, and clear data.
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
         @@ -206,6 +206,34 @@ If that doesn't excite you, nothing will. At this point, you are probably wishin 
     | 
|
| 
       206 
206 
     | 
    
         | 
| 
       207 
207 
     | 
    
         
             
            Luckily, there is an entire directory full of [examples](https://github.com/jnunemaker/toystore/tree/master/examples) and I created a few power user guides, which I will kindly link next.
         
     | 
| 
       208 
208 
     | 
    
         | 
| 
      
 209 
     | 
    
         
            +
            ## Instrumentation
         
     | 
| 
      
 210 
     | 
    
         
            +
             
     | 
| 
      
 211 
     | 
    
         
            +
            ToyStore comes with a log subscriber and automatic metriks instrumentation. By
         
     | 
| 
      
 212 
     | 
    
         
            +
            default these work with ActiveSupport::Notifications, but only require the
         
     | 
| 
      
 213 
     | 
    
         
            +
            pieces of ActiveSupport that are needed and only do so if you actually attempt
         
     | 
| 
      
 214 
     | 
    
         
            +
            to require the instrumentation files listed below.
         
     | 
| 
      
 215 
     | 
    
         
            +
             
     | 
| 
      
 216 
     | 
    
         
            +
            To use the log subscriber:
         
     | 
| 
      
 217 
     | 
    
         
            +
             
     | 
| 
      
 218 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 219 
     | 
    
         
            +
            # Gemfile
         
     | 
| 
      
 220 
     | 
    
         
            +
            gem 'activesupport'
         
     | 
| 
      
 221 
     | 
    
         
            +
             
     | 
| 
      
 222 
     | 
    
         
            +
            # config/initializers/toystore.rb (or wherever you want it)
         
     | 
| 
      
 223 
     | 
    
         
            +
            require 'toy/instrumentation/log_subscriber'
         
     | 
| 
      
 224 
     | 
    
         
            +
            ```
         
     | 
| 
      
 225 
     | 
    
         
            +
             
     | 
| 
      
 226 
     | 
    
         
            +
            To use the metriks instrumentation:
         
     | 
| 
      
 227 
     | 
    
         
            +
             
     | 
| 
      
 228 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 229 
     | 
    
         
            +
            # Gemfile
         
     | 
| 
      
 230 
     | 
    
         
            +
            gem 'activesupport'
         
     | 
| 
      
 231 
     | 
    
         
            +
            gem 'metriks'
         
     | 
| 
      
 232 
     | 
    
         
            +
             
     | 
| 
      
 233 
     | 
    
         
            +
            # config/initializers/toystore.rb (or wherever you want it)
         
     | 
| 
      
 234 
     | 
    
         
            +
            require 'toy/instrumentation/metriks'
         
     | 
| 
      
 235 
     | 
    
         
            +
            ```
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
       209 
237 
     | 
    
         
             
            ## ToyStore Power User Guides
         
     | 
| 
       210 
238 
     | 
    
         | 
| 
       211 
239 
     | 
    
         
             
            * [Wiki Home](https://github.com/jnunemaker/toystore/wiki)
         
     | 
    
        data/gemfiles/rails_3_0.gemfile
    CHANGED
    
    
    
        data/gemfiles/rails_3_1.gemfile
    CHANGED
    
    
    
        data/lib/toy.rb
    CHANGED
    
    | 
         @@ -14,21 +14,11 @@ require 'active_support/core_ext' 
     | 
|
| 
       14 
14 
     | 
    
         
             
            extensions_path = root_path.join('lib', 'toy', 'extensions')
         
     | 
| 
       15 
15 
     | 
    
         
             
            Dir[extensions_path + '**/*.rb'].each { |file| require(file) }
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
      
 17 
     | 
    
         
            +
            require 'toy/instrumenters/noop'
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
       17 
19 
     | 
    
         
             
            module Toy
         
     | 
| 
       18 
20 
     | 
    
         
             
              extend self
         
     | 
| 
       19 
21 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
              def logger
         
     | 
| 
       21 
     | 
    
         
            -
                @logger
         
     | 
| 
       22 
     | 
    
         
            -
              end
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
              def logger?
         
     | 
| 
       25 
     | 
    
         
            -
                @logger.present?
         
     | 
| 
       26 
     | 
    
         
            -
              end
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
              def logger=(logger)
         
     | 
| 
       29 
     | 
    
         
            -
                @logger = logger
         
     | 
| 
       30 
     | 
    
         
            -
              end
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
22 
     | 
    
         
             
              def key_factory=(key_factory)
         
     | 
| 
       33 
23 
     | 
    
         
             
                @key_factory = key_factory
         
     | 
| 
       34 
24 
     | 
    
         
             
              end
         
     | 
| 
         @@ -37,6 +27,14 @@ module Toy 
     | 
|
| 
       37 
27 
     | 
    
         
             
                @key_factory ||= Toy::Identity::UUIDKeyFactory.new
         
     | 
| 
       38 
28 
     | 
    
         
             
              end
         
     | 
| 
       39 
29 
     | 
    
         | 
| 
      
 30 
     | 
    
         
            +
              def instrumenter
         
     | 
| 
      
 31 
     | 
    
         
            +
                @instrumenter || Toy::Instrumenters::Noop
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              def instrumenter=(instrumenter)
         
     | 
| 
      
 35 
     | 
    
         
            +
                @instrumenter = instrumenter
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
       40 
38 
     | 
    
         
             
              module Middleware
         
     | 
| 
       41 
39 
     | 
    
         
             
                autoload 'IdentityMap', 'toy/middleware/identity_map'
         
     | 
| 
       42 
40 
     | 
    
         
             
              end
         
     | 
| 
         @@ -52,7 +50,6 @@ module Toy 
     | 
|
| 
       52 
50 
     | 
    
         
             
              autoload 'Equality',                'toy/equality'
         
     | 
| 
       53 
51 
     | 
    
         
             
              autoload 'Inspect',                 'toy/inspect'
         
     | 
| 
       54 
52 
     | 
    
         
             
              autoload 'Inheritance',             'toy/inheritance'
         
     | 
| 
       55 
     | 
    
         
            -
              autoload 'Logger',                  'toy/logger'
         
     | 
| 
       56 
53 
     | 
    
         
             
              autoload 'MassAssignmentSecurity',  'toy/mass_assignment_security'
         
     | 
| 
       57 
54 
     | 
    
         
             
              autoload 'Persistence',             'toy/persistence'
         
     | 
| 
       58 
55 
     | 
    
         
             
              autoload 'Querying',                'toy/querying'
         
     | 
    
        data/lib/toy/callbacks.rb
    CHANGED
    
    
    
        data/lib/toy/dirty_store.rb
    CHANGED
    
    
    
        data/lib/toy/identity_map.rb
    CHANGED
    
    
| 
         @@ -0,0 +1,49 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'toy/instrumentation/active_support_notifications'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'active_support/log_subscriber'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Toy
         
     | 
| 
      
 5 
     | 
    
         
            +
              module Instrumentation
         
     | 
| 
      
 6 
     | 
    
         
            +
                class LogSubscriber < ::ActiveSupport::LogSubscriber
         
     | 
| 
      
 7 
     | 
    
         
            +
                  def read(event)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    return unless logger.debug?
         
     | 
| 
      
 9 
     | 
    
         
            +
                    log_event :read, event
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def read_multiple(event)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    return unless logger.debug?
         
     | 
| 
      
 14 
     | 
    
         
            +
                    log_event :read_multiple, event
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def key(event)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    return unless logger.debug?
         
     | 
| 
      
 19 
     | 
    
         
            +
                    log_event :key, event
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def create(event)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    return unless logger.debug?
         
     | 
| 
      
 24 
     | 
    
         
            +
                    log_event :create, event
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def update(event)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    return unless logger.debug?
         
     | 
| 
      
 29 
     | 
    
         
            +
                    log_event :update, event
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  def destroy(event)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    return unless logger.debug?
         
     | 
| 
      
 34 
     | 
    
         
            +
                    log_event :destroy, event
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  def log_event(action, event)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    id = event.payload[:id]
         
     | 
| 
      
 39 
     | 
    
         
            +
                    model = event.payload[:model]
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    name = '%s (%.1fms)' % ["#{model.name} #{action}", event.duration]
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    debug "  #{color(name, CYAN, true)}  [ #{id.inspect} ]"
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            Toy::Instrumentation::LogSubscriber.attach_to :toystore
         
     | 
| 
         @@ -0,0 +1,16 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Note: You should never need to require this file directly if you are using
         
     | 
| 
      
 2 
     | 
    
         
            +
            # ActiveSupport::Notifications. Instead, you should require the metriks file
         
     | 
| 
      
 3 
     | 
    
         
            +
            # that lives in the same directory as this file. The benefit is that it
         
     | 
| 
      
 4 
     | 
    
         
            +
            # subscribes to the correct events and does everything for your.
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'toy/instrumentation/subscriber'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'metriks'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            module Toy
         
     | 
| 
      
 9 
     | 
    
         
            +
              module Instrumentation
         
     | 
| 
      
 10 
     | 
    
         
            +
                class MetriksSubscriber < Subscriber
         
     | 
| 
      
 11 
     | 
    
         
            +
                  def update_timer(metric)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    Metriks.timer(metric).update(@duration)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Note: You should never need to require this file directly if you are using
         
     | 
| 
      
 2 
     | 
    
         
            +
            # ActiveSupport::Notifications. Instead, you should require the metriks file
         
     | 
| 
      
 3 
     | 
    
         
            +
            # that lives in the same directory as this file. The benefit is that it
         
     | 
| 
      
 4 
     | 
    
         
            +
            # subscribes to the correct events and does everything for your.
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'toy/instrumentation/subscriber'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'statsd'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            module Toy
         
     | 
| 
      
 9 
     | 
    
         
            +
              module Instrumentation
         
     | 
| 
      
 10 
     | 
    
         
            +
                class StatsdSubscriber < Subscriber
         
     | 
| 
      
 11 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 12 
     | 
    
         
            +
                    attr_accessor :client
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def update_timer(metric)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    if self.class.client
         
     | 
| 
      
 17 
     | 
    
         
            +
                      self.class.client.timing metric, (@duration * 1_000).round
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'toy/instrumentation/subscriber'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Toy
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Instrumentation
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Subscriber
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # Public: Use this as the subscribed block.
         
     | 
| 
      
 7 
     | 
    
         
            +
                  def self.call(name, start, ending, transaction_id, payload)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    new(name, start, ending, transaction_id, payload).update
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  # Private: Initializes a new event processing instance.
         
     | 
| 
      
 12 
     | 
    
         
            +
                  def initialize(name, start, ending, transaction_id, payload)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @name = name
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @start = start
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @ending = ending
         
     | 
| 
      
 16 
     | 
    
         
            +
                    @payload = payload
         
     | 
| 
      
 17 
     | 
    
         
            +
                    @duration = ending - start
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @transaction_id = transaction_id
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    @action = @name.split('.').first
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @model = @payload[:model]
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  # Public: Actually update all the timers for the event.
         
     | 
| 
      
 25 
     | 
    
         
            +
                  #
         
     | 
| 
      
 26 
     | 
    
         
            +
                  # Returns nothing.
         
     | 
| 
      
 27 
     | 
    
         
            +
                  def update
         
     | 
| 
      
 28 
     | 
    
         
            +
                    update_timer "toystore.#{@action}"
         
     | 
| 
      
 29 
     | 
    
         
            +
                    update_timer "toystore.#{@model}.#{@action}"
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  # Internal: Override in subclass.
         
     | 
| 
      
 33 
     | 
    
         
            +
                  def update_timer(metric)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    raise 'not implemented'
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Toy
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Instrumenters
         
     | 
| 
      
 3 
     | 
    
         
            +
                # Instrumentor that is useful for tests as it stores each of the events that
         
     | 
| 
      
 4 
     | 
    
         
            +
                # are instrumented.
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Memory
         
     | 
| 
      
 6 
     | 
    
         
            +
                  Event = Struct.new(:name, :payload, :result)
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_reader :events
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 11 
     | 
    
         
            +
                    @events = []
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def instrument(name, payload = {})
         
     | 
| 
      
 15 
     | 
    
         
            +
                    result = if block_given?
         
     | 
| 
      
 16 
     | 
    
         
            +
                      yield payload
         
     | 
| 
      
 17 
     | 
    
         
            +
                    else
         
     | 
| 
      
 18 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    @events << Event.new(name, payload, result)
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    result
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,24 +1,8 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rack/body_proxy'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            module Toy
         
     | 
| 
       2 
4 
     | 
    
         
             
              module Middleware
         
     | 
| 
       3 
5 
     | 
    
         
             
                class IdentityMap
         
     | 
| 
       4 
     | 
    
         
            -
                  class Body
         
     | 
| 
       5 
     | 
    
         
            -
                    def initialize(target, original)
         
     | 
| 
       6 
     | 
    
         
            -
                      @target   = target
         
     | 
| 
       7 
     | 
    
         
            -
                      @original = original
         
     | 
| 
       8 
     | 
    
         
            -
                    end
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
                    def each(&block)
         
     | 
| 
       11 
     | 
    
         
            -
                      @target.each(&block)
         
     | 
| 
       12 
     | 
    
         
            -
                    end
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
                    def close
         
     | 
| 
       15 
     | 
    
         
            -
                      @target.close if @target.respond_to?(:close)
         
     | 
| 
       16 
     | 
    
         
            -
                    ensure
         
     | 
| 
       17 
     | 
    
         
            -
                      Toy::IdentityMap.enabled = @original
         
     | 
| 
       18 
     | 
    
         
            -
                      Toy::IdentityMap.clear
         
     | 
| 
       19 
     | 
    
         
            -
                    end
         
     | 
| 
       20 
     | 
    
         
            -
                  end
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
6 
     | 
    
         
             
                  def initialize(app)
         
     | 
| 
       23 
7 
     | 
    
         
             
                    @app = app
         
     | 
| 
       24 
8 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -27,9 +11,14 @@ module Toy 
     | 
|
| 
       27 
11 
     | 
    
         
             
                    Toy::IdentityMap.clear
         
     | 
| 
       28 
12 
     | 
    
         
             
                    enabled = Toy::IdentityMap.enabled
         
     | 
| 
       29 
13 
     | 
    
         
             
                    Toy::IdentityMap.enabled = true
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
                     
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    response = @app.call(env)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    response[2] = Rack::BodyProxy.new(response[2]) {
         
     | 
| 
      
 17 
     | 
    
         
            +
                      Toy::IdentityMap.enabled = enabled
         
     | 
| 
      
 18 
     | 
    
         
            +
                      Toy::IdentityMap.clear
         
     | 
| 
      
 19 
     | 
    
         
            +
                    }
         
     | 
| 
      
 20 
     | 
    
         
            +
                    response
         
     | 
| 
       32 
21 
     | 
    
         
             
                  end
         
     | 
| 
       33 
22 
     | 
    
         
             
                end
         
     | 
| 
       34 
23 
     | 
    
         
             
              end
         
     | 
| 
       35 
     | 
    
         
            -
            end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/toy/object.rb
    CHANGED
    
    
    
        data/lib/toy/persistence.rb
    CHANGED
    
    | 
         @@ -75,8 +75,18 @@ module Toy 
     | 
|
| 
       75 
75 
     | 
    
         
             
                  !new_record? && !destroyed?
         
     | 
| 
       76 
76 
     | 
    
         
             
                end
         
     | 
| 
       77 
77 
     | 
    
         | 
| 
       78 
     | 
    
         
            -
                def save( 
     | 
| 
       79 
     | 
    
         
            -
                   
     | 
| 
      
 78 
     | 
    
         
            +
                def save(options={})
         
     | 
| 
      
 79 
     | 
    
         
            +
                  default_payload = {
         
     | 
| 
      
 80 
     | 
    
         
            +
                    :id => persisted_id,
         
     | 
| 
      
 81 
     | 
    
         
            +
                    :model => self.class,
         
     | 
| 
      
 82 
     | 
    
         
            +
                  }
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  new_record = new_record?
         
     | 
| 
      
 85 
     | 
    
         
            +
                  action = new_record ? 'create' : 'update'
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                  Toy.instrumenter.instrument("#{action}.toystore", default_payload) { |payload|
         
     | 
| 
      
 88 
     | 
    
         
            +
                    new_record ? create : update
         
     | 
| 
      
 89 
     | 
    
         
            +
                  }
         
     | 
| 
       80 
90 
     | 
    
         
             
                end
         
     | 
| 
       81 
91 
     | 
    
         | 
| 
       82 
92 
     | 
    
         
             
                def update_attributes(attrs)
         
     | 
| 
         @@ -85,7 +95,14 @@ module Toy 
     | 
|
| 
       85 
95 
     | 
    
         
             
                end
         
     | 
| 
       86 
96 
     | 
    
         | 
| 
       87 
97 
     | 
    
         
             
                def destroy
         
     | 
| 
       88 
     | 
    
         
            -
                   
     | 
| 
      
 98 
     | 
    
         
            +
                  default_payload = {
         
     | 
| 
      
 99 
     | 
    
         
            +
                    :id => persisted_id,
         
     | 
| 
      
 100 
     | 
    
         
            +
                    :model => self.class,
         
     | 
| 
      
 101 
     | 
    
         
            +
                  }
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                  Toy.instrumenter.instrument('destroy.toystore', default_payload) { |payload|
         
     | 
| 
      
 104 
     | 
    
         
            +
                    delete
         
     | 
| 
      
 105 
     | 
    
         
            +
                  }
         
     | 
| 
       89 
106 
     | 
    
         
             
                end
         
     | 
| 
       90 
107 
     | 
    
         | 
| 
       91 
108 
     | 
    
         
             
                def delete
         
     | 
| 
         @@ -112,7 +129,8 @@ module Toy 
     | 
|
| 
       112 
129 
     | 
    
         
             
                  attributes
         
     | 
| 
       113 
130 
     | 
    
         
             
                end
         
     | 
| 
       114 
131 
     | 
    
         | 
| 
       115 
     | 
    
         
            -
                # Public: Choke point for overriding how data gets written.
         
     | 
| 
      
 132 
     | 
    
         
            +
                # Public: Choke point for overriding how data gets written. Don't call this
         
     | 
| 
      
 133 
     | 
    
         
            +
                # directory, but you can safely override it.
         
     | 
| 
       116 
134 
     | 
    
         
             
                def persist
         
     | 
| 
       117 
135 
     | 
    
         
             
                  adapter.write(persisted_id, persisted_attributes)
         
     | 
| 
       118 
136 
     | 
    
         
             
                end
         
     |