activeresource-five 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.rdoc +249 -0
- data/lib/active_resource.rb +44 -0
- data/lib/active_resource/associations.rb +175 -0
- data/lib/active_resource/associations/builder/association.rb +32 -0
- data/lib/active_resource/associations/builder/belongs_to.rb +14 -0
- data/lib/active_resource/associations/builder/has_many.rb +12 -0
- data/lib/active_resource/associations/builder/has_one.rb +12 -0
- data/lib/active_resource/base.rb +1626 -0
- data/lib/active_resource/callbacks.rb +20 -0
- data/lib/active_resource/collection.rb +92 -0
- data/lib/active_resource/connection.rb +299 -0
- data/lib/active_resource/custom_methods.rb +127 -0
- data/lib/active_resource/exceptions.rb +82 -0
- data/lib/active_resource/formats.rb +22 -0
- data/lib/active_resource/formats/json_format.rb +25 -0
- data/lib/active_resource/formats/xml_format.rb +25 -0
- data/lib/active_resource/http_mock.rb +375 -0
- data/lib/active_resource/log_subscriber.rb +15 -0
- data/lib/active_resource/observing.rb +0 -0
- data/lib/active_resource/railtie.rb +15 -0
- data/lib/active_resource/reflection.rb +77 -0
- data/lib/active_resource/schema.rb +57 -0
- data/lib/active_resource/singleton.rb +114 -0
- data/lib/active_resource/threadsafe_attributes.rb +65 -0
- data/lib/active_resource/validations.rb +174 -0
- data/lib/active_resource/version.rb +10 -0
- data/lib/activeresource.rb +1 -0
- metadata +156 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a090060069d258cd94729d4b260529d9e16c8943
|
4
|
+
data.tar.gz: 210bacf920a99fd19e34092b4c27a60e4a9798bf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 77f3941f609d8f612b17c0ee76e182475c8610bd9ef9d0fcddb96338409b3a26fbe08fc6a39270dea394ff9f9af4e833110de2016f7997d53ff7227835e1a6c8
|
7
|
+
data.tar.gz: 1c20287839e4b664aa6b73ac5a4e4fbd46ac2459bf4d991114a83c279f0284ea4e17e31949692d6708fa3daf2a8c48d1afefd3722d8c336bf94b95dd853912e0
|
data/README.rdoc
ADDED
@@ -0,0 +1,249 @@
|
|
1
|
+
= Active Resource Five
|
2
|
+
|
3
|
+
Active Resource (ARes) connects business objects and Representational State Transfer (REST)
|
4
|
+
web services. It implements object-relational mapping for REST web services to provide transparent
|
5
|
+
proxying capabilities between a client (ActiveResource) and a RESTful service (which is provided by Simply RESTful routing
|
6
|
+
in ActionController::Resources).
|
7
|
+
|
8
|
+
There is currently no version 5 release in Ruby gems, so as an interim solution, this release brings 5 functionality to RubyGems so that it can be included in a dependency of other gems without causing dependency conflicts with ActiveResource/ActiveModel 5 etc.
|
9
|
+
|
10
|
+
== Philosophy
|
11
|
+
|
12
|
+
Active Resource attempts to provide a coherent wrapper object-relational mapping for REST
|
13
|
+
web services. It follows the same philosophy as Active Record, in that one of its prime aims
|
14
|
+
is to reduce the amount of code needed to map to these resources. This is made possible
|
15
|
+
by relying on a number of code- and protocol-based conventions that make it easy for Active Resource
|
16
|
+
to infer complex relations and structures. These conventions are outlined in detail in the documentation
|
17
|
+
for ActiveResource::Base.
|
18
|
+
|
19
|
+
== Overview
|
20
|
+
|
21
|
+
Model classes are mapped to remote REST resources by Active Resource much the same way Active Record maps model classes to database
|
22
|
+
tables. When a request is made to a remote resource, a REST JSON request is generated, transmitted, and the result
|
23
|
+
received and serialized into a usable Ruby object.
|
24
|
+
|
25
|
+
== Download and installation
|
26
|
+
|
27
|
+
The latest version of Active Resource can be installed with RubyGems:
|
28
|
+
|
29
|
+
% [sudo] gem install activeresource-five
|
30
|
+
|
31
|
+
Or added to a Gemfile:
|
32
|
+
|
33
|
+
gem 'activeresource-five'
|
34
|
+
|
35
|
+
For compatibility with Rails 5, use:
|
36
|
+
|
37
|
+
gem 'activeresource-five', github: 'rails/activeresource', branch: 'master'
|
38
|
+
|
39
|
+
Source code can be downloaded on GitHub
|
40
|
+
|
41
|
+
* https://github.com/rails/activeresource/tree/master/activeresource
|
42
|
+
|
43
|
+
=== Configuration and Usage
|
44
|
+
|
45
|
+
Putting Active Resource to use is very similar to Active Record. It's as simple as creating a model class
|
46
|
+
that inherits from ActiveResource::Base and providing a <tt>site</tt> class variable to it:
|
47
|
+
|
48
|
+
class Person < ActiveResource::Base
|
49
|
+
self.site = "http://api.people.com:3000"
|
50
|
+
end
|
51
|
+
|
52
|
+
Now the Person class is REST enabled and can invoke REST services very similarly to how Active Record invokes
|
53
|
+
life cycle methods that operate against a persistent store.
|
54
|
+
|
55
|
+
# Find a person with id = 1
|
56
|
+
tyler = Person.find(1)
|
57
|
+
Person.exists?(1) # => true
|
58
|
+
|
59
|
+
As you can see, the methods are quite similar to Active Record's methods for dealing with database
|
60
|
+
records. But rather than dealing directly with a database record, you're dealing with HTTP resources (which may or may not be database records).
|
61
|
+
|
62
|
+
==== Authentication
|
63
|
+
|
64
|
+
Active Resource supports the token based authentication provided by Rails through the <tt>ActionController::HttpAuthentication::Token</tt> class using custom headers.
|
65
|
+
|
66
|
+
class Person < ActiveResource::Base
|
67
|
+
self.headers['Authorization'] = 'Token token="abcd"'
|
68
|
+
end
|
69
|
+
|
70
|
+
You can also set any specific HTTP header using the same way.
|
71
|
+
|
72
|
+
==== Protocol
|
73
|
+
|
74
|
+
Active Resource is built on a standard JSON or XML format for requesting and submitting resources over HTTP. It mirrors the RESTful routing
|
75
|
+
built into Action Controller but will also work with any other REST service that properly implements the protocol.
|
76
|
+
REST uses HTTP, but unlike "typical" web applications, it makes use of all the verbs available in the HTTP specification:
|
77
|
+
|
78
|
+
* GET requests are used for finding and retrieving resources.
|
79
|
+
* POST requests are used to create new resources.
|
80
|
+
* PUT requests are used to update existing resources.
|
81
|
+
* DELETE requests are used to delete resources.
|
82
|
+
|
83
|
+
For more information on how this protocol works with Active Resource, see the ActiveResource::Base documentation;
|
84
|
+
for more general information on REST web services, see the article here[http://en.wikipedia.org/wiki/Representational_State_Transfer].
|
85
|
+
|
86
|
+
==== Find
|
87
|
+
|
88
|
+
Find requests use the GET method and expect the JSON form of whatever resource/resources is/are being requested. So,
|
89
|
+
for a request for a single element, the JSON of that item is expected in response:
|
90
|
+
|
91
|
+
# Expects a response of
|
92
|
+
#
|
93
|
+
# {"id":1,"first":"Tyler","last":"Durden"}
|
94
|
+
#
|
95
|
+
# for GET http://api.people.com:3000/people/1.json
|
96
|
+
#
|
97
|
+
tyler = Person.find(1)
|
98
|
+
|
99
|
+
The JSON document that is received is used to build a new object of type Person, with each
|
100
|
+
JSON element becoming an attribute on the object.
|
101
|
+
|
102
|
+
tyler.is_a? Person # => true
|
103
|
+
tyler.last # => 'Durden'
|
104
|
+
|
105
|
+
Any complex element (one that contains other elements) becomes its own object:
|
106
|
+
|
107
|
+
# With this response:
|
108
|
+
# {"id":1,"first":"Tyler","address":{"street":"Paper St.","state":"CA"}}
|
109
|
+
#
|
110
|
+
# for GET http://api.people.com:3000/people/1.json
|
111
|
+
#
|
112
|
+
tyler = Person.find(1)
|
113
|
+
tyler.address # => <Person::Address::xxxxx>
|
114
|
+
tyler.address.street # => 'Paper St.'
|
115
|
+
|
116
|
+
Collections can also be requested in a similar fashion
|
117
|
+
|
118
|
+
# Expects a response of
|
119
|
+
#
|
120
|
+
# [
|
121
|
+
# {"id":1,"first":"Tyler","last":"Durden"},
|
122
|
+
# {"id":2,"first":"Tony","last":"Stark",}
|
123
|
+
# ]
|
124
|
+
#
|
125
|
+
# for GET http://api.people.com:3000/people.json
|
126
|
+
#
|
127
|
+
people = Person.all
|
128
|
+
people.first # => <Person::xxx 'first' => 'Tyler' ...>
|
129
|
+
people.last # => <Person::xxx 'first' => 'Tony' ...>
|
130
|
+
|
131
|
+
==== Create
|
132
|
+
|
133
|
+
Creating a new resource submits the JSON form of the resource as the body of the request and expects
|
134
|
+
a 'Location' header in the response with the RESTful URL location of the newly created resource. The
|
135
|
+
id of the newly created resource is parsed out of the Location response header and automatically set
|
136
|
+
as the id of the ARes object.
|
137
|
+
|
138
|
+
# {"first":"Tyler","last":"Durden"}
|
139
|
+
#
|
140
|
+
# is submitted as the body on
|
141
|
+
#
|
142
|
+
# if include_root_in_json is not set or set to false => {"first":"Tyler"}
|
143
|
+
# if include_root_in_json is set to true => {"person":{"first":"Tyler"}}
|
144
|
+
#
|
145
|
+
# POST http://api.people.com:3000/people.json
|
146
|
+
#
|
147
|
+
# when save is called on a new Person object. An empty response is
|
148
|
+
# is expected with a 'Location' header value:
|
149
|
+
#
|
150
|
+
# Response (201): Location: http://api.people.com:3000/people/2
|
151
|
+
#
|
152
|
+
tyler = Person.new(:first => 'Tyler')
|
153
|
+
tyler.new? # => true
|
154
|
+
tyler.save # => true
|
155
|
+
tyler.new? # => false
|
156
|
+
tyler.id # => 2
|
157
|
+
|
158
|
+
==== Update
|
159
|
+
|
160
|
+
'save' is also used to update an existing resource and follows the same protocol as creating a resource
|
161
|
+
with the exception that no response headers are needed -- just an empty response when the update on the
|
162
|
+
server side was successful.
|
163
|
+
|
164
|
+
# {"first":"Tyler"}
|
165
|
+
#
|
166
|
+
# is submitted as the body on
|
167
|
+
#
|
168
|
+
# if include_root_in_json is not set or set to false => {"first":"Tyler"}
|
169
|
+
# if include_root_in_json is set to true => {"person":{"first":"Tyler"}}
|
170
|
+
#
|
171
|
+
# PUT http://api.people.com:3000/people/1.json
|
172
|
+
#
|
173
|
+
# when save is called on an existing Person object. An empty response is
|
174
|
+
# is expected with code (204)
|
175
|
+
#
|
176
|
+
tyler = Person.find(1)
|
177
|
+
tyler.first # => 'Tyler'
|
178
|
+
tyler.first = 'Tyson'
|
179
|
+
tyler.save # => true
|
180
|
+
|
181
|
+
==== Delete
|
182
|
+
|
183
|
+
Destruction of a resource can be invoked as a class and instance method of the resource.
|
184
|
+
|
185
|
+
# A request is made to
|
186
|
+
#
|
187
|
+
# DELETE http://api.people.com:3000/people/1.json
|
188
|
+
#
|
189
|
+
# for both of these forms. An empty response with
|
190
|
+
# is expected with response code (200)
|
191
|
+
#
|
192
|
+
tyler = Person.find(1)
|
193
|
+
tyler.destroy # => true
|
194
|
+
tyler.exists? # => false
|
195
|
+
Person.delete(2) # => true
|
196
|
+
Person.exists?(2) # => false
|
197
|
+
|
198
|
+
==== Associations
|
199
|
+
|
200
|
+
Relationships between resources can be declared using the standard association syntax
|
201
|
+
that should be familiar to anyone who uses activerecord. For example, using the
|
202
|
+
class definition below:
|
203
|
+
|
204
|
+
class Post < ActiveResource::Base
|
205
|
+
self.site = "http://blog.io"
|
206
|
+
has_many :comments
|
207
|
+
end
|
208
|
+
|
209
|
+
post = Post.find(1) # issues GET http://blog.io/posts/1.json
|
210
|
+
comments = post.comments # issues GET http://blog.io/posts/1/comments.json
|
211
|
+
|
212
|
+
|
213
|
+
If you control the server, you may wish to include nested resources thus avoiding a
|
214
|
+
second network request. Given the resource above, if the response includes comments
|
215
|
+
in the response, they will be automatically loaded into the activeresource object.
|
216
|
+
The server-side model can be adjusted as follows to include comments in the response.
|
217
|
+
|
218
|
+
class Post < ActiveRecord::Base
|
219
|
+
has_many :comments
|
220
|
+
|
221
|
+
def as_json(options)
|
222
|
+
super.merge(:include=>[:comments])
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
== License
|
227
|
+
|
228
|
+
Active Resource is released under the MIT license:
|
229
|
+
|
230
|
+
* http://www.opensource.org/licenses/MIT
|
231
|
+
|
232
|
+
== Contributing to Active Resource
|
233
|
+
|
234
|
+
Active Resource is work of many contributors. You're encouraged to submit pull requests, propose
|
235
|
+
features and discuss issues.
|
236
|
+
|
237
|
+
See {CONTRIBUTING}[https://github.com/rails/activeresource/blob/master/CONTRIBUTING.md].
|
238
|
+
|
239
|
+
== Support
|
240
|
+
|
241
|
+
API documentation is at
|
242
|
+
|
243
|
+
* http://rubydoc.info/gems/activeresource/4.0.0/frames
|
244
|
+
|
245
|
+
Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here:
|
246
|
+
|
247
|
+
* https://github.com/rails/activeresource/issues
|
248
|
+
|
249
|
+
You can find more usage information in the ActiveResource::Base documentation.
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2006-2012 David Heinemeier Hansson
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
require 'active_support'
|
25
|
+
require 'active_model'
|
26
|
+
require 'active_resource/exceptions'
|
27
|
+
require 'active_resource/version'
|
28
|
+
|
29
|
+
module ActiveResource
|
30
|
+
extend ActiveSupport::Autoload
|
31
|
+
|
32
|
+
autoload :Base
|
33
|
+
autoload :Callbacks
|
34
|
+
autoload :Connection
|
35
|
+
autoload :CustomMethods
|
36
|
+
autoload :Formats
|
37
|
+
autoload :HttpMock
|
38
|
+
autoload :Schema
|
39
|
+
autoload :Singleton
|
40
|
+
autoload :Validations
|
41
|
+
autoload :Collection
|
42
|
+
end
|
43
|
+
|
44
|
+
require 'active_resource/railtie' if defined?(Rails.application)
|
@@ -0,0 +1,175 @@
|
|
1
|
+
module ActiveResource::Associations
|
2
|
+
|
3
|
+
module Builder
|
4
|
+
autoload :Association, 'active_resource/associations/builder/association'
|
5
|
+
autoload :HasMany, 'active_resource/associations/builder/has_many'
|
6
|
+
autoload :HasOne, 'active_resource/associations/builder/has_one'
|
7
|
+
autoload :BelongsTo, 'active_resource/associations/builder/belongs_to'
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
# Specifies a one-to-many association.
|
13
|
+
#
|
14
|
+
# === Options
|
15
|
+
# [:class_name]
|
16
|
+
# Specify the class name of the association. This class name would
|
17
|
+
# be used for resolving the association class.
|
18
|
+
#
|
19
|
+
# ==== Example for [:class_name] - option
|
20
|
+
# GET /posts/123.json delivers following response body:
|
21
|
+
# {
|
22
|
+
# title: "ActiveResource now has associations",
|
23
|
+
# body: "Lorem Ipsum"
|
24
|
+
# comments: [
|
25
|
+
# {
|
26
|
+
# content: "..."
|
27
|
+
# },
|
28
|
+
# {
|
29
|
+
# content: "..."
|
30
|
+
# }
|
31
|
+
# ]
|
32
|
+
# }
|
33
|
+
# ====
|
34
|
+
#
|
35
|
+
# <tt>has_many :comments, :class_name => 'myblog/comment'</tt>
|
36
|
+
# Would resolve those comments into the <tt>Myblog::Comment</tt> class.
|
37
|
+
#
|
38
|
+
# If the response body does not contain an attribute matching the association name
|
39
|
+
# a request sent to the index action under the current resource.
|
40
|
+
# For the example above, if the comments are not present the requested path would be:
|
41
|
+
# GET /posts/123/comments.xml
|
42
|
+
def has_many(name, options = {})
|
43
|
+
Builder::HasMany.build(self, name, options)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Specifies a one-to-one association.
|
47
|
+
#
|
48
|
+
# === Options
|
49
|
+
# [:class_name]
|
50
|
+
# Specify the class name of the association. This class name would
|
51
|
+
# be used for resolving the association class.
|
52
|
+
#
|
53
|
+
# ==== Example for [:class_name] - option
|
54
|
+
# GET /posts/1.json delivers following response body:
|
55
|
+
# {
|
56
|
+
# title: "ActiveResource now has associations",
|
57
|
+
# body: "Lorem Ipsum",
|
58
|
+
# author: {
|
59
|
+
# name: "Gabby Blogger",
|
60
|
+
# }
|
61
|
+
# }
|
62
|
+
# ====
|
63
|
+
#
|
64
|
+
# <tt>has_one :author, :class_name => 'myblog/author'</tt>
|
65
|
+
# Would resolve this author into the <tt>Myblog::Author</tt> class.
|
66
|
+
#
|
67
|
+
# If the response body does not contain an attribute matching the association name
|
68
|
+
# a request is sent to a singleton path under the current resource.
|
69
|
+
# For example, if a Product class <tt>has_one :inventory</tt> calling <tt>Product#inventory</tt>
|
70
|
+
# will generate a request on /products/:product_id/inventory.json.
|
71
|
+
#
|
72
|
+
def has_one(name, options = {})
|
73
|
+
Builder::HasOne.build(self, name, options)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Specifies a one-to-one association with another class. This class should only be used
|
77
|
+
# if this class contains the foreign key.
|
78
|
+
#
|
79
|
+
# Methods will be added for retrieval and query for a single associated object, for which
|
80
|
+
# this object holds an id:
|
81
|
+
#
|
82
|
+
# [association(force_reload = false)]
|
83
|
+
# Returns the associated object. +nil+ is returned if the foreign key is +nil+.
|
84
|
+
# Throws a ActiveResource::ResourceNotFound exception if the foreign key is not +nil+
|
85
|
+
# and the resource is not found.
|
86
|
+
#
|
87
|
+
# (+association+ is replaced with the symbol passed as the first argument, so
|
88
|
+
# <tt>belongs_to :post</tt> would add among others <tt>post.nil?</tt>.
|
89
|
+
#
|
90
|
+
# === Example
|
91
|
+
#
|
92
|
+
# A Comment class declares <tt>belongs_to :post</tt>, which will add:
|
93
|
+
# * <tt>Comment#post</tt> (similar to <tt>Post.find(post_id)</tt>)
|
94
|
+
# The declaration can also include an options hash to specialize the behavior of the association.
|
95
|
+
#
|
96
|
+
# === Options
|
97
|
+
# [:class_name]
|
98
|
+
# Specify the class name for the association. Use it only if that name can't be inferred from association name.
|
99
|
+
# So <tt>belongs_to :post</tt> will by default be linked to the Post class, but if the real class name is Article,
|
100
|
+
# you'll have to specify it with this option.
|
101
|
+
# [:foreign_key]
|
102
|
+
# Specify the foreign key used for the association. By default this is guessed to be the name
|
103
|
+
# of the association with an "_id" suffix. So a class that defines a <tt>belongs_to :post</tt>
|
104
|
+
# association will use "post_id" as the default <tt>:foreign_key</tt>. Similarly,
|
105
|
+
# <tt>belongs_to :article, :class_name => "Post"</tt> will use a foreign key
|
106
|
+
# of "article_id".
|
107
|
+
#
|
108
|
+
# Option examples:
|
109
|
+
# <tt>belongs_to :customer, :class_name => 'User'</tt>
|
110
|
+
# Creates a belongs_to association called customer which is represented through the <tt>User</tt> class.
|
111
|
+
#
|
112
|
+
# <tt>belongs_to :customer, :foreign_key => 'user_id'</tt>
|
113
|
+
# Creates a belongs_to association called customer which would be resolved by the foreign_key <tt>user_id</tt> instead of <tt>customer_id</tt>
|
114
|
+
#
|
115
|
+
def belongs_to(name, options={})
|
116
|
+
Builder::BelongsTo.build(self, name, options)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Defines the belongs_to association finder method
|
120
|
+
def defines_belongs_to_finder_method(reflection)
|
121
|
+
method_name = reflection.name
|
122
|
+
ivar_name = :"@#{method_name}"
|
123
|
+
|
124
|
+
if method_defined?(method_name)
|
125
|
+
instance_variable_set(ivar_name, nil)
|
126
|
+
remove_method(method_name)
|
127
|
+
end
|
128
|
+
|
129
|
+
define_method(method_name) do
|
130
|
+
if instance_variable_defined?(ivar_name)
|
131
|
+
instance_variable_get(ivar_name)
|
132
|
+
elsif attributes.include?(method_name)
|
133
|
+
attributes[method_name]
|
134
|
+
elsif association_id = send(reflection.foreign_key)
|
135
|
+
instance_variable_set(ivar_name, reflection.klass.find(association_id))
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def defines_has_many_finder_method(reflection)
|
141
|
+
method_name = reflection.name
|
142
|
+
ivar_name = :"@#{method_name}"
|
143
|
+
|
144
|
+
define_method(method_name) do
|
145
|
+
if instance_variable_defined?(ivar_name)
|
146
|
+
instance_variable_get(ivar_name)
|
147
|
+
elsif attributes.include?(method_name)
|
148
|
+
attributes[method_name]
|
149
|
+
elsif !new_record?
|
150
|
+
instance_variable_set(ivar_name, reflection.klass.find(:all, :params => {:"#{self.class.element_name}_id" => self.id}))
|
151
|
+
else
|
152
|
+
instance_variable_set(ivar_name, self.class.collection_parser.new)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Defines the has_one association
|
158
|
+
def defines_has_one_finder_method(reflection)
|
159
|
+
method_name = reflection.name
|
160
|
+
ivar_name = :"@#{method_name}"
|
161
|
+
|
162
|
+
define_method(method_name) do
|
163
|
+
if instance_variable_defined?(ivar_name)
|
164
|
+
instance_variable_get(ivar_name)
|
165
|
+
elsif attributes.include?(method_name)
|
166
|
+
attributes[method_name]
|
167
|
+
elsif reflection.klass.respond_to?(:singleton_name)
|
168
|
+
instance_variable_set(ivar_name, reflection.klass.find(:params => {:"#{self.class.element_name}_id" => self.id}))
|
169
|
+
else
|
170
|
+
instance_variable_set(ivar_name, reflection.klass.find(:one, :from => "/#{self.class.collection_name}/#{self.id}/#{method_name}#{self.class.format_extension}"))
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|