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,88 +1,87 @@
|
|
1
|
-
module Resourceful
|
2
|
-
|
3
|
-
|
1
|
+
module Resourceful; end
|
2
|
+
module Resourceful::Model; end
|
3
|
+
|
4
|
+
module Resourceful::Model::ActiverecordAssociations
|
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_resourceful(name, config={})
|
11
|
+
clean_name = Resourceful::Model::Base.cleanup_name(name)
|
12
|
+
config ||= {}
|
13
|
+
raise ArgumentError, "has_many_resourceful requires a :class_name option to be specified" unless config[:class_name]
|
14
|
+
class_name = config.delete(:class_name).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 = class_name.resourceful_constantize
|
30
|
+
raise ArgumentError, "has_many_resourceful :class_name '#{class_name}' is not defined" if klass.nil?
|
31
|
+
unless klass.respond_to?(find_method_name)
|
32
|
+
raise NotImplementedError, "has_many_resourceful 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_resourceful(name, config={})
|
43
|
+
clean_name = Resourceful::Model::Base.cleanup_name(name)
|
44
|
+
config ||= {}
|
45
|
+
raise ArgumentError, "belongs_to_resourceful requires a :class_name option to be specified" unless config[:class_name]
|
46
|
+
class_name = config.delete(:class_name).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 = class_name.resourceful_constantize
|
62
|
+
raise ArgumentError, "belongs_to_resourceful :class_name '#{class_name}' is not defined" if klass.nil?
|
63
|
+
unless self.respond_to?(foreign_key_method)
|
64
|
+
raise ArgumentError, "belongs_to_resourceful 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_resourceful 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,39 +1,38 @@
|
|
1
|
-
module Resourceful
|
2
|
-
|
3
|
-
module AttributeTypes
|
4
|
-
|
5
|
-
module ClassMethods
|
6
|
-
|
7
|
-
ATTRIBUTE_TYPES = {
|
8
|
-
:string => { :method => 'to_s', :kind => ::String },
|
9
|
-
:text => { :method => 'to_s', :kind => ::String },
|
10
|
-
:integer => { :method => 'to_i', :kind => ::Fixnum },
|
11
|
-
:float => { :method => 'to_f', :kind => ::Float },
|
12
|
-
:currency => { :method => 'from_currency_to_f', :kind => ::Float },
|
13
|
-
:date => { :method => 'to_date', :kind => ::Date },
|
14
|
-
:datetime => { :method => 'to_datetime', :kind => ::DateTime },
|
15
|
-
:boolean => { :method => 'to_resourceful_boolean', :kind => ::Object },
|
16
|
-
:other => { :method => 'to_s', :kind => ::String }
|
17
|
-
}
|
18
|
-
|
19
|
-
def attribute_type_to_method(type)
|
20
|
-
(ATTRIBUTE_TYPES.has_key?(type.to_sym) ? ATTRIBUTE_TYPES[type.to_sym] : ATTRIBUTE_TYPES[:other])[:method]
|
21
|
-
end
|
22
|
-
|
23
|
-
def attribute_type_to_kind(type)
|
24
|
-
(ATTRIBUTE_TYPES.has_key?(type.to_sym) ? ATTRIBUTE_TYPES[type.to_sym] : ATTRIBUTE_TYPES[:other])[:kind]
|
25
|
-
end
|
1
|
+
module Resourceful; end
|
2
|
+
module Resourceful::Model; end
|
26
3
|
|
27
|
-
|
28
|
-
|
29
|
-
module InstanceMethods
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.included(receiver)
|
33
|
-
receiver.extend ClassMethods
|
34
|
-
receiver.send :include, InstanceMethods
|
35
|
-
end
|
4
|
+
module Resourceful::Model::AttributeTypes
|
36
5
|
|
6
|
+
module ClassMethods
|
7
|
+
|
8
|
+
ATTRIBUTE_TYPES = {
|
9
|
+
:string => { :method => 'to_s', :kind => ::String },
|
10
|
+
:text => { :method => 'to_s', :kind => ::String },
|
11
|
+
:integer => { :method => 'to_i', :kind => ::Fixnum },
|
12
|
+
:float => { :method => 'to_f', :kind => ::Float },
|
13
|
+
:currency => { :method => 'from_currency_to_f', :kind => ::Float },
|
14
|
+
:date => { :method => 'to_date', :kind => ::Date },
|
15
|
+
:datetime => { :method => 'to_datetime', :kind => ::DateTime },
|
16
|
+
:boolean => { :method => 'to_boolean', :kind => ::Object },
|
17
|
+
:other => { :method => 'to_s', :kind => ::String }
|
18
|
+
}
|
19
|
+
|
20
|
+
def attribute_type_to_method(type)
|
21
|
+
(ATTRIBUTE_TYPES.has_key?(type.to_sym) ? ATTRIBUTE_TYPES[type.to_sym] : ATTRIBUTE_TYPES[:other])[:method]
|
37
22
|
end
|
23
|
+
|
24
|
+
def attribute_type_to_kind(type)
|
25
|
+
(ATTRIBUTE_TYPES.has_key?(type.to_sym) ? ATTRIBUTE_TYPES[type.to_sym] : ATTRIBUTE_TYPES[:other])[:kind]
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
module InstanceMethods
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.included(receiver)
|
34
|
+
receiver.extend ClassMethods
|
35
|
+
receiver.send :include, InstanceMethods
|
38
36
|
end
|
39
|
-
|
37
|
+
|
38
|
+
end
|
@@ -1,187 +1,187 @@
|
|
1
1
|
require 'resourceful/model/attribute_types'
|
2
2
|
|
3
|
-
module Resourceful
|
4
|
-
module Model
|
3
|
+
module Resourceful; end
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
5
|
+
module Resourceful::Model
|
6
|
+
|
7
|
+
class Base
|
8
|
+
include Resourceful::Model::AttributeTypes
|
9
|
+
|
10
|
+
@@agent ||= {}
|
11
|
+
def self.agent(&block)
|
12
|
+
@@agent[self.name.to_s] = block;
|
13
|
+
end
|
14
|
+
|
15
|
+
@@namespaces = [""]
|
16
|
+
def self.namespaces
|
17
|
+
@@namespaces.dup
|
18
|
+
end
|
19
|
+
def self.add_namespace(ns)
|
20
|
+
@@namespaces.unshift(ns)
|
21
|
+
end
|
22
|
+
def self.get_namespaced_klass(class_name)
|
23
|
+
klass = nil
|
24
|
+
@@namespaces.each do |ns|
|
25
|
+
begin
|
26
|
+
klass = "#{ns}::#{class_name}".resourceful_constantize
|
27
|
+
break;
|
28
|
+
rescue Exception => err
|
29
29
|
end
|
30
|
-
klass
|
31
30
|
end
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
31
|
+
klass
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.get(path, opts={})
|
35
|
+
block = opts.delete(:on_response)
|
36
|
+
set_agent.get(path, opts, &block)
|
37
|
+
end
|
38
|
+
def self.get_collection(path, opts={})
|
39
|
+
block = opts.delete(:on_response)
|
40
|
+
(yield set_agent.get(path, opts, &block)).collect{|data| new(data)}
|
41
|
+
end
|
42
|
+
def self.find(id, opts, force)
|
43
|
+
raise NotImplementedError, "no find method has been defined"
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize(data)
|
47
|
+
end
|
48
|
+
|
49
|
+
def data
|
50
|
+
@data
|
51
|
+
end
|
52
|
+
|
53
|
+
def new_record?
|
54
|
+
@data.nil?
|
55
|
+
end
|
56
|
+
|
57
|
+
def attributes(force=false)
|
58
|
+
if @attributes.nil? || force
|
59
|
+
@attributes = {}
|
60
|
+
self.class.ancestors.each do |anc|
|
61
|
+
if @@attributes[anc.to_s]
|
62
|
+
@attributes.merge!(@@attributes[anc.to_s].inject({}) { |hsh, key| hsh[key] = self.send("_#{key}"); hsh })
|
63
63
|
end
|
64
64
|
end
|
65
|
-
@attributes
|
66
65
|
end
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
def save
|
76
|
-
@data = yield attributes(true)
|
77
|
-
reset_attributes
|
78
|
-
end
|
79
|
-
|
80
|
-
def destroy
|
81
|
-
yield attributes(true)
|
82
|
-
@data = nil
|
66
|
+
@attributes
|
67
|
+
end
|
68
|
+
|
69
|
+
def update_attributes(attr_hash={})
|
70
|
+
attr_hash.each do |k,v|
|
71
|
+
self.send("#{k}=", v)
|
83
72
|
end
|
73
|
+
attributes(true)
|
74
|
+
end
|
75
|
+
|
76
|
+
def save
|
77
|
+
@data = yield attributes(true)
|
78
|
+
reset_attributes
|
79
|
+
end
|
80
|
+
|
81
|
+
def destroy
|
82
|
+
yield attributes(true)
|
83
|
+
@data = nil
|
84
|
+
end
|
84
85
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
end
|
86
|
+
def self.cleanup_name(name)
|
87
|
+
name.to_s.gsub(/\W/,'')
|
88
|
+
end
|
89
|
+
|
90
|
+
protected
|
91
|
+
|
92
|
+
def push_data(verb, path, opts, data)
|
93
|
+
block = opts.delete(:on_response)
|
94
|
+
['id', :id].each { |a| data.delete(a) } if data.kind_of?(::Hash)
|
95
|
+
self.class.set_agent.send(verb.to_s, path, opts, data, &block)
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.attribute(name, type, config={})
|
99
|
+
clean_name = cleanup_name(name)
|
100
|
+
add_to_attributes(name.to_s)
|
101
|
+
config ||= {}
|
102
|
+
config[:path] ||= clean_name
|
103
|
+
content_method = attribute_type_to_method(type)
|
104
|
+
# method to get the raw attribute variable data (not intended to be overridden)
|
105
|
+
define_method("_#{clean_name}") do
|
106
|
+
fetch_attribute(clean_name, config, content_method)
|
107
|
+
end
|
108
|
+
# method to read the attribute value (intended to be overridden when necessary)
|
109
|
+
define_method(name) do |*args|
|
110
|
+
reload = args.first || false
|
111
|
+
instance_variable_set("@#{clean_name}", nil) if reload
|
112
|
+
fetch_attribute(clean_name, config, content_method)
|
113
|
+
end
|
114
|
+
# method to write the attribute value
|
115
|
+
define_method("#{name}=") do |value|
|
116
|
+
instance_variable_set("@#{clean_name}", value)
|
117
117
|
end
|
118
|
+
end
|
118
119
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
a
|
129
|
-
end
|
130
|
-
else
|
120
|
+
private
|
121
|
+
|
122
|
+
def fetch_attribute(clean_name, config, content_method)
|
123
|
+
instance_variable_get("@#{clean_name}") || \
|
124
|
+
instance_variable_set("@#{clean_name}", \
|
125
|
+
if (a = attribute(config))
|
126
|
+
begin
|
127
|
+
self.class.get_value(a, config).send(content_method)
|
128
|
+
rescue Exception => err
|
131
129
|
a
|
132
130
|
end
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
def self.add_to_attributes(name)
|
151
|
-
@@attributes ||= {}
|
152
|
-
klass_name = self.name
|
153
|
-
@@attributes[klass_name] ||= []
|
154
|
-
@@attributes[klass_name] << name
|
131
|
+
else
|
132
|
+
a
|
133
|
+
end
|
134
|
+
)
|
135
|
+
end
|
136
|
+
|
137
|
+
def reset_attributes
|
138
|
+
clear_attributes
|
139
|
+
attributes(true)
|
140
|
+
end
|
141
|
+
|
142
|
+
def clear_attributes
|
143
|
+
@@attributes ||= {}
|
144
|
+
klass_name = self.class.name
|
145
|
+
@@attributes[klass_name] ||= []
|
146
|
+
@@attributes[klass_name].each do |a|
|
147
|
+
instance_variable_set("@#{a.to_s.gsub(/\W/,'')}", nil)
|
155
148
|
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def self.add_to_attributes(name)
|
152
|
+
@@attributes ||= {}
|
153
|
+
klass_name = self.name
|
154
|
+
@@attributes[klass_name] ||= []
|
155
|
+
@@attributes[klass_name] << name
|
156
|
+
end
|
156
157
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
end
|
158
|
+
def self.get_value(attribute, opts={})
|
159
|
+
if opts[:value]
|
160
|
+
(attribute =~ opts[:value]) ? ($1 || $&) : nil
|
161
|
+
else
|
162
|
+
attribute
|
163
163
|
end
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
end
|
173
|
-
|
174
|
-
unless @@agent[klass_name].kind_of?(Resourceful::Agent::Base)
|
175
|
-
@@agent[klass_name] = @@agent[klass_name].call
|
164
|
+
end
|
165
|
+
|
166
|
+
def self.set_agent
|
167
|
+
klass_name = ""
|
168
|
+
self.ancestors.each do |anc|
|
169
|
+
if @@agent[anc.to_s]
|
170
|
+
klass_name = anc.to_s
|
171
|
+
break
|
176
172
|
end
|
177
|
-
@@agent[klass_name]
|
178
|
-
end
|
179
|
-
|
180
|
-
def self.add_namespace(ns)
|
181
|
-
@@namespaces.unshift(ns)
|
182
173
|
end
|
183
174
|
|
175
|
+
unless @@agent[klass_name].kind_of?(Resourceful::Agent::Base)
|
176
|
+
@@agent[klass_name] = @@agent[klass_name].call
|
177
|
+
end
|
178
|
+
@@agent[klass_name]
|
184
179
|
end
|
185
180
|
|
181
|
+
def self.add_namespace(ns)
|
182
|
+
@@namespaces.unshift(ns)
|
183
|
+
end
|
184
|
+
|
186
185
|
end
|
187
|
-
|
186
|
+
|
187
|
+
end
|