restly 0.0.1.alpha.4 → 0.0.1.alpha.6
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/lib/restly/associations/base/builders.rb +27 -0
- data/lib/restly/associations/base/conditionals.rb +23 -0
- data/lib/restly/associations/base/loaders.rb +41 -0
- data/lib/restly/associations/base/modifiers.rb +24 -0
- data/lib/restly/associations/base/stubs.rb +21 -0
- data/lib/restly/associations/base.rb +13 -89
- data/lib/restly/associations/belongs_to.rb +2 -14
- data/lib/restly/associations/class_methods.rb +62 -0
- data/lib/restly/associations/has_one.rb +0 -4
- data/lib/restly/associations.rb +26 -83
- data/lib/restly/base/fields.rb +4 -0
- data/lib/restly/base/generic_methods.rb +1 -1
- data/lib/restly/base/instance/actions.rb +8 -5
- data/lib/restly/base/instance/attributes.rb +47 -14
- data/lib/restly/base/instance/persistence.rb +12 -1
- data/lib/restly/base/instance/write_callbacks.rb +9 -1
- data/lib/restly/base/instance.rb +28 -21
- data/lib/restly/base/resource/batch_actions.rb +15 -0
- data/lib/restly/base/resource/finders.rb +1 -1
- data/lib/restly/base/resource.rb +9 -0
- data/lib/restly/base.rb +9 -5
- data/lib/restly/collection.rb +46 -13
- data/lib/restly/configuration.rb +6 -4
- data/lib/restly/controller_methods.rb +5 -10
- data/lib/restly/embedded_associations/base.rb +7 -0
- data/lib/restly/{associations/embeddable_resources.rb → embedded_associations/class_methods.rb} +14 -5
- data/lib/restly/embedded_associations/embedded_in.rb +7 -0
- data/lib/restly/embedded_associations/embeds_many.rb +7 -0
- data/lib/restly/embedded_associations/embeds_one.rb +3 -0
- data/lib/restly/embedded_associations.rb +12 -0
- data/lib/restly/error.rb +1 -1
- data/lib/restly/nested_attributes.rb +2 -0
- data/lib/restly/proxies/associations/collection.rb +5 -4
- data/lib/restly/proxies/associations/instance.rb +2 -2
- data/lib/restly/proxies/base.rb +5 -0
- data/lib/restly/proxies/with_path.rb +2 -0
- data/lib/restly/version.rb +1 -1
- data/lib/restly.rb +2 -1
- data/spec/dummy/app/controllers/api/other_objects_controller.rb +45 -0
- data/spec/dummy/app/controllers/api/sample_objects_controller.rb +4 -4
- data/spec/dummy/app/models/other_object.rb +3 -0
- data/spec/dummy/app/models/sample_object.rb +2 -0
- data/spec/dummy/config/routes.rb +4 -1
- data/spec/restly/{associations/embeddable_resources → embeddable_resources}/embeds_many_spec.rb +0 -0
- data/spec/restly/{associations/embeddable_resources → embeddable_resources}/embeds_one_spec.rb +0 -0
- data/spec/restly/{associations/embeddable_resources_spec.rb → embeddable_resources_spec.rb} +0 -0
- metadata +23 -11
- data/lib/restly/associations/embeddable_resources/embeds_many.rb +0 -11
- data/lib/restly/associations/embeddable_resources/embeds_one.rb +0 -11
@@ -0,0 +1,27 @@
|
|
1
|
+
module Restly::Associations::Base::Builders
|
2
|
+
|
3
|
+
# Build
|
4
|
+
def build(parent, attributes = nil, options = {})
|
5
|
+
|
6
|
+
# Merge Options
|
7
|
+
options.reverse_merge!(self.options)
|
8
|
+
|
9
|
+
# Authorize and Set Path
|
10
|
+
association = authorize(options[:authorize]).with_path(parent, options[:path])
|
11
|
+
|
12
|
+
collection? ? association.build_collection(parent) : association.build_instance(parent, attributes)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def build_instance(parent, attributes)
|
18
|
+
instance = association_class.new(attributes, options)
|
19
|
+
instance.write_attribute("#{@owner.resource_name}_id", parent.id) if association_class.method_defined?("#{@owner.resource_name}_id")
|
20
|
+
Restly::Proxies::Associations::Instance.new(instance, parent)
|
21
|
+
end
|
22
|
+
|
23
|
+
def build_collection(parent)
|
24
|
+
Restly::Proxies::Associations::Collection.new(Restly::Collection.new(association_class), parent)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Restly::Associations::Base::Conditionals
|
2
|
+
|
3
|
+
private
|
4
|
+
|
5
|
+
# Conditionals
|
6
|
+
def valid?(val)
|
7
|
+
valid_instances = Array.wrap(val).reject{ |item| item.resource_name == @association_class.resource_name }.empty?
|
8
|
+
raise Restly::Error::InvalidObject, "#{val} is not a #{association_class}" unless valid_instances
|
9
|
+
end
|
10
|
+
|
11
|
+
def collection?
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
def embedded?
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
def nested?
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Restly::Associations::Base::Loaders
|
2
|
+
|
3
|
+
def load(parent, options)
|
4
|
+
|
5
|
+
# Merge Options
|
6
|
+
options.reverse_merge!(self.options)
|
7
|
+
|
8
|
+
# Authorize and Set Path
|
9
|
+
association = authorize(options[:authorize]).with_path(parent, options[:path])
|
10
|
+
|
11
|
+
# Load Collection or Instance
|
12
|
+
collection? ? association.load_collection(parent) : association.load_instance(parent)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def load_collection(parent, association_class = self.association_class)
|
18
|
+
raise Restly::Error::AssociationError, "Not a collection" unless collection?
|
19
|
+
collection = if embedded?
|
20
|
+
[]
|
21
|
+
else
|
22
|
+
association_class.all
|
23
|
+
end
|
24
|
+
|
25
|
+
Restly::Proxies::Associations::Collection.new(collection, parent)
|
26
|
+
end
|
27
|
+
|
28
|
+
def load_instance(parent, association_class = self.association_class)
|
29
|
+
raise Restly::Error::AssociationError, "Not an instance" if collection?
|
30
|
+
return nil if embedded?
|
31
|
+
instance = if parent.attributes.has_key? "#{name}_id"
|
32
|
+
foreign_key = parent.attributes["#{name}_id"]
|
33
|
+
return nil unless foreign_key
|
34
|
+
association_class.find(foreign_key)
|
35
|
+
else
|
36
|
+
association_class.instance_from_response association_class.connection.get(association_class.path)
|
37
|
+
end
|
38
|
+
Restly::Proxies::Associations::Instance.new(instance, parent)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Restly::Associations::Base::Modifiers
|
2
|
+
|
3
|
+
# Modifiers
|
4
|
+
def authorize(authorization = nil, association_class=self.association_class)
|
5
|
+
duplicate = self.dup
|
6
|
+
duplicate.instance_variable_set :@association_class, if (!association_class.authorized? && @owner.respond_to?(:authorized?) && @owner.authorized?) || authorization
|
7
|
+
association_class.authorize(authorization || @owner.connection)
|
8
|
+
else
|
9
|
+
association_class
|
10
|
+
end
|
11
|
+
duplicate
|
12
|
+
end
|
13
|
+
|
14
|
+
def with_path(parent, path = nil, association_class=self.association_class)
|
15
|
+
duplicate = self.dup
|
16
|
+
duplicate.instance_variable_set :@association_class, if path
|
17
|
+
association_class.with_path(path)
|
18
|
+
else
|
19
|
+
association_class.with_path(association_resource_name, prepend: parent.path)
|
20
|
+
end
|
21
|
+
duplicate
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Restly::Associations::Base::Stubs
|
2
|
+
|
3
|
+
# Stubs
|
4
|
+
def stub(parent, attributes)
|
5
|
+
return nil if !parent.is_a?(Restly::Base) || !attributes.present?
|
6
|
+
collection? ? stub_collection(parent, attributes) : stub_instance(parent, attributes)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def stub_collection(parent, attributes)
|
12
|
+
collection = attributes.map{ |item_attrs| association_class.new(item_attrs, loaded: embedded?) }
|
13
|
+
Restly::Proxies::Associations::Collection.new(collection, parent)
|
14
|
+
end
|
15
|
+
|
16
|
+
def stub_instance(parent, attributes)
|
17
|
+
instance = association_class.new(attributes, loaded: embedded?)
|
18
|
+
Restly::Proxies::Associations::Instance.new(instance, parent)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -1,4 +1,17 @@
|
|
1
1
|
class Restly::Associations::Base
|
2
|
+
extend ActiveSupport::Autoload
|
3
|
+
|
4
|
+
autoload :Loaders
|
5
|
+
autoload :Stubs
|
6
|
+
autoload :Builders
|
7
|
+
autoload :Modifiers
|
8
|
+
autoload :Conditionals
|
9
|
+
|
10
|
+
include Loaders
|
11
|
+
include Stubs
|
12
|
+
include Builders
|
13
|
+
include Modifiers
|
14
|
+
include Conditionals
|
2
15
|
|
3
16
|
attr_reader :name, :association_class, :namespace, :polymorphic, :options
|
4
17
|
|
@@ -12,97 +25,8 @@ class Restly::Associations::Base
|
|
12
25
|
@options = options
|
13
26
|
end
|
14
27
|
|
15
|
-
def load(parent, options)
|
16
|
-
|
17
|
-
# Merge Options
|
18
|
-
options.reverse_merge!(self.options)
|
19
|
-
|
20
|
-
# Authorize and Set Path
|
21
|
-
association = authorize(options[:authorize]).with_path(parent, options[:path])
|
22
|
-
|
23
|
-
# Load Collection or Instance
|
24
|
-
collection? ? association.load_collection(parent) : association.load_instance(parent)
|
25
|
-
end
|
26
|
-
|
27
|
-
def load_collection(parent, association_class = self.association_class)
|
28
|
-
raise Restly::Error::AssociationError, "Not a collection" unless collection?
|
29
|
-
return [] if embedded?
|
30
|
-
Restly::Proxies::Associations::Collection.new(association_class.all, parent)
|
31
|
-
end
|
32
|
-
|
33
|
-
def load_instance(parent, association_class = self.association_class)
|
34
|
-
raise Restly::Error::AssociationError, "Not an instance" if collection?
|
35
|
-
return nil if embedded?
|
36
|
-
instance = if parent.attributes.has_key? "#{name}_id"
|
37
|
-
foreign_key = parent.attributes["#{name}_id"]
|
38
|
-
return nil unless foreign_key
|
39
|
-
association_class.find(foreign_key)
|
40
|
-
else
|
41
|
-
association_class.instance_from_response association_class.connection.get(association_class.path)
|
42
|
-
end
|
43
|
-
Restly::Proxies::Associations::Instance.new(instance, parent)
|
44
|
-
end
|
45
|
-
|
46
|
-
def valid?(val)
|
47
|
-
valid_instances = Array.wrap(val).reject{ |item| item.resource_name == @association_class.resource_name }.empty?
|
48
|
-
raise Restly::Error::InvalidObject, "#{val} is not a #{association_class}" unless valid_instances
|
49
|
-
end
|
50
|
-
|
51
|
-
# Stubs
|
52
|
-
def stub(parent, attributes)
|
53
|
-
return nil if !parent.is_a?(Restly::Base) || !attributes.present?
|
54
|
-
collection? ? stub_collection(parent, attributes) : stub_instance(parent, attributes)
|
55
|
-
end
|
56
|
-
|
57
|
-
def stub_collection(parent, attributes)
|
58
|
-
collection = attributes.map{ |item_attrs| association_class.new(item_attrs, loaded: embedded?) }
|
59
|
-
Restly::Proxies::Associations::Collection.new(collection, parent)
|
60
|
-
end
|
61
|
-
|
62
|
-
def stub_instance(parent, attributes)
|
63
|
-
instance = association_class.new(attributes, loaded: embedded?)
|
64
|
-
Restly::Proxies::Associations::Instance.new(instance, parent)
|
65
|
-
end
|
66
|
-
|
67
|
-
# Build
|
68
|
-
def build(parent, attributes = nil, options = {})
|
69
|
-
raise NoMethodError, "Build not available for collection." if collection?
|
70
|
-
instance = association_class.new(attributes, options)
|
71
|
-
instance.write_attribute("#{@owner.resource_name}_id", parent.id) if association_class.method_defined?("#{@owner.resource_name}_id")
|
72
|
-
Restly::Proxies::Associations::Instance.new(instance, parent)
|
73
|
-
end
|
74
|
-
|
75
|
-
# Modifiers
|
76
|
-
def authorize(authorization = nil, association_class=self.association_class)
|
77
|
-
duplicate = self.dup
|
78
|
-
duplicate.instance_variable_set :@association_class, if (!association_class.authorized? && @owner.respond_to?(:authorized?) && @owner.authorized?) || authorization
|
79
|
-
association_class.authorize(authorization || @owner.connection)
|
80
|
-
else
|
81
|
-
association_class
|
82
|
-
end
|
83
|
-
duplicate
|
84
|
-
end
|
85
|
-
|
86
|
-
def with_path(parent, path = nil, association_class=self.association_class)
|
87
|
-
duplicate = self.dup
|
88
|
-
duplicate.instance_variable_set :@association_class, if path
|
89
|
-
association_class.with_path(path)
|
90
|
-
else
|
91
|
-
association_class.with_path(association_resource_name, prepend: parent.path)
|
92
|
-
end
|
93
|
-
duplicate
|
94
|
-
end
|
95
|
-
|
96
28
|
private
|
97
29
|
|
98
|
-
def collection?
|
99
|
-
false
|
100
|
-
end
|
101
|
-
|
102
|
-
def embedded?
|
103
|
-
false
|
104
|
-
end
|
105
|
-
|
106
30
|
def association_resource_name
|
107
31
|
collection? ? association_class.resource_name.pluralize : association_class.resource_name
|
108
32
|
end
|
@@ -8,6 +8,8 @@ class Restly::Associations::BelongsTo < Restly::Associations::Base
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
private
|
12
|
+
|
11
13
|
def set_polymorphic_class(parent)
|
12
14
|
duplicate = self.dup
|
13
15
|
duplicate.instance_variable_set(:@association_class, parent.send("#{name}_type"))
|
@@ -15,18 +17,4 @@ class Restly::Associations::BelongsTo < Restly::Associations::Base
|
|
15
17
|
duplicate
|
16
18
|
end
|
17
19
|
|
18
|
-
def with_path(parent, path = nil, association_class=self.association_class)
|
19
|
-
duplicate = self.dup
|
20
|
-
duplicate.instance_variable_set :@association_class, if path
|
21
|
-
association_class.with_path(path)
|
22
|
-
else
|
23
|
-
association_class
|
24
|
-
end
|
25
|
-
duplicate
|
26
|
-
end
|
27
|
-
|
28
|
-
def collection?
|
29
|
-
false
|
30
|
-
end
|
31
|
-
|
32
20
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Restly::Associations::ClassMethods
|
2
|
+
|
3
|
+
def resource_name
|
4
|
+
name.gsub(/.*::/,'').underscore
|
5
|
+
end
|
6
|
+
|
7
|
+
def reflect_on_resource_association(association_name)
|
8
|
+
reflect_on_all_resource_associations[association_name]
|
9
|
+
end
|
10
|
+
|
11
|
+
def reflect_on_all_resource_associations
|
12
|
+
resource_associations
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# Belongs to
|
18
|
+
def belongs_to_resource(name, options = {})
|
19
|
+
exclude_field(name) if ancestors.include?(Restly::Base)
|
20
|
+
self.resource_associations[name] = Restly::Associations::BelongsTo.new(self, name, options)
|
21
|
+
|
22
|
+
define_method name do |options={}|
|
23
|
+
get_association(name, options)
|
24
|
+
end
|
25
|
+
|
26
|
+
define_method "#{name}=" do |value|
|
27
|
+
set_association name, value
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
# Has One
|
33
|
+
def has_one_resource(name, options = {})
|
34
|
+
exclude_field(name) if ancestors.include?(Restly::Base)
|
35
|
+
self.resource_associations[name] = Restly::Associations::HasOne.new(self, name, options)
|
36
|
+
|
37
|
+
define_method name do |options={}|
|
38
|
+
get_association(name, options)
|
39
|
+
end
|
40
|
+
|
41
|
+
define_method "#{name}=" do |value|
|
42
|
+
set_association name, value
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
# Has One
|
48
|
+
def has_many_resources(name, options = {})
|
49
|
+
exclude_field(name) if ancestors.include?(Restly::Base)
|
50
|
+
self.resource_associations[name] = Restly::Associations::HasMany.new(self, name, options)
|
51
|
+
|
52
|
+
define_method name do |options={}|
|
53
|
+
get_association(name, options)
|
54
|
+
end
|
55
|
+
|
56
|
+
define_method "#{name}=" do |value|
|
57
|
+
set_association name, value
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
data/lib/restly/associations.rb
CHANGED
@@ -8,9 +8,9 @@ module Restly::Associations
|
|
8
8
|
autoload :HasManyThrough
|
9
9
|
autoload :HasOne
|
10
10
|
autoload :HasOneThrough
|
11
|
-
autoload :
|
11
|
+
autoload :ClassMethods
|
12
12
|
|
13
|
-
class
|
13
|
+
class AssociationsHash < HashWithIndifferentAccess
|
14
14
|
end
|
15
15
|
|
16
16
|
class IndifferentSet < Set
|
@@ -25,15 +25,13 @@ module Restly::Associations
|
|
25
25
|
included do
|
26
26
|
|
27
27
|
include Restly::ConcernedInheritance
|
28
|
-
extend EmbeddableResources if self == Restly::Base
|
29
28
|
include Restly::NestedAttributes
|
30
29
|
|
31
|
-
delegate :resource_name, to: :klass
|
32
30
|
class_attribute :resource_associations, instance_reader: false, instance_writer: false
|
33
31
|
|
34
32
|
attr_reader :association_attributes
|
35
33
|
|
36
|
-
self.resource_associations =
|
34
|
+
self.resource_associations = AssociationsHash.new
|
37
35
|
|
38
36
|
inherited do
|
39
37
|
self.resource_associations = resource_associations.dup
|
@@ -41,19 +39,12 @@ module Restly::Associations
|
|
41
39
|
|
42
40
|
end
|
43
41
|
|
44
|
-
def
|
45
|
-
|
42
|
+
def resource_name
|
43
|
+
self.class.resource_name
|
46
44
|
end
|
47
45
|
|
48
|
-
def
|
49
|
-
|
50
|
-
association.valid?(val)
|
51
|
-
@association_attributes[attr] = val
|
52
|
-
end
|
53
|
-
|
54
|
-
def get_association(attr, options={})
|
55
|
-
association = klass.reflect_on_resource_association(attr)
|
56
|
-
(@association_attributes ||= {}.with_indifferent_access)[attr] || set_association(attr, association.load(self, options))
|
46
|
+
def associations
|
47
|
+
IndifferentSet.new self.class.reflect_on_all_resource_associations.keys.map(&:to_sym)
|
57
48
|
end
|
58
49
|
|
59
50
|
def respond_to_association?(m)
|
@@ -66,6 +57,25 @@ module Restly::Associations
|
|
66
57
|
|
67
58
|
private
|
68
59
|
|
60
|
+
def set_association(attr, val)
|
61
|
+
association = self.class.reflect_on_resource_association(attr)
|
62
|
+
association.valid?(val)
|
63
|
+
@association_attributes[attr] = val
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_association(attr, options={})
|
67
|
+
association = self.class.reflect_on_resource_association(attr)
|
68
|
+
|
69
|
+
if (stubbed = association.stub self, @association_attributes[attr]).present?
|
70
|
+
stubbed
|
71
|
+
elsif (loaded = association.load self, options).present?
|
72
|
+
loaded
|
73
|
+
else
|
74
|
+
association.build(self)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
69
79
|
def method_missing(m, *args, &block)
|
70
80
|
if !!(/(?<attr>\w+)(?<setter>=)?$/ =~ m.to_s) && associations.include?(m)
|
71
81
|
attr = attr.to_sym
|
@@ -80,71 +90,4 @@ module Restly::Associations
|
|
80
90
|
end
|
81
91
|
end
|
82
92
|
|
83
|
-
def klass
|
84
|
-
self.class
|
85
|
-
end
|
86
|
-
|
87
|
-
module ClassMethods
|
88
|
-
|
89
|
-
def resource_name
|
90
|
-
name.gsub(/.*::/,'').underscore
|
91
|
-
end
|
92
|
-
|
93
|
-
def reflect_on_resource_association(association_name)
|
94
|
-
reflect_on_all_resource_associations[association_name]
|
95
|
-
end
|
96
|
-
|
97
|
-
def reflect_on_all_resource_associations
|
98
|
-
resource_associations
|
99
|
-
end
|
100
|
-
|
101
|
-
private
|
102
|
-
|
103
|
-
# Belongs to
|
104
|
-
def belongs_to_resource(name, options = {})
|
105
|
-
exclude_field(name) if ancestors.include?(Restly::Base)
|
106
|
-
self.resource_associations[name] = association = BelongsTo.new(self, name, options)
|
107
|
-
|
108
|
-
define_method name do |options={}|
|
109
|
-
get_association(name, options)
|
110
|
-
end
|
111
|
-
|
112
|
-
define_method "#{name}=" do |value|
|
113
|
-
set_association name, value
|
114
|
-
end
|
115
|
-
|
116
|
-
end
|
117
|
-
|
118
|
-
# Has One
|
119
|
-
def has_one_resource(name, options = {})
|
120
|
-
exclude_field(name) if ancestors.include?(Restly::Base)
|
121
|
-
self.resource_associations[name] = association = HasOne.new(self, name, options)
|
122
|
-
|
123
|
-
define_method name do |options={}|
|
124
|
-
get_association(name, options)
|
125
|
-
end
|
126
|
-
|
127
|
-
define_method "#{name}=" do |value|
|
128
|
-
set_association name, value
|
129
|
-
end
|
130
|
-
|
131
|
-
end
|
132
|
-
|
133
|
-
# Has One
|
134
|
-
def has_many_resources(name, options = {})
|
135
|
-
exclude_field(name) if ancestors.include?(Restly::Base)
|
136
|
-
self.resource_associations[name] = association = HasMany.new(self, name, options)
|
137
|
-
|
138
|
-
define_method name do |options={}|
|
139
|
-
get_association(name, options)
|
140
|
-
end
|
141
|
-
|
142
|
-
define_method "#{name}=" do |value|
|
143
|
-
set_association name, value
|
144
|
-
end
|
145
|
-
|
146
|
-
end
|
147
|
-
|
148
|
-
end
|
149
|
-
|
150
93
|
end
|
data/lib/restly/base/fields.rb
CHANGED
@@ -18,6 +18,8 @@ module Restly::Base::Fields
|
|
18
18
|
|
19
19
|
module SharedMethods
|
20
20
|
|
21
|
+
private
|
22
|
+
|
21
23
|
def set_field(attr)
|
22
24
|
base = self.is_a?(Class) ? self : singleton_class
|
23
25
|
unless base.send :instance_method_already_implemented?, attr
|
@@ -30,6 +32,8 @@ module Restly::Base::Fields
|
|
30
32
|
|
31
33
|
module ClassMethods
|
32
34
|
|
35
|
+
private
|
36
|
+
|
33
37
|
def field(attr)
|
34
38
|
if attr.is_a?(Hash) && attr[:from_spec]
|
35
39
|
before_initialize do
|
@@ -10,14 +10,17 @@ module Restly::Base::Instance::Actions
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def delete
|
13
|
-
|
14
|
-
|
15
|
-
false
|
16
|
-
freeze
|
17
|
-
end
|
13
|
+
response = connection.delete(path_with_format, params: params)
|
14
|
+
freeze
|
18
15
|
response.status < 300
|
19
16
|
end
|
20
17
|
|
18
|
+
def destroy
|
19
|
+
run_callbacks :destroy do
|
20
|
+
delete
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
21
24
|
private
|
22
25
|
|
23
26
|
def update
|
@@ -21,9 +21,9 @@ module Restly::Base::Instance::Attributes
|
|
21
21
|
def write_attribute(attr, val)
|
22
22
|
if fields.include?(attr)
|
23
23
|
send("#{attr}_will_change!".to_sym) unless val == @attributes[attr.to_sym] || !@loaded
|
24
|
-
@attributes[attr.to_sym] = val
|
24
|
+
@attributes[attr.to_sym] = Attribute.new(val)
|
25
25
|
|
26
|
-
elsif (association =
|
26
|
+
elsif (association = self.class.reflect_on_resource_association attr).present?
|
27
27
|
set_association attr, association.stub(self, val) unless (@association_attributes ||= {}.with_indifferent_access)[attr].present?
|
28
28
|
|
29
29
|
else
|
@@ -44,17 +44,6 @@ module Restly::Base::Instance::Attributes
|
|
44
44
|
|
45
45
|
alias :attribute :read_attribute
|
46
46
|
|
47
|
-
def inspect
|
48
|
-
inspection = if @attributes
|
49
|
-
fields.collect { |name|
|
50
|
-
"#{name}: #{attribute_for_inspect(name)}"
|
51
|
-
}.compact.join(", ")
|
52
|
-
else
|
53
|
-
"not initialized"
|
54
|
-
end
|
55
|
-
"#<#{self.class} #{inspection}>"
|
56
|
-
end
|
57
|
-
|
58
47
|
def has_attribute?(attr)
|
59
48
|
attribute(attr)
|
60
49
|
end
|
@@ -67,6 +56,17 @@ module Restly::Base::Instance::Attributes
|
|
67
56
|
respond_to_attribute?(m) || super
|
68
57
|
end
|
69
58
|
|
59
|
+
def inspect
|
60
|
+
inspection = if @attributes
|
61
|
+
fields.collect { |name|
|
62
|
+
"#{name}: #{attribute_for_inspect(name)}"
|
63
|
+
}.compact.join(", ")
|
64
|
+
else
|
65
|
+
"not initialized"
|
66
|
+
end
|
67
|
+
"#<#{self.class} #{inspection}>"
|
68
|
+
end
|
69
|
+
|
70
70
|
private
|
71
71
|
|
72
72
|
def attribute_for_inspect(attr_name)
|
@@ -83,7 +83,7 @@ module Restly::Base::Instance::Attributes
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def method_missing(m, *args, &block)
|
86
|
-
if !!(/(?<attr>\w+)(?<setter>=)?$/ =~ m.to_s) && fields.include?(
|
86
|
+
if !!(/(?<attr>\w+)(?<setter>=)?$/ =~ m.to_s) && fields.include?(attr)
|
87
87
|
case !!setter
|
88
88
|
when true
|
89
89
|
write_attribute(attr, *args)
|
@@ -95,4 +95,37 @@ module Restly::Base::Instance::Attributes
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
+
class Attribute < Restly::Proxies::Base
|
99
|
+
|
100
|
+
def initialize(attr)
|
101
|
+
@attr = attr
|
102
|
+
case @attr
|
103
|
+
when String
|
104
|
+
type_convert_string
|
105
|
+
end
|
106
|
+
super(@attr)
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def type_convert_string
|
112
|
+
time = (@attr.to_time rescue nil)
|
113
|
+
date = (@attr.to_date rescue nil)
|
114
|
+
# int = (@attr.to_i rescue nil)
|
115
|
+
# flt = (@attr.to_f rescue nil)
|
116
|
+
@attr = if time.try(:iso8601) == @attr
|
117
|
+
time
|
118
|
+
elsif date.try(:to_s) == @attr
|
119
|
+
date
|
120
|
+
#elsif int.try (:to_s) == @attr
|
121
|
+
# int
|
122
|
+
#elsif flt.try (:to_s) == @attr
|
123
|
+
# flt
|
124
|
+
else
|
125
|
+
@attr
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
98
131
|
end
|
@@ -1,8 +1,19 @@
|
|
1
1
|
module Restly::Base::Instance::Persistence
|
2
2
|
|
3
3
|
def exists?
|
4
|
-
|
4
|
+
return false unless id
|
5
|
+
|
6
|
+
begin
|
7
|
+
@response ||= connection.get(path, force: true)
|
8
|
+
|
9
|
+
rescue OAuth2::Error => e
|
10
|
+
@response = e.response
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
status = @response.status.to_i
|
5
15
|
status < 300 && status >= 200
|
16
|
+
|
6
17
|
end
|
7
18
|
|
8
19
|
def persisted?
|
@@ -19,7 +19,7 @@ module Restly::Base::Instance::WriteCallbacks
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def savable_resource
|
22
|
-
{resource_name => attributes_with_present_values}
|
22
|
+
{resource_name => attributes_with_present_values(writeable_attributes)}
|
23
23
|
end
|
24
24
|
|
25
25
|
def attributes_with_present_values(attributes=self.attributes)
|
@@ -33,5 +33,13 @@ module Restly::Base::Instance::WriteCallbacks
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
def writeable_attributes(attributes=self.attributes)
|
37
|
+
if (maa = mass_assignment_authorizer :default).is_a? ActiveModel::MassAssignmentSecurity::BlackList
|
38
|
+
attributes.reject{ |key, val| maa.map(&:to_sym).include?(key.to_sym) }
|
39
|
+
elsif mass_assignment_authorizer.is_a? ActiveModel::MassAssignmentSecurity::BlackList
|
40
|
+
attributes.select{ |key, val| maa.map(&:to_sym).include?(key.to_sym) }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
36
44
|
|
37
45
|
end
|