Trouble viewing images by collection_id

I've set up so that my users can create individual collections and add listings to each collection. I then created a main page in my site navigation that shows all collections by all users. I'm now trying to view the first 3 listing images for each collection on that main page. I've got it working so far where I view the first 3 images from the entire listings database, but it's not specific by collection_id. I'll add what I've tried in a reply here so I can type it out clearly so you can see where I am with this...

Posted over 4 years ago by Amy Peterson
Posted over 4 years ago by Amy Peterson

My main nav view page in my Pages directory:
(my file url is Pages/section.html.erb)

<% @collections.each do |collection| %>

<% @listings.limit(3).each do |listing| %>
<%= image_tag listing.image.url(:small) %>
<% end %>

<%= collection.name %>
By <%= collection.user.business_name %>
<% end %>


My pages_controller.rb:

def sections
@collections = Collection.all.order("created_at DESC")

# ------ERROR: "Couldn't find Listing with 'id'="---------
# @listings = Listing.find(params[:collection_id])

# ------THIS GIVES ME THE FIRST 3 LISTINGS IN THE DATABASE-----
# @listings = Listing.all

# --------ERROR: "Couldn't find Listing with 'id'={:collection_id=>nil}"-------
# @listings = Listing.find(collection_id: @collection)

# ------THESE SERVE BLANK COLLECTIONS -- BUT NO ERRORS -----
@listings = Listing.where(collection_id: @collection)
# @listings = Listing.where(collection_id: :collection_id)
# @listings = Listing.where(collection_id: @collection_id)

# -----ERROR: "undefined method `limit' for nil:NilClass"------
# @collection_id = Collection.find_by(name: params[:collection_id])

# ------THIS GIVES ME THE LAST 3 LISTINGS IN THE DATABASE-----
# if params[:collection_id].blank?
# @listings = Listing.all.order("created_at DESC")
# else
# @collection = Collection.where(params[:collection_id]).id
# @listings = Listing.where(collection_id: @collection)
# end
end

What I have in my collections show page when the users add listings to their collections:
@listings = Listing.where(collection_id: @collection).order("created_at DESC")

You can see I've tried a number of ways in my pages_controller to bring in 3 images by collection_id and I'm stuck : /

What am I missing?

1
Posted over 4 years ago by Alex Yang

You've asked a good question - I can see that you're trying to better understand how to retrieve objects from a database. The issue isn't how you're defining @listings, but how you're defining @collection / @collection_id. The error messages you're seeing keep on mentioning nil (e.g. Couldn't find Listing with 'id'={:collection_id=>nil}, undefined method `limit' for nil:NilClass) because @collection / @collection_id hasn't yet been defined and therefore is nil.

While this isn't the most efficient way to do it, here's an approach that will work and makes the logic easier to understand (assume that @listings = Listing.all):

<% @collections.each do |collection| %>

<% @listings.where(collection_id: collection).order("created_at DESC").limit(3).each do |listing| %>
<%= image_tag listing.image.url(:small) %>
<% end %>

<%= collection.name %>
By <%= collection.user.business_name %>
<% end %>

In English, we're looping through each collection and for each one, we're filtering to only those Listings that belong in that collection, ordering them in chronological order, and then taking the 3 most recent. Let me know if that makes sense.

1
Posted over 4 years ago by Amy Peterson

Thanks Alex, yes that does make sense. I did try it and I'm still getting an error. I was given a suggestion yesterday and it works for me this way:

<% @collections.each do |collection| %>
<div class="item">
<div class="well clearfix">

<div class="photos clearfix">
<% collection.listings.limit(3).each do |listing| %>
<div class="frame">
<%= image_tag listing.image.url(:thumb) %>
</div>
<% end %>
</div>

<div class="details">
<p class="name"><%= collection.name %></p>
<p>By <%= collection.user.business_name %></p>
</div>

</div>
</div>
<% end %>

Is this a viable solution?

Then, the last thing I'm interested in knowing how to do with images is I'm looking to have the each image in their own div class "frame" so that I can size only the first image much larger than the other 2. I am trying to achieve the similar treatment you see on the Etsy home page for Trending items where they have 3 images, the first image is on top the width of the column and the other 2 are inline thumbnails underneath. Do you have a recommendation on how best to achieve that?

1
Posted over 4 years ago by Amy Peterson

Hi Alex, I've done more digging and learned more about limit and offset. Can you take a look at my current code and tell me if this is viable? It is actually returning exactly what I'm looking for...The first image is now my main hero set at the column width, and the next 3 images for that collection are now thumbnails underneath the main image. I only question this from asking if it's "code-correct" to have mutliple "...each do's" in the same view, even though they're using different methods?

<div class="row">
<% @collections.each do |collection| %>
<div class="item">
<div class="well clearfix">

<% collection.listings.limit(1).offset(0).each do |listing| %>
<%= image_tag listing.image.url(:medium) %>
<% end %>

<div class="photos clearfix">
<% collection.listings.limit(3).offset(1).each do |listing| %>
<div class="frame">
<%= image_tag listing.image.url(:thumb) %>
</div>
<% end %>
</div>

<div class="details">
<p class="name"><%= collection.name %></p>
<p>By <%= collection.user.business_name %></p>
</div>

</div>
</div>
<% end %>
</div>

1
Posted over 4 years ago by Alex Yang

Amy, this is great! I'd forgotten that your collection_ids were already associated with your Listings - your solution is more elegant than mine. It's fine to have multiple loops in the same view, though in this case, you don't need to use the loop starting with

<% collection.listings.limit(3).offset(1).each do |listing| %>

Since it's only retrieving one Listing, you're better off just writing:

<div class="photos clearfix">
<div class="frame">
<%= image_tag collection.listings.limit(3).offset(1).image.url(:thumb) %>
</div>
</div>

1
Posted over 4 years ago by Amy Peterson

Yeah?! Great Alex thanks, it feels good to know I'm making progress and learning. I have one last issue before I'm done with all of these listings and collections, but I'll post a new question for that so this thread stays on specific topic. It's also related to linked objects and databases. Seems that's the hardest part for me. TBC...

1