restly 0.0.1.alpha.4 → 0.0.1.alpha.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|