api_resource 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- metadata +179 -123
- data/.document +0 -5
- data/.rspec +0 -5
- data/.travis.yml +0 -4
- data/Gemfile +0 -37
- data/Gemfile.lock +0 -190
- data/Guardfile +0 -27
- data/Rakefile +0 -49
- data/VERSION +0 -1
- data/api_resource.gemspec +0 -180
- data/lib/api_resource.rb +0 -130
- data/lib/api_resource/association_activation.rb +0 -19
- data/lib/api_resource/associations.rb +0 -218
- data/lib/api_resource/associations/association_proxy.rb +0 -116
- data/lib/api_resource/associations/belongs_to_remote_object_proxy.rb +0 -16
- data/lib/api_resource/associations/dynamic_resource_scope.rb +0 -23
- data/lib/api_resource/associations/generic_scope.rb +0 -68
- data/lib/api_resource/associations/has_many_remote_object_proxy.rb +0 -16
- data/lib/api_resource/associations/has_many_through_remote_object_proxy.rb +0 -13
- data/lib/api_resource/associations/has_one_remote_object_proxy.rb +0 -24
- data/lib/api_resource/associations/multi_argument_resource_scope.rb +0 -15
- data/lib/api_resource/associations/multi_object_proxy.rb +0 -84
- data/lib/api_resource/associations/related_object_hash.rb +0 -12
- data/lib/api_resource/associations/relation_scope.rb +0 -25
- data/lib/api_resource/associations/resource_scope.rb +0 -32
- data/lib/api_resource/associations/scope.rb +0 -132
- data/lib/api_resource/associations/single_object_proxy.rb +0 -82
- data/lib/api_resource/attributes.rb +0 -243
- data/lib/api_resource/base.rb +0 -717
- data/lib/api_resource/callbacks.rb +0 -45
- data/lib/api_resource/connection.rb +0 -195
- data/lib/api_resource/core_extensions.rb +0 -7
- data/lib/api_resource/custom_methods.rb +0 -117
- data/lib/api_resource/decorators.rb +0 -6
- data/lib/api_resource/decorators/caching_decorator.rb +0 -20
- data/lib/api_resource/exceptions.rb +0 -99
- data/lib/api_resource/formats.rb +0 -22
- data/lib/api_resource/formats/json_format.rb +0 -25
- data/lib/api_resource/formats/xml_format.rb +0 -36
- data/lib/api_resource/local.rb +0 -12
- data/lib/api_resource/log_subscriber.rb +0 -15
- data/lib/api_resource/mocks.rb +0 -277
- data/lib/api_resource/model_errors.rb +0 -82
- data/lib/api_resource/observing.rb +0 -27
- data/lib/api_resource/railtie.rb +0 -24
- data/lib/api_resource/scopes.rb +0 -48
- data/nohup.out +0 -63
- data/spec/lib/api_resource_spec.rb +0 -43
- data/spec/lib/associations_spec.rb +0 -751
- data/spec/lib/attributes_spec.rb +0 -191
- data/spec/lib/base_spec.rb +0 -655
- data/spec/lib/callbacks_spec.rb +0 -68
- data/spec/lib/connection_spec.rb +0 -137
- data/spec/lib/local_spec.rb +0 -20
- data/spec/lib/mocks_spec.rb +0 -45
- data/spec/lib/model_errors_spec.rb +0 -29
- data/spec/lib/prefixes_spec.rb +0 -107
- data/spec/spec_helper.rb +0 -82
- data/spec/support/mocks/association_mocks.rb +0 -63
- data/spec/support/mocks/error_resource_mocks.rb +0 -21
- data/spec/support/mocks/prefix_model_mocks.rb +0 -5
- data/spec/support/mocks/test_resource_mocks.rb +0 -44
- data/spec/support/requests/association_requests.rb +0 -31
- data/spec/support/requests/error_resource_requests.rb +0 -25
- data/spec/support/requests/prefix_model_requests.rb +0 -7
- data/spec/support/requests/test_resource_requests.rb +0 -38
- data/spec/support/test_resource.rb +0 -72
- data/spec/tmp/DIR +0 -0
data/lib/api_resource.rb
DELETED
@@ -1,130 +0,0 @@
|
|
1
|
-
require 'active_support'
|
2
|
-
require 'active_support/inflector'
|
3
|
-
require 'active_support/core_ext'
|
4
|
-
require 'api_resource/core_extensions'
|
5
|
-
|
6
|
-
require 'active_model'
|
7
|
-
|
8
|
-
require 'log4r'
|
9
|
-
require 'log4r/outputter/consoleoutputters'
|
10
|
-
|
11
|
-
require 'api_resource/exceptions'
|
12
|
-
|
13
|
-
require 'differ'
|
14
|
-
require 'colorize'
|
15
|
-
|
16
|
-
module ApiResource
|
17
|
-
|
18
|
-
extend ActiveSupport::Autoload
|
19
|
-
|
20
|
-
autoload :Associations
|
21
|
-
autoload :AssociationActivation
|
22
|
-
autoload :Attributes
|
23
|
-
autoload :Base
|
24
|
-
autoload :Callbacks
|
25
|
-
autoload :Connection
|
26
|
-
autoload :CustomMethods
|
27
|
-
autoload :Decorators
|
28
|
-
autoload :Formats
|
29
|
-
autoload :Local
|
30
|
-
autoload :LogSubscriber
|
31
|
-
autoload :Mocks
|
32
|
-
autoload :ModelErrors
|
33
|
-
autoload :Observing
|
34
|
-
autoload :Scopes
|
35
|
-
autoload :Validations
|
36
|
-
|
37
|
-
require 'api_resource/railtie'
|
38
|
-
|
39
|
-
mattr_writer :logger
|
40
|
-
mattr_accessor :raise_missing_definition_error; self.raise_missing_definition_error = false
|
41
|
-
|
42
|
-
DEFAULT_TIMEOUT = 10 # seconds
|
43
|
-
|
44
|
-
# Load a fix for inflections for words ending in ess
|
45
|
-
ActiveSupport::Inflector.inflections do |inflect|
|
46
|
-
inflect.singular(/ess$/i, 'ess')
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.load_mocks_and_factories
|
50
|
-
require 'hash_dealer'
|
51
|
-
Mocks.clear_endpoints
|
52
|
-
Mocks.init
|
53
|
-
|
54
|
-
Dir["#{File.dirname(__FILE__)}/../spec/support/requests/*.rb"].each {|f|
|
55
|
-
require f
|
56
|
-
}
|
57
|
-
Dir["#{File.dirname(__FILE__)}/../spec/support/**/*.rb"].each {|f|
|
58
|
-
require f
|
59
|
-
}
|
60
|
-
end
|
61
|
-
|
62
|
-
class << self
|
63
|
-
|
64
|
-
delegate :site, :site=, :format, :format=,
|
65
|
-
:token, :token=, :timeout,
|
66
|
-
:open_timeout,
|
67
|
-
:reset_connection, :ttl, :ttl=,
|
68
|
-
:to => ApiResource::Base
|
69
|
-
|
70
|
-
end
|
71
|
-
|
72
|
-
def self.cache(reset = false)
|
73
|
-
@cache = nil if reset
|
74
|
-
@cache ||= begin
|
75
|
-
defined?(Rails) ? Rails.cache : ActiveSupport::Cache::MemoryStore.new
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
# set the timeout val and reset the connection
|
80
|
-
def self.timeout=(val)
|
81
|
-
ApiResource::Base.timeout = val
|
82
|
-
self.reset_connection
|
83
|
-
val
|
84
|
-
end
|
85
|
-
|
86
|
-
# set the timeout val and reset the connection
|
87
|
-
def self.open_timeout=(val)
|
88
|
-
ApiResource::Base.open_timeout = val
|
89
|
-
self.reset_connection
|
90
|
-
val
|
91
|
-
end
|
92
|
-
self.timeout = self.open_timeout = DEFAULT_TIMEOUT
|
93
|
-
|
94
|
-
# Run a block with a given token - useful for AroundFilters
|
95
|
-
def self.with_token(new_token, &block)
|
96
|
-
old_token = self.token
|
97
|
-
begin
|
98
|
-
self.token = new_token
|
99
|
-
yield
|
100
|
-
ensure
|
101
|
-
self.token = old_token
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def self.with_ttl(new_ttl, &block)
|
106
|
-
old_ttl = self.ttl
|
107
|
-
begin
|
108
|
-
self.ttl = new_ttl
|
109
|
-
yield
|
110
|
-
ensure
|
111
|
-
self.ttl = old_ttl
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
# logger
|
116
|
-
def self.logger
|
117
|
-
return @logger if @logger
|
118
|
-
@logger = Log4r::Logger.new("api_resource")
|
119
|
-
@logger.outputters = [Log4r::StdoutOutputter.new('console')]
|
120
|
-
@logger.level = Log4r::INFO
|
121
|
-
@logger
|
122
|
-
end
|
123
|
-
|
124
|
-
# Use this method to enable logging in the future
|
125
|
-
# def self.logging(val = nil)
|
126
|
-
# return (@@logging || false) unless val
|
127
|
-
# return @@logging = val
|
128
|
-
# end
|
129
|
-
|
130
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module ApiResource
|
2
|
-
module AssociationActivation
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
included do
|
6
|
-
class_attribute :association_types
|
7
|
-
# our default association types
|
8
|
-
self.association_types = {:belongs_to => :single, :has_one => :single, :has_many => :multi}
|
9
|
-
end
|
10
|
-
|
11
|
-
module ClassMethods
|
12
|
-
def activate_associations(assoc_types = nil)
|
13
|
-
self.association_types = assoc_types unless assoc_types.nil?
|
14
|
-
self.send(:include, ApiResource::Associations)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
end
|
@@ -1,218 +0,0 @@
|
|
1
|
-
require 'active_support'
|
2
|
-
require 'active_support/string_inquirer'
|
3
|
-
require 'api_resource/association_activation'
|
4
|
-
require 'api_resource/associations/relation_scope'
|
5
|
-
require 'api_resource/associations/resource_scope'
|
6
|
-
require 'api_resource/associations/dynamic_resource_scope'
|
7
|
-
require 'api_resource/associations/generic_scope'
|
8
|
-
require 'api_resource/associations/multi_argument_resource_scope'
|
9
|
-
require 'api_resource/associations/multi_object_proxy'
|
10
|
-
require 'api_resource/associations/single_object_proxy'
|
11
|
-
require 'api_resource/associations/belongs_to_remote_object_proxy'
|
12
|
-
require 'api_resource/associations/has_one_remote_object_proxy'
|
13
|
-
require 'api_resource/associations/has_many_remote_object_proxy'
|
14
|
-
require 'api_resource/associations/has_many_through_remote_object_proxy'
|
15
|
-
require 'api_resource/associations/related_object_hash'
|
16
|
-
|
17
|
-
module ApiResource
|
18
|
-
|
19
|
-
module Associations
|
20
|
-
extend ActiveSupport::Concern
|
21
|
-
|
22
|
-
included do
|
23
|
-
|
24
|
-
unless self.ancestors.include?(ApiResource::AssociationActivation)
|
25
|
-
raise Exception.new(
|
26
|
-
"Can't include Associations without AssociationActivation"
|
27
|
-
)
|
28
|
-
end
|
29
|
-
|
30
|
-
class_attribute :related_objects
|
31
|
-
attr_accessor :assoc_attributes
|
32
|
-
|
33
|
-
define_method(:assoc_attributes) do
|
34
|
-
@assoc_attributes ||= Hash.new
|
35
|
-
end
|
36
|
-
|
37
|
-
self.clear_related_objects
|
38
|
-
|
39
|
-
# we need to add an inherited method here, but it can't happen
|
40
|
-
# until after this module in included/extended, so it's in its own
|
41
|
-
# little mini module
|
42
|
-
extend InheritedMethod
|
43
|
-
|
44
|
-
self.define_association_methods
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
# module methods to include the proper associations in various libraries - this is usually loaded in Railties
|
49
|
-
def self.activate_active_record
|
50
|
-
ActiveRecord::Base.class_eval do
|
51
|
-
include ApiResource::AssociationActivation
|
52
|
-
self.activate_associations(
|
53
|
-
:has_many_remote => :has_many_remote,
|
54
|
-
:belongs_to_remote => :belongs_to_remote,
|
55
|
-
:has_one_remote => :has_one_remote,
|
56
|
-
)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
module InheritedMethod
|
61
|
-
# define a method to reset our related objects
|
62
|
-
def inherited(descendant)
|
63
|
-
# we only want to do this in direct descendants of ApiResoruce::Base
|
64
|
-
if self == ApiResource::Base
|
65
|
-
descendant.clear_related_objects
|
66
|
-
else
|
67
|
-
descendant.clone_related_objects
|
68
|
-
end
|
69
|
-
super(descendant)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
module ClassMethods
|
74
|
-
|
75
|
-
# Define the methods for creating and testing for associations, unfortunately
|
76
|
-
# scopes are different enough to require different methods :(
|
77
|
-
def define_association_methods
|
78
|
-
self.association_types.each_key do |assoc|
|
79
|
-
self.instance_eval <<-EOE, __FILE__, __LINE__ + 1
|
80
|
-
def #{assoc}(*args)
|
81
|
-
options = args.extract_options!
|
82
|
-
options = options.with_indifferent_access
|
83
|
-
# Raise an error if we have multiple args and options
|
84
|
-
raise "Invalid arguments to #{assoc}" unless options.blank? || args.length == 1
|
85
|
-
args.each do |arg|
|
86
|
-
klass_name = (options[:class_name] ? options[:class_name].to_s.classify : arg.to_s.classify)
|
87
|
-
# add this to any descendants - the other methods etc are handled by inheritance
|
88
|
-
([self] + self.descendants).each do |klass|
|
89
|
-
#We need to merge upon itself to generate a new object since the children all share their related objects with each other
|
90
|
-
klass.related_objects = klass.related_objects.merge(:#{assoc} => klass.related_objects[:#{assoc}].merge(arg.to_sym => klass_name))
|
91
|
-
end
|
92
|
-
# We need to define reader and writer methods here
|
93
|
-
define_association_as_attribute(:#{assoc}, arg)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def #{assoc}?(name)
|
98
|
-
return self.related_objects[:#{assoc}][name.to_s.pluralize.to_sym].present? || self.related_objects[:#{assoc}][name.to_s.singularize.to_sym].present?
|
99
|
-
end
|
100
|
-
|
101
|
-
def #{assoc}_class_name(name)
|
102
|
-
raise "No such" + :#{assoc}.to_s + " association on #{name}" unless self.#{assoc}?(name)
|
103
|
-
return self.find_namespaced_class_name(self.related_objects[:#{assoc}][name.to_sym])
|
104
|
-
end
|
105
|
-
|
106
|
-
EOE
|
107
|
-
# For convenience we will define the methods for testing for the existence of an association
|
108
|
-
# and getting the class for an association as instance methods too to avoid tons of self.class calls
|
109
|
-
self.class_eval <<-EOE, __FILE__, __LINE__ + 1
|
110
|
-
def #{assoc}?(name)
|
111
|
-
return self.class.#{assoc}?(name)
|
112
|
-
end
|
113
|
-
|
114
|
-
def #{assoc}_class_name(name)
|
115
|
-
return self.class.#{assoc}_class_name(name)
|
116
|
-
end
|
117
|
-
EOE
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
def association?(assoc)
|
122
|
-
self.related_objects.any? do |key, value|
|
123
|
-
next if key.to_s == "scopes"
|
124
|
-
value.detect { |k,v| k.to_sym == assoc.to_sym }
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def association_names
|
129
|
-
# structure is {:has_many => {"myname" => "ClassName"}}
|
130
|
-
self.related_objects.clone.delete_if{|k,v| k.to_s == "scopes"}.collect{|k,v| v.keys.collect(&:to_sym)}.flatten
|
131
|
-
end
|
132
|
-
|
133
|
-
def association_class_name(assoc)
|
134
|
-
raise ArgumentError, "#{assoc} is not a valid association of #{self}" unless self.association?(assoc)
|
135
|
-
result = self.related_objects.detect do |key,value|
|
136
|
-
ret = value.detect{|k,v| k.to_sym == assoc.to_sym }
|
137
|
-
return self.find_namespaced_class_name(ret[1]) if ret
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
protected
|
142
|
-
|
143
|
-
def clear_related_objects
|
144
|
-
# Hash to hold onto the definitions of the related objects
|
145
|
-
self.related_objects = RelatedObjectHash.new
|
146
|
-
self.association_types.keys.each do |type|
|
147
|
-
self.related_objects[type] = RelatedObjectHash.new({})
|
148
|
-
end
|
149
|
-
|
150
|
-
# TODO :Remove scopes from related_objects.
|
151
|
-
self.related_objects[:scopes] = RelatedObjectHash.new({})
|
152
|
-
end
|
153
|
-
|
154
|
-
def clone_related_objects
|
155
|
-
# Hash to hold onto the definitions of the related objects
|
156
|
-
self.related_objects = self.related_objects.clone
|
157
|
-
self.association_types.keys.each do |type|
|
158
|
-
self.related_objects[type] = self.related_objects[type].clone
|
159
|
-
end
|
160
|
-
# TODO :Remove scopes from related_objects.
|
161
|
-
self.related_objects[:scopes] = self.related_objects[:scopes].clone
|
162
|
-
end
|
163
|
-
|
164
|
-
def define_association_as_attribute(assoc_type, assoc_name)
|
165
|
-
# set up dirty tracking for associations
|
166
|
-
|
167
|
-
self.class_eval <<-EOE, __FILE__, __LINE__ + 1
|
168
|
-
def #{assoc_name}
|
169
|
-
self.assoc_attributes[:#{assoc_name}] ||= (self.attributes[:#{assoc_name}] || #{self.association_types[assoc_type.to_sym].to_s.classify}ObjectProxy.new(self.association_class_name('#{assoc_name}'), nil, self))
|
170
|
-
end
|
171
|
-
def #{assoc_name}=(val)
|
172
|
-
# get old internal object
|
173
|
-
old_internal_object = self.#{assoc_name}.internal_object
|
174
|
-
self.#{assoc_name}.internal_object = val
|
175
|
-
#{assoc_name}_will_change! unless self.#{assoc_name} == old_internal_object
|
176
|
-
self.#{assoc_name}.internal_object
|
177
|
-
end
|
178
|
-
def #{assoc_name}?
|
179
|
-
self.#{assoc_name}.internal_object.present?
|
180
|
-
end
|
181
|
-
EOE
|
182
|
-
end
|
183
|
-
|
184
|
-
def find_namespaced_class_name(klass)
|
185
|
-
# return the name if it is itself namespaced
|
186
|
-
return klass if klass =~ /::/
|
187
|
-
ancestors = self.name.split("::")
|
188
|
-
if ancestors.size > 1
|
189
|
-
receiver = Object
|
190
|
-
namespaces = ancestors[0..-2].collect do |mod|
|
191
|
-
receiver = receiver.const_get(mod)
|
192
|
-
end
|
193
|
-
if namespace = namespaces.reverse.detect{|ns| ns.const_defined?(klass, false)}
|
194
|
-
return namespace.const_get(klass).name
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
return klass
|
199
|
-
end
|
200
|
-
|
201
|
-
end
|
202
|
-
|
203
|
-
def association?(assoc)
|
204
|
-
self.class.association?(assoc)
|
205
|
-
end
|
206
|
-
|
207
|
-
def association_class_name(assoc)
|
208
|
-
self.class.association_class_name(assoc)
|
209
|
-
end
|
210
|
-
|
211
|
-
# list of all association names
|
212
|
-
def association_names
|
213
|
-
self.class.association_names
|
214
|
-
end
|
215
|
-
|
216
|
-
end
|
217
|
-
|
218
|
-
end
|
@@ -1,116 +0,0 @@
|
|
1
|
-
module ApiResource
|
2
|
-
|
3
|
-
module Associations
|
4
|
-
|
5
|
-
class AssociationProxy
|
6
|
-
|
7
|
-
|
8
|
-
cattr_accessor :remote_path_element; self.remote_path_element = :service_uri
|
9
|
-
cattr_accessor :include_class_scopes; self.include_class_scopes = true
|
10
|
-
|
11
|
-
attr_accessor :owner, :loaded, :klass, :internal_object, :remote_path, :scopes, :times_loaded
|
12
|
-
|
13
|
-
# TODO: added owner - moved it to the end because the tests don't use it - it's useful here though
|
14
|
-
def initialize(klass_name, contents, owner = nil)
|
15
|
-
raise "Cannot create an association proxy to the unknown object #{klass_name}" unless defined?(klass_name.to_s.classify)
|
16
|
-
# A simple attr_accessor for testing purposes
|
17
|
-
self.times_loaded = 0
|
18
|
-
self.owner = owner
|
19
|
-
self.klass = klass_name.to_s.classify.constantize
|
20
|
-
self.load(contents)
|
21
|
-
self.loaded = {}.with_indifferent_access
|
22
|
-
if self.class.include_class_scopes
|
23
|
-
self.scopes = self.scopes.reverse_merge(self.klass.scopes)
|
24
|
-
end
|
25
|
-
# Now that we have set up all the scopes with the load method we need to create methods
|
26
|
-
self.scopes.each do |key, _|
|
27
|
-
next if self.respond_to?(key)
|
28
|
-
self.instance_eval <<-EOE, __FILE__, __LINE__ + 1
|
29
|
-
def #{key}(opts = {})
|
30
|
-
@#{key} ||= ApiResource::Associations::RelationScope.new(self, :#{key}, opts)
|
31
|
-
end
|
32
|
-
EOE
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def serializable_hash(options = {})
|
37
|
-
raise "Not Implemented: This method must be implemented in a subclass"
|
38
|
-
end
|
39
|
-
|
40
|
-
def scopes
|
41
|
-
@scopes ||= {}.with_indifferent_access
|
42
|
-
end
|
43
|
-
|
44
|
-
def scope?(scp)
|
45
|
-
self.scopes.keys.include?(scp.to_s)
|
46
|
-
end
|
47
|
-
|
48
|
-
def internal_object
|
49
|
-
@internal_object ||= self.load_scope_with_options(:all, {})
|
50
|
-
end
|
51
|
-
|
52
|
-
def blank?
|
53
|
-
self.internal_object.blank?
|
54
|
-
end
|
55
|
-
alias_method :empty?, :blank?
|
56
|
-
|
57
|
-
def method_missing(method, *args, &block)
|
58
|
-
self.internal_object.send(method, *args, &block)
|
59
|
-
end
|
60
|
-
|
61
|
-
def reload
|
62
|
-
if self
|
63
|
-
remove_instance_variable(:@internal_object) if instance_variable_defined?(:@internal_object)
|
64
|
-
self.load(self.load_from_remote({}))
|
65
|
-
self
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def to_s
|
70
|
-
self.internal_object.to_s
|
71
|
-
end
|
72
|
-
|
73
|
-
def inspect
|
74
|
-
self.internal_object.inspect
|
75
|
-
end
|
76
|
-
|
77
|
-
def ==(other)
|
78
|
-
raise "Not Implemented: This method must be implemented in a subclass"
|
79
|
-
end
|
80
|
-
|
81
|
-
protected
|
82
|
-
# This method loads a particular scope with a set of options from the remote server
|
83
|
-
def load_scope_with_options(scope, options)
|
84
|
-
raise "Not Implemented: This method must be implemented in a subclass"
|
85
|
-
end
|
86
|
-
# This method is a helper to initialize for loading the data passed in to create this object
|
87
|
-
def load(contents)
|
88
|
-
raise "Not Implemented: This method must be implemented in a subclass"
|
89
|
-
end
|
90
|
-
|
91
|
-
# get the remote URI based on our config and options
|
92
|
-
def build_load_path(options)
|
93
|
-
path = self.remote_path
|
94
|
-
# add a format if it doesn't exist and there is no query string yet
|
95
|
-
path += ".#{self.klass.format.extension}" unless path =~ /\./ || path =~/\?/
|
96
|
-
# add the query string, allowing for other user-provided options in the remote_path if we have options
|
97
|
-
unless options.blank?
|
98
|
-
path += (path =~ /\?/ ? "&" : "?") + options.to_query
|
99
|
-
end
|
100
|
-
path
|
101
|
-
end
|
102
|
-
|
103
|
-
# get data from the remote server
|
104
|
-
def load_from_remote(options)
|
105
|
-
self.klass.connection.get(self.build_load_path(options))
|
106
|
-
end
|
107
|
-
# This method create the key for the loaded hash, it ensures that a unique set of scopes
|
108
|
-
# with a unique set of options is only loaded once
|
109
|
-
def loaded_hash_key(scope, options)
|
110
|
-
options.to_a.sort.inject(scope) {|accum,(k,v)| accum << "_#{k}_#{v}"}
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
end
|
115
|
-
|
116
|
-
end
|