Here is step by step replacing:
images = @element.measurements.map {|e| e.images}.reject!(&:blank?)
For this line of code it is better to produce next relation
has_many :images, through: :measurements
# OR for better naming
has_many :measurement_images, through: :measurements, source: :images
Then you can just do:
images = @element.measurement_images
Which will execute next SQL
SELECT *
FROM images
INNER JOIN measurements
ON measurements.id = images.measurement_id
WHERE measurements.element_id = $1
So no need to reject blank images as INNER JOIN just do exactly that, throws away non-matching records, check out the doc
After creating this has_many through relation, next code won't produce any N+1 issues:
images.map {|i| i.file.url}
Also you can minimize the output by adding #select, but I don't advise you to do that, as it complicates code a lot and heavily coupled on image library implementation, so in case of updating library you can break the code.
But for note, if you use paperclip gem with default URL generation pattern you can do something like this:
image_ulrs = @element
.measurement_images
.select(
:id,
:type, # if you have STI model
:<your_file_field>_file_name,
:<your_file_field>_updated_at
).map { |i| i.file.url }
<your_file_field> is the first argument which is passed to has_attached_file for example
has_attached_file :attachment
will result in
...
.select(
:id,
:type, # if you have STI model
:attachment_file_name,
:attachment_updated_at
)
but again I do NOT suggest to do that as it does not give a lot of performance improvement but can be a headache in future.
joins(element: :images)should probably do. - Aleksei Matiushkinincludes(element: :images)is more appropriate - Luiz E.Measurement::ActiveRecord_AssociationRelation- user5639287@element.measurements.includes(images: :measurements).select('images.file')? it might work - Luiz E.selectand I gotMeasuremetswithoutimages. - user5639287