Module: AmsLazyRelationships
- Defined in:
- lib/ams_lazy_relationships/extensions/reflection.rb,
lib/ams_lazy_relationships.rb,
lib/ams_lazy_relationships/loaders.rb,
lib/ams_lazy_relationships/version.rb,
lib/ams_lazy_relationships/extensions.rb,
lib/ams_lazy_relationships/loaders/base.rb,
lib/ams_lazy_relationships/loaders/direct.rb,
lib/ams_lazy_relationships/loaders/association.rb,
lib/ams_lazy_relationships/loaders/simple_has_many.rb,
lib/ams_lazy_relationships/loaders/simple_belongs_to.rb
Overview
There is a general problem inside AMS related to custom association finder
combined with include_data setting:
class BlogPostSerializer < BaseSerializer
belongs_to :category do
include_data :if_sideloaded
object.categories.last
end
end
The problem is that belongs_to block will be fully evaluated each time for
each object, and only after that AMS is able to take into account
include_data mode -
https://github.com/rails-api/active_model_serializers/blob/v0.10.10/lib/active_model/serializer/reflection.rb#L162-L163
def value(serializer, include_slice)
# ...
block_value = instance_exec(serializer, &block) if block
return unless include_data?(include_slice)
# ...
end
That causing redundant (and so huge potentially!) SQL queries and AR objects
allocation when include_data appears to be false but belongs_to block
defines instant (not a kind of AR::Relation) custom association finder.
Described problem is a very specific use case for pure AMS applications.
The bad news is that ams_lazy_relationships always utilizes the
association block -
https://github.com/Bajena/ams_lazy_relationships/blob/v0.2.0/lib/ams_lazy_relationships/core/relationship_wrapper_methods.rb#L32-L36
def define_lazy_association(type, name, options, block) #... block ||= lambda do |serializer| serializer.public_send("lazy_#name") end
public_send(type, name.to_sym, , &block)
#...
end
This way we break include_data optimizations for the host application.
In order to overcome that we are forced to monkey-patch
AmsLazyRelationships::Extensions::Reflection#value method and make it to be
ready for Proc returned by association block. This way we will use a kind of
block ||= lambda do |serializer|
-> { serializer.public_send("lazy_#{name}") }
end
as association block, then AMS will evaluate it, get the value of include_data
setting, make a decision do we need to continue with that association, if so -
will finally evaluate the proc with lazy relationship inside it.
Defined Under Namespace
Modules: Core, Extensions, Loaders
Constant Summary collapse
- VERSION =
"0.4.0"