lazy_resource 0.1.0
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/.gitignore +18 -0
- data/.rspec +3 -0
- data/.rvmrc +1 -0
- data/Gemfile +14 -0
- data/Guardfile +5 -0
- data/LICENSE +22 -0
- data/README.md +127 -0
- data/Rakefile +6 -0
- data/examples/github.rb +64 -0
- data/lazy_resource.gemspec +22 -0
- data/lib/lazy_resource.rb +39 -0
- data/lib/lazy_resource/attributes.rb +131 -0
- data/lib/lazy_resource/errors.rb +72 -0
- data/lib/lazy_resource/http_mock.rb +23 -0
- data/lib/lazy_resource/mapping.rb +73 -0
- data/lib/lazy_resource/relation.rb +132 -0
- data/lib/lazy_resource/request.rb +63 -0
- data/lib/lazy_resource/resource.rb +197 -0
- data/lib/lazy_resource/resource_queue.rb +40 -0
- data/lib/lazy_resource/types.rb +53 -0
- data/lib/lazy_resource/url_generation.rb +98 -0
- data/lib/lazy_resource/version.rb +3 -0
- data/spec/fixtures/comment.rb +6 -0
- data/spec/fixtures/post.rb +6 -0
- data/spec/fixtures/user.rb +9 -0
- data/spec/lazy_resource/attributes_spec.rb +157 -0
- data/spec/lazy_resource/errors_spec.rb +48 -0
- data/spec/lazy_resource/mapping_spec.rb +237 -0
- data/spec/lazy_resource/relation_spec.rb +169 -0
- data/spec/lazy_resource/request_spec.rb +143 -0
- data/spec/lazy_resource/resource_queue_spec.rb +66 -0
- data/spec/lazy_resource/resource_spec.rb +463 -0
- data/spec/lazy_resource/types_spec.rb +109 -0
- data/spec/lazy_resource/url_generation_spec.rb +155 -0
- data/spec/spec_helper.rb +25 -0
- metadata +165 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
module LazyResource
|
2
|
+
class ResourceQueue
|
3
|
+
include LazyResource::UrlGeneration
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@queue = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def queue(relation)
|
10
|
+
@queue.push(relation)
|
11
|
+
end
|
12
|
+
|
13
|
+
def flush!
|
14
|
+
@queue = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def request_queue
|
18
|
+
Thread.current[:request_queue] ||= Typhoeus::Hydra.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
send_to_request_queue!
|
23
|
+
request_queue.run
|
24
|
+
end
|
25
|
+
|
26
|
+
def send_to_request_queue!
|
27
|
+
while(relation = @queue.pop)
|
28
|
+
request = Request.new(url_for(relation), relation)
|
29
|
+
request_queue.queue(request)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def url_for(relation)
|
34
|
+
url = ''
|
35
|
+
url << relation.klass.site
|
36
|
+
url << self.class.collection_path(relation.to_params, nil, relation.from)
|
37
|
+
url
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module LazyResource
|
2
|
+
module Types
|
3
|
+
class Array < ::Array
|
4
|
+
def self.parse(o)
|
5
|
+
o.to_a
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class String < ::String
|
10
|
+
def self.parse(o)
|
11
|
+
o.to_s
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Fixnum < ::Fixnum
|
16
|
+
def self.parse(o)
|
17
|
+
o.to_i
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Boolean
|
22
|
+
def self.parse(o)
|
23
|
+
if [true, '1', 'true'].include? o
|
24
|
+
true
|
25
|
+
else
|
26
|
+
false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Float < ::Float
|
32
|
+
def self.parse(o)
|
33
|
+
o.to_f
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Hash < ::Hash
|
38
|
+
def self.parse(o)
|
39
|
+
o
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class DateTime < ::DateTime
|
44
|
+
def self.parse(o)
|
45
|
+
if o.is_a?(::DateTime)
|
46
|
+
o
|
47
|
+
else
|
48
|
+
super(o)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module LazyResource
|
2
|
+
module UrlGeneration
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def element_path(options = nil)
|
6
|
+
self.class.element_path(self.primary_key, options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def element_url(options = nil)
|
10
|
+
url = self.class.site.to_s.gsub(/\/$/, '')
|
11
|
+
url << self.element_path(options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def new_element_path
|
15
|
+
self.class.new_element_path
|
16
|
+
end
|
17
|
+
|
18
|
+
def collection_path(options = nil)
|
19
|
+
self.class.collection_path(options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def collection_url(options = nil)
|
23
|
+
url = self.class.site.to_s.gsub(/\/$/, '')
|
24
|
+
url << self.collection_path(options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def split_options(options = {})
|
28
|
+
self.class.split_options(options)
|
29
|
+
end
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
# Gets the \prefix for a resource's nested URL (e.g., <tt>prefix/collectionname/1</tt>)
|
33
|
+
def prefix(options={})
|
34
|
+
path = '/'
|
35
|
+
options = options.to_a.uniq
|
36
|
+
path = options.inject(path) do |uri, option|
|
37
|
+
key, value = option[0].to_s, option[1]
|
38
|
+
uri << ActiveSupport::Inflector.pluralize(key.gsub("_id", ''))
|
39
|
+
uri << "/#{value}/"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# Gets the element path for the given ID in +id+. If the +query_options+ parameter is omitted, Rails
|
45
|
+
# will split from the \prefix options.
|
46
|
+
#
|
47
|
+
# ==== Options
|
48
|
+
# +prefix_options+ - A \hash to add a \prefix to the request for nested URLs (e.g., <tt>:account_id => 19</tt>
|
49
|
+
# would yield a URL like <tt>/accounts/19/purchases.json</tt>).
|
50
|
+
#
|
51
|
+
# +query_options+ - A \hash to add items to the query string for the request.
|
52
|
+
def element_path(id, prefix_options = {}, query_options = nil, from = nil)
|
53
|
+
prefix_options, query_options = split_options(prefix_options) if query_options.nil?
|
54
|
+
"#{prefix(prefix_options)}#{from || collection_name}/#{URI.escape id.to_s}#{query_string(query_options)}"
|
55
|
+
end
|
56
|
+
|
57
|
+
# Gets the new element path for REST resources.
|
58
|
+
#
|
59
|
+
# ==== Options
|
60
|
+
# * +prefix_options+ - A hash to add a prefix to the request for nested URLs (e.g., <tt>:account_id => 19</tt>
|
61
|
+
# would yield a URL like <tt>/accounts/19/purchases/new.json</tt>).
|
62
|
+
def new_element_path(prefix_options = {}, from = nil)
|
63
|
+
"#{prefix(prefix_options)}#{from || collection_name}/new"
|
64
|
+
end
|
65
|
+
|
66
|
+
# Gets the collection path for the REST resources. If the +query_options+ parameter is omitted, Rails
|
67
|
+
# will split from the +prefix_options+.
|
68
|
+
#
|
69
|
+
# ==== Options
|
70
|
+
# * +prefix_options+ - A hash to add a prefix to the request for nested URLs (e.g., <tt>:account_id => 19</tt>
|
71
|
+
# would yield a URL like <tt>/accounts/19/purchases.json</tt>).
|
72
|
+
# * +query_options+ - A hash to add items to the query string for the request.
|
73
|
+
def collection_path(prefix_options = {}, query_options = nil, from = nil)
|
74
|
+
prefix_options, query_options = split_options(prefix_options) if query_options.nil?
|
75
|
+
"#{prefix(prefix_options)}#{from || collection_name}#{query_string(query_options)}"
|
76
|
+
end
|
77
|
+
|
78
|
+
# Builds the query string for the request.
|
79
|
+
def query_string(options)
|
80
|
+
"?#{options.to_query}" unless options.nil? || options.empty?
|
81
|
+
end
|
82
|
+
|
83
|
+
# split an option hash into two hashes, one containing the prefix options,
|
84
|
+
# and the other containing the leftovers.
|
85
|
+
def split_options(options = {})
|
86
|
+
prefix_options, query_options = {}, {}
|
87
|
+
|
88
|
+
(options || {}).each do |key, value|
|
89
|
+
next if key.blank?
|
90
|
+
(key =~ /\w*_id/ ? prefix_options : query_options)[key.to_sym] = value
|
91
|
+
end
|
92
|
+
|
93
|
+
[prefix_options, query_options]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class AttributeObject
|
4
|
+
include LazyResource::Attributes
|
5
|
+
|
6
|
+
attr_accessor :fetched
|
7
|
+
|
8
|
+
def self.resource_queue
|
9
|
+
@resource_queue ||= LazyResource::ResourceQueue.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.request_queue
|
13
|
+
@request_queue ||= Typhoeus::Hydra.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def fetched?
|
17
|
+
@fetched
|
18
|
+
end
|
19
|
+
|
20
|
+
def element_name
|
21
|
+
"attribute_object"
|
22
|
+
end
|
23
|
+
|
24
|
+
def id
|
25
|
+
1
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe LazyResource::Attributes do
|
30
|
+
before :each do
|
31
|
+
AttributeObject.attribute(:name, String)
|
32
|
+
@foo = AttributeObject.new
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '.attribute' do
|
36
|
+
it 'adds the attribute to the attributes hash' do
|
37
|
+
AttributeObject.attributes[:name].should == { :type => String, :options => {} }
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'creates a getter method' do
|
41
|
+
@foo.respond_to?(:name).should == true
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'creates a setter method' do
|
45
|
+
@foo.respond_to?(:name=).should == true
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'creates a question method' do
|
49
|
+
@foo.respond_to?(:name?).should == true
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'getter' do
|
53
|
+
it 'runs fetch_all if the current object is not fetched' do
|
54
|
+
@foo.fetched = false
|
55
|
+
AttributeObject.should_receive(:fetch_all)
|
56
|
+
@foo.name
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'does not run fetch_all if the current object is fetched' do
|
60
|
+
@foo.fetched = true
|
61
|
+
AttributeObject.should_not_receive(:fetch_all)
|
62
|
+
@foo.name
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'associations' do
|
66
|
+
before :each do
|
67
|
+
AttributeObject.attribute(:posts, [Post])
|
68
|
+
AttributeObject.attribute(:user, User)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'returns a relation with the specified where values' do
|
72
|
+
Post.should_receive(:where).with(:attribute_object_id => 1)
|
73
|
+
@foo.fetched = false
|
74
|
+
@foo.posts
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'finds a singular resource' do
|
78
|
+
User.should_receive(:where).with(:attribute_object_id => 1)
|
79
|
+
@foo.fetched = false
|
80
|
+
@foo.user
|
81
|
+
end
|
82
|
+
|
83
|
+
describe ':using' do
|
84
|
+
before :each do
|
85
|
+
AttributeObject.attribute(:posts_url, String)
|
86
|
+
AttributeObject.attribute(:user_url, String)
|
87
|
+
AttributeObject.attribute(:posts, [Post], :using => :posts_url)
|
88
|
+
AttributeObject.attribute(:user, User, :using => :user_url)
|
89
|
+
@foo.send(:instance_variable_set, "@posts_url", 'http://example.com/path/to/posts')
|
90
|
+
@foo.send(:instance_variable_set, "@user_url", 'http://example.com/path/to/user')
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'finds a collection using the specified url' do
|
94
|
+
relation = LazyResource::Relation.new(Post)
|
95
|
+
request = LazyResource::Request.new(@foo.posts_url, relation)
|
96
|
+
LazyResource::Request.should_receive(:new).with(@foo.posts_url, relation).and_return(request)
|
97
|
+
LazyResource::Relation.should_receive(:new).with(Post, :fetched => true).and_return(relation)
|
98
|
+
@foo.class.request_queue.should_receive(:queue).with(request)
|
99
|
+
@foo.fetched = false
|
100
|
+
@foo.posts
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'finds a singular resource with the specified url' do
|
104
|
+
resource = User.load({})
|
105
|
+
request = LazyResource::Request.new(@foo.user_url, resource)
|
106
|
+
LazyResource::Request.should_receive(:new).with(@foo.user_url, resource).and_return(request)
|
107
|
+
@foo.class.request_queue.should_receive(:queue).with(request)
|
108
|
+
@foo.fetched = false
|
109
|
+
@foo.user
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe '.primary_key_name' do
|
117
|
+
after :all do
|
118
|
+
AttributeObject.primary_key_name = 'id'
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'defaults to id' do
|
122
|
+
AttributeObject.primary_key_name.should == 'id'
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'returns the primary_key_name instance variable' do
|
126
|
+
AttributeObject.primary_key_name.should == AttributeObject.instance_variable_get("@primary_key_name")
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe '.primary_key_name=' do
|
131
|
+
after :all do
|
132
|
+
AttributeObject.primary_key_name = 'id'
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'sets the primary_key_name' do
|
136
|
+
AttributeObject.primary_key_name = 'name'
|
137
|
+
AttributeObject.instance_variable_get("@primary_key_name").should == 'name'
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe '.attributes' do
|
142
|
+
it 'returns a hash of the defined attributes' do
|
143
|
+
AttributeObject.attributes.should == { :name => { :type => String, :options => {} },
|
144
|
+
:posts => { :type => [Post], :options => { :using => :posts_url } },
|
145
|
+
:user => { :type => User, :options => { :using => :user_url } },
|
146
|
+
:posts_url => { :type => String, :options => {} },
|
147
|
+
:user_url => { :type => String, :options => {} } }
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '#primary_key' do
|
152
|
+
it 'returns the value at the primary_key_name' do
|
153
|
+
obj = AttributeObject.new
|
154
|
+
obj.primary_key.should == obj.send(AttributeObject.primary_key_name)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LazyResource::ConnectionError do
|
4
|
+
describe '#to_s' do
|
5
|
+
it 'prints a message with the response code and message' do
|
6
|
+
error = LazyResource::ConnectionError.new(Typhoeus::Response.new(:code => 300, :body => 'redirect'))
|
7
|
+
error.to_s.should match(/300/)
|
8
|
+
error.to_s.should match(/redirect/)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe LazyResource::Redirection do
|
14
|
+
describe '#to_s' do
|
15
|
+
it 'prints the response\'s redirection location' do
|
16
|
+
error = LazyResource::Redirection.new(Typhoeus::Response.new(:code => 300, :body => 'redirect', :headers => { :Location => 'http://example.com' }))
|
17
|
+
error.to_s.should match(/example\.com/)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe LazyResource::MethodNotAllowed do
|
23
|
+
describe '#allowed_methods' do
|
24
|
+
it 'prints the allowed methods' do
|
25
|
+
error = LazyResource::MethodNotAllowed.new(Typhoeus::Response.new(:code => 405, :headers => { 'Allow' => 'put' }))
|
26
|
+
error.allowed_methods.should == [:put]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe LazyResource::TimeoutError do
|
32
|
+
describe '#new' do
|
33
|
+
it 'only accepts a message' do
|
34
|
+
error = LazyResource::TimeoutError.new('timed out')
|
35
|
+
error.to_s.should == 'timed out'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe LazyResource::SSLError do
|
41
|
+
describe '#new' do
|
42
|
+
it 'only accepts a message' do
|
43
|
+
error = LazyResource::SSLError.new('timed out')
|
44
|
+
error.to_s.should == 'timed out'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,237 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Foo
|
4
|
+
include LazyResource::Mapping
|
5
|
+
include LazyResource::Types
|
6
|
+
|
7
|
+
attr_accessor :id, :name, :created_at, :post, :comments, :comments_text
|
8
|
+
|
9
|
+
def self.attributes
|
10
|
+
@attributes ||= {
|
11
|
+
:id => { :type => Fixnum },
|
12
|
+
:name => { :type => String },
|
13
|
+
:created_at => { :type => DateTime },
|
14
|
+
:post => { :type => Bar },
|
15
|
+
:comments => { :type => [Buzz] },
|
16
|
+
:comments_text => { :type => [String] }
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Bar
|
22
|
+
include LazyResource::Mapping
|
23
|
+
include LazyResource::Types
|
24
|
+
|
25
|
+
attr_accessor :title
|
26
|
+
|
27
|
+
def self.attributes
|
28
|
+
@attributes ||= {
|
29
|
+
:title => { :type => String }
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Buzz
|
35
|
+
include LazyResource::Mapping
|
36
|
+
include LazyResource::Types
|
37
|
+
|
38
|
+
attr_accessor :body
|
39
|
+
|
40
|
+
def self.attributes
|
41
|
+
@attributes ||= {
|
42
|
+
:body => { :type => String }
|
43
|
+
}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe LazyResource::Mapping do
|
48
|
+
describe '.load' do
|
49
|
+
before :each do
|
50
|
+
@now = DateTime.now
|
51
|
+
@now_as_sting = @now.to_s
|
52
|
+
@post = Bar.new
|
53
|
+
@post.title = "Lorem Ipsum"
|
54
|
+
@comments = []
|
55
|
+
4.times do
|
56
|
+
comment = Buzz.new
|
57
|
+
comment.body = "Lorem Ipsum"
|
58
|
+
@comments << comment
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'loads single objects' do
|
63
|
+
user = Foo.load({
|
64
|
+
:id => 123,
|
65
|
+
:name => 'Andrew',
|
66
|
+
:created_at => @now,
|
67
|
+
:post => @post,
|
68
|
+
:comments => @comments
|
69
|
+
})
|
70
|
+
|
71
|
+
user.id.should == 123
|
72
|
+
user.name.should == 'Andrew'
|
73
|
+
user.created_at.should == @now
|
74
|
+
user.post.should == @post
|
75
|
+
user.comments.should == @comments
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'loads an array of objects' do
|
79
|
+
users = Foo.load([
|
80
|
+
{
|
81
|
+
:id => 123
|
82
|
+
},
|
83
|
+
{
|
84
|
+
:id => 123
|
85
|
+
}
|
86
|
+
])
|
87
|
+
|
88
|
+
users.each do |user|
|
89
|
+
user.id.should == 123
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '.root_node_name' do
|
95
|
+
after :each do
|
96
|
+
LazyResource::Mapping.root_node_name = nil
|
97
|
+
Foo.root_node_name = nil
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'defaults to nil' do
|
101
|
+
Foo.root_node_name.should == nil
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'specifies the root node name' do
|
105
|
+
Foo.root_node_name = :data
|
106
|
+
Foo.root_node_name.should == :data
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'maps the object at that value' do
|
110
|
+
Foo.root_node_name = :data
|
111
|
+
user = Foo.load({ 'data' => { :id => 123 } })
|
112
|
+
user.id.should == 123
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'maps objects without root node names, even if a root node name is defined' do
|
116
|
+
Foo.root_node_name = :data
|
117
|
+
user = Foo.load({ :id => 123 })
|
118
|
+
user.id.should == 123
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'maps collections at the root node name' do
|
122
|
+
Foo.root_node_name = :data
|
123
|
+
users = Foo.load({ 'data' => [{ :id => 123 }, { :id => 124 }]})
|
124
|
+
users.map(&:id).should == [123,124]
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'maps collections without root node names, even if a root node name is defined' do
|
128
|
+
Foo.root_node_name = :data
|
129
|
+
users = Foo.load([{ :id => 123 }, { :id => 124 }])
|
130
|
+
users.map(&:id).should == [123,124]
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'looks in the module for the root node name' do
|
134
|
+
LazyResource::Mapping.root_node_name = :data
|
135
|
+
Foo.root_node_name.should == :data
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'handles root node names that are strings or symbols' do
|
139
|
+
Foo.root_node_name = :data
|
140
|
+
user = Foo.load('data' => { :id => 123 })
|
141
|
+
user.id.should == 123
|
142
|
+
Foo.root_node_name = 'data'
|
143
|
+
user = Foo.load('data' => { :id => 123 })
|
144
|
+
user.id.should == 123
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe '#load' do
|
149
|
+
before :each do
|
150
|
+
@now = DateTime.now
|
151
|
+
@now_as_string = @now.to_s
|
152
|
+
@post = Bar.new
|
153
|
+
@post.title = "Lorem Ipsum"
|
154
|
+
@comments = []
|
155
|
+
4.times do
|
156
|
+
comment = Buzz.new
|
157
|
+
comment.body = "Lorem Ipsum"
|
158
|
+
@comments << comment
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'loads attributes' do
|
163
|
+
user = Foo.new
|
164
|
+
user.load({ :name => 'Bob' })
|
165
|
+
user.name.should == 'Bob'
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'overwrites existing attributes' do
|
169
|
+
user = Foo.new
|
170
|
+
user.name = 'Andrew'
|
171
|
+
user.load({ :name => 'Bob' })
|
172
|
+
user.name.should == 'Bob'
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'loads objects based on their type in the attributes method' do
|
176
|
+
user = Foo.new
|
177
|
+
user.load({
|
178
|
+
:id => "123",
|
179
|
+
:name => "Andrew",
|
180
|
+
:created_at => @now_as_string
|
181
|
+
})
|
182
|
+
|
183
|
+
user.id.should == 123
|
184
|
+
user.name.should == 'Andrew'
|
185
|
+
user.created_at.to_s.should == @now_as_string
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'loads associations' do
|
189
|
+
user = Foo.new
|
190
|
+
user.load({
|
191
|
+
:post => {
|
192
|
+
:title => 'Lorem Ipsum'
|
193
|
+
}
|
194
|
+
})
|
195
|
+
|
196
|
+
user.post.title.should == 'Lorem Ipsum'
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'loads association arrays' do
|
200
|
+
user = Foo.new
|
201
|
+
user.load({
|
202
|
+
:comments => [
|
203
|
+
{ :body => 'Lorem Ipsum' },
|
204
|
+
{ :body => 'Lorem Ipsum' }
|
205
|
+
]
|
206
|
+
})
|
207
|
+
|
208
|
+
user.comments.each do |comment|
|
209
|
+
comment.body.should == 'Lorem Ipsum'
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'loads arrays' do
|
214
|
+
user = Foo.new
|
215
|
+
user.load({
|
216
|
+
:comments_text => [
|
217
|
+
'Lorem Ipsum',
|
218
|
+
'Lorem Ipsum'
|
219
|
+
]
|
220
|
+
})
|
221
|
+
|
222
|
+
user.comments_text.each do |comment|
|
223
|
+
comment.should == 'Lorem Ipsum'
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'skips unknown attributes' do
|
228
|
+
user = Foo.new
|
229
|
+
user.load({
|
230
|
+
:fizz => '',
|
231
|
+
:name => 'Andrew'
|
232
|
+
})
|
233
|
+
|
234
|
+
user.name.should == 'Andrew'
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|