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.
Files changed (63) hide show
  1. data/.rspec +1 -1
  2. data/CHANGELOG.md +17 -0
  3. data/Gemfile +1 -1
  4. data/lib/morpheus.rb +3 -23
  5. data/lib/morpheus/base.rb +11 -11
  6. data/lib/morpheus/client.rb +10 -0
  7. data/lib/morpheus/client/associations.rb +6 -6
  8. data/lib/morpheus/client/cached_request_formatter.rb +20 -0
  9. data/lib/morpheus/client/log_subscriber.rb +2 -28
  10. data/lib/morpheus/client/railtie.rb +4 -4
  11. data/lib/morpheus/client/request_formatter.rb +50 -0
  12. data/lib/morpheus/client/uncached_request_formatter.rb +40 -0
  13. data/lib/morpheus/configuration.rb +30 -9
  14. data/lib/morpheus/mixins.rb +16 -0
  15. data/lib/morpheus/mixins/associations.rb +39 -37
  16. data/lib/morpheus/mixins/associations/association.rb +112 -0
  17. data/lib/morpheus/mixins/associations/belongs_to_association.rb +47 -0
  18. data/lib/morpheus/mixins/associations/has_many_association.rb +72 -0
  19. data/lib/morpheus/mixins/associations/has_one_association.rb +48 -0
  20. data/lib/morpheus/mixins/attributes.rb +97 -95
  21. data/lib/morpheus/mixins/conversion.rb +16 -14
  22. data/lib/morpheus/mixins/filtering.rb +13 -11
  23. data/lib/morpheus/mixins/finders.rb +47 -45
  24. data/lib/morpheus/mixins/introspection.rb +15 -13
  25. data/lib/morpheus/mixins/persistence.rb +32 -30
  26. data/lib/morpheus/mixins/reflections.rb +17 -15
  27. data/lib/morpheus/mixins/request_handling.rb +27 -25
  28. data/lib/morpheus/mixins/response_parsing.rb +10 -8
  29. data/lib/morpheus/mixins/url_support.rb +27 -25
  30. data/lib/morpheus/reflection.rb +5 -2
  31. data/lib/morpheus/type_caster.rb +1 -1
  32. data/lib/morpheus/version.rb +1 -1
  33. data/morpheus.gemspec +2 -2
  34. data/spec/dummy/app/resources/book.rb +1 -1
  35. data/spec/morpheus/base_spec.rb +35 -35
  36. data/spec/morpheus/client/cached_request_formatter_spec.rb +28 -0
  37. data/spec/morpheus/client/log_subscriber_spec.rb +53 -10
  38. data/spec/morpheus/client/request_formatter_spec.rb +5 -0
  39. data/spec/morpheus/client/uncached_request_formatter_spec.rb +29 -0
  40. data/spec/morpheus/configuration_spec.rb +49 -11
  41. data/spec/morpheus/{associations → mixins/associations}/association_spec.rb +1 -1
  42. data/spec/morpheus/{associations → mixins/associations}/belongs_to_association_spec.rb +1 -1
  43. data/spec/morpheus/{associations → mixins/associations}/has_many_association_spec.rb +1 -1
  44. data/spec/morpheus/{associations → mixins/associations}/has_one_association_spec.rb +1 -1
  45. data/spec/morpheus/mixins/associations_spec.rb +1 -1
  46. data/spec/morpheus/mixins/attributes_spec.rb +27 -6
  47. data/spec/morpheus/mixins/conversion_spec.rb +1 -1
  48. data/spec/morpheus/mixins/filtering_spec.rb +2 -2
  49. data/spec/morpheus/mixins/finders_spec.rb +1 -1
  50. data/spec/morpheus/mixins/introspection_spec.rb +1 -1
  51. data/spec/morpheus/mixins/persistence_spec.rb +1 -1
  52. data/spec/morpheus/mixins/reflections_spec.rb +1 -1
  53. data/spec/morpheus/mixins/request_handling_spec.rb +2 -2
  54. data/spec/morpheus/mixins/response_parsing_spec.rb +2 -2
  55. data/spec/morpheus/mixins/url_support_spec.rb +2 -2
  56. data/spec/morpheus/response_parser_spec.rb +5 -1
  57. data/spec/regressions/sorting_resources_spec.rb +119 -0
  58. data/spec/spec_helper.rb +3 -2
  59. metadata +159 -87
  60. data/lib/morpheus/associations/association.rb +0 -110
  61. data/lib/morpheus/associations/belongs_to_association.rb +0 -45
  62. data/lib/morpheus/associations/has_many_association.rb +0 -70
  63. data/lib/morpheus/associations/has_one_association.rb +0 -46
@@ -1,22 +1,24 @@
1
1
  module Morpheus
2
- module Conversion
2
+ module Mixins
3
+ module Conversion
3
4
 
4
- def to_model
5
- self
6
- end
5
+ def to_model
6
+ self
7
+ end
7
8
 
8
- def to_param
9
- id.to_s unless new_record?
10
- end
9
+ def to_param
10
+ id.to_s unless new_record?
11
+ end
11
12
 
12
- def to_key
13
- attributes.keys if persisted?
14
- end
13
+ def to_key
14
+ attributes.keys if persisted?
15
+ end
15
16
 
16
- def to_partial_path
17
- underscored_model_name = self.class.model_name.underscore
18
- "#{underscored_model_name.pluralize}/#{underscored_model_name}"
19
- end
17
+ def to_partial_path
18
+ underscored_model_name = self.class.model_name.underscore
19
+ "#{underscored_model_name.pluralize}/#{underscored_model_name}"
20
+ end
20
21
 
22
+ end
21
23
  end
22
24
  end
@@ -1,21 +1,23 @@
1
1
  module Morpheus
2
- module Filtering
2
+ module Mixins
3
+ module Filtering
3
4
 
4
- def self.included(base)
5
- base.extend(ClassMethods)
6
- end
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
7
8
 
8
- module ClassMethods
9
+ module ClassMethods
9
10
 
10
- def filter(name, &block)
11
- (@filters ||= []) << Filter.new(name, &block)
12
- end
11
+ def filter(name, &block)
12
+ (@filters ||= []) << Filter.new(name, &block)
13
+ end
14
+
15
+ def find_filter(name)
16
+ (@filters ||= []).find { |filter| filter.name == name }
17
+ end
13
18
 
14
- def find_filter(name)
15
- (@filters ||= []).find { |filter| filter.name == name }
16
19
  end
17
20
 
18
21
  end
19
-
20
22
  end
21
23
  end
@@ -1,65 +1,67 @@
1
1
  module Morpheus
2
- module Finders
2
+ module Mixins
3
+ module Finders
3
4
 
4
- def self.included(base)
5
- base.extend(ClassMethods)
6
- end
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
7
8
 
8
- module ClassMethods
9
+ module ClassMethods
9
10
 
10
- def find(*args)
11
- options = args.extract_options!
12
- if args.length == 1
13
- case args.first
14
- when Integer, String
15
- attributes = [UrlBuilder.find_one(self, args.first.to_i), nil, { :id => args.first.to_i }]
16
- get(*attributes)
17
- when Array
18
- attributes = UrlBuilder.find_some(self, args.first.sort).push({ :ids => args.first })
19
- get(*attributes)
11
+ def find(*args)
12
+ options = args.extract_options!
13
+ if args.length == 1
14
+ case args.first
15
+ when Integer, String
16
+ attributes = [UrlBuilder.find_one(self, args.first.to_i), nil, { :id => args.first.to_i }]
17
+ get(*attributes)
18
+ when Array
19
+ attributes = UrlBuilder.find_some(self, args.first.sort).push({ :ids => args.first })
20
+ get(*attributes)
21
+ else
22
+ raise ArgumentError, "Unrecognized argument (#{args.first.inspect})."
23
+ end
20
24
  else
21
- raise ArgumentError, "Unrecognized argument (#{args.first.inspect})."
25
+ attributes = UrlBuilder.find_some(self, args.sort).push({ :ids => args })
26
+ get(*attributes)
22
27
  end
23
- else
24
- attributes = UrlBuilder.find_some(self, args.sort).push({ :ids => args })
25
- get(*attributes)
26
28
  end
27
- end
28
29
 
29
- def scoped
30
- Relation.new(self)
31
- end
30
+ def scoped
31
+ Relation.new(self)
32
+ end
32
33
 
33
- def all
34
- attributes = [UrlBuilder.find_all(self), nil, {}]
35
- get(*attributes)
36
- end
34
+ def all
35
+ attributes = [UrlBuilder.find_all(self), nil, {}]
36
+ get(*attributes)
37
+ end
37
38
 
38
- def first
39
- limit(1).first
40
- end
39
+ def first
40
+ limit(1).first
41
+ end
41
42
 
42
- def where(query_attributes)
43
- Relation.new(self).where(query_attributes)
44
- end
43
+ def where(query_attributes)
44
+ Relation.new(self).where(query_attributes)
45
+ end
45
46
 
46
- def limit(amount)
47
- Relation.new(self).limit(amount)
48
- end
47
+ def limit(amount)
48
+ Relation.new(self).limit(amount)
49
+ end
49
50
 
50
- def page(page_number)
51
- Relation.new(self).page(page_number)
52
- end
51
+ def page(page_number)
52
+ Relation.new(self).page(page_number)
53
+ end
53
54
 
54
- def results_per_page
55
- @results_per_page || 10
56
- end
55
+ def results_per_page
56
+ @results_per_page || 10
57
+ end
58
+
59
+ def results_per_page=(_results_per_page)
60
+ @results_per_page = _results_per_page
61
+ end
57
62
 
58
- def results_per_page=(_results_per_page)
59
- @results_per_page = _results_per_page
60
63
  end
61
64
 
62
65
  end
63
-
64
66
  end
65
67
  end
@@ -1,21 +1,23 @@
1
1
  module Morpheus
2
- module Introspection
2
+ module Mixins
3
+ module Introspection
3
4
 
4
- def persisted?
5
- !id.nil?
6
- end
5
+ def persisted?
6
+ !id.nil?
7
+ end
7
8
 
8
- def new_record?
9
- !persisted?
10
- end
9
+ def new_record?
10
+ !persisted?
11
+ end
11
12
 
12
- def destroyed?
13
- false
14
- end
13
+ def destroyed?
14
+ false
15
+ end
15
16
 
16
- def respond_to?(method, include_private = false)
17
- attributes.include?(method) ? true : super
18
- end
17
+ def respond_to?(method, include_private = false)
18
+ attributes.include?(method) ? true : super
19
+ end
19
20
 
21
+ end
20
22
  end
21
23
  end
@@ -1,45 +1,47 @@
1
1
  module Morpheus
2
- module Persistence
2
+ module Mixins
3
+ module Persistence
3
4
 
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?
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
13
7
  end
14
8
 
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))
9
+ def save(with_validations = true)
10
+ attributes_for_save = { self.class.attributes_root => attributes_without_basic_attributes.reject { |k,v| v.nil? } }
11
+
12
+ if with_validations
13
+ return false unless valid?
14
+ end
15
+
16
+ if new_record?
17
+ built_object = self.class.post(*UrlBuilder.save(self.class, nil, attributes_for_save))
18
+ else
19
+ built_object = self.class.put(*UrlBuilder.save(self.class, id, attributes_for_save))
20
+ end
21
+ built_object.instance_variables.each do |iv|
22
+ self.instance_variable_set(iv, built_object.instance_variable_get(iv))
23
+ end
24
+ @valid
19
25
  end
20
- built_object.instance_variables.each do |iv|
21
- self.instance_variable_set(iv, built_object.instance_variable_get(iv))
26
+
27
+ def update_attributes(new_attributes)
28
+ merge_attributes(new_attributes)
29
+ save
22
30
  end
23
- @valid
24
- end
25
31
 
26
- def update_attributes(new_attributes)
27
- merge_attributes(new_attributes)
28
- save
29
- end
32
+ def destroy
33
+ self.class.delete(UrlBuilder.destroy(self.class, id))
34
+ end
30
35
 
31
- def destroy
32
- self.class.delete(UrlBuilder.destroy(self.class, id))
33
- end
36
+ module ClassMethods
34
37
 
35
- module ClassMethods
38
+ def create(new_attributes = {})
39
+ new(new_attributes).tap { |new_instance| new_instance.save }
40
+ end
41
+ alias :create! :create
36
42
 
37
- def create(new_attributes = {})
38
- new(new_attributes).tap { |new_instance| new_instance.save }
39
43
  end
40
- alias :create! :create
41
44
 
42
45
  end
43
-
44
46
  end
45
47
  end
@@ -1,27 +1,29 @@
1
1
  module Morpheus
2
- module Reflections
2
+ module Mixins
3
+ module Reflections
3
4
 
4
- def self.included(base)
5
- base.extend(ClassMethods)
6
- end
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
7
8
 
8
- module ClassMethods
9
+ module ClassMethods
9
10
 
10
- def create_reflection(macro, name, options)
11
- Reflection.new(macro, name, options).tap do |reflection|
12
- reflections.merge!(name => reflection)
11
+ def create_reflection(macro, name, options)
12
+ Reflection.new(macro, name, options).tap do |reflection|
13
+ reflections.merge!(name => reflection)
14
+ end
13
15
  end
14
- end
15
16
 
16
- def reflections
17
- @reflections ||= {}
18
- end
17
+ def reflections
18
+ @reflections ||= {}
19
+ end
20
+
21
+ def reflect_on_association(association)
22
+ reflections[association.to_sym].is_a?(Reflection) ? reflections[association.to_sym] : nil
23
+ end
19
24
 
20
- def reflect_on_association(association)
21
- reflections[association.to_sym].is_a?(Reflection) ? reflections[association.to_sym] : nil
22
25
  end
23
26
 
24
27
  end
25
-
26
28
  end
27
29
  end
@@ -1,37 +1,39 @@
1
1
  module Morpheus
2
- module RequestHandling
2
+ module Mixins
3
+ module RequestHandling
3
4
 
4
- def self.included(base)
5
- base.extend(ClassMethods)
6
- end
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
7
8
 
8
- module ClassMethods
9
+ module ClassMethods
9
10
 
10
- def get(path, params = nil, metadata = {}, &block)
11
- request = Request.enqueue(:get, path, params)
12
- request.on_complete = block if block_given?
13
- response_from_request(request, metadata)
14
- end
11
+ def get(path, params = nil, metadata = {}, &block)
12
+ request = Request.enqueue(:get, path, params)
13
+ request.on_complete = block if block_given?
14
+ response_from_request(request, metadata)
15
+ end
15
16
 
16
- def post(path, params = nil, metadata = {}, &block)
17
- request = Request.enqueue(:post, path, params)
18
- request.on_complete = block if block_given?
19
- response_from_request(request, metadata)
20
- end
17
+ def post(path, params = nil, metadata = {}, &block)
18
+ request = Request.enqueue(:post, path, params)
19
+ request.on_complete = block if block_given?
20
+ response_from_request(request, metadata)
21
+ end
21
22
 
22
- def put(path, params = nil, metadata = {}, &block)
23
- request = Request.enqueue(:put, path, params)
24
- request.on_complete = block if block_given?
25
- response_from_request(request, metadata)
26
- end
23
+ def put(path, params = nil, metadata = {}, &block)
24
+ request = Request.enqueue(:put, path, params)
25
+ request.on_complete = block if block_given?
26
+ response_from_request(request, metadata)
27
+ end
28
+
29
+ def delete(path, params = nil, metadata = {}, &block)
30
+ request = Request.enqueue(:delete, path, params)
31
+ request.on_complete = block if block_given?
32
+ response_from_request(request, metadata)
33
+ end
27
34
 
28
- def delete(path, params = nil, metadata = {}, &block)
29
- request = Request.enqueue(:delete, path, params)
30
- request.on_complete = block if block_given?
31
- response_from_request(request, metadata)
32
35
  end
33
36
 
34
37
  end
35
-
36
38
  end
37
39
  end
@@ -1,16 +1,18 @@
1
1
  module Morpheus
2
- module ResponseParsing
2
+ module Mixins
3
+ module ResponseParsing
3
4
 
4
- def self.included(base)
5
- base.extend(ClassMethods)
6
- end
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
7
8
 
8
- module ClassMethods
9
+ module ClassMethods
9
10
 
10
- def response_from_request(request, metadata)
11
- ResponseParser.parse(self, request, metadata)
12
- end
11
+ def response_from_request(request, metadata)
12
+ ResponseParser.parse(self, request, metadata)
13
+ end
13
14
 
15
+ end
14
16
  end
15
17
  end
16
18
  end
@@ -1,39 +1,41 @@
1
1
  module Morpheus
2
- module UrlSupport
2
+ module Mixins
3
+ module UrlSupport
3
4
 
4
- def self.included(base)
5
- base.extend(ClassMethods)
6
- end
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
7
8
 
8
- module ClassMethods
9
+ module ClassMethods
9
10
 
10
- def url_name
11
- @url_name ||= model_name.underscore
12
- end
13
- alias_method :singular_url_name, :url_name
11
+ def url_name
12
+ @url_name ||= model_name.underscore
13
+ end
14
+ alias_method :singular_url_name, :url_name
14
15
 
15
- def plural_url_name
16
- url_name.pluralize
17
- end
16
+ def plural_url_name
17
+ url_name.pluralize
18
+ end
18
19
 
19
- def set_base_url(url_name)
20
- @url_name = url_name
21
- end
20
+ def set_base_url(url_name)
21
+ @url_name = url_name
22
+ end
22
23
 
23
- def attributes_root
24
- @attributes_root ||= model_name.underscore
25
- end
24
+ def attributes_root
25
+ @attributes_root ||= model_name.underscore
26
+ end
26
27
 
27
- def set_attributes_root(name)
28
- @attributes_root = name
29
- end
28
+ def set_attributes_root(name)
29
+ @attributes_root = name
30
+ end
31
+
32
+ def set_base_model_name(name)
33
+ set_base_url(name)
34
+ set_attributes_root(name)
35
+ end
30
36
 
31
- def set_base_model_name(name)
32
- set_base_url(name)
33
- set_attributes_root(name)
34
37
  end
35
38
 
36
39
  end
37
-
38
40
  end
39
41
  end