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 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 && @attributes[attr].nil? && !!options[:autoload] && !loaded? && exists?
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
- Restly::Collection.new resource, nil, response: response
23
+ Collection.new resource, nil, response: response
22
24
  end
23
25
 
24
26
  def instance_from_response(response)
@@ -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
- def page(num)
4
- with_params(page: num, per_page: per_page).all.paginate(page: num, per_page: per_page)
4
+ included do
5
+ delegate :pagination_options, :pagination_mapping, to: :resource
5
6
  end
6
7
 
7
- def current_page
8
- pagination[:current_page] || pagination[:page]
8
+ def paginates?
9
+ !!current_page
9
10
  end
10
11
 
11
- def per_page
12
- @pagination_opts[:per_page] || pagination[:per_page]
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
- def response_per_page
16
- pagination[:per_page]
17
- end
19
+ private
18
20
 
19
- def total_pages
20
- pagination[:total_pages]
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 total_entries
24
- pagination[:total_entries]
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
- parsed = @response.parsed || {}
31
- pagination = parsed[:pagination] || parsed
32
- pagination.select!{ |k,v| /page|current_page|entries|total_entries|per_page|total_pages|total/ =~ k.to_s }
33
- pagination.with_indifferent_access
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
@@ -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
- raise Restly::Error::ConnectionError, "#{response.status}: #{status_string(response.status)}" if response.status >= 500
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
 
@@ -1,3 +1,3 @@
1
1
  module Restly
2
- VERSION = "0.0.1.beta.2"
2
+ VERSION = "0.0.1.beta.3"
3
3
  end
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.2
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-21 00:00:00.000000000 Z
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