New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changed partial rendering to allow collections which don't implement #to_ary
.
#25912
Changed partial rendering to allow collections which don't implement #to_ary
.
#25912
Conversation
r? @schneems (@rails-bot has picked a reviewer for you, use r? to override) |
y.yield(Customer.new("david")) | ||
y.yield(Customer.new("mary")) | ||
end | ||
assert_equal "Hello: davidHello: mary", @view.render(:partial => "test/customer", collection: customers) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ruby 1.9 hash syntax here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops! That's a hard one to break. I'll push a new commit momentarily.
db1e227
to
a0e0cf9
Compare
This transforms for instance scoped objects into arrays and avoid unneeded queries [#5958 state:committed]
Action view tests seems to be broken. |
a0e0cf9
to
ebd8c69
Compare
An optimization was introduced in rails@27f4ffd which tried to `#to_ary` the collection to prevent unnecessary queries for ActiveRecord scopes/relations. If the given collection did not respond to `#to_ary`, and empty collection was returned. That meant you couldn't use collections built from `Enumerator` nor `Enumerable`. With this change, `#collection_from_options` will attempt the optimization, but fall back to passing along the given collection, as-is.
This will ensure we attempt to render an empty collection, meaning we don't actually render anything at all. Allowing `nil` or a falsey value through results in calling `render_partial` rather than `render_collection`, which isn't what we want.
ebd8c69
to
e4a4936
Compare
I've fixed the broken ActiveView test. I'm happy to squash this all into a single commit if y'all are happy with it. |
Let's also change |
And there's no need to check respond_to, this should be enough ... collection = @options[:collection]
collection ? collection.to_a : [] |
I wonder, will that have the desired consequence? More things implement My understanding of the original optimization was to cause an ActiveRecord scope to evaluate and then prevent extra DB calls. In that case, the |
Yeah, the original intention was basically to pre-buffer the Otherwise we're likely to run into an issue with our need for As you note, we know it's not infinite, because we know we're about to call |
We can safely assume we're not dealing with an infinite collection as we're about to call `each` on it and collect the results until it terminates on its own. Given that, `to_a` is implemented by the normal Array-like objects, and less Array-like objects like `Enumerator` and `Enumerator::Lazy`.
3ee41ed
to
87899cf
Compare
Many thanks for the feedback and help, @spastorino and @rafaelfranca. If I might ask one more thing... would you be open to me back porting this to |
…tion_to_allow_custom_collection Changed partial rendering to allow collections which don't implement `#to_ary`.
I've backported to 5-0-stable, I don't think it worth backporting to 4-2-stable. |
I was mostly interested in |
The Rails PR that introduced the backwards-incompatible change that prompted this: rails/rails#25912 rails/rails@87899cf The Rails changelog entry is under 5.0.1.rc1: https://github.com/rails/rails/blob/v5.0.1/actionview/CHANGELOG.md#rails-501rc1-december-01-2016 See also #508
This breaks backwards compatibility for collections that implement |
@glebm Yeah, I think I'm okay with that. I'm not sure Either one of those alone might be insufficient to justify a change on a stable branch, but combined, I don't think it's worth trying both methods. Happy to revisit if this turns out to be a wider problem, though. |
An optimization was introduced in 27f4ffd which will call
#to_ary
on the collection to prevent unnecessary queries for ActiveRecord scopes/relations. If the given collection did not respond to#to_ary
, an empty collection was returned. That meant you couldn't use collections built fromEnumerator
norEnumerable
.With this change,
#collection_from_options
will attempt the optimization, but fall back to passing along the given collection, as-is. This is an alternative to #22005 which will raise an exception if you attempt to use something like anEnumerator
orEnumerable
instance.