activeresource 3.0.20 → 3.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activeresource might be problematic. Click here for more details.
- data/CHANGELOG +5 -61
- data/README.rdoc +1 -1
- data/examples/performance.rb +70 -0
- data/lib/active_resource/base.rb +78 -47
- data/lib/active_resource/connection.rb +8 -7
- data/lib/active_resource/custom_methods.rb +2 -2
- data/lib/active_resource/exceptions.rb +3 -0
- data/lib/active_resource/http_mock.rb +61 -27
- data/lib/active_resource/observing.rb +8 -0
- data/lib/active_resource/schema.rb +1 -3
- data/lib/active_resource/validations.rb +8 -16
- data/lib/active_resource/version.rb +3 -3
- metadata +52 -48
- checksums.yaml +0 -7
data/CHANGELOG
CHANGED
@@ -1,70 +1,14 @@
|
|
1
|
-
|
1
|
+
*Rails 3.1.0 (unreleased)*
|
2
2
|
|
3
|
-
|
3
|
+
* No changes
|
4
4
|
|
5
|
-
*
|
6
|
-
|
7
|
-
## Rails 3.0.18 (Jan 2, 2013)
|
8
|
-
|
9
|
-
* No changes.
|
10
|
-
|
11
|
-
## Rails 3.0.14 (Jun 12, 2012)
|
12
|
-
|
13
|
-
* No changes.
|
14
|
-
|
15
|
-
* Rails 3.0.13 (May 31, 2012)
|
16
|
-
|
17
|
-
* No changes.
|
18
|
-
|
19
|
-
*Rails 3.0.10 (August 16, 2011)*
|
20
|
-
|
21
|
-
* No changes.
|
22
|
-
|
23
|
-
|
24
|
-
*Rails 3.0.9 (June 16, 2011)*
|
25
|
-
|
26
|
-
*No changes.
|
27
|
-
|
28
|
-
|
29
|
-
*Rails 3.0.8 (June 7, 2011)*
|
30
|
-
|
31
|
-
*No changes.
|
32
|
-
|
33
|
-
|
34
|
-
*Rails 3.0.7 (April 18, 2011)*
|
35
|
-
|
36
|
-
*No changes.
|
37
|
-
|
38
|
-
|
39
|
-
*Rails 3.0.6 (April 5, 2011)
|
40
|
-
|
41
|
-
* No changes.
|
42
|
-
|
43
|
-
|
44
|
-
*Rails 3.0.5 (February 26, 2011)*
|
45
|
-
|
46
|
-
* No changes.
|
47
|
-
|
48
|
-
|
49
|
-
*Rails 3.0.4 (February 8, 2011)*
|
50
|
-
|
51
|
-
* No changes.
|
52
|
-
|
53
|
-
|
54
|
-
*Rails 3.0.3 (November 16, 2010)*
|
55
|
-
|
56
|
-
* No changes.
|
57
|
-
|
58
|
-
|
59
|
-
*Rails 3.0.2 (November 15, 2010)*
|
60
|
-
|
61
|
-
* No changes.
|
5
|
+
*Rails 3.0.2 (unreleased)*
|
62
6
|
|
7
|
+
* No changes
|
63
8
|
|
64
9
|
*Rails 3.0.1 (October 15, 2010)*
|
65
10
|
|
66
|
-
* No
|
67
|
-
|
11
|
+
* No Changes, just a version bump.
|
68
12
|
|
69
13
|
*Rails 3.0.0 (August 29, 2010)*
|
70
14
|
|
data/README.rdoc
CHANGED
@@ -95,7 +95,7 @@ Collections can also be requested in a similar fashion
|
|
95
95
|
#
|
96
96
|
# for GET http://api.people.com:3000/people.xml
|
97
97
|
#
|
98
|
-
people = Person.
|
98
|
+
people = Person.all
|
99
99
|
people.first # => <Person::xxx 'first' => 'Ryan' ...>
|
100
100
|
people.last # => <Person::xxx 'first' => 'Jim' ...>
|
101
101
|
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_resource'
|
3
|
+
require 'benchmark'
|
4
|
+
|
5
|
+
TIMES = (ENV['N'] || 10_000).to_i
|
6
|
+
|
7
|
+
# deep nested resource
|
8
|
+
attrs = {
|
9
|
+
:id => 1,
|
10
|
+
:name => 'Luis',
|
11
|
+
:age => 21,
|
12
|
+
:friends => [
|
13
|
+
{
|
14
|
+
:name => 'JK',
|
15
|
+
:age => 24,
|
16
|
+
:colors => ['red', 'green', 'blue'],
|
17
|
+
:brothers => [
|
18
|
+
{
|
19
|
+
:name => 'Mateo',
|
20
|
+
:age => 35,
|
21
|
+
:children => [{ :name => 'Edith', :age => 5 }, { :name => 'Martha', :age => 4 }]
|
22
|
+
},
|
23
|
+
{
|
24
|
+
:name => 'Felipe',
|
25
|
+
:age => 33,
|
26
|
+
:children => [{ :name => 'Bryan', :age => 1 }, { :name => 'Luke', :age => 0 }]
|
27
|
+
}
|
28
|
+
]
|
29
|
+
},
|
30
|
+
{
|
31
|
+
:name => 'Eduardo',
|
32
|
+
:age => 20,
|
33
|
+
:colors => [],
|
34
|
+
:brothers => [
|
35
|
+
{
|
36
|
+
:name => 'Sebas',
|
37
|
+
:age => 23,
|
38
|
+
:children => [{ :name => 'Andres', :age => 0 }, { :name => 'Jorge', :age => 2 }]
|
39
|
+
},
|
40
|
+
{
|
41
|
+
:name => 'Elsa',
|
42
|
+
:age => 19,
|
43
|
+
:children => [{ :name => 'Natacha', :age => 1 }]
|
44
|
+
},
|
45
|
+
{
|
46
|
+
:name => 'Milena',
|
47
|
+
:age => 16,
|
48
|
+
:children => []
|
49
|
+
}
|
50
|
+
]
|
51
|
+
}
|
52
|
+
]
|
53
|
+
}
|
54
|
+
|
55
|
+
class Customer < ActiveResource::Base
|
56
|
+
self.site = "http://37s.sunrise.i:3000"
|
57
|
+
end
|
58
|
+
|
59
|
+
module Nested
|
60
|
+
class Customer < ActiveResource::Base
|
61
|
+
self.site = "http://37s.sunrise.i:3000"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
Benchmark.bm(40) do |x|
|
66
|
+
x.report('Model.new (instantiation)') { TIMES.times { Customer.new } }
|
67
|
+
x.report('Nested::Model.new (instantiation)') { TIMES.times { Nested::Customer.new } }
|
68
|
+
x.report('Model.new (setting attributes)') { TIMES.times { Customer.new attrs } }
|
69
|
+
x.report('Nested::Model.new (setting attributes)') { TIMES.times { Nested::Customer.new attrs } }
|
70
|
+
end
|
data/lib/active_resource/base.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'active_support'
|
2
2
|
require 'active_support/core_ext/class/attribute_accessors'
|
3
|
-
require 'active_support/core_ext/class/
|
3
|
+
require 'active_support/core_ext/class/attribute'
|
4
4
|
require 'active_support/core_ext/hash/indifferent_access'
|
5
5
|
require 'active_support/core_ext/kernel/reporting'
|
6
6
|
require 'active_support/core_ext/module/attr_accessor_with_default'
|
@@ -12,6 +12,7 @@ require 'active_support/core_ext/object/duplicable'
|
|
12
12
|
require 'set'
|
13
13
|
require 'uri'
|
14
14
|
|
15
|
+
require 'active_support/core_ext/uri'
|
15
16
|
require 'active_resource/exceptions'
|
16
17
|
require 'active_resource/connection'
|
17
18
|
require 'active_resource/formats'
|
@@ -166,6 +167,7 @@ module ActiveResource
|
|
166
167
|
# # GET http://api.people.com:3000/people/999.xml
|
167
168
|
# ryan = Person.find(999) # 404, raises ActiveResource::ResourceNotFound
|
168
169
|
#
|
170
|
+
#
|
169
171
|
# <tt>404</tt> is just one of the HTTP error response codes that Active Resource will handle with its own exception. The
|
170
172
|
# following HTTP response codes will also result in these exceptions:
|
171
173
|
#
|
@@ -194,6 +196,16 @@ module ActiveResource
|
|
194
196
|
# redirect_to :action => 'new'
|
195
197
|
# end
|
196
198
|
#
|
199
|
+
# When a GET is requested for a nested resource and you don't provide the prefix_param
|
200
|
+
# an ActiveResource::MissingPrefixParam will be raised.
|
201
|
+
#
|
202
|
+
# class Comment < ActiveResource::Base
|
203
|
+
# self.site = "http://someip.com/posts/:post_id/"
|
204
|
+
# end
|
205
|
+
#
|
206
|
+
# Comment.find(1)
|
207
|
+
# # => ActiveResource::MissingPrefixParam: post_id prefix_option is missing
|
208
|
+
#
|
197
209
|
# === Validation errors
|
198
210
|
#
|
199
211
|
# Active Resource supports validations on resources and will return errors if any of these validations fail
|
@@ -251,6 +263,8 @@ module ActiveResource
|
|
251
263
|
# The logger for diagnosing and tracing Active Resource calls.
|
252
264
|
cattr_accessor :logger
|
253
265
|
|
266
|
+
class_attribute :_format
|
267
|
+
|
254
268
|
class << self
|
255
269
|
# Creates a schema for this resource - setting the attributes that are
|
256
270
|
# known prior to fetching an instance from the remote system.
|
@@ -403,8 +417,8 @@ module ActiveResource
|
|
403
417
|
@site = nil
|
404
418
|
else
|
405
419
|
@site = create_site_uri_from(site)
|
406
|
-
@user =
|
407
|
-
@password =
|
420
|
+
@user = URI.parser.unescape(@site.user) if @site.user
|
421
|
+
@password = URI.parser.unescape(@site.password) if @site.password
|
408
422
|
end
|
409
423
|
end
|
410
424
|
|
@@ -480,13 +494,13 @@ module ActiveResource
|
|
480
494
|
format = mime_type_reference_or_format.is_a?(Symbol) ?
|
481
495
|
ActiveResource::Formats[mime_type_reference_or_format] : mime_type_reference_or_format
|
482
496
|
|
483
|
-
|
497
|
+
self._format = format
|
484
498
|
connection.format = format if site
|
485
499
|
end
|
486
500
|
|
487
501
|
# Returns the current format, default is ActiveResource::Formats::XmlFormat.
|
488
502
|
def format
|
489
|
-
|
503
|
+
self._format || ActiveResource::Formats::XmlFormat
|
490
504
|
end
|
491
505
|
|
492
506
|
# Sets the number of seconds after which requests to the REST API should time out.
|
@@ -508,9 +522,9 @@ module ActiveResource
|
|
508
522
|
#
|
509
523
|
# * <tt>:key</tt> - An OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
|
510
524
|
# * <tt>:cert</tt> - An OpenSSL::X509::Certificate object as client certificate
|
511
|
-
# * <tt>:ca_file</tt> - Path to a CA certification file in PEM format. The file can
|
525
|
+
# * <tt>:ca_file</tt> - Path to a CA certification file in PEM format. The file can contain several CA certificates.
|
512
526
|
# * <tt>:ca_path</tt> - Path of a CA certification directory containing certifications in PEM format.
|
513
|
-
# * <tt>:verify_mode</tt> - Flags for server the certification verification at
|
527
|
+
# * <tt>:verify_mode</tt> - Flags for server the certification verification at beginning of SSL/TLS session. (OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER is acceptable)
|
514
528
|
# * <tt>:verify_callback</tt> - The verify callback for the server certification verification.
|
515
529
|
# * <tt>:verify_depth</tt> - The maximum depth for the certificate chain verification.
|
516
530
|
# * <tt>:cert_store</tt> - OpenSSL::X509::Store to verify peer certificate.
|
@@ -577,7 +591,7 @@ module ActiveResource
|
|
577
591
|
# Default value is <tt>site.path</tt>.
|
578
592
|
def prefix=(value = '/')
|
579
593
|
# Replace :placeholders with '#{embedded options[:lookups]}'
|
580
|
-
prefix_call = value.gsub(/:\w+/) { |key| "\#{URI.escape options[#{key}].to_s}" }
|
594
|
+
prefix_call = value.gsub(/:\w+/) { |key| "\#{URI.parser.escape options[#{key}].to_s}" }
|
581
595
|
|
582
596
|
# Clear prefix parameters in case they have been cached
|
583
597
|
@prefix_parameters = nil
|
@@ -621,8 +635,10 @@ module ActiveResource
|
|
621
635
|
# # => /posts/5/comments/1.xml?active=1
|
622
636
|
#
|
623
637
|
def element_path(id, prefix_options = {}, query_options = nil)
|
638
|
+
check_prefix_options(prefix_options)
|
639
|
+
|
624
640
|
prefix_options, query_options = split_options(prefix_options) if query_options.nil?
|
625
|
-
"#{prefix(prefix_options)}#{collection_name}/#{URI.escape id.to_s}.#{format.extension}#{query_string(query_options)}"
|
641
|
+
"#{prefix(prefix_options)}#{collection_name}/#{URI.parser.escape id.to_s}.#{format.extension}#{query_string(query_options)}"
|
626
642
|
end
|
627
643
|
|
628
644
|
# Gets the new element path for REST resources.
|
@@ -663,6 +679,7 @@ module ActiveResource
|
|
663
679
|
# # => /posts/5/comments.xml?active=1
|
664
680
|
#
|
665
681
|
def collection_path(prefix_options = {}, query_options = nil)
|
682
|
+
check_prefix_options(prefix_options)
|
666
683
|
prefix_options, query_options = split_options(prefix_options) if query_options.nil?
|
667
684
|
"#{prefix(prefix_options)}#{collection_name}.#{format.extension}#{query_string(query_options)}"
|
668
685
|
end
|
@@ -678,7 +695,7 @@ module ActiveResource
|
|
678
695
|
# Returns the new resource instance.
|
679
696
|
#
|
680
697
|
def build(attributes = {})
|
681
|
-
attrs = connection.get("#{new_element_path}").merge(attributes)
|
698
|
+
attrs = self.format.decode(connection.get("#{new_element_path}").body).merge(attributes)
|
682
699
|
self.new(attrs)
|
683
700
|
end
|
684
701
|
|
@@ -842,6 +859,14 @@ module ActiveResource
|
|
842
859
|
end
|
843
860
|
|
844
861
|
private
|
862
|
+
|
863
|
+
def check_prefix_options(prefix_options)
|
864
|
+
p_options = HashWithIndifferentAccess.new(prefix_options)
|
865
|
+
prefix_parameters.each do |p|
|
866
|
+
raise(MissingPrefixParam, "#{p} prefix_option is missing") if p_options[p].blank?
|
867
|
+
end
|
868
|
+
end
|
869
|
+
|
845
870
|
# Find every resource
|
846
871
|
def find_every(options)
|
847
872
|
begin
|
@@ -850,11 +875,11 @@ module ActiveResource
|
|
850
875
|
instantiate_collection(get(from, options[:params]))
|
851
876
|
when String
|
852
877
|
path = "#{from}#{query_string(options[:params])}"
|
853
|
-
instantiate_collection(connection.get(path, headers) || [])
|
878
|
+
instantiate_collection(format.decode(connection.get(path, headers).body) || [])
|
854
879
|
else
|
855
880
|
prefix_options, query_options = split_options(options[:params])
|
856
881
|
path = collection_path(prefix_options, query_options)
|
857
|
-
instantiate_collection( (connection.get(path, headers) || []), prefix_options )
|
882
|
+
instantiate_collection( (format.decode(connection.get(path, headers).body) || []), prefix_options )
|
858
883
|
end
|
859
884
|
rescue ActiveResource::ResourceNotFound
|
860
885
|
# Swallowing ResourceNotFound exceptions and return nil - as per
|
@@ -870,7 +895,7 @@ module ActiveResource
|
|
870
895
|
instantiate_record(get(from, options[:params]))
|
871
896
|
when String
|
872
897
|
path = "#{from}#{query_string(options[:params])}"
|
873
|
-
instantiate_record(connection.get(path, headers))
|
898
|
+
instantiate_record(format.decode(connection.get(path, headers).body))
|
874
899
|
end
|
875
900
|
end
|
876
901
|
|
@@ -878,7 +903,7 @@ module ActiveResource
|
|
878
903
|
def find_single(scope, options)
|
879
904
|
prefix_options, query_options = split_options(options[:params])
|
880
905
|
path = element_path(scope, prefix_options, query_options)
|
881
|
-
instantiate_record(connection.get(path, headers), prefix_options)
|
906
|
+
instantiate_record(format.decode(connection.get(path, headers).body), prefix_options)
|
882
907
|
end
|
883
908
|
|
884
909
|
def instantiate_collection(collection, prefix_options = {})
|
@@ -886,7 +911,7 @@ module ActiveResource
|
|
886
911
|
end
|
887
912
|
|
888
913
|
def instantiate_record(record, prefix_options = {})
|
889
|
-
new(record).tap do |resource|
|
914
|
+
new(record, true).tap do |resource|
|
890
915
|
resource.prefix_options = prefix_options
|
891
916
|
end
|
892
917
|
end
|
@@ -894,12 +919,12 @@ module ActiveResource
|
|
894
919
|
|
895
920
|
# Accepts a URI and creates the site URI from that.
|
896
921
|
def create_site_uri_from(site)
|
897
|
-
site.is_a?(URI) ? site.dup :
|
922
|
+
site.is_a?(URI) ? site.dup : URI.parser.parse(site)
|
898
923
|
end
|
899
924
|
|
900
925
|
# Accepts a URI and creates the proxy URI from that.
|
901
926
|
def create_proxy_uri_from(proxy)
|
902
|
-
proxy.is_a?(URI) ? proxy.dup :
|
927
|
+
proxy.is_a?(URI) ? proxy.dup : URI.parser.parse(proxy)
|
903
928
|
end
|
904
929
|
|
905
930
|
# contains a set of the current prefix parameters.
|
@@ -924,10 +949,6 @@ module ActiveResource
|
|
924
949
|
|
925
950
|
[ prefix_options, query_options ]
|
926
951
|
end
|
927
|
-
|
928
|
-
def uri_parser
|
929
|
-
@uri_parser ||= URI.const_defined?(:Parser) ? URI::Parser.new : URI
|
930
|
-
end
|
931
952
|
end
|
932
953
|
|
933
954
|
attr_accessor :attributes #:nodoc:
|
@@ -959,9 +980,10 @@ module ActiveResource
|
|
959
980
|
#
|
960
981
|
# my_other_course = Course.new(:name => "Philosophy: Reason and Being", :lecturer => "Ralph Cling")
|
961
982
|
# my_other_course.save
|
962
|
-
def initialize(attributes = {})
|
983
|
+
def initialize(attributes = {}, persisted = false)
|
963
984
|
@attributes = {}.with_indifferent_access
|
964
985
|
@prefix_options = {}
|
986
|
+
@persisted = persisted
|
965
987
|
load(attributes)
|
966
988
|
end
|
967
989
|
|
@@ -987,10 +1009,7 @@ module ActiveResource
|
|
987
1009
|
# not_ryan.hash # => {:not => "an ARes instance"}
|
988
1010
|
def clone
|
989
1011
|
# Clone all attributes except the pk and any nested ARes
|
990
|
-
cloned = attributes.reject {|k,v| k == self.class.primary_key || v.is_a?(ActiveResource::Base)}.
|
991
|
-
attrs[k] = v.clone
|
992
|
-
attrs
|
993
|
-
end
|
1012
|
+
cloned = Hash[attributes.reject {|k,v| k == self.class.primary_key || v.is_a?(ActiveResource::Base)}.map { |k, v| [k, v.clone] }]
|
994
1013
|
# Form the new resource - bypass initialize of resource with 'new' as that will call 'load' which
|
995
1014
|
# attempts to convert hashes into member objects and arrays into collections of objects. We want
|
996
1015
|
# the raw objects to be cloned so we bypass load by directly setting the attributes hash.
|
@@ -1014,7 +1033,7 @@ module ActiveResource
|
|
1014
1033
|
# is_new.new? # => false
|
1015
1034
|
#
|
1016
1035
|
def new?
|
1017
|
-
|
1036
|
+
!persisted?
|
1018
1037
|
end
|
1019
1038
|
alias :new_record? :new?
|
1020
1039
|
|
@@ -1031,7 +1050,7 @@ module ActiveResource
|
|
1031
1050
|
# not_persisted.persisted? # => true
|
1032
1051
|
#
|
1033
1052
|
def persisted?
|
1034
|
-
|
1053
|
+
@persisted
|
1035
1054
|
end
|
1036
1055
|
|
1037
1056
|
# Gets the <tt>\id</tt> attribute of the resource.
|
@@ -1076,7 +1095,7 @@ module ActiveResource
|
|
1076
1095
|
end
|
1077
1096
|
|
1078
1097
|
# Delegates to id in order to allow two resources of the same type and \id to work with something like:
|
1079
|
-
# [Person.find
|
1098
|
+
# [(a = Person.find 1), (b = Person.find 2)] & [(c = Person.find 1), (d = Person.find 4)] # => [a]
|
1080
1099
|
def hash
|
1081
1100
|
id.hash
|
1082
1101
|
end
|
@@ -1220,9 +1239,10 @@ module ActiveResource
|
|
1220
1239
|
@attributes[key.to_s] =
|
1221
1240
|
case value
|
1222
1241
|
when Array
|
1223
|
-
resource =
|
1242
|
+
resource = nil
|
1224
1243
|
value.map do |attrs|
|
1225
1244
|
if attrs.is_a?(Hash)
|
1245
|
+
resource ||= find_or_create_resource_for_collection(key)
|
1226
1246
|
resource.new(attrs)
|
1227
1247
|
else
|
1228
1248
|
attrs.duplicable? ? attrs.dup : attrs
|
@@ -1232,7 +1252,7 @@ module ActiveResource
|
|
1232
1252
|
resource = find_or_create_resource_for(key)
|
1233
1253
|
resource.new(value)
|
1234
1254
|
else
|
1235
|
-
value.dup
|
1255
|
+
value.duplicable? ? value.dup : value
|
1236
1256
|
end
|
1237
1257
|
end
|
1238
1258
|
self
|
@@ -1318,8 +1338,9 @@ module ActiveResource
|
|
1318
1338
|
end
|
1319
1339
|
|
1320
1340
|
def load_attributes_from_response(response)
|
1321
|
-
if response['Content-Length'] != "0" && response.body.strip.size > 0
|
1341
|
+
if !response['Content-Length'].blank? && response['Content-Length'] != "0" && !response.body.nil? && response.body.strip.size > 0
|
1322
1342
|
load(self.class.format.decode(response.body))
|
1343
|
+
@persisted = true
|
1323
1344
|
end
|
1324
1345
|
end
|
1325
1346
|
|
@@ -1347,34 +1368,44 @@ module ActiveResource
|
|
1347
1368
|
end
|
1348
1369
|
|
1349
1370
|
# Tries to find a resource in a non empty list of nested modules
|
1350
|
-
#
|
1351
|
-
def
|
1371
|
+
# if it fails, then the resource is created
|
1372
|
+
def find_or_create_resource_in_modules(resource_name, module_names)
|
1352
1373
|
receiver = Object
|
1353
1374
|
namespaces = module_names[0, module_names.size-1].map do |module_name|
|
1354
1375
|
receiver = receiver.const_get(module_name)
|
1355
1376
|
end
|
1356
|
-
|
1357
|
-
|
1377
|
+
const_args = RUBY_VERSION < "1.9" ? [resource_name] : [resource_name, false]
|
1378
|
+
if namespace = namespaces.reverse.detect { |ns| ns.const_defined?(*const_args) }
|
1379
|
+
namespace.const_get(*const_args)
|
1358
1380
|
else
|
1359
|
-
|
1381
|
+
create_resource_for(resource_name)
|
1360
1382
|
end
|
1361
1383
|
end
|
1362
1384
|
|
1363
1385
|
# Tries to find a resource for a given name; if it fails, then the resource is created
|
1364
1386
|
def find_or_create_resource_for(name)
|
1365
1387
|
resource_name = name.to_s.camelize
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
self.class.const_get(resource_name)
|
1371
|
-
end
|
1372
|
-
rescue NameError
|
1373
|
-
if self.class.const_defined?(resource_name)
|
1374
|
-
resource = self.class.const_get(resource_name)
|
1388
|
+
|
1389
|
+
const_args = RUBY_VERSION < "1.9" ? [resource_name] : [resource_name, false]
|
1390
|
+
if self.class.const_defined?(*const_args)
|
1391
|
+
self.class.const_get(*const_args)
|
1375
1392
|
else
|
1376
|
-
|
1393
|
+
ancestors = self.class.name.split("::")
|
1394
|
+
if ancestors.size > 1
|
1395
|
+
find_or_create_resource_in_modules(resource_name, ancestors)
|
1396
|
+
else
|
1397
|
+
if Object.const_defined?(*const_args)
|
1398
|
+
Object.const_get(*const_args)
|
1399
|
+
else
|
1400
|
+
create_resource_for(resource_name)
|
1401
|
+
end
|
1402
|
+
end
|
1377
1403
|
end
|
1404
|
+
end
|
1405
|
+
|
1406
|
+
# Create and return a class definition for a resource inside the current resource
|
1407
|
+
def create_resource_for(resource_name)
|
1408
|
+
resource = self.class.const_set(resource_name, Class.new(ActiveResource::Base))
|
1378
1409
|
resource.prefix = self.class.prefix
|
1379
1410
|
resource.site = self.class.site
|
1380
1411
|
resource
|
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'active_support/core_ext/benchmark'
|
2
|
+
require 'active_support/core_ext/uri'
|
3
|
+
require 'active_support/core_ext/object/inclusion'
|
2
4
|
require 'net/https'
|
3
5
|
require 'date'
|
4
6
|
require 'time'
|
@@ -31,21 +33,20 @@ module ActiveResource
|
|
31
33
|
def initialize(site, format = ActiveResource::Formats::XmlFormat)
|
32
34
|
raise ArgumentError, 'Missing site URI' unless site
|
33
35
|
@user = @password = nil
|
34
|
-
@uri_parser = URI.const_defined?(:Parser) ? URI::Parser.new : URI
|
35
36
|
self.site = site
|
36
37
|
self.format = format
|
37
38
|
end
|
38
39
|
|
39
40
|
# Set URI for remote service.
|
40
41
|
def site=(site)
|
41
|
-
@site = site.is_a?(URI) ? site :
|
42
|
-
@user =
|
43
|
-
@password =
|
42
|
+
@site = site.is_a?(URI) ? site : URI.parser.parse(site)
|
43
|
+
@user = URI.parser.unescape(@site.user) if @site.user
|
44
|
+
@password = URI.parser.unescape(@site.password) if @site.password
|
44
45
|
end
|
45
46
|
|
46
47
|
# Set the proxy for remote service.
|
47
48
|
def proxy=(proxy)
|
48
|
-
@proxy = proxy.is_a?(URI) ? proxy :
|
49
|
+
@proxy = proxy.is_a?(URI) ? proxy : URI.parser.parse(proxy)
|
49
50
|
end
|
50
51
|
|
51
52
|
# Sets the user for remote service.
|
@@ -76,7 +77,7 @@ module ActiveResource
|
|
76
77
|
# Executes a GET request.
|
77
78
|
# Used to get (find) resources.
|
78
79
|
def get(path, headers = {})
|
79
|
-
with_auth {
|
80
|
+
with_auth { request(:get, path, build_request_headers(headers, :get, self.site.merge(path))) }
|
80
81
|
end
|
81
82
|
|
82
83
|
# Executes a DELETE request (see HTTP protocol documentation if unfamiliar).
|
@@ -277,7 +278,7 @@ module ActiveResource
|
|
277
278
|
def legitimize_auth_type(auth_type)
|
278
279
|
return :basic if auth_type.nil?
|
279
280
|
auth_type = auth_type.to_sym
|
280
|
-
[:basic, :digest]
|
281
|
+
auth_type.in?([:basic, :digest]) ? auth_type : :basic
|
281
282
|
end
|
282
283
|
end
|
283
284
|
end
|
@@ -54,7 +54,7 @@ module ActiveResource
|
|
54
54
|
#
|
55
55
|
# Person.find(:all, :from => :active)
|
56
56
|
def get(custom_method_name, options = {})
|
57
|
-
connection.get(custom_method_collection_url(custom_method_name, options), headers)
|
57
|
+
format.decode(connection.get(custom_method_collection_url(custom_method_name, options), headers).body)
|
58
58
|
end
|
59
59
|
|
60
60
|
def post(custom_method_name, options = {}, body = '')
|
@@ -85,7 +85,7 @@ module ActiveResource
|
|
85
85
|
|
86
86
|
module InstanceMethods
|
87
87
|
def get(method_name, options = {})
|
88
|
-
connection.get(custom_method_element_url(method_name, options), self.class.headers)
|
88
|
+
self.class.format.decode(connection.get(custom_method_element_url(method_name, options), self.class.headers).body)
|
89
89
|
end
|
90
90
|
|
91
91
|
def post(method_name, options = {}, body = nil)
|
@@ -36,6 +36,9 @@ module ActiveResource
|
|
36
36
|
def to_s; response['Location'] ? "#{super} => #{response['Location']}" : super; end
|
37
37
|
end
|
38
38
|
|
39
|
+
# Raised when ...
|
40
|
+
class MissingPrefixParam < ArgumentError; end # :nodoc:
|
41
|
+
|
39
42
|
# 4xx Client Error
|
40
43
|
class ClientError < ConnectionError; end # :nodoc:
|
41
44
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_support/core_ext/kernel/reporting'
|
2
|
+
require 'active_support/core_ext/object/inclusion'
|
2
3
|
|
3
4
|
module ActiveResource
|
4
5
|
class InvalidRequestError < StandardError; end #:nodoc:
|
@@ -8,8 +9,8 @@ module ActiveResource
|
|
8
9
|
# requests.
|
9
10
|
#
|
10
11
|
# To test your Active Resource model, you simply call the ActiveResource::HttpMock.respond_to
|
11
|
-
# method with an attached block.
|
12
|
-
# each request should return.
|
12
|
+
# method with an attached block. The block declares a set of URIs with expected input, and the output
|
13
|
+
# each request should return. The passed in block has any number of entries in the following generalized
|
13
14
|
# format:
|
14
15
|
#
|
15
16
|
# mock.http_method(path, request_headers = {}, body = nil, status = 200, response_headers = {})
|
@@ -28,7 +29,7 @@ module ActiveResource
|
|
28
29
|
# <tt>request_headers</tt> listed above.
|
29
30
|
#
|
30
31
|
# In order for a mock to deliver its content, the incoming request must match by the <tt>http_method</tt>,
|
31
|
-
# +path+ and <tt>request_headers</tt>.
|
32
|
+
# +path+ and <tt>request_headers</tt>. If no match is found an +InvalidRequestError+ exception
|
32
33
|
# will be raised showing you what request it could not find a response for and also what requests and response
|
33
34
|
# pairs have been recorded so you can create a new mock for that request.
|
34
35
|
#
|
@@ -60,15 +61,26 @@ module ActiveResource
|
|
60
61
|
# end
|
61
62
|
module_eval <<-EOE, __FILE__, __LINE__ + 1
|
62
63
|
def #{method}(path, request_headers = {}, body = nil, status = 200, response_headers = {})
|
63
|
-
|
64
|
+
request = Request.new(:#{method}, path, nil, request_headers)
|
65
|
+
response = Response.new(body || "", status, response_headers)
|
66
|
+
|
67
|
+
delete_duplicate_responses(request)
|
68
|
+
|
69
|
+
@responses << [request, response]
|
64
70
|
end
|
65
71
|
EOE
|
66
72
|
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def delete_duplicate_responses(request)
|
77
|
+
@responses.delete_if {|r| r[0] == request }
|
78
|
+
end
|
67
79
|
end
|
68
80
|
|
69
81
|
class << self
|
70
82
|
|
71
|
-
# Returns an array of all request objects that have been sent to the mock.
|
83
|
+
# Returns an array of all request objects that have been sent to the mock. You can use this to check
|
72
84
|
# if your model actually sent an HTTP request.
|
73
85
|
#
|
74
86
|
# ==== Example
|
@@ -93,18 +105,18 @@ module ActiveResource
|
|
93
105
|
end
|
94
106
|
|
95
107
|
# Returns the list of requests and their mocked responses. Look up a
|
96
|
-
# response for a request using responses.assoc(request)
|
108
|
+
# response for a request using <tt>responses.assoc(request)</tt>.
|
97
109
|
def responses
|
98
110
|
@@responses ||= []
|
99
111
|
end
|
100
112
|
|
101
113
|
# Accepts a block which declares a set of requests and responses for the HttpMock to respond to in
|
102
114
|
# the following format:
|
103
|
-
#
|
115
|
+
#
|
104
116
|
# mock.http_method(path, request_headers = {}, body = nil, status = 200, response_headers = {})
|
105
|
-
#
|
117
|
+
#
|
106
118
|
# === Example
|
107
|
-
#
|
119
|
+
#
|
108
120
|
# @matz = { :id => 1, :name => "Matz" }.to_xml(:root => "person")
|
109
121
|
# ActiveResource::HttpMock.respond_to do |mock|
|
110
122
|
# mock.post "/people.xml", {}, @matz, 201, "Location" => "/people/1.xml"
|
@@ -112,73 +124,91 @@ module ActiveResource
|
|
112
124
|
# mock.put "/people/1.xml", {}, nil, 204
|
113
125
|
# mock.delete "/people/1.xml", {}, nil, 200
|
114
126
|
# end
|
115
|
-
#
|
127
|
+
#
|
116
128
|
# Alternatively, accepts a hash of <tt>{Request => Response}</tt> pairs allowing you to generate
|
117
129
|
# these the following format:
|
118
|
-
#
|
130
|
+
#
|
119
131
|
# ActiveResource::Request.new(method, path, body, request_headers)
|
120
132
|
# ActiveResource::Response.new(body, status, response_headers)
|
121
|
-
#
|
133
|
+
#
|
122
134
|
# === Example
|
123
|
-
#
|
135
|
+
#
|
124
136
|
# Request.new(:#{method}, path, nil, request_headers)
|
125
|
-
#
|
137
|
+
#
|
126
138
|
# @matz = { :id => 1, :name => "Matz" }.to_xml(:root => "person")
|
127
139
|
#
|
128
140
|
# create_matz = ActiveResource::Request.new(:post, '/people.xml', @matz, {})
|
129
141
|
# created_response = ActiveResource::Response.new("", 201, {"Location" => "/people/1.xml"})
|
130
142
|
# get_matz = ActiveResource::Request.new(:get, '/people/1.xml', nil)
|
131
143
|
# ok_response = ActiveResource::Response.new("", 200, {})
|
132
|
-
#
|
144
|
+
#
|
133
145
|
# pairs = {create_matz => created_response, get_matz => ok_response}
|
134
|
-
#
|
146
|
+
#
|
135
147
|
# ActiveResource::HttpMock.respond_to(pairs)
|
136
148
|
#
|
137
149
|
# Note, by default, every time you call +respond_to+, any previous request and response pairs stored
|
138
150
|
# in HttpMock will be deleted giving you a clean slate to work on.
|
139
|
-
#
|
151
|
+
#
|
140
152
|
# If you want to override this behaviour, pass in +false+ as the last argument to +respond_to+
|
141
|
-
#
|
153
|
+
#
|
142
154
|
# === Example
|
143
|
-
#
|
155
|
+
#
|
144
156
|
# ActiveResource::HttpMock.respond_to do |mock|
|
145
157
|
# mock.send(:get, "/people/1", {}, "XML1")
|
146
158
|
# end
|
147
159
|
# ActiveResource::HttpMock.responses.length #=> 1
|
148
|
-
#
|
160
|
+
#
|
149
161
|
# ActiveResource::HttpMock.respond_to(false) do |mock|
|
150
162
|
# mock.send(:get, "/people/2", {}, "XML2")
|
151
163
|
# end
|
152
164
|
# ActiveResource::HttpMock.responses.length #=> 2
|
153
|
-
#
|
165
|
+
#
|
154
166
|
# This also works with passing in generated pairs of requests and responses, again, just pass in false
|
155
167
|
# as the last argument:
|
156
|
-
#
|
168
|
+
#
|
157
169
|
# === Example
|
158
|
-
#
|
170
|
+
#
|
159
171
|
# ActiveResource::HttpMock.respond_to do |mock|
|
160
172
|
# mock.send(:get, "/people/1", {}, "XML1")
|
161
173
|
# end
|
162
174
|
# ActiveResource::HttpMock.responses.length #=> 1
|
163
|
-
#
|
175
|
+
#
|
164
176
|
# get_matz = ActiveResource::Request.new(:get, '/people/1.xml', nil)
|
165
177
|
# ok_response = ActiveResource::Response.new("", 200, {})
|
166
|
-
#
|
178
|
+
#
|
167
179
|
# pairs = {get_matz => ok_response}
|
168
180
|
#
|
169
181
|
# ActiveResource::HttpMock.respond_to(pairs, false)
|
170
182
|
# ActiveResource::HttpMock.responses.length #=> 2
|
183
|
+
#
|
184
|
+
# # If you add a response with an existing request, it will be replaced
|
185
|
+
#
|
186
|
+
# fail_response = ActiveResource::Response.new("", 404, {})
|
187
|
+
# pairs = {get_matz => fail_response}
|
188
|
+
#
|
189
|
+
# ActiveResource::HttpMock.respond_to(pairs, false)
|
190
|
+
# ActiveResource::HttpMock.responses.length #=> 2
|
191
|
+
#
|
171
192
|
def respond_to(*args) #:yields: mock
|
172
193
|
pairs = args.first || {}
|
173
194
|
reset! if args.last.class != FalseClass
|
174
|
-
|
195
|
+
|
175
196
|
if block_given?
|
176
197
|
yield Responder.new(responses)
|
177
198
|
else
|
199
|
+
delete_responses_to_replace pairs.to_a
|
200
|
+
responses.concat pairs.to_a
|
178
201
|
Responder.new(responses)
|
179
202
|
end
|
180
203
|
end
|
181
204
|
|
205
|
+
def delete_responses_to_replace(new_responses)
|
206
|
+
new_responses.each{|nr|
|
207
|
+
request_to_remove = nr[0]
|
208
|
+
@@responses = responses.delete_if{|r| r[0] == request_to_remove}
|
209
|
+
}
|
210
|
+
end
|
211
|
+
|
182
212
|
# Deletes all logged requests and responses.
|
183
213
|
def reset!
|
184
214
|
requests.clear
|
@@ -269,8 +299,10 @@ module ActiveResource
|
|
269
299
|
end
|
270
300
|
end
|
271
301
|
|
302
|
+
# Returns true if code is 2xx,
|
303
|
+
# false otherwise.
|
272
304
|
def success?
|
273
|
-
(200..299)
|
305
|
+
code.in?(200..299)
|
274
306
|
end
|
275
307
|
|
276
308
|
def [](key)
|
@@ -281,6 +313,8 @@ module ActiveResource
|
|
281
313
|
headers[key] = value
|
282
314
|
end
|
283
315
|
|
316
|
+
# Returns true if the other is a Response with an equal body, equal message
|
317
|
+
# and equal headers. Otherwise it returns false.
|
284
318
|
def ==(other)
|
285
319
|
if (other.is_a?(Response))
|
286
320
|
other.body == body && other.message == message && other.headers == headers
|
@@ -5,6 +5,14 @@ module ActiveResource
|
|
5
5
|
|
6
6
|
included do
|
7
7
|
%w( create save update destroy ).each do |method|
|
8
|
+
# def create_with_notifications(*args, &block)
|
9
|
+
# notify_observers(:before_create)
|
10
|
+
# if result = create_without_notifications(*args, &block)
|
11
|
+
# notify_observers(:after_create)
|
12
|
+
# end
|
13
|
+
# result
|
14
|
+
# end
|
15
|
+
# alias_method_chain(create, :notifications)
|
8
16
|
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
9
17
|
def #{method}_with_notifications(*args, &block)
|
10
18
|
notify_observers(:before_#{method})
|
@@ -4,7 +4,7 @@ module ActiveResource # :nodoc:
|
|
4
4
|
class Schema # :nodoc:
|
5
5
|
# attributes can be known to be one of these types. They are easy to
|
6
6
|
# cast to/from.
|
7
|
-
KNOWN_ATTRIBUTE_TYPES = %w( string integer float )
|
7
|
+
KNOWN_ATTRIBUTE_TYPES = %w( string text integer float decimal datetime timestamp time date binary boolean )
|
8
8
|
|
9
9
|
# An array of attribute definitions, representing the attributes that
|
10
10
|
# have been defined.
|
@@ -39,8 +39,6 @@ module ActiveResource # :nodoc:
|
|
39
39
|
|
40
40
|
# The following are the attribute types supported by Active Resource
|
41
41
|
# migrations.
|
42
|
-
# TODO: We should eventually support all of these:
|
43
|
-
# %w( string text integer float decimal datetime timestamp time date binary boolean ).each do |attr_type|
|
44
42
|
KNOWN_ATTRIBUTE_TYPES.each do |attr_type|
|
45
43
|
class_eval <<-EOV, __FILE__, __LINE__ + 1
|
46
44
|
def #{attr_type.to_s}(*args)
|
@@ -8,12 +8,12 @@ module ActiveResource
|
|
8
8
|
# Active Resource validation is reported to and from this object, which is used by Base#save
|
9
9
|
# to determine whether the object in a valid state to be saved. See usage example in Validations.
|
10
10
|
class Errors < ActiveModel::Errors
|
11
|
-
# Grabs errors from an array of messages (like ActiveRecord::Validations)
|
11
|
+
# Grabs errors from an array of messages (like ActiveRecord::Validations).
|
12
12
|
# The second parameter directs the errors cache to be cleared (default)
|
13
|
-
# or not (by passing true)
|
13
|
+
# or not (by passing true).
|
14
14
|
def from_array(messages, save_cache = false)
|
15
15
|
clear unless save_cache
|
16
|
-
humanized_attributes = @base.attributes.keys.
|
16
|
+
humanized_attributes = Hash[@base.attributes.keys.map { |attr_name| [attr_name.humanize, attr_name] }]
|
17
17
|
messages.each do |message|
|
18
18
|
attr_message = humanized_attributes.keys.detect do |attr_name|
|
19
19
|
if message[0, attr_name.size + 1] == "#{attr_name} "
|
@@ -68,20 +68,12 @@ module ActiveResource
|
|
68
68
|
|
69
69
|
# Validate a resource and save (POST) it to the remote web service.
|
70
70
|
# If any local validations fail - the save (POST) will not be attempted.
|
71
|
-
def save_with_validation(options=
|
72
|
-
perform_validation =
|
73
|
-
when Hash
|
74
|
-
options[:validate] != false
|
75
|
-
when NilClass
|
76
|
-
true
|
77
|
-
else
|
78
|
-
ActiveSupport::Deprecation.warn "save(#{options}) is deprecated, please give save(:validate => #{options}) instead", caller
|
79
|
-
options
|
80
|
-
end
|
71
|
+
def save_with_validation(options={})
|
72
|
+
perform_validation = options[:validate] != false
|
81
73
|
|
82
74
|
# clear the remote validations so they don't interfere with the local
|
83
75
|
# ones. Otherwise we get an endless loop and can never change the
|
84
|
-
# fields so as to make the resource valid
|
76
|
+
# fields so as to make the resource valid.
|
85
77
|
@remote_errors = nil
|
86
78
|
if perform_validation && valid? || !perform_validation
|
87
79
|
save_without_validation
|
@@ -92,7 +84,7 @@ module ActiveResource
|
|
92
84
|
rescue ResourceInvalid => error
|
93
85
|
# cache the remote errors because every call to <tt>valid?</tt> clears
|
94
86
|
# all errors. We must keep a copy to add these back after local
|
95
|
-
# validations
|
87
|
+
# validations.
|
96
88
|
@remote_errors = error
|
97
89
|
load_remote_errors(@remote_errors, true)
|
98
90
|
false
|
@@ -100,7 +92,7 @@ module ActiveResource
|
|
100
92
|
|
101
93
|
|
102
94
|
# Loads the set of remote errors into the object's Errors based on the
|
103
|
-
# content-type of the error-block received
|
95
|
+
# content-type of the error-block received.
|
104
96
|
def load_remote_errors(remote_errors, save_cache = false ) #:nodoc:
|
105
97
|
case self.class.format
|
106
98
|
when ActiveResource::Formats[:xml]
|
metadata
CHANGED
@@ -1,53 +1,52 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: activeresource
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: 6
|
5
|
+
version: 3.1.0.beta1
|
5
6
|
platform: ruby
|
6
|
-
authors:
|
7
|
+
authors:
|
7
8
|
- David Heinemeier Hansson
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
|
13
|
+
date: 2011-05-04 00:00:00 -05:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
14
17
|
name: activesupport
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - '='
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 3.0.20
|
20
|
-
type: :runtime
|
21
18
|
prerelease: false
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
name: activemodel
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - '='
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 3.0.20
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - "="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 3.1.0.beta1
|
34
25
|
type: :runtime
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activemodel
|
35
29
|
prerelease: false
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - "="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 3.1.0.beta1
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id002
|
38
|
+
description: REST on Rails. Wrap your RESTful web app with Ruby classes and work with them like Active Record models.
|
43
39
|
email: david@loudthinking.com
|
44
40
|
executables: []
|
41
|
+
|
45
42
|
extensions: []
|
46
|
-
|
43
|
+
|
44
|
+
extra_rdoc_files:
|
47
45
|
- README.rdoc
|
48
|
-
files:
|
46
|
+
files:
|
49
47
|
- CHANGELOG
|
50
48
|
- README.rdoc
|
49
|
+
- examples/performance.rb
|
51
50
|
- examples/simple.rb
|
52
51
|
- lib/active_resource/base.rb
|
53
52
|
- lib/active_resource/connection.rb
|
@@ -64,29 +63,34 @@ files:
|
|
64
63
|
- lib/active_resource/validations.rb
|
65
64
|
- lib/active_resource/version.rb
|
66
65
|
- lib/active_resource.rb
|
66
|
+
has_rdoc: true
|
67
67
|
homepage: http://www.rubyonrails.org
|
68
68
|
licenses: []
|
69
|
-
|
69
|
+
|
70
70
|
post_install_message:
|
71
|
-
rdoc_options:
|
72
|
-
-
|
71
|
+
rdoc_options:
|
72
|
+
- --main
|
73
73
|
- README.rdoc
|
74
|
-
require_paths:
|
74
|
+
require_paths:
|
75
75
|
- lib
|
76
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
-
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
78
79
|
- - ">="
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
+
- !ruby/object:Gem::Version
|
80
81
|
version: 1.8.7
|
81
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 1.3.1
|
86
88
|
requirements: []
|
89
|
+
|
87
90
|
rubyforge_project: activeresource
|
88
|
-
rubygems_version:
|
91
|
+
rubygems_version: 1.6.2
|
89
92
|
signing_key:
|
90
|
-
specification_version:
|
93
|
+
specification_version: 3
|
91
94
|
summary: REST modeling framework (part of Rails).
|
92
95
|
test_files: []
|
96
|
+
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 12c4fd12a01df590f853606ab4b5f6e5661e8d8f
|
4
|
-
data.tar.gz: 5ee8a3bfb4aaf107fe9a7341dce4a39badca74e5
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: 7e7719bc289dcce220968d1f44d89c22046df8b1934dbd484c6334b4c21eb336a6eec629b62e5dd8f08d7c7f3d032366a300a854ca3613f95908066b013a9a80
|
7
|
-
data.tar.gz: 1cc60aa0ab2e1629d4853b734c1dd8fabf7ff34b88523f6d7e43756cf8ed054d17144fe37cd8d46f84e7ad1e54909e76ba5db449d85c1e99b5a8d32f374d567f
|