morpheus 0.3.6 → 0.3.7

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.
Files changed (71) hide show
  1. data/.autotest +12 -0
  2. data/.rspec +1 -0
  3. data/README.md +77 -0
  4. data/Rakefile +16 -0
  5. data/lib/morpheus.rb +2 -2
  6. data/lib/morpheus/base.rb +1 -1
  7. data/lib/morpheus/client/inflections.rb +1 -1
  8. data/lib/morpheus/configuration.rb +41 -43
  9. data/lib/morpheus/errors.rb +1 -1
  10. data/lib/morpheus/mixins/associations.rb +3 -1
  11. data/lib/morpheus/mixins/attributes.rb +66 -67
  12. data/lib/morpheus/mixins/conversion.rb +9 -13
  13. data/lib/morpheus/mixins/filtering.rb +4 -1
  14. data/lib/morpheus/mixins/finders.rb +4 -1
  15. data/lib/morpheus/mixins/introspection.rb +12 -16
  16. data/lib/morpheus/mixins/persistence.rb +25 -26
  17. data/lib/morpheus/mixins/reflections.rb +4 -1
  18. data/lib/morpheus/mixins/request_handling.rb +4 -1
  19. data/lib/morpheus/mixins/response_parsing.rb +12 -12
  20. data/lib/morpheus/mixins/url_support.rb +4 -1
  21. data/lib/morpheus/request.rb +34 -34
  22. data/lib/morpheus/response.rb +2 -2
  23. data/lib/morpheus/response_parser.rb +9 -4
  24. data/lib/morpheus/version.rb +1 -1
  25. data/morpheus.gemspec +4 -4
  26. data/spec/dummy/app/resources/author.rb +0 -1
  27. data/spec/dummy/app/resources/book.rb +0 -1
  28. data/spec/dummy/app/resources/dog.rb +3 -3
  29. data/spec/dummy/app/resources/meeting.rb +1 -2
  30. data/spec/dummy/config/application.rb +7 -36
  31. data/spec/dummy/config/environments/production.rb +1 -1
  32. data/spec/dummy/config/initializers/morpheus.rb +1 -1
  33. data/spec/dummy/config/locales/en.yml +1 -1
  34. data/spec/dummy/config/routes.rb +0 -56
  35. data/spec/morpheus/associations/association_spec.rb +51 -33
  36. data/spec/morpheus/associations/belongs_to_association_spec.rb +14 -2
  37. data/spec/morpheus/associations/has_many_association_spec.rb +31 -11
  38. data/spec/morpheus/associations/has_one_association_spec.rb +14 -2
  39. data/spec/morpheus/base_spec.rb +104 -100
  40. data/spec/morpheus/client/associations_spec.rb +43 -36
  41. data/spec/morpheus/client/log_subscriber_spec.rb +33 -0
  42. data/spec/morpheus/client/railtie_spec.rb +5 -0
  43. data/spec/morpheus/configuration_spec.rb +92 -113
  44. data/spec/morpheus/mixins/associations_spec.rb +90 -108
  45. data/spec/morpheus/mixins/attributes_spec.rb +71 -77
  46. data/spec/morpheus/mixins/conversion_spec.rb +49 -59
  47. data/spec/morpheus/mixins/filtering_spec.rb +13 -0
  48. data/spec/morpheus/mixins/finders_spec.rb +180 -217
  49. data/spec/morpheus/mixins/introspection_spec.rb +81 -124
  50. data/spec/morpheus/mixins/persistence_spec.rb +140 -133
  51. data/spec/morpheus/mixins/{reflection_spec.rb → reflections_spec.rb} +28 -28
  52. data/spec/morpheus/mixins/request_handling_spec.rb +21 -0
  53. data/spec/morpheus/mixins/response_parsing_spec.rb +10 -2
  54. data/spec/morpheus/mixins/url_support_spec.rb +29 -0
  55. data/spec/morpheus/reflection_spec.rb +21 -0
  56. data/spec/morpheus/relation_spec.rb +34 -58
  57. data/spec/morpheus/request_cache_spec.rb +33 -2
  58. data/spec/morpheus/request_queue_spec.rb +37 -0
  59. data/spec/morpheus/request_spec.rb +102 -1
  60. data/spec/morpheus/response_parser_spec.rb +17 -0
  61. data/spec/morpheus/response_spec.rb +55 -51
  62. data/spec/morpheus/type_caster_spec.rb +128 -118
  63. data/spec/morpheus/url_builder_spec.rb +41 -0
  64. data/spec/shared/active_model_lint_test.rb +2 -2
  65. data/spec/spec_helper.rb +7 -14
  66. data/spec/support/configuration.rb +3 -4
  67. metadata +32 -16
  68. data/README.rdoc +0 -44
  69. data/autotest/discover.rb +0 -7
  70. data/lib/morpheus/mock.rb +0 -66
  71. data/spec/morpheus/mock_spec.rb +0 -133
@@ -1,6 +1,9 @@
1
1
  module Morpheus
2
2
  module Filtering
3
- extend ActiveSupport::Concern
3
+
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
4
7
 
5
8
  module ClassMethods
6
9
 
@@ -1,6 +1,9 @@
1
1
  module Morpheus
2
2
  module Finders
3
- extend ActiveSupport::Concern
3
+
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
4
7
 
5
8
  module ClassMethods
6
9
 
@@ -1,25 +1,21 @@
1
1
  module Morpheus
2
2
  module Introspection
3
- extend ActiveSupport::Concern
4
3
 
5
- module InstanceMethods
6
-
7
- def persisted?
8
- !id.nil?
9
- end
10
-
11
- def new_record?
12
- !persisted?
13
- end
4
+ def persisted?
5
+ !id.nil?
6
+ end
14
7
 
15
- def destroyed?
16
- false
17
- end
8
+ def new_record?
9
+ !persisted?
10
+ end
18
11
 
19
- def respond_to?(method, include_private = false)
20
- attributes.include?(method) ? true : super
21
- end
12
+ def destroyed?
13
+ false
14
+ end
22
15
 
16
+ def respond_to?(method, include_private = false)
17
+ attributes.include?(method) ? true : super
23
18
  end
19
+
24
20
  end
25
21
  end
@@ -1,36 +1,35 @@
1
1
  module Morpheus
2
2
  module Persistence
3
- extend ActiveSupport::Concern
4
-
5
- module InstanceMethods
6
-
7
- def save(with_validations = true)
8
- attributes_for_save = { self.class.attributes_root => attributes_without_basic_attributes.reject { |k,v| v.nil? } }
9
-
10
- if with_validations
11
- return false unless valid?
12
- end
13
-
14
- if new_record?
15
- built_object = self.class.post(*UrlBuilder.save(self.class, nil, attributes_for_save))
16
- else
17
- built_object = self.class.put(*UrlBuilder.save(self.class, id, attributes_for_save))
18
- end
19
- built_object.instance_variables.each do |iv|
20
- self.instance_variable_set(iv, built_object.instance_variable_get(iv))
21
- end
22
- @valid
23
- end
24
3
 
25
- def update_attributes(new_attributes)
26
- merge_attributes(new_attributes)
27
- save
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ def save(with_validations = true)
9
+ attributes_for_save = { self.class.attributes_root => attributes_without_basic_attributes.reject { |k,v| v.nil? } }
10
+
11
+ if with_validations
12
+ return false unless valid?
28
13
  end
29
14
 
30
- def destroy
31
- self.class.delete(UrlBuilder.destroy(self.class, id))
15
+ if new_record?
16
+ built_object = self.class.post(*UrlBuilder.save(self.class, nil, attributes_for_save))
17
+ else
18
+ built_object = self.class.put(*UrlBuilder.save(self.class, id, attributes_for_save))
32
19
  end
20
+ built_object.instance_variables.each do |iv|
21
+ self.instance_variable_set(iv, built_object.instance_variable_get(iv))
22
+ end
23
+ @valid
24
+ end
25
+
26
+ def update_attributes(new_attributes)
27
+ merge_attributes(new_attributes)
28
+ save
29
+ end
33
30
 
31
+ def destroy
32
+ self.class.delete(UrlBuilder.destroy(self.class, id))
34
33
  end
35
34
 
36
35
  module ClassMethods
@@ -1,6 +1,9 @@
1
1
  module Morpheus
2
2
  module Reflections
3
- extend ActiveSupport::Concern
3
+
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
4
7
 
5
8
  module ClassMethods
6
9
 
@@ -1,6 +1,9 @@
1
1
  module Morpheus
2
2
  module RequestHandling
3
- extend ActiveSupport::Concern
3
+
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
4
7
 
5
8
  module ClassMethods
6
9
 
@@ -1,6 +1,9 @@
1
1
  module Morpheus
2
2
  module ResponseParsing
3
- extend ActiveSupport::Concern
3
+
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
4
7
 
5
8
  module ClassMethods
6
9
 
@@ -10,18 +13,15 @@ module Morpheus
10
13
 
11
14
  end
12
15
 
13
- module InstanceMethods
14
-
15
- def build_from_response(response)
16
- content = Yajl::Parser.parse(response.body)['content']
17
- if content.keys.include?('type')
18
- content['type'].constantize.new.merge_attributes(content)
19
- else
20
- merge_attributes(content)
21
- end
16
+ def build_from_response(response)
17
+ content = Yajl::Parser.parse(response.body)['content']
18
+ if content.keys.include?('type')
19
+ content['type'].constantize.new.merge_attributes(content)
20
+ else
21
+ merge_attributes(content)
22
22
  end
23
- private :build_from_response
24
-
25
23
  end
24
+ private :build_from_response
25
+
26
26
  end
27
27
  end
@@ -1,6 +1,9 @@
1
1
  module Morpheus
2
2
  module UrlSupport
3
- extend ActiveSupport::Concern
3
+
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
4
7
 
5
8
  module ClassMethods
6
9
 
@@ -2,40 +2,40 @@ module Morpheus
2
2
  class Request < Typhoeus::Request
3
3
  attr_reader :path, :params, :method
4
4
 
5
- def initialize(path, options = {})
6
- if options[:method] == :put
7
- options[:method] = :post
8
- options[:params].merge!(:_method => :put)
9
- end
10
-
11
- options[:username] = Configuration.username if Configuration.username
12
- options[:password] = Configuration.password if Configuration.password
13
-
14
- super(Configuration.host + path, options)
15
- end
16
-
17
- def cache_key
18
- [method, url, params].hash
19
- end
20
-
21
- def response=(response)
22
- RequestCache.cache[cache_key] = response
23
- response.tag_for_caching!
24
- super
25
- end
26
-
27
- def response
28
- RequestQueue.run! if RequestQueue.has_request?(self)
29
- RequestCache.cache[cache_key] || super
30
- end
31
-
32
- def self.enqueue(method, path, params)
33
- options = { :method => method }
34
- options.merge!(:params => params) if params
35
- new(path, options).tap do |request|
36
- RequestQueue.enqueue(request)
37
- end
38
- end
5
+ def initialize(path, options = {})
6
+ if options[:method] == :put
7
+ options[:method] = :post
8
+ options[:params].merge!(:_method => :put)
9
+ end
10
+
11
+ options[:username] = Configuration.username if Configuration.username
12
+ options[:password] = Configuration.password if Configuration.password
13
+
14
+ super(Configuration.host + path, options)
15
+ end
16
+
17
+ def cache_key
18
+ [method, url, params].hash
19
+ end
20
+
21
+ def response=(response)
22
+ RequestCache.cache[cache_key] = response
23
+ response.tag_for_caching!
24
+ super
25
+ end
26
+
27
+ def response
28
+ RequestQueue.run! if RequestQueue.has_request?(self)
29
+ RequestCache.cache[cache_key]|| super
30
+ end
31
+
32
+ def self.enqueue(method, path, params)
33
+ options = { :method => method }
34
+ options.merge!(:params => params) unless params.blank?
35
+ new(path, options).tap do |request|
36
+ RequestQueue.enqueue(request)
37
+ end
38
+ end
39
39
 
40
40
  end
41
41
  end
@@ -11,11 +11,11 @@ module Morpheus
11
11
  @cached = tagged_for_caching?
12
12
  end
13
13
  end
14
-
14
+
15
15
  def tag_for_caching!
16
16
  @tagged_for_caching = true
17
17
  end
18
-
18
+
19
19
  def tagged_for_caching?
20
20
  @tagged_for_caching ||= false
21
21
  end
@@ -10,8 +10,13 @@ module Morpheus
10
10
 
11
11
  def self.parse(owner, request, metadata)
12
12
  parser = new(owner, request, metadata)
13
-
14
- ActiveSupport::Notifications.instrument('request.morpheus', :url => request.url, :params => request.params, :method => request.method, :class => owner, :response => request.response) do
13
+ ActiveSupport::Notifications.instrument('request.morpheus',
14
+ :url => request.url,
15
+ :params => request.params,
16
+ :method => request.method,
17
+ :class => owner,
18
+ :response => request.response
19
+ ) do
15
20
  @parsed_response = parser.parse
16
21
  end
17
22
  RequestCache.cache.clear unless request.method == :get
@@ -40,7 +45,7 @@ module Morpheus
40
45
  def content
41
46
  @content ||= Yajl::Parser.parse(@response.body).try(:[], 'content')
42
47
  end
43
-
48
+
44
49
  def response_errors
45
50
  @response_errors ||= Yajl::Parser.parse(@response.body).try(:[], 'errors')
46
51
  end
@@ -56,7 +61,7 @@ module Morpheus
56
61
  end
57
62
  end
58
63
  end
59
-
64
+
60
65
  def build_object_with_attributes(attributes)
61
66
  if attributes.keys.include?('type')
62
67
  attributes['type'].constantize.new(attributes)
@@ -1,3 +1,3 @@
1
1
  module Morpheus
2
- VERSION = '0.3.6'
2
+ VERSION = '0.3.7'
3
3
  end
data/morpheus.gemspec CHANGED
@@ -17,11 +17,11 @@ Gem::Specification.new do |gem|
17
17
 
18
18
  gem.add_dependency 'yajl-ruby', '~> 0.8.2'
19
19
  gem.add_dependency 'typhoeus', '~> 0.2.4'
20
- gem.add_dependency 'activemodel', '~> 3.0.0'
21
- gem.add_dependency 'activesupport', '~> 3.0.0'
22
- gem.add_dependency 'i18n', '~> 0.5.0'
20
+ gem.add_dependency 'activemodel', '> 3.0.0'
21
+ gem.add_dependency 'activesupport', '> 3.0.0'
22
+ gem.add_dependency 'i18n', '> 0.5.0'
23
23
 
24
- gem.add_development_dependency 'rails', '~> 3.0.0'
24
+ gem.add_development_dependency 'rails', '> 3.0.0'
25
25
  gem.add_development_dependency 'sqlite3', '~> 1.3.3'
26
26
  gem.add_development_dependency 'rspec-rails', '~> 2.7.0'
27
27
  gem.add_development_dependency 'rcov', '~> 0.9.11'
@@ -1,5 +1,4 @@
1
1
  class Author < Morpheus::Base
2
2
  property :name
3
-
4
3
  has_many :books
5
4
  end
@@ -1,5 +1,4 @@
1
1
  class Book < Morpheus::Base
2
2
  property :title
3
-
4
3
  belongs_to :author
5
4
  end
@@ -1,10 +1,10 @@
1
1
  class Dog < Morpheus::Base
2
2
  property :name
3
3
  property :breed
4
-
5
4
  validates_presence_of :name
6
-
5
+
7
6
  def bark!
8
- "Bow-wow-wow"
7
+ 'Bow-wow-wow'
9
8
  end
9
+
10
10
  end
@@ -1,6 +1,5 @@
1
1
  class Meeting < Morpheus::Base
2
- property :title
3
-
2
+ property :title
4
3
  belongs_to :conference
5
4
  has_many :attendees
6
5
  has_one :speaker
@@ -1,45 +1,16 @@
1
1
  require File.expand_path('../boot', __FILE__)
2
2
 
3
- require "active_model/railtie"
4
- require "active_record/railtie"
5
- require "action_controller/railtie"
6
- require "action_view/railtie"
7
- require "action_mailer/railtie"
3
+ require 'active_model/railtie'
4
+ require 'active_record/railtie'
5
+ require 'action_controller/railtie'
6
+ require 'action_view/railtie'
7
+ require 'action_mailer/railtie'
8
8
 
9
9
  Bundler.require
10
- require "morpheus"
10
+ require 'morpheus'
11
11
 
12
12
  module Dummy
13
13
  class Application < Rails::Application
14
- # Settings in config/environments/* take precedence over those specified here.
15
- # Application configuration should go into files in config/initializers
16
- # -- all .rb files in that directory are automatically loaded.
17
-
18
- # Custom directories with classes and modules you want to be autoloadable.
19
- config.autoload_paths += %W(#{config.root}/resources)
20
-
21
- # Only load the plugins named here, in the order given (default is alphabetical).
22
- # :all can be used as a placeholder for all plugins not explicitly named.
23
- # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
24
-
25
- # Activate observers that should always be running.
26
- # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
27
-
28
- # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
29
- # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
30
- # config.time_zone = 'Central Time (US & Canada)'
31
-
32
- # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
33
- # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
34
- # config.i18n.default_locale = :de
35
-
36
- # JavaScript files you want as :defaults (application.js is always included).
37
- # config.action_view.javascript_expansions[:defaults] = %w(jquery rails)
38
-
39
- # Configure the default encoding used in templates for Ruby 1.9.
40
- config.encoding = "utf-8"
41
-
42
- # Configure sensitive parameters which will be filtered from the log file.
43
- config.filter_parameters += [:password]
14
+ config.encoding = 'utf-8'
44
15
  end
45
16
  end
@@ -10,7 +10,7 @@ Dummy::Application.configure do
10
10
  config.action_controller.perform_caching = true
11
11
 
12
12
  # Specifies the header that your server uses for sending files
13
- config.action_dispatch.x_sendfile_header = "X-Sendfile"
13
+ config.action_dispatch.x_sendfile_header = 'X-Sendfile'
14
14
 
15
15
  # For nginx:
16
16
  # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'