restly 0.0.1.beta.2 → 0.0.1.beta.3
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/restly/base.rb +4 -0
- data/lib/restly/base/instance/attributes.rb +22 -3
- data/lib/restly/base/instance/persistence.rb +9 -2
- data/lib/restly/base/pagination_options.rb +41 -0
- data/lib/restly/base/resource/finders.rb +3 -1
- data/lib/restly/collection.rb +1 -8
- data/lib/restly/collection/pagination.rb +31 -19
- data/lib/restly/connection.rb +6 -2
- data/lib/restly/version.rb +1 -1
- metadata +3 -2
data/lib/restly/base.rb
CHANGED
@@ -8,6 +8,7 @@ module Restly
|
|
8
8
|
autoload :Includes
|
9
9
|
autoload :Fields
|
10
10
|
autoload :EmbeddedAssociations
|
11
|
+
autoload :PaginationOptions
|
11
12
|
|
12
13
|
# Thread Local Accessor
|
13
14
|
extend Restly::ThreadLocal
|
@@ -42,6 +43,9 @@ module Restly
|
|
42
43
|
include Instance
|
43
44
|
include Fields
|
44
45
|
|
46
|
+
# Pagination Options
|
47
|
+
include PaginationOptions
|
48
|
+
|
45
49
|
# Set up the Attributes
|
46
50
|
thread_local_accessor :current_token
|
47
51
|
class_attribute :path, instance_writer: false, instance_reader: false
|
@@ -79,8 +79,7 @@ module Restly::Base::Instance::Attributes
|
|
79
79
|
def write_attribute(attr, val)
|
80
80
|
if fields.include?(attr)
|
81
81
|
send("#{attr}_will_change!") if val != read_attribute(attr) && loaded?
|
82
|
-
@attributes[attr.to_sym] = val
|
83
|
-
|
82
|
+
@attributes[attr.to_sym] = convert_attr_type(val)
|
84
83
|
else
|
85
84
|
ActiveSupport::Notifications.instrument("missing_attribute.restly", attr: attr)
|
86
85
|
end
|
@@ -90,7 +89,7 @@ module Restly::Base::Instance::Attributes
|
|
90
89
|
options.reverse_merge!({ autoload: true })
|
91
90
|
|
92
91
|
# Try and get the attribute if the item is not loaded
|
93
|
-
if initialized? && attr.to_sym != :id &&
|
92
|
+
if initialized? && attr.to_sym != :id && attribute_not_loaded?(attr) && !!options[:autoload] && !loaded? && exists?
|
94
93
|
load!
|
95
94
|
end
|
96
95
|
|
@@ -110,4 +109,24 @@ module Restly::Base::Instance::Attributes
|
|
110
109
|
self.attributes = parsed_response(response)
|
111
110
|
end
|
112
111
|
|
112
|
+
def attribute_loaded?(attr)
|
113
|
+
@attributes.has_key? attr
|
114
|
+
end
|
115
|
+
|
116
|
+
def attribute_not_loaded?(attr)
|
117
|
+
!attribute_loaded?(attr)
|
118
|
+
end
|
119
|
+
|
120
|
+
def convert_attr_type(val)
|
121
|
+
time = (val.to_time rescue nil)
|
122
|
+
date = (val.to_date rescue nil)
|
123
|
+
if time.try(:iso8601) == val
|
124
|
+
time
|
125
|
+
elsif date.try(:to_s) == val
|
126
|
+
date
|
127
|
+
else
|
128
|
+
val
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
113
132
|
end
|
@@ -25,13 +25,20 @@ module Restly::Base::Instance::Persistence
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def reload!
|
28
|
-
return unless initialized?
|
28
|
+
return unless initialized? && loaded?
|
29
29
|
raise Restly::Error::MissingId, "Cannot reload #{resource_name}, either it hasn't been created or it is missing an ID." unless exists?
|
30
|
+
@loaded = true
|
30
31
|
set_attributes_from_response connection.get(path_with_format, force: true)
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def load!
|
36
|
+
return unless initialized? && loaded?
|
37
|
+
raise Restly::Error::MissingId, "Cannot load #{resource_name}, either it hasn't been created or it is missing an ID." unless exists?
|
31
38
|
@loaded = true
|
39
|
+
set_attributes_from_response connection.get(path_with_format)
|
32
40
|
self
|
33
41
|
end
|
34
42
|
|
35
|
-
alias :load! :reload!
|
36
43
|
|
37
44
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Restly::Base::PaginationOptions
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
Collection = Restly::Collection
|
5
|
+
|
6
|
+
included do
|
7
|
+
extend ClassMethods
|
8
|
+
class_attribute :pagination_mapping, :pagination_options, instance_writer: false
|
9
|
+
|
10
|
+
pagination per_page: 25
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
|
16
|
+
delegate :page, to: :empty_collection
|
17
|
+
|
18
|
+
def pagination(options={})
|
19
|
+
# Assert Main Options
|
20
|
+
options.assert_valid_keys :per_page, :mapping
|
21
|
+
|
22
|
+
# Reverse Merge and Assert Mappings
|
23
|
+
(options[:mapping] ||= {}).reverse_merge!({ current_page: :page,
|
24
|
+
per_page: :per_page,
|
25
|
+
total_pages: :total_pages,
|
26
|
+
total_entries: :total_entries })
|
27
|
+
|
28
|
+
options[:mapping].assert_valid_keys :root, :current_page, :per_page, :total_pages, :total_entries
|
29
|
+
|
30
|
+
# Set the options
|
31
|
+
self.pagination_mapping = options.delete(:mapping)
|
32
|
+
self.pagination_options = options
|
33
|
+
end
|
34
|
+
|
35
|
+
def empty_collection
|
36
|
+
Collection.new(self, [])
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Restly::Base::Resource::Finders
|
2
2
|
|
3
|
+
Collection = Restly::Collection
|
4
|
+
|
3
5
|
def find(id, *args)
|
4
6
|
options = args.extract_options!
|
5
7
|
|
@@ -18,7 +20,7 @@ module Restly::Base::Resource::Finders
|
|
18
20
|
|
19
21
|
def collection_from_response(response)
|
20
22
|
raise Restly::Error::InvalidResponse unless response.is_a? OAuth2::Response
|
21
|
-
|
23
|
+
Collection.new resource, nil, response: response
|
22
24
|
end
|
23
25
|
|
24
26
|
def instance_from_response(response)
|
data/lib/restly/collection.rb
CHANGED
@@ -7,6 +7,7 @@ class Restly::Collection < Array
|
|
7
7
|
include Restly::Base::Resource::BatchActions
|
8
8
|
include Restly::Base::GenericMethods
|
9
9
|
include ErrorHandling
|
10
|
+
include Pagination
|
10
11
|
|
11
12
|
delegate :resource_name, :new, :client, to: :resource
|
12
13
|
|
@@ -46,14 +47,6 @@ class Restly::Collection < Array
|
|
46
47
|
|
47
48
|
alias :collect :map
|
48
49
|
|
49
|
-
#def paginate(opts={})
|
50
|
-
# @pagination_opts = opts
|
51
|
-
# collection = self.dup
|
52
|
-
# collection.extend(Restly::Collection::Pagination)
|
53
|
-
# return page(opts[:page]) unless opts[:page] == current_page && opts[:per_page] == response_per_page
|
54
|
-
# collection
|
55
|
-
#end
|
56
|
-
|
57
50
|
def <<(instance)
|
58
51
|
raise Restly::Error::InvalidObject, "Object is not an instance of #{resource}" unless accepts?(instance)
|
59
52
|
super(instance)
|
@@ -1,36 +1,48 @@
|
|
1
1
|
module Restly::Collection::Pagination
|
2
|
+
extend ActiveSupport::Concern
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
included do
|
5
|
+
delegate :pagination_options, :pagination_mapping, to: :resource
|
5
6
|
end
|
6
7
|
|
7
|
-
def
|
8
|
-
|
8
|
+
def paginates?
|
9
|
+
!!current_page
|
9
10
|
end
|
10
11
|
|
11
|
-
def
|
12
|
-
|
12
|
+
def page(num, options={})
|
13
|
+
num = 1 unless (num = num.to_i) > 0
|
14
|
+
options.assert_valid_keys(:per_page)
|
15
|
+
per_page = (options[:per_page] || pagination_options[:per_page]).to_i
|
16
|
+
resource.with_params(page: num, per_page: per_page).all
|
13
17
|
end
|
14
18
|
|
15
|
-
|
16
|
-
pagination[:per_page]
|
17
|
-
end
|
19
|
+
private
|
18
20
|
|
19
|
-
def
|
20
|
-
|
21
|
+
def method_missing(m, *args, &block)
|
22
|
+
mapping = pagination_mapping[m]
|
23
|
+
if pagination.has_key? mapping
|
24
|
+
raise ArgumentError, "doesn't accept arguments" if args.present?
|
25
|
+
pagination[mapping].try(:to_i)
|
26
|
+
else
|
27
|
+
super
|
28
|
+
end
|
21
29
|
end
|
22
30
|
|
23
|
-
def
|
24
|
-
|
31
|
+
def respond_to_missing?(m, include_private = false)
|
32
|
+
mapping = pagination_mapping[m]
|
33
|
+
pagination.has_key? mapping
|
25
34
|
end
|
26
35
|
|
27
|
-
private
|
28
|
-
|
29
36
|
def pagination
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
37
|
+
return {} unless response.parsed.is_a? Hash
|
38
|
+
if (root = pagination_mapping[:root])
|
39
|
+
response.parsed[root.to_sym] || response.parsed[root.to_s] || {}
|
40
|
+
else
|
41
|
+
pagination_keys = pagination_mapping.values.compact.map do |key|
|
42
|
+
[key.to_s, key.to_sym]
|
43
|
+
end.flatten
|
44
|
+
response.parsed.slice(*pagination_keys)
|
45
|
+
end.with_indifferent_access
|
34
46
|
end
|
35
47
|
|
36
48
|
end
|
data/lib/restly/connection.rb
CHANGED
@@ -121,7 +121,11 @@ class Restly::Connection < OAuth2::AccessToken
|
|
121
121
|
|
122
122
|
cache_log("Restly::CacheExpire", cache_key, :yellow) { Rails.cache.delete(cache_key) } if response.error
|
123
123
|
|
124
|
-
|
124
|
+
if response.status >= 500
|
125
|
+
site = URI.parse(client.site)
|
126
|
+
formatted_path = ["#{site.scheme}://#{site.host}", "#{site.port}", path].join
|
127
|
+
raise Restly::Error::ConnectionError, "#{response.status}: #{status_string(response.status)}\nurl: #{formatted_path}"
|
128
|
+
end
|
125
129
|
|
126
130
|
# Return the response
|
127
131
|
response
|
@@ -130,7 +134,7 @@ class Restly::Connection < OAuth2::AccessToken
|
|
130
134
|
|
131
135
|
def request_log(name, path, verb, color=:light_green, &block)
|
132
136
|
site = URI.parse(client.site)
|
133
|
-
formatted_path = ["#{site.scheme}://#{site.host}", path].join
|
137
|
+
formatted_path = ["#{site.scheme}://#{site.host}", ":#{site.port}", path].join
|
134
138
|
ActiveSupport::Notifications.instrument("request.restly", url: formatted_path, method: verb, name: name, color: color, &block)
|
135
139
|
end
|
136
140
|
|
data/lib/restly/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: restly
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1.beta.
|
4
|
+
version: 0.0.1.beta.3
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: oauth2
|
@@ -195,6 +195,7 @@ files:
|
|
195
195
|
- lib/restly/base/instance/error_handling.rb
|
196
196
|
- lib/restly/base/instance/persistence.rb
|
197
197
|
- lib/restly/base/instance/write_callbacks.rb
|
198
|
+
- lib/restly/base/pagination_options.rb
|
198
199
|
- lib/restly/base/resource.rb
|
199
200
|
- lib/restly/base/resource/batch_actions.rb
|
200
201
|
- lib/restly/base/resource/finders.rb
|