2

This is somewhat related my question about joins here. By default when I use listing.image.name in my search results view, it does a full query to find the image for every listing in my results array. It even does an extra query just to check if the listing has any images. So to avoid this, I'm adding the following to my Thinking Sphinx query:

@ts_params[:sql][:joins] = "INNER JOIN listing_images ON listing_images.listing_id = listings.id AND listing_images.position = 0"
@ts_params[:sql][:select] = "listings.*, listing_images.image as image_name, listing_images.id as image_id"

This works, however I'm not sure how to generate the full image_url using carrierwave. Previously, where it was doing an extra query per result, I was using listing.image.image_url(:sizename). So, I can find the image name and ID from my join as above, but how to I convert this to a full image url via carrierwave? Is there a built-in method to retrieve the url, that doesn't require an 'image' object?

I tried listing.image_id.image_url(:sizename) but it gave an undefined method error as expected.

Community
  • 1
  • 1
Dave
  • 1,051
  • 1
  • 10
  • 20
  • 1
    I've managed to get this working manually entering the url, <%= image_tag "https://s3urlhere/uploads/listing_image/image/#{listing.image_id}/medium_#{listing.image_name}", :alt => listing.title %> - surely theres a way to build this url using carrierwave? – Dave Sep 23 '13 at 16:43

2 Answers2

1

From carrierwave's perspective, the answer is obvious:

user.avatar.url
user.avatar.thumbnail.url

Here, user is an instance of a model, and avatar is the field on the model with mount_uploader called on it. In your case this would be something like:

listing_image.image_name.url
listing_image.image_name.thumbnail.url

That probably doesn't work, though, because it looks like you may be loading your listing_image fields into the Listing instead of through includes (or the dreaded N+1 non-eager loads). You may need to resolve your other stackoverflow question before this one will be possible.

Edit:

Per our discussion on your other issue, once you've got a has_one :main_image for just the one ListingImage you want, you're going to use something like @listing.main_image.image_name.url and, if you have a version named "thumbnail", @listing.main_image.image_name.thumbnail.url.

Community
  • 1
  • 1
Taavo
  • 2,406
  • 1
  • 17
  • 17
  • Ok I'll probably end up using eager loading as per your answer in my last question - but surely its best using joins where possible as it saves a query? – Dave Sep 25 '13 at 20:09
  • Per [the docs](http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations), `includes`, which we discussed in the other thread, uses "the minimum possible number of queries." In practice, I've found that it prefers a cheap extra query (but not N queries) to a huge, expensive join. If you see `includes` performing N extra queries, it could be a weird interaction with thinking sphinx worth reporting to the author of that gem. – Taavo Sep 25 '13 at 20:24
0

I had the similar issue when I was fetching image using query and wanted to build image url using db field instead of issuing full sql query for each image.

I found out that with couple of field fetched from related image table we can build image which will not run any sql for image if we have three fields id, updated_at and image_name this field should be from the table where image is being saved. It could be from the main table where image is saved as separate column or completely separate table use to specially for image here is a sample code

It can be in your helper or in decorator as per your choice

  def logo_url(id, updated_at, name)
    return if id.blank? || updated_at.blank? || name.blank? 

    Company.new(id: id, updated_at: updated_at, logo: name).logo
  end

and in view you can call this helper method as

<%= logo_url(company.id, company.updated_at, company.logo).url %>

This way you can have your image with url without executing sql query on each image.

Sandeep Garg
  • 1,292
  • 1
  • 13
  • 31