remotable 0.3.0 → 0.4.0.beta2

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.
@@ -4,20 +4,20 @@ require "active_support/concern"
4
4
 
5
5
  module ActiveResourceFixes
6
6
  extend ActiveSupport::Concern
7
-
8
-
7
+
8
+
9
9
  # ! ActiveModel::AttributeMethods assumes that :attribute is the target
10
10
  # for attribute lookup. ActiveResource doesn't define that method.
11
11
  def attribute(method)
12
12
  attributes[method]
13
13
  end
14
-
15
-
14
+
15
+
16
16
  included do
17
17
  alias_method_chain :destroy, :validation
18
18
  end
19
-
20
-
19
+
20
+
21
21
  # ActiveResource::Validations overrides ActiveResource::Base#save
22
22
  # to rescue from ActiveResource::ResourceInvalid and record the
23
23
  # resource's errors. Do the same for `destroy`.
@@ -31,7 +31,7 @@ module ActiveResourceFixes
31
31
  load_remote_errors(@remote_errors, true)
32
32
  false
33
33
  end
34
-
34
+
35
35
  end
36
36
 
37
37
 
@@ -50,19 +50,19 @@ module ActiveResourceFixes30
50
50
  super(method_symbol, include_private)
51
51
  end
52
52
  end
53
-
53
+
54
54
  # ! in this method, don't check the Content-Type header: rack doesn't always return it
55
55
  def load_attributes_from_response(response)
56
56
  if !response.body.nil? && response.body.strip.size > 0
57
57
  load(self.class.format.decode(response.body))
58
58
  end
59
59
  end
60
-
60
+
61
61
  end
62
62
 
63
63
 
64
64
  module ActiveResourceFixes31
65
-
65
+
66
66
  # ActiveResource hacks method_missing without hacking respond_to?
67
67
  # In fact, it responds to any method that ends in an equals sign.
68
68
  # It also responds to any method that matches an attribute name.
@@ -76,7 +76,7 @@ module ActiveResourceFixes31
76
76
  super(method_symbol, include_private)
77
77
  end
78
78
  end
79
-
79
+
80
80
  # ! in this method, don't check the Content-Type header: rack doesn't always return it
81
81
  def load_attributes_from_response(response)
82
82
  if !response.body.nil? && response.body.strip.size > 0
@@ -84,7 +84,7 @@ module ActiveResourceFixes31
84
84
  @persisted = true
85
85
  end
86
86
  end
87
-
87
+
88
88
  end
89
89
 
90
90
  if Rails.version >= '3.2'
@@ -101,12 +101,12 @@ ActiveResource::Base.send(:include, ActiveResourceFixes)
101
101
 
102
102
 
103
103
  module ActiveResourceJsonFormatFixes
104
-
104
+
105
105
  def decode(json)
106
106
  return {} if json.blank? # <-- insert this line. json will be nil if response is 304
107
107
  super
108
108
  end
109
-
109
+
110
110
  end
111
111
 
112
112
  ActiveResource::Formats::JsonFormat.extend ActiveResourceJsonFormatFixes
@@ -117,7 +117,7 @@ ActiveResource::Formats::JsonFormat.extend ActiveResourceJsonFormatFixes
117
117
  # However, this is not what Rails Responders are inclined to return.
118
118
 
119
119
  class ActiveResource::Errors
120
-
120
+
121
121
  # Grabs errors from an array of messages (like ActiveRecord::Validations).
122
122
  # The second parameter directs the errors cache to be cleared (default)
123
123
  # or not (by passing true).
@@ -130,5 +130,5 @@ class ActiveResource::Errors
130
130
  end
131
131
  end
132
132
  end
133
-
133
+
134
134
  end
@@ -7,51 +7,60 @@ module Remotable
7
7
  module Adapters
8
8
  module ActiveResource
9
9
  extend ActiveSupport::Concern
10
-
11
-
12
-
10
+
11
+
12
+
13
13
  def key?(attribute)
14
14
  attributes.key?(attribute.to_s)
15
15
  end
16
-
16
+
17
17
  def [](attribute)
18
18
  attributes[attribute.to_s]
19
19
  end
20
-
20
+
21
21
  def []=(attribute, value)
22
22
  attributes[attribute.to_s] = value
23
23
  end
24
-
25
-
26
-
24
+
25
+
26
+
27
27
  # If we use `remote_key` to explicitly set the path where
28
28
  # this resource ought to be found, then we should use the
29
29
  # same path when updating or destroying this resource.
30
- #
30
+ #
31
31
  # To accomplish this, we need to override ActiveResource's
32
32
  # element_path to return the canonical path for this resource.
33
-
33
+
34
34
  attr_accessor :remote_key_path
35
-
35
+
36
36
  def element_path(*args)
37
37
  return remote_key_path if remote_key_path
38
38
  super
39
39
  end
40
-
41
-
42
-
40
+
41
+
42
+
43
+ def destroy
44
+ super
45
+ rescue ::ActiveResource::ResourceNotFound
46
+ $!.extend Remotable::NotFound
47
+ raise
48
+ end
49
+
50
+
51
+
43
52
  module ClassMethods
44
-
53
+
45
54
  IF_MODIFIED_SINCE = "If-Modified-Since".freeze
46
-
47
-
48
-
55
+
56
+
57
+
49
58
  def new_resource
50
59
  new
51
60
  end
52
-
53
-
54
-
61
+
62
+
63
+
55
64
  # This is always invoked by instance#fetch_remote_resource.
56
65
  # It expects to find a remote counterpart for a local resource.
57
66
  # It should always return a NullRemote object that doesn't
@@ -59,8 +68,8 @@ module Remotable
59
68
  def find_by_for_local(local_record, path)
60
69
  had_previous_value = headers.key?(IF_MODIFIED_SINCE)
61
70
  previous_value = headers[IF_MODIFIED_SINCE]
62
-
63
- headers[IF_MODIFIED_SINCE] = Remotable.http_format_time(local_record.updated_at) if local_record.accepts_not_modified?
71
+
72
+ headers[IF_MODIFIED_SINCE] = Remotable.http_format_time(local_record.remote_updated_at) if local_record.accepts_not_modified?
64
73
  find_by(path)
65
74
  ensure
66
75
  if had_previous_value
@@ -69,19 +78,22 @@ module Remotable
69
78
  headers.delete(IF_MODIFIED_SINCE)
70
79
  end
71
80
  end
72
-
81
+
73
82
  def find_by(path)
74
83
  find_by!(path)
75
84
  rescue ::ActiveResource::ResourceNotFound
76
85
  nil
77
86
  end
78
-
87
+
79
88
  def find_by!(path)
80
89
  expanded_path = expanded_path_for(path)
81
90
  Remotable.logger.info "[remotable:#{name.underscore}] GET #{expanded_path} (timeout: #{timeout})"
82
91
  find(:one, :from => expanded_path).tap do |resource|
83
92
  resource.remote_key_path = expanded_path if resource
84
93
  end
94
+ rescue SocketError, EOFError
95
+ $!.extend Remotable::NetworkError
96
+ raise
85
97
  rescue ::ActiveResource::TimeoutError
86
98
  $!.extend Remotable::TimeoutError
87
99
  raise
@@ -90,9 +102,9 @@ module Remotable
90
102
  $!.extend Remotable::TimeoutError if $!.response.code == 504
91
103
  raise
92
104
  end
93
-
94
-
95
-
105
+
106
+
107
+
96
108
  def expanded_path_for(path)
97
109
  if relative_path?(path)
98
110
  URI.join_url_segments(prefix, collection_name, "#{path}.#{format.extension}")
@@ -100,15 +112,15 @@ module Remotable
100
112
  path
101
113
  end
102
114
  end
103
-
104
-
105
-
115
+
116
+
117
+
106
118
  private
107
-
119
+
108
120
  def relative_path?(path)
109
121
  !(path.start_with?("/") || path["://"])
110
122
  end
111
-
123
+
112
124
  end
113
125
  end
114
126
  end
@@ -1,7 +1,7 @@
1
1
  module Enumerable
2
-
2
+
3
3
  def map_to_self(result={})
4
4
  inject(result) {|hash, value| hash.merge(value => value)}
5
5
  end
6
-
6
+
7
7
  end
@@ -1,23 +1,23 @@
1
1
  module Remotable
2
2
  module CoreExt
3
3
  module Object
4
-
5
-
4
+
5
+
6
6
  def respond_to_all?(*methods)
7
7
  respond_to = method(:respond_to?)
8
8
  methods.flatten.all?(&respond_to)
9
9
  end
10
-
10
+
11
11
  def responds_to(*methods)
12
12
  respond_to = method(:respond_to?)
13
13
  methods.flatten.select(&respond_to)
14
14
  end
15
-
15
+
16
16
  def does_not_respond_to(*methods)
17
17
  methods.flatten - self.responds_to(methods)
18
18
  end
19
-
20
-
19
+
20
+
21
21
  end
22
22
  end
23
23
  end
@@ -4,16 +4,16 @@ require "uri"
4
4
  module Remotable
5
5
  module CoreExt
6
6
  module URI
7
-
8
-
7
+
8
+
9
9
  def join_url_segments(*segments)
10
10
  segments = segments.dup.flatten.map(&:to_s)
11
11
  first_segment = segments.shift.gsub(/\/$/, "")
12
12
  segments.map! { |seg| seg.gsub(/(^\/)|(\/$)/, "") }
13
13
  [first_segment, *segments].join("/")
14
14
  end
15
-
16
-
15
+
16
+
17
17
  end
18
18
  end
19
19
  end
@@ -2,4 +2,6 @@ module Remotable
2
2
  module Error; end
3
3
  module TimeoutError; include Error; end
4
4
  module ServiceUnavailableError; include Error; end
5
+ module NetworkError; include Error; end
6
+ module NotFound; include Error; end
5
7
  end
@@ -1,37 +1,37 @@
1
1
  module Remotable
2
2
  class LoggerWrapper
3
-
3
+
4
4
  def initialize(logger)
5
5
  @logger = logger
6
6
  end
7
-
7
+
8
8
  attr_reader :logger
9
-
9
+
10
10
  def debug(*args)
11
11
  logger.debug(*args) if log? :debug
12
12
  end
13
-
13
+
14
14
  def info(*args)
15
15
  logger.info(*args) if log? :info
16
16
  end
17
-
17
+
18
18
  def warn(*args)
19
19
  logger.warn(*args) if log? :warn
20
20
  end
21
-
21
+
22
22
  def error(*args)
23
23
  logger.error(*args) if log? :error
24
24
  end
25
-
25
+
26
26
  private
27
-
27
+
28
28
  LEVELS = [:debug, :info, :warn, :error].freeze
29
-
29
+
30
30
  def log?(value)
31
31
  level = LEVELS.index(Remotable.log_level)
32
32
  value = LEVELS.index(value)
33
33
  value >= level
34
34
  end
35
-
35
+
36
36
  end
37
37
  end
@@ -1,11 +1,11 @@
1
1
  module Remotable
2
2
  module Nosync
3
-
4
-
3
+
4
+
5
5
  def nosync!
6
6
  self.nosync = true
7
7
  end
8
-
8
+
9
9
  def nosync(new_value=true)
10
10
  old_value = @nosync
11
11
  self.nosync = new_value
@@ -13,19 +13,19 @@ module Remotable
13
13
  ensure
14
14
  @nosync = old_value
15
15
  end
16
-
16
+
17
17
  def nosync=(val)
18
18
  @nosync = val
19
19
  end
20
-
20
+
21
21
  def nosync_value?
22
22
  !@nosync.nil?
23
23
  end
24
-
24
+
25
25
  def nosync?
26
26
  @nosync == true
27
27
  end
28
-
29
-
28
+
29
+
30
30
  end
31
31
  end
@@ -1,8 +1,8 @@
1
1
  module Remotable
2
2
  class NullRemote
3
-
3
+
4
4
  class << self
5
-
5
+
6
6
  # This is always invoked by instance#fetch_remote_resource.
7
7
  # It expects to find a remote counterpart for a local resource.
8
8
  # It should always return a NullRemote object that doesn't
@@ -10,7 +10,7 @@ module Remotable
10
10
  def find_by_for_local(local_record, remote_key, fetch_value)
11
11
  new
12
12
  end
13
-
13
+
14
14
  # This is always invoked via class#find_remote_resource_by
15
15
  # by class#fetch_by. It gives the remote model an opportunity
16
16
  # to discover a remote object that doesn't have a local
@@ -19,36 +19,36 @@ module Remotable
19
19
  def find_by(remote_attr, value)
20
20
  nil
21
21
  end
22
-
22
+
23
23
  def new_resource
24
24
  new
25
25
  end
26
-
26
+
27
27
  end
28
-
29
-
30
-
28
+
29
+
30
+
31
31
  # NullRemote needs to receive setter messages and
32
32
  # swallow them. It doesn't need to respond to getter
33
33
  # messages since it has nothing to say.
34
34
  def []=(attribute, value)
35
35
  end
36
-
36
+
37
37
  def key?(attribute)
38
38
  false
39
39
  end
40
-
40
+
41
41
  def save
42
42
  true
43
43
  end
44
-
44
+
45
45
  def errors
46
46
  {}
47
47
  end
48
-
48
+
49
49
  def destroy
50
50
  true
51
51
  end
52
-
52
+
53
53
  end
54
54
  end