morpheus 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -1,22 +1,24 @@
|
|
1
1
|
module Morpheus
|
2
|
-
module
|
2
|
+
module Mixins
|
3
|
+
module Conversion
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
def to_model
|
6
|
+
self
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
def to_param
|
10
|
+
id.to_s unless new_record?
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
def to_key
|
14
|
+
attributes.keys if persisted?
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
2
|
+
module Mixins
|
3
|
+
module Filtering
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
+
module ClassMethods
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
2
|
+
module Mixins
|
3
|
+
module Finders
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
+
module ClassMethods
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
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
|
-
|
30
|
-
|
31
|
-
|
30
|
+
def scoped
|
31
|
+
Relation.new(self)
|
32
|
+
end
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
def all
|
35
|
+
attributes = [UrlBuilder.find_all(self), nil, {}]
|
36
|
+
get(*attributes)
|
37
|
+
end
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
def first
|
40
|
+
limit(1).first
|
41
|
+
end
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
|
43
|
+
def where(query_attributes)
|
44
|
+
Relation.new(self).where(query_attributes)
|
45
|
+
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
47
|
+
def limit(amount)
|
48
|
+
Relation.new(self).limit(amount)
|
49
|
+
end
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
51
|
+
def page(page_number)
|
52
|
+
Relation.new(self).page(page_number)
|
53
|
+
end
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
2
|
+
module Mixins
|
3
|
+
module Introspection
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
def persisted?
|
6
|
+
!id.nil?
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
def new_record?
|
10
|
+
!persisted?
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
def destroyed?
|
14
|
+
false
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
2
|
+
module Mixins
|
3
|
+
module Persistence
|
3
4
|
|
4
|
-
|
5
|
-
|
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
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
21
|
-
|
26
|
+
|
27
|
+
def update_attributes(new_attributes)
|
28
|
+
merge_attributes(new_attributes)
|
29
|
+
save
|
22
30
|
end
|
23
|
-
@valid
|
24
|
-
end
|
25
31
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
32
|
+
def destroy
|
33
|
+
self.class.delete(UrlBuilder.destroy(self.class, id))
|
34
|
+
end
|
30
35
|
|
31
|
-
|
32
|
-
self.class.delete(UrlBuilder.destroy(self.class, id))
|
33
|
-
end
|
36
|
+
module ClassMethods
|
34
37
|
|
35
|
-
|
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
|
2
|
+
module Mixins
|
3
|
+
module Reflections
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
+
module ClassMethods
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
17
|
-
|
18
|
-
|
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
|
2
|
+
module Mixins
|
3
|
+
module RequestHandling
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
+
module ClassMethods
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
2
|
+
module Mixins
|
3
|
+
module ResponseParsing
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
+
module ClassMethods
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
2
|
+
module Mixins
|
3
|
+
module UrlSupport
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
+
module ClassMethods
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
def url_name
|
12
|
+
@url_name ||= model_name.underscore
|
13
|
+
end
|
14
|
+
alias_method :singular_url_name, :url_name
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
def plural_url_name
|
17
|
+
url_name.pluralize
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
def set_base_url(url_name)
|
21
|
+
@url_name = url_name
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
def attributes_root
|
25
|
+
@attributes_root ||= model_name.underscore
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|