Images on Active Storage not displayed on the ERB page but another ERB page are displayed - ruby-on-rails

I am bit lost somewhere, as I have build gallery with active storage and it's fine and I am able to see images and upload the images
Here is a screenshot
But one problem, as I try to create a new page for listing page, I am trying to get images on thumb page
<div class="row">
<div class="col-md-3">
<ul class="sidebar-list">
<li class="sidebar-item"><%= link_to "Your tools Listings", tools_path, class: "sidebar-link active" %></li>
</ul>
</div>
<div class="col-md-9">
<div class="panel panel-default">
<div class="panel-heading">
Listings
</div>
<div class="panel-body">
<% #tools.each do |tool| %>
<div class="row">
<div class="col-md-2">
<%= tool.images %>
</div>
<div class="col-md-7">
<h4><%= tool.listing_name %></h4>
</div>
<div class="col-md-3 right">
<%= link_to "Update", listing_tool_path(tool), class: "btn btn-black-free-account" %>
</div>
</div>
<hr/>
<% end %>
</div>
</div>
</div>
</div>
it should be fine as long it shows a text-based of images see screenshot below
So I need to change these images as I am using the same method as the first screenshot, as the code below
<% if #tool.images.attached? %>
<div class="panel panel-default">
<div class="panel-heading">
Photo Display
</div>
<br>
<div class="row">
<% #tool.images.each do |image| %>
<div class="col-md-4">
<div class="panel panel-default tools-gallery-panel">
<div class="panel-heading preview ">
<%= link_to image_tag(image, class:"img-thumbnail tools-gallery"), image %>
</div>
<div class="panel-body">
<span class="pull-right">
<i class="fa fa-trash-o fa-lg" aria-hidden="true"></i>
<%= link_to "Remove", delete_image_attachment_tool_path(image), method: :delete, data: {confirm: "Are you sure?"} %>
</span>
</div>
</div>
</div>
<% end %>
<% end %>
</div>
so I copied
<%= link_to image_tag(image, class:"img-thumbnail tools-gallery"), image %>
this to new listing pages stuff
so I modify the listing page
<% #tools.each do |tool| %>
<div class="row">
<div class="col-md-2">
<%= tool.images %>
<%= link_to image_tag(tool.images, class:"thumbnail"), images %>
</div>
<div class="col-md-7">
<h4><%= tool.listing_name %></h4>
</div>
<div class="col-md-3 right">
<%= link_to "Update", listing_tool_path(tool), class: "btn btn-black-free-account" %>
</div>
</div>
<hr/>
<% end %>
and all I got an error
even I have tried this
<%= link_to image_tag(tool, class:"thumbnail"), images %>
Tool.rb
class Tool < ApplicationRecord
belongs_to :user
has_many_attached :images
validates :tool_type, presence: true
validates :power_type, presence: true
validates :accessories, presence: true
validates :brand, presence: true
validates :price, presence: true
end
and I get same error, Any suggest would be great

In your model you have has_many_attached :images
tool.images regardless the number of images will alway return an ActiveSTorage::Attached::Many which is an Enumerable so you will have to loop through it to get each image, in the loop each image will be an ActiveStorage::Blob, to use image_tag you will need a url for the image, to get the url from the blob you would use url_for(image).
Here is an example:
<% tool.images.each do |image| %>
<%= image_tag(url_for(image), class: 'some-class') %>
<% end %>
In your case you wanted the image to be a link, that is easy to do as well you just have to pass the correct information to link_to. You can do this in multiple ways this is the way I think is the easiest to read.
With a link:
<% tool.images.each do |image| %>
<%= link_to "Path to Tool as string" do %>
<%= image_tag(url_for(image), class: 'some-class') %>
<% end %>
<% end %>

This is the API for link_to:
link_to name, options = {}, html_options = nil
This is the API for image_tag:
image_tag source, options={}
Lastly, you're seeing this error:
Can't resolve image into URL: undefined `to_model` for #<ActiveStorage::Attached::Many>
You are getting this error because you're try to create an image tag with a single image not a collection of "many".
Look at your original working code (superfluous HTML stripped away):
<% #tool.images.each do |image| %>
<%= link_to image_tag(image, class:"img-thumbnail tools-gallery"), image %>
<% end %>
Notice how you are looping through all the images? That is because a #tool has many images. It is an array of images. Inside the link_to block, you're defining an image_tag properly with a single image as the reference. Now lets look at your erroneous code:
<% #tools.each do |tool| %>
<%= tool.images %>
<%= image_tag(tool.images, class:"thumbnail"), images %>
<% end %>
This is weird. You're calling this:
<%= tool.images %>
Which just displays an instance of #<ActiveStorage::Attached::Many> and you're calling this:
<%= link_to image_tag(tool.images, class:"thumbnail"), images %>
Which just attempts (and fails) to link an array of images to a single image_tag instance which we know is invalid thanks to the api. You likely want to do this:
<% #tools.each do |tool| %>
<%= tool.images.each |image| %>
<%= image_tag(image, class:"thumbnail"), image %>
<% end %>
<% end %>

Related

request active storage image show only one not all images

As Rookie Rails, i am able to get all images to display on the html.erb as using model as has_many_attached :images
but i have tried many different way like this code below
<div class="row">
<div class="col-md-12">
<% if #tool.images.attached? %>
<% #tool.images.each do |image| %>
<div class="img-fluid <%= 'active' if image.id == #images[0].id %>">
<%= link_to image_tag(image), image %>
</div>
<% end %>
<% end %>
</div>
</div>
but didn't show one image but only a few images as I am trying to fix this
image.id == #images[0].id
this code is dont display one image, do you know where i can use this code into this as i have tried many way but all failed
if i use this code
<!-- Image -->
<div class="row">
<div class="col-md-12">
<% if #tool.images.attached? %>
<% #tool.images.each do |image| %>
<%= link_to image_tag(image, class:"tools-gallery"), image %>
<% end %>
<% end %>
</div>
</div>
<br/>
it show fine and able to get displayed
but I don't want two images or more, it ok for the gallery but not this pages as it need show one image.
and the controller.rb
def show
#images = #tool.images
end
<div class="row">
<div class="col-md-12">
<%= image_tag #tool.images.first if #tool.images.attached? %>
</div>
</div>

Nil:nil class error on each loop when Form to build object loaded on page first

I have a form on a page that is building a “tip” for a “guide”. Below the form, I am running an each loop over all the #guide.tips. I keep getting an error as the each loop is loading the forms blank object as it sees it as a tip. I’ve currently solved the problem by using jQuery to inject the form after page load, but there has to be a better solution.
Each Loop on Guide.html.erb
<% if !#guide.tips.blank? %>
<% #guide.tips.each do |tip| %>
<div class="row mx-1">
<div class="col-md-3 border-right">
<div class="float-left">
<%= image_tag avatar_url(tip.user), class: "float-left text-left align-middle rounded img-fluid mx-3", width: "30%" %>
<p><%= tip.user.fullname %></p>
</div>
<div class="float-right mr-3">
<%= link_to like_tip_path(tip), method: :put do %>
<div class="fas fa-angle-up"></div>
<%= tip.get_upvotes.size %>
<% end %><br/>
<%= link_to dislike_tip_path(tip), method: :put do %>
<div class="fas fa-angle-down"></div>
<%= tip.get_downvotes.size %>
<% end %>
</div>
</div>
<div class="col-md-8 ml-3">
<h6><%= tip.title %> -<span class="ml-1"><small><%= tip.created_at.strftime("%A, %d %b %Y %l:%M %p")%></small></span></h6>
<%= tip.tip %>
</div>
</div><hr/>
<% end %>
<% end %>
Tips_Controller.rb
def new
#guide = Guide.find(params[:guide_id])
#tip = Tip.new
end
def edit
end
def create
#guide = Guide.find(params[:guide_id])
params[:tip][:user_id] = current_user.id
#tip = #guide.tips.create!(tip_params)
redirect_to guide_path(#guide)
end
Tip Form Partial
<%= form_for([#guide, #guide.tips.build]) do |f| %>
<div class="form-group row">
<div class="col-sm-12">
<p class="text-left">Tip Title</p>
<%= f.text_field :title, placeholder: "Enter Title", class: "form-control" %>
</div>
<div class="col-sm-12 mt-2">
<p class="text-left">Your Tip</p>
<%= f.text_area :tip, placeholder:"What's your tip for this travel guide?", class: 'form-control' %>
</div>
</div>
<div class="form-group row">
<div class="col-md">
<%= f.submit 'Submit', class: 'btn btn-primary btn-block' %>
</div>
</div>
<% end %>
Here is another solution that does not separate the logic between the controller and the view and cleans up your empty array statement for your loop
Each Loop on Guide.html.erb
<% #guide.tips.each do |tip| %>
<div class="row mx-1">
<div class="col-md-3 border-right">
<div class="float-left">
<%= image_tag avatar_url(tip.user), class: "float-left text-left align-middle rounded img-fluid mx-3", width: "30%" %>
<p><%= tip.user.fullname %></p>
</div>
<div class="float-right mr-3">
<%= link_to like_tip_path(tip), method: :put do %>
<div class="fas fa-angle-up"></div>
<%= tip.get_upvotes.size %>
<% end %><br/>
<%= link_to dislike_tip_path(tip), method: :put do %>
<div class="fas fa-angle-down"></div>
<%= tip.get_downvotes.size %>
<% end %>
</div>
</div>
<div class="col-md-8 ml-3">
<h6><%= tip.title %> -<span class="ml-1"><small><%= tip.created_at.strftime("%A, %d %b %Y %l:%M %p")%></small></span></h6>
<%= tip.tip %>
</div>
</div><hr/>
<% end unless #guide.tips.blank? %>
Tip Form Partial
By creating the Tip from outside the association (i.e. not using build), it will not be loaded into the class variable's children
<%= form_for([#guide, Tip.new(guide: #guide)]) do |f| %>
<div class="form-group row">
<div class="col-sm-12">
<p class="text-left">Tip Title</p>
<%= f.text_field :title, placeholder: "Enter Title", class: "form-control" %>
</div>
<div class="col-sm-12 mt-2">
<p class="text-left">Your Tip</p>
<%= f.text_area :tip, placeholder:"What's your tip for this travel guide?", class: 'form-control' %>
</div>
</div>
<div class="form-group row">
<div class="col-md">
<%= f.submit 'Submit', class: 'btn btn-primary btn-block' %>
</div>
</div>
<% end %>
Another Example / Q&A
Using the structure you already have you could do:
<% if #guide.tips.count > 1 %> (assuming this will always be shown with an empty "build" tip)
or you can use:
<% next unless tip.persisted? %>
inside the loop, before the actual form.
You also don't need the blank? check as an .each on an empty enumerator simply won't execute the block, and as long as there's a has_many relationship between guide and tips it will always yield a collection proxy.
I would write it as:
<% #guide.tips.each do |tip| %>
<% next unless tip.persisted? %>
<div class="row mx-1">
<div class="col-md-3 border-right">
...
<% end %>

Lightbox with Rails

So I am trying to use Lightbox2 on my application. I installed the gem and followed all the steps, but having trouble figuring out where to call it in the application.
This is my post index
<div class="container">
<div id="profuploads">
<div id="posts" class="transitions-enabled">
<% #posts.each do |post| %>
<div class="box panel panel-default">
<%= link_to image_tag(post.image.url(:medium)), post %>
<div class="panel-body">
<strong><%= post.user.username if post.user %></strong><br/>
<%= post.description %>
<% if post.user == current_user %>
<div class="actions">
<%= link_to 'Edit', edit_post_path(post) %>
<%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %>
</div>
<% end %>
</div>
</div>
<% end %>
</div>
</div>
</div>
This is my post show
<div class="row">
<div class="col-md-offset-1 col-md-10">
<div class="panel panel-default">
<div class="panel-heading center">
<%= image_tag #post.image.url, height: '300' %>
</div>
<div class="panel-body">
<p><strong><%= link_to(#post.user.username.capitalize, user_path(#post.user.id)) if #post.user %></strong></p>
<p><%= #post.description %></p>
<div class="votes">
<strong>VIEWS</strong>
<%= #post.hits %>
<div class="votes">
<%= link_to like_post_path(#post), method: :put do%>
<button type="button" class="btn btn-info" aria-label="Left Align">
<span class="glyphicon glyphicon-thumbs-up glyphicon-align-center" aria-hidden="true"></span>
<span class="badge"><%= #post.get_upvotes.size %></span>
</button>
<%end%>
</div>
<% if #post.user == current_user %>
<%= link_to 'Edit', edit_post_path(#post) %>
<% end %>
</div>
</div>
</div>
</div>
With Lightbox do I need to just git rid of my post show page altogether?
Lightbox is a javascript library which needs proper html markup in order to do it's work. Your show view looks good except it does not include the markup Lightbox looks for.
From Lightbox Getting Started guide:
Add a data-lightbox attribute to any image link to enable Lightbox. For the value of the attribute, use a unique name for each image. For example:
Image #1
When Lightbox initializes, it looks for any image tags that contain data-lightbox attribute and hooks its handlers to them. You need to provide this attribute:
<%= image_tag #post.image.url, height: '300', "data-lightbox" => #post.image.url %>
This should make Lightbox pick up your images.

Ruby on Rails View Rendering DB Info On Page

I am working on a project and currently working on one of the views which is a page of different categories. Everything is rendering correctly however it's also putting the db info in the page.
Here is the code of my view
<div class="categories">
<div class="container blurbs">
<div class="cards row">
<%= #categories.each do |c| %>
<div class="card col-xs-4" %>
<%= image_tag c.image, :class => "cat" %>
<h4 class="title"><%= c.title %></h4>
</div>
<% end %>
</div>
</div>
</div>
Here is a link to a
screenshot of rendered page
Yes, fix is:
<div class="categories">
<div class="container blurbs">
<div class="cards row">
<% #categories.each do |c| %>
<div class="card col-xs-4" %>
<%= image_tag c.image, :class => "cat" %>
<h4 class="title"><%= c.title %></h4>
</div>
<% end %>
</div>
</div>
</div>
Look I removed = from this <%=.. In the below line :
<% #categories.each do |c| %>
#each method returns the collection after it completed its iterations. And due to this <%=, the return value of each which is #categories printed back. But if you use <%.. only, all above things will happen, but it wouldn't print back the object #categories.
when you use the tags <%= ... %> whatever is within the tags gets displayed on the page. In your current view you have
<%= #categories.each do |c| %>
<div class="card col-xs-4" %>
<%= image_tag c.image, :class => "cat" %>
<h4 class="title"><%= c.title %></h4>
</div>
<% end %>
Which displays the entirety of whatever the loop returns which is where you're getting the display. Change the tags to be <% #categories.each do |c| %> and you'll be good to go.

Reply to comment in the same page not in comments/new path, Rails 4

I have created commenting system to provide functions like creating comments and replying them.
I used http://www.sitepoint.com/nested-comments-rails/ guide. Worked just perfect. But in this example to reply to some comment it goes to other path, that is what I want to avoid.
Code so far:
Advertisement#show here I want to create reply to comment.
<%= comments_tree_for #comments %>
<h1>New comment</h1>
<%= render 'comments/form' %>
_comment.html.rb
<div class="well">
<h2><%= comment.title %></h2>
<p class="text-muted"><%= comment.root? ? "Started by" : "Replied by" %> <strong><%= comment.author %></strong> on
<%= l(comment.created_at, format: '%B, %d %Y %H:%M:%S') %></p>
<blockquote>
<p><%= comment.body %></p>
</blockquote>
<% from_reply_form ||= nil %>
<% unless from_reply_form %>
<% if comment.leaf? %>
<small class="text-muted">There are no replies yet - be the first one to reply!</small>
<% end %>
<p><%= link_to 'reply', new_comment_path(comment.id) %></p>
<% end %>
</div>
_form.html.erb
<%= form_for(#comment) do |f| %>
<% if #comment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#comment.errors.count, "error") %> prohibited this comment from being saved:</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :advertisement_id, :value => #advertisement.id%>
<%= f.hidden_field :user_id, :value => current_user.id%>
<%= f.hidden_field :parent_id %>
<div class="form-group">
<%= f.label :body %>
<%= f.text_area :body, class: 'form-control', required: true %>
</div>
<%= f.submit class: 'btn btn-primary' %>
<% end %>
Is there any trustworthy guide to help me ?
The link_to 'reply', new_comment_path(comment.id) line creates a hyperlink to new comment page and when clicked it takes you to next page to create the comment. Instead you can replace it with a div containing the form the toggles and submits new convo from the same page. Bootstrap comes handy here.
A Mock up of the idea: http://jsfiddle.net/bpya4fce/1/
You can build up using this idea. Hope this helps :)
P.S: Make sure that you fetch the variables required for the form in the action of view where you embed the form, i.e if you're embedding the form in show.html.erb, ensure the necessary variables are fetched in the show action/method of controller. In the earlier scenario, it'll be fetched in the new action of the CommentsController.
<div class="container">
<blockquote>
<h2>Posted Comment</h2>
Lorem Ipsum. You can reply to this below.
</blockquote>
<div class="panel-group" id="accordion">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion"
href="#collapseOne">
Click to reply
</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse">
<div class="panel-body">
### The comment form comes here ###<br/>
### render :partial => 'comment/form'
</div>
</div>
</div>
</div>
Not sure if this is what you wanted. Hope this example code gives you some idea.
Be sure to complete the code and test it :)
_comment.html.rb
<% from_reply_form ||= nil %>
<% unless from_reply_form %>
<% if comment.leaf? %>
<small class="text-muted">There are no replies yet - be the first one to reply!</small>
<% end %>
<!-- HERE adding a hidden DIV that contains a form. -->
<div class='hidden-reply-form-<%= comment.id%>'>
<%= render partial: 'comments/form', locals: {comment: Comment.new} %>
</div>
<p><%= link_to 'reply', new_comment_path(comment.id), class: 'reply', id: comment.id %></p>
<% end %>
</div>
<script>
// HERE use reply link to toggle the hidden div.
$(function(){
$(".reply").click(function(){
// toggle replying div.
// .....
});
})
</script>

Resources