Skip to content

Commit 34e7e3c

Browse files
committed
Add a way to temporarily opt-out to #all now lazily making requests:
- ### Problem In 9372d5a we made a change that defer the http request submission until the collection is used. ```ruby # Before Product.all #=> HTTP request is made # After products = Product.all #=> No HTTP request is made products.each { ... } #=> HTTP request is made here ``` This create issues for codepaths that used to expect the `Product.all` to make the http request and this feels like a breaking change that should go through a deprecation cycle (too late now but let's have a way to opt-out to the new behaviour). ### Context We have a safety net in our application that does something like this: ```ruby products = allow_explicit_http_connections do Product.all end products.each { ... } ``` This is now broken because we make the request outside of the explictly allowed resiliency block. ### Solution Introduce a way to opt out to the new behaviour and trigger a deprecation warning.
1 parent e577c6d commit 34e7e3c

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,16 @@ people = Person.where(last_name: "Durden")
192192
people.first # => <Person::xxx 'first_name' => 'Tyler' ...>
193193
```
194194

195+
##### A note on finding all resources
196+
197+
Previously, Active Resource would eagerly load resources when `Person.all` was called. This behaviour is now
198+
deprecated and Active Resource now lazy loads collections. The http request is deferred until the collection is
199+
explicitly accessed.
200+
201+
You can opt-in to the new behaviour by setting the `ActiveResource::Base.lazy_collections = false`.
202+
Note that this setting is temporary to allow your application to progressivly transition to the new behaviour.
203+
This setting will be removed in the next versions of Active Resource.
204+
195205
### Create
196206

197207
Creating a new resource submits the JSON form of the resource as the body of the request and expects

lib/active_resource/base.rb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ def self.logger=(logger)
371371
@@logger = logger
372372
end
373373

374+
class_attribute :lazy_collections, default: true, instance_accessor: false
374375
class_attribute :_query_format
375376
class_attribute :_format
376377
class_attribute :_collection_parser
@@ -384,6 +385,16 @@ class << self
384385
include ThreadsafeAttributes
385386
threadsafe_attribute :_headers, :_connection, :_user, :_password, :_bearer_token, :_site, :_proxy
386387

388+
def new_lazy_collections=(value)
389+
ActiveResource.deprecator.warn(<<~MSG)
390+
ActiveResource::Base#lazy_collections= is deprecated with no replacement.
391+
MSG
392+
393+
self.old_lazy_collections = value
394+
end
395+
alias_method :old_lazy_collections=, :lazy_collections=
396+
alias_method :lazy_collections=, :new_lazy_collections=
397+
387398
# Creates a schema for this resource - setting the attributes that are
388399
# known prior to fetching an instance from the remote system.
389400
#
@@ -1126,7 +1137,11 @@ def last(*args)
11261137
# This is an alias for find(:all). You can pass in all the same
11271138
# arguments to this method as you can to <tt>find(:all)</tt>
11281139
def all(*args)
1129-
WhereClause.new(self, *args)
1140+
if lazy_collections
1141+
WhereClause.new(self, *args)
1142+
else
1143+
find(:all, *args)
1144+
end
11301145
end
11311146

11321147
# This is an alias for all. You can pass in all the same

test/cases/finder_test.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,30 @@ def test_all
6161
assert_equal "David", all.last.name
6262
end
6363

64+
def test_all_loads_the_collection_lazily
65+
all = Person.all
66+
assert_empty(ActiveResource::HttpMock.requests)
67+
68+
assert_equal(2, all.size)
69+
assert_not_empty(ActiveResource::HttpMock.requests)
70+
end
71+
72+
def test_all_loads_the_collection_eagerly
73+
previous_value = ActiveResource::Base.lazy_collections
74+
75+
assert_deprecated(/ActiveResource::Base#lazy_collections= is deprecated/, ActiveResource.deprecator) do
76+
ActiveResource::Base.lazy_collections = false
77+
end
78+
79+
all = Person.all
80+
assert_not_empty(ActiveResource::HttpMock.requests)
81+
assert_equal(2, all.size)
82+
ensure
83+
assert_deprecated(/ActiveResource::Base#lazy_collections= is deprecated/, ActiveResource.deprecator) do
84+
ActiveResource::Base.lazy_collections = previous_value
85+
end
86+
end
87+
6488
def test_all_with_params
6589
all = StreetAddress.all(params: { person_id: 1 })
6690
assert_equal 1, all.size

0 commit comments

Comments
 (0)