kelredd-resourceful 0.7.24 → 0.7.25
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.
- data/Rakefile +1 -0
- data/lib/resourceful.rb +1 -1
- data/lib/resourceful/agent/base.rb +59 -59
- data/lib/resourceful/agent/mechanize.rb +33 -33
- data/lib/resourceful/agent/rest_client.rb +47 -47
- data/lib/resourceful/exceptions.rb +20 -20
- data/lib/resourceful/extensions.rb +34 -182
- data/lib/resourceful/model/activerecord_associations.rb +77 -78
- data/lib/resourceful/model/attribute_types.rb +34 -35
- data/lib/resourceful/model/base.rb +164 -164
- data/lib/resourceful/model/embedded_associations.rb +56 -57
- data/lib/resourceful/model/external_associations.rb +77 -78
- data/lib/resourceful/model/findable.rb +93 -94
- data/lib/resourceful/model/json.rb +62 -62
- data/lib/resourceful/model/xml.rb +70 -70
- data/lib/resourceful/resource/cache.rb +37 -42
- data/lib/resourceful/resource/format.rb +43 -47
- data/lib/resourceful/shoulda/test_unit.rb +90 -112
- data/lib/resourceful/version.rb +1 -1
- metadata +12 -2
@@ -1,63 +1,62 @@
|
|
1
|
-
module Resourceful
|
2
|
-
|
3
|
-
module EmbeddedAssociations
|
4
|
-
|
5
|
-
module ClassMethods
|
6
|
-
|
7
|
-
protected
|
8
|
-
|
9
|
-
def contains_one(name, config={})
|
10
|
-
clean_name = cleanup_name(name)
|
11
|
-
config ||= {}
|
12
|
-
config[:path] ||= clean_name
|
13
|
-
raise ArgumentError, "contains_one requires a :class option to be specified" unless config[:class]
|
14
|
-
class_name = config.delete(:class).to_s
|
15
|
-
define_method(name) do
|
16
|
-
klass = self.class.get_namespaced_klass(class_name)
|
17
|
-
raise ArgumentError, "contains_one :class '#{class_name}' is not defined in any given namespaces" if klass.nil?
|
18
|
-
instance_variable_get("@#{clean_name}") || \
|
19
|
-
instance_variable_set("@#{clean_name}", \
|
20
|
-
if (c = child(config))
|
21
|
-
klass.new(c) rescue c
|
22
|
-
else
|
23
|
-
c
|
24
|
-
end
|
25
|
-
)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def contains_many(name, config={})
|
30
|
-
clean_name = cleanup_name(name)
|
31
|
-
config ||= {}
|
32
|
-
config[:path] ||= clean_name
|
33
|
-
raise ArgumentError, "contains_many requires a :class option to be specified" unless config[:class]
|
34
|
-
class_name = config.delete(:class).to_s
|
35
|
-
define_method(name) do
|
36
|
-
klass = self.class.get_namespaced_klass(class_name)
|
37
|
-
raise ArgumentError, "contains_many :class '#{class_name}' is not defined in any given namespaces" if klass.nil?
|
38
|
-
instance_variable_get("@#{clean_name}") || \
|
39
|
-
instance_variable_set("@#{clean_name}", \
|
40
|
-
if ((c = child(config)) && c.respond_to?(:collect))
|
41
|
-
c.collect do |item|
|
42
|
-
klass.new(item) rescue item
|
43
|
-
end
|
44
|
-
else
|
45
|
-
c
|
46
|
-
end
|
47
|
-
)
|
48
|
-
end
|
49
|
-
end
|
1
|
+
module Resourceful; end
|
2
|
+
module Resourceful::Model; end
|
50
3
|
|
51
|
-
|
4
|
+
module Resourceful::Model::EmbeddedAssociations
|
52
5
|
|
53
|
-
|
6
|
+
module ClassMethods
|
7
|
+
|
8
|
+
protected
|
9
|
+
|
10
|
+
def contains_one(name, config={})
|
11
|
+
clean_name = cleanup_name(name)
|
12
|
+
config ||= {}
|
13
|
+
config[:path] ||= clean_name
|
14
|
+
raise ArgumentError, "contains_one requires a :class option to be specified" unless config[:class]
|
15
|
+
class_name = config.delete(:class).to_s
|
16
|
+
define_method(name) do
|
17
|
+
klass = self.class.get_namespaced_klass(class_name)
|
18
|
+
raise ArgumentError, "contains_one :class '#{class_name}' is not defined in any given namespaces" if klass.nil?
|
19
|
+
instance_variable_get("@#{clean_name}") || \
|
20
|
+
instance_variable_set("@#{clean_name}", \
|
21
|
+
if (c = child(config))
|
22
|
+
klass.new(c) rescue c
|
23
|
+
else
|
24
|
+
c
|
25
|
+
end
|
26
|
+
)
|
54
27
|
end
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
28
|
+
end
|
29
|
+
|
30
|
+
def contains_many(name, config={})
|
31
|
+
clean_name = cleanup_name(name)
|
32
|
+
config ||= {}
|
33
|
+
config[:path] ||= clean_name
|
34
|
+
raise ArgumentError, "contains_many requires a :class option to be specified" unless config[:class]
|
35
|
+
class_name = config.delete(:class).to_s
|
36
|
+
define_method(name) do
|
37
|
+
klass = self.class.get_namespaced_klass(class_name)
|
38
|
+
raise ArgumentError, "contains_many :class '#{class_name}' is not defined in any given namespaces" if klass.nil?
|
39
|
+
instance_variable_get("@#{clean_name}") || \
|
40
|
+
instance_variable_set("@#{clean_name}", \
|
41
|
+
if ((c = child(config)) && c.respond_to?(:collect))
|
42
|
+
c.collect do |item|
|
43
|
+
klass.new(item) rescue item
|
44
|
+
end
|
45
|
+
else
|
46
|
+
c
|
47
|
+
end
|
48
|
+
)
|
59
49
|
end
|
60
|
-
|
61
50
|
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
module InstanceMethods
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.included(receiver)
|
58
|
+
receiver.extend ClassMethods
|
59
|
+
receiver.send :include, InstanceMethods
|
62
60
|
end
|
63
|
-
|
61
|
+
|
62
|
+
end
|
@@ -1,88 +1,87 @@
|
|
1
|
-
module Resourceful
|
2
|
-
|
3
|
-
|
1
|
+
module Resourceful; end
|
2
|
+
module Resourceful::Model; end
|
3
|
+
|
4
|
+
module Resourceful::Model::ExternalAssociations
|
4
5
|
|
5
|
-
|
6
|
+
module ClassMethods
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
33
|
-
config[foreign_key_name] = self.send(foreign_key_method)
|
34
|
-
instance_variable_set("@#{clean_name}", klass.send(find_method_name, :all, config, reload || force))
|
35
|
-
else
|
36
|
-
assoc_val
|
37
|
-
end
|
8
|
+
protected
|
9
|
+
|
10
|
+
def has_many(name, config={})
|
11
|
+
clean_name = cleanup_name(name)
|
12
|
+
config ||= {}
|
13
|
+
raise ArgumentError, "has_many requires a :class option to be specified" unless config[:class]
|
14
|
+
class_name = config.delete(:class).to_s
|
15
|
+
find_method_name = (config.delete(:method) || 'find').to_s
|
16
|
+
force = config.delete(:force) || false
|
17
|
+
foreign_key_name = config.delete(:foreign_key) || "#{self.name.demodulize.underscore}_id"
|
18
|
+
foreign_key_method = config.delete(:foreign_key_method) || 'id'
|
19
|
+
Resourceful.add_to_associations(self.name, clean_name, {
|
20
|
+
:type => :has_many,
|
21
|
+
:class_name => class_name,
|
22
|
+
:foreign_key_name => foreign_key_name,
|
23
|
+
:foreign_key_method => foreign_key_method,
|
24
|
+
:find_method_name => find_method_name
|
25
|
+
})
|
26
|
+
define_method(name) do |*args|
|
27
|
+
reload = args.first || false
|
28
|
+
if reload || (assoc_val = instance_variable_get("@#{clean_name}")).nil?
|
29
|
+
klass = self.class.get_namespaced_klass(class_name)
|
30
|
+
raise ArgumentError, "has_many :class '#{class_name}' is not defined in any given namespaces" if klass.nil?
|
31
|
+
unless klass.respond_to?(find_method_name)
|
32
|
+
raise NotImplementedError, "has_many expects #{klass} to implement a Findable method named '#{find_method_name}'"
|
38
33
|
end
|
34
|
+
config[foreign_key_name] = self.send(foreign_key_method)
|
35
|
+
instance_variable_set("@#{clean_name}", klass.send(find_method_name, :all, config, reload || force))
|
36
|
+
else
|
37
|
+
assoc_val
|
39
38
|
end
|
39
|
+
end
|
40
|
+
end
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
68
|
-
fk = self.send(foreign_key_method)
|
69
|
-
instance_variable_set("@#{clean_name}", fk.nil? || (fk.respond_to?('empty?') && fk.empty?) ? nil : klass.send(find_method_name, fk, config, reload || force))
|
70
|
-
else
|
71
|
-
assoc_val
|
72
|
-
end
|
42
|
+
def belongs_to(name, config={})
|
43
|
+
clean_name = cleanup_name(name)
|
44
|
+
config ||= {}
|
45
|
+
raise ArgumentError, "belongs_to requires a :class option to be specified" unless config[:class]
|
46
|
+
class_name = config.delete(:class).to_s
|
47
|
+
find_method_name = (config.delete(:method) || 'find').to_s
|
48
|
+
force = config.delete(:force) || false
|
49
|
+
foreign_key_name = config.delete(:foreign_key_name) || 'id'
|
50
|
+
foreign_key_method = config.delete(:foreign_key) || "#{clean_name}_id"
|
51
|
+
Resourceful.add_to_associations(self.name, clean_name, {
|
52
|
+
:type => :belongs_to,
|
53
|
+
:class_name => class_name,
|
54
|
+
:foreign_key_name => foreign_key_name,
|
55
|
+
:foreign_key_method => foreign_key_method,
|
56
|
+
:find_method_name => find_method_name
|
57
|
+
})
|
58
|
+
define_method(name) do |*args|
|
59
|
+
reload = args.first || false
|
60
|
+
if reload || (assoc_val = instance_variable_get("@#{clean_name}")).nil?
|
61
|
+
klass = self.class.get_namespaced_klass(class_name)
|
62
|
+
raise ArgumentError, "belongs_to :class '#{class_name}' is not defined in any given namespaces" if klass.nil?
|
63
|
+
unless self.respond_to?(foreign_key_method)
|
64
|
+
raise ArgumentError, "belongs_to requires a '#{foreign_key_method}' method defined to return the foreign_key"
|
65
|
+
end
|
66
|
+
unless klass.respond_to?(find_method_name)
|
67
|
+
raise NotImplementedError, "belongs_to expects #{klass} to implement a Findable method named '#{find_method_name}'"
|
73
68
|
end
|
69
|
+
fk = self.send(foreign_key_method)
|
70
|
+
instance_variable_set("@#{clean_name}", fk.nil? || (fk.respond_to?('empty?') && fk.empty?) ? nil : klass.send(find_method_name, fk, config, reload || force))
|
71
|
+
else
|
72
|
+
assoc_val
|
74
73
|
end
|
75
|
-
|
76
|
-
end
|
77
|
-
|
78
|
-
module InstanceMethods
|
79
74
|
end
|
80
|
-
|
81
|
-
def self.included(receiver)
|
82
|
-
receiver.extend ClassMethods
|
83
|
-
receiver.send :include, InstanceMethods
|
84
|
-
end
|
85
|
-
|
86
75
|
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
module InstanceMethods
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.included(receiver)
|
83
|
+
receiver.extend ClassMethods
|
84
|
+
receiver.send :include, InstanceMethods
|
87
85
|
end
|
88
|
-
|
86
|
+
|
87
|
+
end
|
@@ -1,102 +1,101 @@
|
|
1
|
-
module Resourceful
|
2
|
-
|
3
|
-
|
1
|
+
module Resourceful; end
|
2
|
+
module Resourceful::Model; end
|
3
|
+
|
4
|
+
module Resourceful::Model::Findable
|
4
5
|
|
5
|
-
|
6
|
+
module ClassMethods
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def all
|
23
|
-
find(:all)
|
24
|
-
end
|
25
|
-
def first
|
26
|
-
find(:first)
|
27
|
-
end
|
28
|
-
def last
|
29
|
-
find(:last)
|
30
|
-
end
|
31
|
-
|
32
|
-
def findable_index
|
33
|
-
raise NotImplementedError, "Findable expects a public class method 'findable_index'"
|
34
|
-
end
|
35
|
-
|
36
|
-
def findable_search
|
37
|
-
# defaults to non namespaced downcased name of the class
|
38
|
-
self.name.demodulize.underscore.to_s.gsub(/^.*::/, '')
|
39
|
-
end
|
40
|
-
|
8
|
+
def find(id, opts={}, force=false)
|
9
|
+
opts ||= {}
|
10
|
+
opts = findable_default_opts.merge(opts) if respond_to?(:findable_default_opts)
|
11
|
+
case id
|
12
|
+
when :all
|
13
|
+
self.get_collection("#{findable_index}.#{format}", opts, findable_search, force)
|
14
|
+
when :first
|
15
|
+
self.get_collection("#{findable_index}.#{format}", opts, findable_search, force).first
|
16
|
+
when :last
|
17
|
+
self.get_collection("#{findable_index}.#{format}", opts, findable_search, force).last
|
18
|
+
else
|
19
|
+
self.get("#{findable_index}/#{id}.#{format}", opts, findable_search, force)
|
41
20
|
end
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
# default, override to customize, set to nil for push data hash style nesting
|
84
|
-
self.class.name.demodulize.underscore
|
85
|
-
end
|
86
|
-
|
87
|
-
private
|
88
|
-
|
89
|
-
def nested_attr_hash(attr_hash)
|
90
|
-
push_data_nesting ? {push_data_nesting => attr_hash} : attr_hash
|
21
|
+
end
|
22
|
+
|
23
|
+
def all
|
24
|
+
find(:all)
|
25
|
+
end
|
26
|
+
def first
|
27
|
+
find(:first)
|
28
|
+
end
|
29
|
+
def last
|
30
|
+
find(:last)
|
31
|
+
end
|
32
|
+
|
33
|
+
def findable_index
|
34
|
+
raise NotImplementedError, "Findable expects a public class method 'findable_index'"
|
35
|
+
end
|
36
|
+
|
37
|
+
def findable_search
|
38
|
+
# defaults to non namespaced downcased name of the class
|
39
|
+
self.name.demodulize.underscore.to_s.gsub(/^.*::/, '')
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
module InstanceMethods
|
45
|
+
|
46
|
+
def save
|
47
|
+
super do |attribute_hash|
|
48
|
+
if new_record?
|
49
|
+
self.push_data('post', \
|
50
|
+
"#{self.class.findable_index}.#{self.class.format}", \
|
51
|
+
{:params => self.class.findable_default_opts.merge(push_data_params)}, \
|
52
|
+
nested_attr_hash(attribute_hash), \
|
53
|
+
self.class.findable_search \
|
54
|
+
)
|
55
|
+
else
|
56
|
+
self.push_data('put', \
|
57
|
+
"#{self.class.findable_index}/#{self.id}.#{self.class.format}", \
|
58
|
+
{:params => self.class.findable_default_opts.merge(push_data_params)}, \
|
59
|
+
nested_attr_hash(attribute_hash), \
|
60
|
+
self.class.findable_search \
|
61
|
+
)
|
91
62
|
end
|
92
|
-
|
93
63
|
end
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
64
|
+
end
|
65
|
+
|
66
|
+
def destroy
|
67
|
+
super do |attribute_hash|
|
68
|
+
unless new_record?
|
69
|
+
self.push_data('delete', \
|
70
|
+
"#{self.class.findable_index}/#{self.id}.#{self.class.format}", \
|
71
|
+
{:params => self.class.findable_default_opts.merge(push_data_params)}, \
|
72
|
+
{} \
|
73
|
+
)
|
74
|
+
end
|
98
75
|
end
|
99
|
-
|
100
76
|
end
|
77
|
+
|
78
|
+
def push_data_params
|
79
|
+
# override to customize save url params
|
80
|
+
{}
|
81
|
+
end
|
82
|
+
|
83
|
+
def push_data_nesting
|
84
|
+
# default, override to customize, set to nil for push data hash style nesting
|
85
|
+
self.class.name.demodulize.underscore
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def nested_attr_hash(attr_hash)
|
91
|
+
push_data_nesting ? {push_data_nesting => attr_hash} : attr_hash
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.included(receiver)
|
97
|
+
receiver.extend ClassMethods
|
98
|
+
receiver.send :include, InstanceMethods
|
101
99
|
end
|
102
|
-
|
100
|
+
|
101
|
+
end
|