morpheus 0.4.0 → 0.5.0
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/.rspec +1 -1
- data/CHANGELOG.md +17 -0
- data/Gemfile +1 -1
- data/lib/morpheus.rb +3 -23
- data/lib/morpheus/base.rb +11 -11
- data/lib/morpheus/client.rb +10 -0
- data/lib/morpheus/client/associations.rb +6 -6
- data/lib/morpheus/client/cached_request_formatter.rb +20 -0
- data/lib/morpheus/client/log_subscriber.rb +2 -28
- data/lib/morpheus/client/railtie.rb +4 -4
- data/lib/morpheus/client/request_formatter.rb +50 -0
- data/lib/morpheus/client/uncached_request_formatter.rb +40 -0
- data/lib/morpheus/configuration.rb +30 -9
- data/lib/morpheus/mixins.rb +16 -0
- data/lib/morpheus/mixins/associations.rb +39 -37
- data/lib/morpheus/mixins/associations/association.rb +112 -0
- data/lib/morpheus/mixins/associations/belongs_to_association.rb +47 -0
- data/lib/morpheus/mixins/associations/has_many_association.rb +72 -0
- data/lib/morpheus/mixins/associations/has_one_association.rb +48 -0
- data/lib/morpheus/mixins/attributes.rb +97 -95
- data/lib/morpheus/mixins/conversion.rb +16 -14
- data/lib/morpheus/mixins/filtering.rb +13 -11
- data/lib/morpheus/mixins/finders.rb +47 -45
- data/lib/morpheus/mixins/introspection.rb +15 -13
- data/lib/morpheus/mixins/persistence.rb +32 -30
- data/lib/morpheus/mixins/reflections.rb +17 -15
- data/lib/morpheus/mixins/request_handling.rb +27 -25
- data/lib/morpheus/mixins/response_parsing.rb +10 -8
- data/lib/morpheus/mixins/url_support.rb +27 -25
- data/lib/morpheus/reflection.rb +5 -2
- data/lib/morpheus/type_caster.rb +1 -1
- data/lib/morpheus/version.rb +1 -1
- data/morpheus.gemspec +2 -2
- data/spec/dummy/app/resources/book.rb +1 -1
- data/spec/morpheus/base_spec.rb +35 -35
- data/spec/morpheus/client/cached_request_formatter_spec.rb +28 -0
- data/spec/morpheus/client/log_subscriber_spec.rb +53 -10
- data/spec/morpheus/client/request_formatter_spec.rb +5 -0
- data/spec/morpheus/client/uncached_request_formatter_spec.rb +29 -0
- data/spec/morpheus/configuration_spec.rb +49 -11
- data/spec/morpheus/{associations → mixins/associations}/association_spec.rb +1 -1
- data/spec/morpheus/{associations → mixins/associations}/belongs_to_association_spec.rb +1 -1
- data/spec/morpheus/{associations → mixins/associations}/has_many_association_spec.rb +1 -1
- data/spec/morpheus/{associations → mixins/associations}/has_one_association_spec.rb +1 -1
- data/spec/morpheus/mixins/associations_spec.rb +1 -1
- data/spec/morpheus/mixins/attributes_spec.rb +27 -6
- data/spec/morpheus/mixins/conversion_spec.rb +1 -1
- data/spec/morpheus/mixins/filtering_spec.rb +2 -2
- data/spec/morpheus/mixins/finders_spec.rb +1 -1
- data/spec/morpheus/mixins/introspection_spec.rb +1 -1
- data/spec/morpheus/mixins/persistence_spec.rb +1 -1
- data/spec/morpheus/mixins/reflections_spec.rb +1 -1
- data/spec/morpheus/mixins/request_handling_spec.rb +2 -2
- data/spec/morpheus/mixins/response_parsing_spec.rb +2 -2
- data/spec/morpheus/mixins/url_support_spec.rb +2 -2
- data/spec/morpheus/response_parser_spec.rb +5 -1
- data/spec/regressions/sorting_resources_spec.rb +119 -0
- data/spec/spec_helper.rb +3 -2
- metadata +159 -87
- data/lib/morpheus/associations/association.rb +0 -110
- data/lib/morpheus/associations/belongs_to_association.rb +0 -45
- data/lib/morpheus/associations/has_many_association.rb +0 -70
- data/lib/morpheus/associations/has_one_association.rb +0 -46
    
        data/.rspec
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            -- | 
| 1 | 
            +
            --order rand
         | 
    
        data/CHANGELOG.md
    ADDED
    
    | @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            # 0.5.0
         | 
| 2 | 
            +
            * Upgrading typhoeus to ~> 0.4.2
         | 
| 3 | 
            +
            * Morpheus::Client::LogSubscriber has been refactored out into separate formatter classes.
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            # 0.4.0
         | 
| 6 | 
            +
            * Updated yajl-ruby to ~> 1.1.0 [3f30762](https://github.com/ryanmoran/morpheus/commit/3f30762528f4fc6b1f35775ce81e5ba1c03bc3c7).
         | 
| 7 | 
            +
            * Updated typhoeus to ~> 0.3.3 [cf474b6](https://github.com/ryanmoran/morpheus/commit/cf474b651a77a8359ebb25600ab2be8a57a06df2).
         | 
| 8 | 
            +
            * Added Yajl::ParseError exception handling support [3234984](https://github.com/ryanmoran/morpheus/commit/32349841d155188fe37906351f5091e756deca76).
         | 
| 9 | 
            +
            * Continuing to add spec coverage.
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            # 0.3.9
         | 
| 12 | 
            +
            * Fixed ResponseCache hashing issue where duplicate cache_key values were being created for different responses [5b507a7](https://github.com/ryanmoran/morpheus/commit/5b507a78e53120239ad38df0018b7324bd5969e9).
         | 
| 13 | 
            +
            * Continuing to add spec coverage.
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            # 0.3.8
         | 
| 16 | 
            +
            * Fixed dependency version issues with activemodel, activesupport, and i18n [36575ef](https://github.com/ryanmoran/morpheus/commit/36575efe6ca42edf1e7b461658c55048823730f7).
         | 
| 17 | 
            +
            * Continuing to add spec coverage.
         | 
    
        data/Gemfile
    CHANGED
    
    
    
        data/lib/morpheus.rb
    CHANGED
    
    | @@ -13,11 +13,11 @@ require 'active_model' | |
| 13 13 | 
             
            # The bulk of the library consists of the Base class and its mix-in modules, the request/response wrappers,
         | 
| 14 14 | 
             
            # mocking, configuration, errors, and classes managing associations, reflections, relations, and typecasting.
         | 
| 15 15 | 
             
            module Morpheus
         | 
| 16 | 
            -
              autoload :Version, 'morpheus/version'
         | 
| 17 | 
            -
             | 
| 18 16 | 
             
              autoload :Base,           'morpheus/base'
         | 
| 17 | 
            +
              autoload :Client,         'morpheus/client'
         | 
| 19 18 | 
             
              autoload :Configuration,  'morpheus/configuration'
         | 
| 20 19 | 
             
              autoload :Filter,         'morpheus/filter'
         | 
| 20 | 
            +
              autoload :Mixins,         'morpheus/mixins'
         | 
| 21 21 | 
             
              autoload :Mock,           'morpheus/mock'
         | 
| 22 22 | 
             
              autoload :Reflection,     'morpheus/reflection'
         | 
| 23 23 | 
             
              autoload :Relation,       'morpheus/relation'
         | 
| @@ -28,19 +28,7 @@ module Morpheus | |
| 28 28 | 
             
              autoload :ResponseParser, 'morpheus/response_parser'
         | 
| 29 29 | 
             
              autoload :TypeCaster,     'morpheus/type_caster'
         | 
| 30 30 | 
             
              autoload :UrlBuilder,     'morpheus/url_builder'
         | 
| 31 | 
            -
             | 
| 32 | 
            -
              # Mixins provide behaviors to the Base class.
         | 
| 33 | 
            -
              autoload :Associations,    'morpheus/mixins/associations'
         | 
| 34 | 
            -
              autoload :Attributes,      'morpheus/mixins/attributes'
         | 
| 35 | 
            -
              autoload :Conversion,      'morpheus/mixins/conversion'
         | 
| 36 | 
            -
              autoload :Filtering,       'morpheus/mixins/filtering'
         | 
| 37 | 
            -
              autoload :Finders,         'morpheus/mixins/finders'
         | 
| 38 | 
            -
              autoload :Introspection,   'morpheus/mixins/introspection'
         | 
| 39 | 
            -
              autoload :Persistence,     'morpheus/mixins/persistence'
         | 
| 40 | 
            -
              autoload :Reflections,     'morpheus/mixins/reflections'
         | 
| 41 | 
            -
              autoload :RequestHandling, 'morpheus/mixins/request_handling'
         | 
| 42 | 
            -
              autoload :ResponseParsing, 'morpheus/mixins/response_parsing'
         | 
| 43 | 
            -
              autoload :UrlSupport,      'morpheus/mixins/url_support'
         | 
| 31 | 
            +
              autoload :Version,        'morpheus/version'
         | 
| 44 32 |  | 
| 45 33 | 
             
              # Error classes
         | 
| 46 34 | 
             
              autoload :ConfigurationError,          'morpheus/errors'
         | 
| @@ -52,14 +40,6 @@ module Morpheus | |
| 52 40 | 
             
              autoload :InvalidResponseCode,         'morpheus/errors'
         | 
| 53 41 | 
             
            end
         | 
| 54 42 |  | 
| 55 | 
            -
            # Associations for application objects, typically ActiveRecord, to resource
         | 
| 56 | 
            -
            module Morpheus
         | 
| 57 | 
            -
              module Client
         | 
| 58 | 
            -
                autoload :Associations,  'morpheus/client/associations'
         | 
| 59 | 
            -
                autoload :LogSubscriber, 'morpheus/client/log_subscriber'
         | 
| 60 | 
            -
              end
         | 
| 61 | 
            -
            end
         | 
| 62 | 
            -
             | 
| 63 43 | 
             
            # The Railtie loads the LogSubscriber for printing output to the Rails log, and
         | 
| 64 44 | 
             
            # Associations which plug-in to ActiveRecord to link associated resources.
         | 
| 65 45 | 
             
            require 'morpheus/client/railtie'     if defined?(Rails)
         | 
    
        data/lib/morpheus/base.rb
    CHANGED
    
    | @@ -17,17 +17,17 @@ module Morpheus | |
| 17 17 | 
             
                # In many cases they rely upon other classes in the library to complete
         | 
| 18 18 | 
             
                # their functionality. The helper classes can be used stand-alone, but
         | 
| 19 19 | 
             
                # are most effective when used as collaborators to the mix-in behaviors.
         | 
| 20 | 
            -
                include Associations
         | 
| 21 | 
            -
                include Attributes
         | 
| 22 | 
            -
                include Conversion
         | 
| 23 | 
            -
                include Filtering
         | 
| 24 | 
            -
                include Finders
         | 
| 25 | 
            -
                include Introspection
         | 
| 26 | 
            -
                include Persistence
         | 
| 27 | 
            -
                include Reflections
         | 
| 28 | 
            -
                include RequestHandling
         | 
| 29 | 
            -
                include ResponseParsing
         | 
| 30 | 
            -
                include UrlSupport
         | 
| 20 | 
            +
                include Mixins::Associations
         | 
| 21 | 
            +
                include Mixins::Attributes
         | 
| 22 | 
            +
                include Mixins::Conversion
         | 
| 23 | 
            +
                include Mixins::Filtering
         | 
| 24 | 
            +
                include Mixins::Finders
         | 
| 25 | 
            +
                include Mixins::Introspection
         | 
| 26 | 
            +
                include Mixins::Persistence
         | 
| 27 | 
            +
                include Mixins::Reflections
         | 
| 28 | 
            +
                include Mixins::RequestHandling
         | 
| 29 | 
            +
                include Mixins::ResponseParsing
         | 
| 30 | 
            +
                include Mixins::UrlSupport
         | 
| 31 31 |  | 
| 32 32 | 
             
                # Defines a default 'id' property on all instances of Morpheus::Base and subclasses
         | 
| 33 33 | 
             
                property :id, :integer
         | 
| @@ -0,0 +1,10 @@ | |
| 1 | 
            +
            # Associations for application objects, typically ActiveRecord, to resource
         | 
| 2 | 
            +
            module Morpheus
         | 
| 3 | 
            +
              module Client
         | 
| 4 | 
            +
                autoload :Associations,             'morpheus/client/associations'
         | 
| 5 | 
            +
                autoload :CachedRequestFormatter,   'morpheus/client/cached_request_formatter'
         | 
| 6 | 
            +
                autoload :LogSubscriber,            'morpheus/client/log_subscriber'
         | 
| 7 | 
            +
                autoload :RequestFormatter,         'morpheus/client/request_formatter'
         | 
| 8 | 
            +
                autoload :UncachedRequestFormatter, 'morpheus/client/uncached_request_formatter'
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
            end
         | 
| @@ -11,11 +11,11 @@ module Morpheus | |
| 11 11 | 
             
                    def belongs_to_resource(association, options = {})
         | 
| 12 12 | 
             
                      define_method association do
         | 
| 13 13 | 
             
                        instance_variable_get("@#{association}") ||
         | 
| 14 | 
            -
                          instance_variable_set("@#{association}", Morpheus::Associations::BelongsToAssociation.new(self, association, :options => options))
         | 
| 14 | 
            +
                          instance_variable_set("@#{association}", Morpheus::Mixins::Associations::BelongsToAssociation.new(self, association, :options => options))
         | 
| 15 15 | 
             
                      end
         | 
| 16 16 |  | 
| 17 17 | 
             
                      define_method "#{association}=" do |target|
         | 
| 18 | 
            -
                        instance_variable_set("@#{association}", Morpheus::Associations::BelongsToAssociation.new(self, association, :target => target, :options => options))
         | 
| 18 | 
            +
                        instance_variable_set("@#{association}", Morpheus::Mixins::Associations::BelongsToAssociation.new(self, association, :target => target, :options => options))
         | 
| 19 19 | 
             
                        send("#{association}_id=", target.id)
         | 
| 20 20 | 
             
                      end
         | 
| 21 21 |  | 
| @@ -24,22 +24,22 @@ module Morpheus | |
| 24 24 | 
             
                    def has_many_resources(association, options = {})
         | 
| 25 25 | 
             
                      define_method association do
         | 
| 26 26 | 
             
                        instance_variable_get("@#{association}") ||
         | 
| 27 | 
            -
                          instance_variable_set("@#{association}", Morpheus::Associations::HasManyAssociation.new(self, association, :options => options))
         | 
| 27 | 
            +
                          instance_variable_set("@#{association}", Morpheus::Mixins::Associations::HasManyAssociation.new(self, association, :options => options))
         | 
| 28 28 | 
             
                      end
         | 
| 29 29 |  | 
| 30 30 | 
             
                      define_method "#{association}=" do |target|
         | 
| 31 | 
            -
                        instance_variable_set("@#{association}", Morpheus::Associations::HasManyAssociation.new(self, association, :target => target, :options => options))
         | 
| 31 | 
            +
                        instance_variable_set("@#{association}", Morpheus::Mixins::Associations::HasManyAssociation.new(self, association, :target => target, :options => options))
         | 
| 32 32 | 
             
                      end
         | 
| 33 33 | 
             
                    end
         | 
| 34 34 |  | 
| 35 35 | 
             
                    def has_one_resource(association, options = {})
         | 
| 36 36 | 
             
                      define_method association do
         | 
| 37 37 | 
             
                        instance_variable_get("@#{association}") ||
         | 
| 38 | 
            -
                          instance_variable_set("@#{association}", Morpheus::Associations::HasOneAssociation.new(self, association, :options => options))
         | 
| 38 | 
            +
                          instance_variable_set("@#{association}", Morpheus::Mixins::Associations::HasOneAssociation.new(self, association, :options => options))
         | 
| 39 39 | 
             
                      end
         | 
| 40 40 |  | 
| 41 41 | 
             
                      define_method "#{association}=" do |target|
         | 
| 42 | 
            -
                        instance_variable_set("@#{association}", Morpheus::Associations::HasOneAssociation.new(self, association, :target => target, :options => options))
         | 
| 42 | 
            +
                        instance_variable_set("@#{association}", Morpheus::Mixins::Associations::HasOneAssociation.new(self, association, :target => target, :options => options))
         | 
| 43 43 | 
             
                      end
         | 
| 44 44 | 
             
                    end
         | 
| 45 45 |  | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            module Morpheus
         | 
| 2 | 
            +
              module Client
         | 
| 3 | 
            +
                class CachedRequestFormatter < RequestFormatter
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                  def call
         | 
| 6 | 
            +
                    "#{request_statement} #{payload}"
         | 
| 7 | 
            +
                  end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  def request_statement
         | 
| 10 | 
            +
                    statement = "CACHE (#{duration}ms)"
         | 
| 11 | 
            +
                    color(statement, request_color, true)
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  def duration
         | 
| 15 | 
            +
                    event.duration
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
            end
         | 
| @@ -12,37 +12,11 @@ module Morpheus | |
| 12 12 | 
             
                  end
         | 
| 13 13 |  | 
| 14 14 | 
             
                  def uncached_request(event)
         | 
| 15 | 
            -
                     | 
| 16 | 
            -
                    request_statement = "#{event.payload[:class].to_s} #{event.payload[:method].to_s.upcase} (#{duration}ms)"
         | 
| 17 | 
            -
                    if odd?
         | 
| 18 | 
            -
                      request_statement = color(request_statement, MAGENTA, true)
         | 
| 19 | 
            -
                      payload           = color(payload(event), nil, true)
         | 
| 20 | 
            -
                    else
         | 
| 21 | 
            -
                      request_statement = color(request_statement, CYAN, true)
         | 
| 22 | 
            -
                      payload           = payload(event)
         | 
| 23 | 
            -
                    end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                    response_color = case event.payload[:response].code
         | 
| 26 | 
            -
                    when 200..299 then GREEN
         | 
| 27 | 
            -
                    when 400..599 then RED
         | 
| 28 | 
            -
                    else               YELLOW
         | 
| 29 | 
            -
                    end
         | 
| 30 | 
            -
                    response_statement = color("[#{event.payload[:response].code}]", response_color, true)
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                    "#{request_statement} #{response_statement} #{payload}"
         | 
| 15 | 
            +
                    UncachedRequestFormatter.call(self, event, odd?)
         | 
| 33 16 | 
             
                  end
         | 
| 34 17 |  | 
| 35 18 | 
             
                  def cached_request(event)
         | 
| 36 | 
            -
                     | 
| 37 | 
            -
                    request_statement = "CACHE (#{duration}ms)"
         | 
| 38 | 
            -
                    if odd?
         | 
| 39 | 
            -
                      request_statement = color(request_statement, MAGENTA, true)
         | 
| 40 | 
            -
                      payload           = color(payload(event), nil, true)
         | 
| 41 | 
            -
                    else
         | 
| 42 | 
            -
                      request_statement = color(request_statement, CYAN, true)
         | 
| 43 | 
            -
                      payload           = payload(event)
         | 
| 44 | 
            -
                    end
         | 
| 45 | 
            -
                    "#{request_statement} #{payload}"
         | 
| 19 | 
            +
                    CachedRequestFormatter.call(self, event, odd?)
         | 
| 46 20 | 
             
                  end
         | 
| 47 21 |  | 
| 48 22 | 
             
                  def payload(event)
         | 
| @@ -4,19 +4,19 @@ module Morpheus | |
| 4 4 |  | 
| 5 5 | 
             
                  if defined?(ActiveRecord)
         | 
| 6 6 | 
             
                    ActiveRecord::Base.send(:include, Morpheus::Client::Associations)
         | 
| 7 | 
            -
                    ActiveRecord::Base.send(:include, Morpheus::UrlSupport)
         | 
| 7 | 
            +
                    ActiveRecord::Base.send(:include, Morpheus::Mixins::UrlSupport)
         | 
| 8 8 | 
             
                  end
         | 
| 9 9 |  | 
| 10 | 
            -
                  initializer  | 
| 10 | 
            +
                  initializer 'morpheus.client.configure_request_cache' do |app|
         | 
| 11 11 | 
             
                    app.middleware.use Morpheus::RequestQueue
         | 
| 12 12 | 
             
                    app.middleware.use Morpheus::RequestCache
         | 
| 13 13 | 
             
                  end
         | 
| 14 14 |  | 
| 15 | 
            -
                  initializer  | 
| 15 | 
            +
                  initializer 'morpheus.configure_logger', :after => :initialize_logger do |app|
         | 
| 16 16 | 
             
                    Morpheus::Configuration.logger = Rails.logger
         | 
| 17 17 | 
             
                  end
         | 
| 18 18 |  | 
| 19 | 
            -
                  initializer  | 
| 19 | 
            +
                  initializer 'morpheus.client.log_subscriber', :after => 'morpheus.configure_logger' do
         | 
| 20 20 | 
             
                    Morpheus::Client::LogSubscriber.attach_to :morpheus
         | 
| 21 21 | 
             
                  end
         | 
| 22 22 |  | 
| @@ -0,0 +1,50 @@ | |
| 1 | 
            +
            module Morpheus
         | 
| 2 | 
            +
              module Client
         | 
| 3 | 
            +
                class RequestFormatter
         | 
| 4 | 
            +
                  MAGENTA = ActiveSupport::LogSubscriber::MAGENTA
         | 
| 5 | 
            +
                  CYAN    = ActiveSupport::LogSubscriber::CYAN
         | 
| 6 | 
            +
                  GREEN   = ActiveSupport::LogSubscriber::GREEN
         | 
| 7 | 
            +
                  RED     = ActiveSupport::LogSubscriber::RED
         | 
| 8 | 
            +
                  YELLOW  = ActiveSupport::LogSubscriber::YELLOW
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  attr_reader :subscriber, :event
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def self.call(subscriber, event, odd)
         | 
| 13 | 
            +
                    new(subscriber, event, odd).call
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def initialize(subscriber, event, odd)
         | 
| 17 | 
            +
                    @subscriber = subscriber
         | 
| 18 | 
            +
                    @event      = event
         | 
| 19 | 
            +
                    @odd        = odd
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  def odd?
         | 
| 23 | 
            +
                    @odd
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def payload
         | 
| 27 | 
            +
                    if odd?
         | 
| 28 | 
            +
                      color(formatted_payload, nil, true)
         | 
| 29 | 
            +
                    else
         | 
| 30 | 
            +
                      formatted_payload
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  def color(*args)
         | 
| 35 | 
            +
                    subscriber.send(:color, *args)
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  def formatted_payload
         | 
| 39 | 
            +
                    payload  = "#{event.payload[:url]}"
         | 
| 40 | 
            +
                    payload << " #{event.payload[:params].inspect}" unless event.payload[:params].blank?
         | 
| 41 | 
            +
                    payload
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  def request_color
         | 
| 45 | 
            +
                    odd? ? MAGENTA : CYAN
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
            end
         | 
| @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            module Morpheus
         | 
| 2 | 
            +
              module Client
         | 
| 3 | 
            +
                class UncachedRequestFormatter < RequestFormatter
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                  def call
         | 
| 6 | 
            +
                    "#{request_statement} #{response_statement} #{payload}"
         | 
| 7 | 
            +
                  end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  def request_statement
         | 
| 10 | 
            +
                    klass     = event.payload[:class]
         | 
| 11 | 
            +
                    method    = event.payload[:method].to_s.upcase
         | 
| 12 | 
            +
                    statement = "#{klass} #{method} (#{duration})"
         | 
| 13 | 
            +
                    color(statement, request_color, true)
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def response_statement
         | 
| 17 | 
            +
                    statement = "[#{response.code}]"
         | 
| 18 | 
            +
                    color(statement, response_color, true)
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def response
         | 
| 22 | 
            +
                    event.payload[:response]
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  def duration
         | 
| 26 | 
            +
                    value = response.time * 1000
         | 
| 27 | 
            +
                    "#{value}ms"
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  def response_color
         | 
| 31 | 
            +
                    case response.code
         | 
| 32 | 
            +
                    when 200..299 then GREEN
         | 
| 33 | 
            +
                    when 400..599 then RED
         | 
| 34 | 
            +
                    else               YELLOW
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
            end
         | 
| @@ -2,33 +2,54 @@ module Morpheus | |
| 2 2 | 
             
              module Configuration
         | 
| 3 3 | 
             
                extend self
         | 
| 4 4 |  | 
| 5 | 
            -
                 | 
| 5 | 
            +
                def attributes
         | 
| 6 | 
            +
                  @attributes ||= {}
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def username=(username)
         | 
| 10 | 
            +
                  attributes[:username] = username
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def username
         | 
| 14 | 
            +
                  attributes[:username]
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def password=(password)
         | 
| 18 | 
            +
                  attributes[:password] = password
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def password
         | 
| 22 | 
            +
                  attributes[:password]
         | 
| 23 | 
            +
                end
         | 
| 6 24 |  | 
| 7 25 | 
             
                # Sets and gets the remote host service domain.
         | 
| 8 26 | 
             
                # The domain must be set before any requests can be made.
         | 
| 9 | 
            -
                 | 
| 27 | 
            +
                def host=(host)
         | 
| 28 | 
            +
                  attributes[:host] = host
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 10 31 | 
             
                def host
         | 
| 11 | 
            -
                   | 
| 32 | 
            +
                  attributes[:host] || raise(Morpheus::ConfigurationError,
         | 
| 12 33 | 
             
                    'The request HOST has not been set. Please set the host using Morpheus::Configuration.host = "http://www.example.com"')
         | 
| 13 34 | 
             
                end
         | 
| 14 35 |  | 
| 15 36 | 
             
                # Links to the underlying libcurl request pool.
         | 
| 16 37 | 
             
                # Allows for concurrent requests.
         | 
| 17 38 | 
             
                def hydra
         | 
| 18 | 
            -
                  Typhoeus::Hydra.hydra
         | 
| 39 | 
            +
                  attributes[:hydra] ||= Typhoeus::Hydra.hydra
         | 
| 19 40 | 
             
                end
         | 
| 20 41 |  | 
| 21 42 | 
             
                def hydra=(hydra)
         | 
| 22 | 
            -
                  Typhoeus::Hydra.hydra = hydra
         | 
| 43 | 
            +
                  attributes[:hydra] = Typhoeus::Hydra.hydra = hydra
         | 
| 23 44 | 
             
                end
         | 
| 24 45 |  | 
| 25 46 | 
             
                # Handles the default logger that is used by the LogSubscriber
         | 
| 26 47 | 
             
                def logger
         | 
| 27 | 
            -
                   | 
| 48 | 
            +
                  attributes[:logger] ||= ::Logger.new(STDOUT)
         | 
| 28 49 | 
             
                end
         | 
| 29 50 |  | 
| 30 51 | 
             
                def logger=(logger)
         | 
| 31 | 
            -
                   | 
| 52 | 
            +
                  attributes[:logger] = logger
         | 
| 32 53 | 
             
                end
         | 
| 33 54 |  | 
| 34 55 | 
             
                # Can be set or unset to allow for test suite mocking.
         | 
| @@ -44,11 +65,11 @@ module Morpheus | |
| 44 65 | 
             
                end
         | 
| 45 66 |  | 
| 46 67 | 
             
                def parse_error_handler
         | 
| 47 | 
            -
                   | 
| 68 | 
            +
                  attributes[:parse_error_handler]
         | 
| 48 69 | 
             
                end
         | 
| 49 70 |  | 
| 50 71 | 
             
                def parse_error_handler=(handler)
         | 
| 51 | 
            -
                   | 
| 72 | 
            +
                  attributes[:parse_error_handler] = handler
         | 
| 52 73 | 
             
                end
         | 
| 53 74 |  | 
| 54 75 | 
             
              end
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            # Mixins provide behaviors to support the Base class.
         | 
| 2 | 
            +
            module Morpheus
         | 
| 3 | 
            +
              module Mixins
         | 
| 4 | 
            +
                autoload :Associations,    'morpheus/mixins/associations'
         | 
| 5 | 
            +
                autoload :Attributes,      'morpheus/mixins/attributes'
         | 
| 6 | 
            +
                autoload :Conversion,      'morpheus/mixins/conversion'
         | 
| 7 | 
            +
                autoload :Filtering,       'morpheus/mixins/filtering'
         | 
| 8 | 
            +
                autoload :Finders,         'morpheus/mixins/finders'
         | 
| 9 | 
            +
                autoload :Introspection,   'morpheus/mixins/introspection'
         | 
| 10 | 
            +
                autoload :Persistence,     'morpheus/mixins/persistence'
         | 
| 11 | 
            +
                autoload :Reflections,     'morpheus/mixins/reflections'
         | 
| 12 | 
            +
                autoload :RequestHandling, 'morpheus/mixins/request_handling'
         | 
| 13 | 
            +
                autoload :ResponseParsing, 'morpheus/mixins/response_parsing'
         | 
| 14 | 
            +
                autoload :UrlSupport,      'morpheus/mixins/url_support'
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            end
         | 
| @@ -1,57 +1,59 @@ | |
| 1 1 | 
             
            module Morpheus
         | 
| 2 | 
            -
              module  | 
| 3 | 
            -
                 | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
                   | 
| 10 | 
            -
             | 
| 2 | 
            +
              module Mixins
         | 
| 3 | 
            +
                module Associations
         | 
| 4 | 
            +
                  autoload :Association,          'morpheus/mixins/associations/association'
         | 
| 5 | 
            +
                  autoload :BelongsToAssociation, 'morpheus/mixins/associations/belongs_to_association'
         | 
| 6 | 
            +
                  autoload :HasManyAssociation,   'morpheus/mixins/associations/has_many_association'
         | 
| 7 | 
            +
                  autoload :HasOneAssociation,    'morpheus/mixins/associations/has_one_association'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  def self.included(base)
         | 
| 10 | 
            +
                    base.extend(ClassMethods)
         | 
| 11 | 
            +
                  end
         | 
| 11 12 |  | 
| 12 | 
            -
             | 
| 13 | 
            +
                  module ClassMethods
         | 
| 13 14 |  | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 15 | 
            +
                    def belongs_to(association, options = {})
         | 
| 16 | 
            +
                      attribute_id_sym  = "#{association}_id".to_sym
         | 
| 16 17 |  | 
| 17 | 
            -
             | 
| 18 | 
            +
                      property attribute_id_sym
         | 
| 18 19 |  | 
| 19 | 
            -
             | 
| 20 | 
            +
                      create_reflection(:belongs_to, association, options)
         | 
| 20 21 |  | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 22 | 
            +
                      define_method association do
         | 
| 23 | 
            +
                        instance_variable_get("@#{association}") ||
         | 
| 24 | 
            +
                          instance_variable_set("@#{association}", BelongsToAssociation.new(self, association, :options => options))
         | 
| 25 | 
            +
                      end
         | 
| 25 26 |  | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 27 | 
            +
                      define_method "#{association}=" do |target|
         | 
| 28 | 
            +
                        instance_variable_set("@#{association}", BelongsToAssociation.new(self, association, :target => target, :options => options))
         | 
| 29 | 
            +
                        send("#{association}_id=", target.id)
         | 
| 30 | 
            +
                      end
         | 
| 29 31 | 
             
                    end
         | 
| 30 | 
            -
                  end
         | 
| 31 32 |  | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 33 | 
            +
                    def has_many(association, options = {})
         | 
| 34 | 
            +
                      create_reflection(:has_many, association, options)
         | 
| 34 35 |  | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 36 | 
            +
                      define_method association do
         | 
| 37 | 
            +
                        instance_variable_get("@#{association}") ||
         | 
| 38 | 
            +
                          instance_variable_set("@#{association}", HasManyAssociation.new(self, association, :options => options))
         | 
| 39 | 
            +
                      end
         | 
| 38 40 | 
             
                    end
         | 
| 39 | 
            -
                  end
         | 
| 40 41 |  | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 42 | 
            +
                    def has_one(association, options = {})
         | 
| 43 | 
            +
                      create_reflection(:has_one, association, options)
         | 
| 43 44 |  | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 45 | 
            +
                      define_method association do
         | 
| 46 | 
            +
                        instance_variable_get("@#{association}") ||
         | 
| 47 | 
            +
                          instance_variable_set("@#{association}", HasOneAssociation.new(self, association, :options => options))
         | 
| 48 | 
            +
                      end
         | 
| 48 49 |  | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 50 | 
            +
                      define_method "#{association}=" do |target|
         | 
| 51 | 
            +
                        instance_variable_set("@#{association}", HasOneAssociation.new(self, association, :target => target, :options => options))
         | 
| 52 | 
            +
                      end
         | 
| 51 53 | 
             
                    end
         | 
| 54 | 
            +
             | 
| 52 55 | 
             
                  end
         | 
| 53 56 |  | 
| 54 57 | 
             
                end
         | 
| 55 | 
            -
             | 
| 56 58 | 
             
              end
         | 
| 57 59 | 
             
            end
         |