restly 0.0.1.alpha.16 → 0.0.1.alpha.18
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/README.md +2 -112
- data/lib/restly.rb +26 -1
- data/lib/restly/associations.rb +25 -12
- data/lib/restly/associations/base/conditionals.rb +2 -2
- data/lib/restly/base.rb +1 -0
- data/lib/restly/base/fields.rb +21 -17
- data/lib/restly/base/includes.rb +7 -2
- data/lib/restly/base/instance.rb +31 -12
- data/lib/restly/base/instance/actions.rb +2 -2
- data/lib/restly/base/instance/attributes.rb +46 -40
- data/lib/restly/base/instance/comparable.rb +13 -0
- data/lib/restly/base/instance/error_handling.rb +60 -0
- data/lib/restly/base/instance/persistence.rb +1 -1
- data/lib/restly/base/resource/specification/fields.rb +2 -2
- data/lib/restly/base/resource/specification/mass_assignment_security.rb +1 -1
- data/lib/restly/client.rb +20 -7
- data/lib/restly/collection.rb +48 -12
- data/lib/restly/collection/error_handling.rb +17 -0
- data/lib/restly/connection.rb +55 -11
- data/lib/restly/error.rb +5 -9
- data/lib/restly/middleware.rb +15 -2
- data/lib/restly/nested_attributes.rb +29 -23
- data/lib/restly/notifications.rb +65 -0
- data/lib/restly/version.rb +1 -1
- data/spec/restly/active_model_lint_spec.rb +11 -0
- data/spec/restly/associations/base/builders_spec.rb +8 -0
- data/spec/restly/associations/base/conditionals_spec.rb +8 -0
- data/spec/restly/associations/base/loaders_spec.rb +8 -0
- data/spec/restly/associations/base/modifiers_spec.rb +8 -0
- data/spec/restly/associations/base/stubs_spec.rb +8 -0
- data/spec/restly/associations/class_methods.rb +0 -0
- data/spec/restly/base/instance/comparable_spec.rb +8 -0
- metadata +22 -2
data/README.md
CHANGED
@@ -16,118 +16,8 @@ Or install it yourself as:
|
|
16
16
|
|
17
17
|
$ gem install restly
|
18
18
|
|
19
|
-
##
|
20
|
-
|
21
|
-
|
22
|
-
```sh
|
23
|
-
$ rails generate restly:configuration
|
24
|
-
```
|
25
|
-
|
26
|
-
This will generate a file like so:
|
27
|
-
|
28
|
-
```yaml
|
29
|
-
development: &development
|
30
|
-
site: http://example.com # Change This
|
31
|
-
default_format: json # defaults to: json
|
32
|
-
|
33
|
-
## Would you like requests to be cached?
|
34
|
-
# cache: true
|
35
|
-
# cache_options:
|
36
|
-
# expires_in: 3600
|
37
|
-
|
38
|
-
## Enable Oauth?
|
39
|
-
# use_oauth: true
|
40
|
-
# oauth_options:
|
41
|
-
# client_id: %client_id%
|
42
|
-
# client_secret: %client_secret%
|
43
|
-
|
44
|
-
test:
|
45
|
-
<<: *development
|
46
|
-
|
47
|
-
production:
|
48
|
-
site: http://example.com # Change This
|
49
|
-
default_format: json # defaults to: json
|
50
|
-
|
51
|
-
# Would you like requests to be cached?
|
52
|
-
cache: true
|
53
|
-
cache_options:
|
54
|
-
expires_in: 3600
|
55
|
-
|
56
|
-
## Enable Oauth?
|
57
|
-
# use_oauth: true
|
58
|
-
# oauth_options:
|
59
|
-
# client_id: %client_id%
|
60
|
-
# client_secret: %client_secret%
|
61
|
-
|
62
|
-
```
|
63
|
-
|
64
|
-
=======
|
65
|
-
*__Restly ships with OAuth2 support, allowing you to authorize requests before making them.__*
|
66
|
-
|
67
|
-
## Creating a Restly Model
|
68
|
-
|
69
|
-
### Using the generator
|
70
|
-
|
71
|
-
```
|
72
|
-
$ rails generate restly:model MyModel
|
73
|
-
```
|
74
|
-
|
75
|
-
This will generate a model that looks like this:
|
76
|
-
|
77
|
-
```ruby
|
78
|
-
class MyModel < Restly::Base
|
79
|
-
|
80
|
-
# self.resource_name = 'my_model'
|
81
|
-
# self.path = 'some_path/to_resource' # defaults to: 'resource_name.pluralized'
|
82
|
-
|
83
|
-
end
|
84
|
-
```
|
85
|
-
=======
|
86
|
-
Generates:
|
87
|
-
|
88
|
-
```
|
89
|
-
class MyModel < Restly::Base
|
90
|
-
|
91
|
-
field :id # implied
|
92
|
-
field :my_attr
|
93
|
-
|
94
|
-
end
|
95
|
-
```
|
96
|
-
|
97
|
-
## Interacting With Objects
|
98
|
-
|
99
|
-
In restly interacting with objects is familiar.
|
100
|
-
|
101
|
-
__Getting the Collection:__
|
102
|
-
|
103
|
-
```ruby
|
104
|
-
MyModel.all
|
105
|
-
```
|
106
|
-
|
107
|
-
__Finding an Instance:__
|
108
|
-
|
109
|
-
```ruby
|
110
|
-
my_instance = MyModel.find(1)
|
111
|
-
```
|
112
|
-
|
113
|
-
__Updating an Instance:__
|
114
|
-
|
115
|
-
```ruby
|
116
|
-
my_instance.update_attributes({my_attr: 'val'})
|
117
|
-
```
|
118
|
-
|
119
|
-
or
|
120
|
-
|
121
|
-
```ruby
|
122
|
-
my_instance.my_attr = 'val'
|
123
|
-
my_instance.save
|
124
|
-
```
|
125
|
-
|
126
|
-
__Creating an Instance__
|
127
|
-
|
128
|
-
```
|
129
|
-
my_instance
|
130
|
-
```
|
19
|
+
## Getting Started
|
20
|
+
For information on how to use restly and how to get started, head over to the [Documentation](http://jwaldrip.github.com/restly).
|
131
21
|
|
132
22
|
## Contributing
|
133
23
|
|
data/lib/restly.rb
CHANGED
@@ -30,4 +30,29 @@ module Restly
|
|
30
30
|
|
31
31
|
end
|
32
32
|
|
33
|
-
require 'restly/railtie' if Object.const_defined?('Rails')
|
33
|
+
require 'restly/railtie' if Object.const_defined?('Rails')
|
34
|
+
require 'restly/notifications'
|
35
|
+
|
36
|
+
class Object
|
37
|
+
|
38
|
+
@@__method_calls ||= {}
|
39
|
+
|
40
|
+
def current_method(index=0)
|
41
|
+
/`(?<curr_method>.*?)'/ =~ caller[index]
|
42
|
+
curr_method
|
43
|
+
end
|
44
|
+
|
45
|
+
def method_called(enum, *args)
|
46
|
+
count = enum.count
|
47
|
+
method = Digest::MD5.hexdigest( current_method(1) + args.to_sentence )
|
48
|
+
|
49
|
+
@@__method_calls.delete_if { |k, v| v[:timestamp] < Time.now - 10 }
|
50
|
+
@@__method_calls[method.to_sym] ||= {}
|
51
|
+
@@__method_calls[method.to_sym][:count] ||= 0
|
52
|
+
@@__method_calls[method.to_sym][:count] += 1
|
53
|
+
@@__method_calls[method.to_sym][:timestamp] = Time.now
|
54
|
+
|
55
|
+
@@__method_calls[method.to_sym][:count] >= count
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/lib/restly/associations.rb
CHANGED
@@ -56,7 +56,11 @@ module Restly::Associations
|
|
56
56
|
private
|
57
57
|
|
58
58
|
def association_attributes
|
59
|
-
@association_attributes ||=
|
59
|
+
@association_attributes ||= HashWithIndifferentAccess.new
|
60
|
+
end
|
61
|
+
|
62
|
+
def loaded_associations
|
63
|
+
@loaded_associations ||= HashWithIndifferentAccess.new
|
60
64
|
end
|
61
65
|
|
62
66
|
def set_association(attr, val)
|
@@ -66,19 +70,22 @@ module Restly::Associations
|
|
66
70
|
end
|
67
71
|
|
68
72
|
def get_association(attr, options={})
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
73
|
+
return loaded_associations[attr] if loaded_associations[attr].present?
|
74
|
+
ActiveSupport::Notifications.instrument("load_association.restly", model: self.class.name, association: attr) do
|
75
|
+
association = self.class.reflect_on_resource_association(attr)
|
76
|
+
|
77
|
+
loaded_associations[attr] = if (stubbed = association.stub self, association_attributes[attr]).present?
|
78
|
+
stubbed
|
79
|
+
elsif (loaded = association.load self, options).present?
|
80
|
+
loaded
|
81
|
+
else
|
82
|
+
association.build(self)
|
83
|
+
end
|
76
84
|
end
|
77
|
-
|
78
85
|
end
|
79
86
|
|
80
|
-
def
|
81
|
-
if !!(/(?<attr>\w+)(?<setter>=)?$/ =~ m.to_s) &&
|
87
|
+
def association_missing(m, *args)
|
88
|
+
if !!(/(?<attr>\w+)(?<setter>=)?$/ =~ m.to_s) && respond_to_association?(m)
|
82
89
|
attr = attr.to_sym
|
83
90
|
case !!setter
|
84
91
|
when true
|
@@ -87,8 +94,14 @@ module Restly::Associations
|
|
87
94
|
get_association(attr)
|
88
95
|
end
|
89
96
|
else
|
90
|
-
|
97
|
+
raise Restly::Error::InvalidAssociation, "Association is invalid"
|
91
98
|
end
|
92
99
|
end
|
93
100
|
|
101
|
+
def method_missing(m, *args, &block)
|
102
|
+
association_missing(m, *args)
|
103
|
+
rescue Restly::Error::InvalidAssociation
|
104
|
+
super
|
105
|
+
end
|
106
|
+
|
94
107
|
end
|
@@ -2,8 +2,8 @@ module Restly::Associations::Base::Conditionals
|
|
2
2
|
|
3
3
|
# Conditionals
|
4
4
|
def valid?(val)
|
5
|
-
valid_instances = Array.wrap(val).reject{ |item| item.resource_name == association_class.resource_name }.empty?
|
6
|
-
raise Restly::Error::InvalidObject, "#{val} is not a #{association_class}" unless valid_instances
|
5
|
+
#valid_instances = Array.wrap(val).reject{ |item| item.resource_name == association_class.resource_name }.empty?
|
6
|
+
#raise Restly::Error::InvalidObject, "#{val} is not a #{association_class}" unless valid_instances
|
7
7
|
end
|
8
8
|
|
9
9
|
def collection?
|
data/lib/restly/base.rb
CHANGED
data/lib/restly/base/fields.rb
CHANGED
@@ -5,7 +5,7 @@ module Restly::Base::Fields
|
|
5
5
|
extend ClassMethods
|
6
6
|
|
7
7
|
class_attribute :fields
|
8
|
-
self.fields = FieldSet.new
|
8
|
+
self.fields = FieldSet.new(self)
|
9
9
|
field :id
|
10
10
|
|
11
11
|
inherited do
|
@@ -20,45 +20,49 @@ module Restly::Base::Fields
|
|
20
20
|
|
21
21
|
def field(attr)
|
22
22
|
if attr.is_a?(Symbol) || attr.is_a?(String)
|
23
|
-
unless instance_method_already_implemented? attr
|
24
|
-
|
25
|
-
self.fields += [attr]
|
26
|
-
end
|
23
|
+
define_attribute_method attr unless instance_method_already_implemented? attr
|
24
|
+
self.fields += [attr]
|
27
25
|
else
|
28
26
|
raise Restly::Error::InvalidField, "field must be a symbol or string."
|
29
27
|
end
|
30
28
|
end
|
31
29
|
|
32
30
|
def exclude_field(name)
|
33
|
-
|
34
|
-
# Remove from the class
|
35
31
|
self.fields -= [name]
|
36
|
-
|
37
|
-
# Remove from the instance
|
38
|
-
before_initialize do
|
39
|
-
self.fields -= [name]
|
40
|
-
end
|
41
|
-
|
42
32
|
end
|
43
33
|
|
44
34
|
end
|
45
35
|
|
46
36
|
class FieldSet < Set
|
47
37
|
|
38
|
+
attr_reader :owner
|
39
|
+
|
40
|
+
def initialize(owner, fields=[])
|
41
|
+
@owner = owner
|
42
|
+
super(fields)
|
43
|
+
|
44
|
+
self.each { |value| owner.send(:define_attribute_method, value) unless owner.send(:instance_method_already_implemented?, value.to_sym) }
|
45
|
+
end
|
46
|
+
|
48
47
|
def include?(value)
|
49
48
|
super(value.to_sym) || super(value.to_s)
|
50
49
|
end
|
51
50
|
|
52
51
|
def <<(value)
|
52
|
+
owner.send(:define_attribute_method, value) unless owner.send(:instance_method_already_implemented?, value.to_sym)
|
53
53
|
super(value.to_sym)
|
54
54
|
end
|
55
55
|
|
56
|
-
def +(
|
57
|
-
|
56
|
+
def +(other_array)
|
57
|
+
other_array.map!(&:to_sym)
|
58
|
+
other_array.each { |value| owner.send(:define_attribute_method, value) unless owner.send(:instance_method_already_implemented?, value.to_sym) }
|
59
|
+
super(other_array)
|
58
60
|
end
|
59
61
|
|
60
|
-
def -(
|
61
|
-
|
62
|
+
def -(other_array)
|
63
|
+
other_array.map!(&:to_sym)
|
64
|
+
other_array.each { |value| owner.send(:define_attribute_method, value) if owner.send(:instance_method_already_implemented?, value.to_sym) }
|
65
|
+
super(other_array)
|
62
66
|
end
|
63
67
|
|
64
68
|
end
|
data/lib/restly/base/includes.rb
CHANGED
@@ -11,12 +11,17 @@ module Restly::Base::Includes
|
|
11
11
|
delegate :site, :site=, :format, :format=, to: :client
|
12
12
|
|
13
13
|
def client
|
14
|
-
@client
|
14
|
+
return @client if @client
|
15
|
+
@client = Restly::Client.new(nil, nil)
|
16
|
+
@client.resource = self
|
17
|
+
@client
|
15
18
|
end
|
16
19
|
|
17
20
|
def client=(client)
|
18
|
-
raise Restly::Error::InvalidClient, "Client is invalid!"
|
21
|
+
raise Restly::Error::InvalidClient, "Client is invalid!" unless client.is_a?(Restly::Client)
|
19
22
|
@client = client
|
23
|
+
@client.resource = self
|
24
|
+
@client
|
20
25
|
end
|
21
26
|
|
22
27
|
def has_specification
|
data/lib/restly/base/instance.rb
CHANGED
@@ -5,15 +5,19 @@ module Restly::Base::Instance
|
|
5
5
|
autoload :Attributes
|
6
6
|
autoload :Persistence
|
7
7
|
autoload :WriteCallbacks
|
8
|
+
autoload :Comparable
|
9
|
+
autoload :ErrorHandling
|
8
10
|
|
9
11
|
include Restly::Base::GenericMethods
|
10
12
|
include Actions
|
11
13
|
include Attributes
|
12
14
|
include Persistence
|
13
15
|
include WriteCallbacks
|
16
|
+
include Comparable
|
17
|
+
include ErrorHandling
|
14
18
|
|
15
19
|
included do
|
16
|
-
attr_reader :init_options, :response
|
20
|
+
attr_reader :init_options, :response, :errors
|
17
21
|
delegate :spec, to: :resource
|
18
22
|
end
|
19
23
|
|
@@ -22,25 +26,30 @@ module Restly::Base::Instance
|
|
22
26
|
@init_options = options
|
23
27
|
@attributes = HashWithIndifferentAccess.new
|
24
28
|
@association_cache = {}
|
25
|
-
@association_attributes =
|
29
|
+
@association_attributes = HashWithIndifferentAccess.new
|
26
30
|
@aggregation_cache = {}
|
27
31
|
@attributes_cache = {}
|
28
32
|
@previously_changed = {}
|
29
33
|
@changed_attributes = {}
|
34
|
+
@errors = ActiveModel::Errors.new(self)
|
30
35
|
|
31
|
-
|
32
|
-
@readonly = options[:readonly] || false
|
33
|
-
set_response options[:response] if options[:response]
|
34
|
-
@loaded = options.has_key?(:loaded) ? options[:loaded] : true
|
35
|
-
self.attributes = attributes if attributes
|
36
|
-
self.connection = options[:connection] if options[:connection].is_a?(OAuth2::AccessToken)
|
36
|
+
ActiveSupport::Notifications.instrument("load_instance.restly", instance: self) do
|
37
37
|
|
38
|
-
|
38
|
+
run_callbacks :initialize do
|
39
|
+
|
40
|
+
@readonly = options[:readonly] || false
|
41
|
+
set_response options[:response] if options[:response]
|
42
|
+
@loaded = options.has_key?(:loaded) ? options[:loaded] : true
|
43
|
+
self.attributes = attributes if attributes
|
44
|
+
self.connection = options[:connection] if options[:connection].is_a?(OAuth2::AccessToken)
|
45
|
+
|
46
|
+
end
|
39
47
|
|
48
|
+
end
|
40
49
|
end
|
41
50
|
|
42
51
|
def loaded?
|
43
|
-
|
52
|
+
!!@loaded
|
44
53
|
end
|
45
54
|
|
46
55
|
def connection
|
@@ -66,13 +75,21 @@ module Restly::Base::Instance
|
|
66
75
|
end
|
67
76
|
end
|
68
77
|
|
78
|
+
def to_param
|
79
|
+
id.to_s
|
80
|
+
end
|
81
|
+
|
69
82
|
private
|
70
83
|
|
71
84
|
def set_response(response)
|
72
85
|
raise Restly::Error::InvalidResponse unless response.is_a? OAuth2::Response
|
73
86
|
@response = response
|
74
87
|
if response.try(:body)
|
75
|
-
|
88
|
+
if response_has_errors?(response)
|
89
|
+
set_errors_from_response
|
90
|
+
else
|
91
|
+
set_attributes_from_response
|
92
|
+
end
|
76
93
|
end
|
77
94
|
end
|
78
95
|
|
@@ -80,7 +97,9 @@ module Restly::Base::Instance
|
|
80
97
|
return {} unless response
|
81
98
|
parsed = response.parsed || {}
|
82
99
|
if parsed.is_a?(Hash) && parsed[resource_name]
|
83
|
-
parsed[resource_name]
|
100
|
+
parsed[resource_name].with_indifferent_access
|
101
|
+
elsif parsed.is_a?(Hash)
|
102
|
+
parsed.with_indifferent_access
|
84
103
|
else
|
85
104
|
parsed
|
86
105
|
end
|
@@ -25,13 +25,13 @@ module Restly::Base::Instance::Actions
|
|
25
25
|
|
26
26
|
def update
|
27
27
|
run_callbacks :update do
|
28
|
-
|
28
|
+
set_response(connection.put path_with_format, body: @request_body, params: params)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
def create
|
33
33
|
run_callbacks :create do
|
34
|
-
|
34
|
+
set_response(connection.post path_with_format, body: @request_body, params: params)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require "colorize"
|
2
|
-
|
3
1
|
module Restly::Base::Instance::Attributes
|
4
2
|
|
5
3
|
def update_attributes(attributes)
|
@@ -9,49 +7,35 @@ module Restly::Base::Instance::Attributes
|
|
9
7
|
|
10
8
|
def attributes=(attributes)
|
11
9
|
attributes.each do |k, v|
|
12
|
-
|
10
|
+
self[k] = v
|
13
11
|
end
|
14
12
|
end
|
15
13
|
|
16
14
|
def attributes
|
17
15
|
fields.reduce(HashWithIndifferentAccess.new) do |hash, key|
|
18
|
-
hash[key] = read_attribute
|
16
|
+
hash[key] = read_attribute(key, autoload: false)
|
19
17
|
hash
|
20
18
|
end
|
21
19
|
end
|
22
20
|
|
23
|
-
def
|
24
|
-
|
25
|
-
send("#{attr}_will_change!".to_sym) unless val == @attributes[attr.to_sym] || !@loaded
|
26
|
-
@attributes[attr.to_sym] = Attribute.new(val)
|
27
|
-
|
28
|
-
elsif (association = self.class.reflect_on_resource_association attr).present?
|
29
|
-
set_association attr, association.stub(self, val) unless (@association_attributes ||= {}.with_indifferent_access)[attr].present?
|
30
|
-
|
31
|
-
else
|
32
|
-
puts "WARNING: Attribute `#{attr}` not written. ".colorize(:yellow) +
|
33
|
-
"To fix this add the following the the model. -- field :#{attr}"
|
34
|
-
end
|
21
|
+
def attribute(key, options={})
|
22
|
+
read_attribute(key)
|
35
23
|
end
|
36
24
|
|
37
|
-
def
|
38
|
-
|
39
|
-
if @attributes[attr.to_sym].nil? && !!options[:autoload] && !loaded?
|
40
|
-
load!
|
41
|
-
read_attribute(attr)
|
42
|
-
else
|
43
|
-
@attributes[attr.to_sym]
|
44
|
-
end
|
25
|
+
def []=(key, value)
|
26
|
+
send "#{key}=", value
|
45
27
|
end
|
46
28
|
|
47
|
-
|
29
|
+
def [](key)
|
30
|
+
send key
|
31
|
+
end
|
48
32
|
|
49
33
|
def has_attribute?(attr)
|
50
|
-
attribute(attr)
|
34
|
+
fields.include?(attr) && attribute(attr)
|
51
35
|
end
|
52
36
|
|
53
37
|
def respond_to_attribute?(m)
|
54
|
-
!!(/(?<attr>\w+)(?<setter>=)?$/ =~ m.to_s) &&
|
38
|
+
!!(/(?<attr>\w+)(?<setter>=)?$/ =~ m.to_s) && fields.include?(attr)
|
55
39
|
end
|
56
40
|
|
57
41
|
def respond_to?(m, include_private = false)
|
@@ -71,6 +55,41 @@ module Restly::Base::Instance::Attributes
|
|
71
55
|
|
72
56
|
private
|
73
57
|
|
58
|
+
def attribute_missing(m, *args)
|
59
|
+
if !!(/(?<attr>\w+)(?<setter>=)?$/ =~ m.to_s) && fields.include?(attr)
|
60
|
+
case !!setter
|
61
|
+
when true
|
62
|
+
write_attribute(attr, *args)
|
63
|
+
when false
|
64
|
+
read_attribute(attr, *args)
|
65
|
+
end
|
66
|
+
else
|
67
|
+
raise Restly::Error::InvalidAttribute, "Attribute does not exist!"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def method_missing(m, *args, &block)
|
72
|
+
attribute_missing(m, *args)
|
73
|
+
rescue Restly::Error::InvalidAttribute
|
74
|
+
super
|
75
|
+
end
|
76
|
+
|
77
|
+
def write_attribute(attr, val)
|
78
|
+
if fields.include?(attr)
|
79
|
+
send("#{attr}_will_change!".to_sym) unless val == @attributes[attr.to_sym] || !@loaded
|
80
|
+
@attributes[attr.to_sym] = Attribute.new(val)
|
81
|
+
|
82
|
+
else
|
83
|
+
ActiveSupport::Notifications.instrument("missing_attribute.restly", attr: attr)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def read_attribute(attr, options={})
|
88
|
+
options.reverse_merge!({ autoload: true })
|
89
|
+
load! if (key = attr.to_sym) != :id && @attributes[key].nil? && !!options[:autoload] && !loaded? && !exists?
|
90
|
+
@attributes[attr.to_sym]
|
91
|
+
end
|
92
|
+
|
74
93
|
def attribute_for_inspect(attr_name)
|
75
94
|
value = attribute(attr_name, autoload: false)
|
76
95
|
if value.is_a?(String) && value.length > 50
|
@@ -84,19 +103,6 @@ module Restly::Base::Instance::Attributes
|
|
84
103
|
self.attributes = parsed_response(response)
|
85
104
|
end
|
86
105
|
|
87
|
-
def method_missing(m, *args, &block)
|
88
|
-
if !!(/(?<attr>\w+)(?<setter>=)?$/ =~ m.to_s) && fields.include?(attr)
|
89
|
-
case !!setter
|
90
|
-
when true
|
91
|
-
write_attribute(attr, *args)
|
92
|
-
when false
|
93
|
-
read_attribute(attr)
|
94
|
-
end
|
95
|
-
else
|
96
|
-
super(m, *args, &block)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
106
|
class Attribute < Restly::Proxies::Base
|
101
107
|
|
102
108
|
def initialize(attr)
|