Lightbox with Rails - ruby-on-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.

Related

Haiving a problem to Paginate an iteration with Kaminari

I'm trying to paginate a result of an iteration using Kaminari. The pagination is showing well but its not cutting it into another page. All is showing on the same page even when I click on page 2, it still the same result as page 1
I'm using rails 6 and ruby 2.5
in my controller i have this
def dashboard
user_gigs = current_user.gigs
#user_gigs_pager = Kaminari.paginate_array(user_gigs).page(params[:page]).per(4)
end
then in my view I call the paginate
<div class="card">
<div class="card-header-title is-centered">
<%= paginate #user_gigs_pager %>
</div>
</div>
this my full view code
<% current_user.gigs.each do |gig| %>
<%# <% user_gigs = current_user.gigs %>
<div class="column is-one-third">
<div class="card">
<div class="card-image">
<%= link_to edit_gig_path(gig) do %>
<figure class="image is-4by3">
<!-- Gig Cover Image Here -->
<%= image_tag gig_cover(gig) %>
</figure>
<% end %>
</div>
<div class="card-content p-t-5 p-b-5">
<p class="subtitle is-6 m-b-5"><%= link_to gig.title.truncate(20), gig_path(gig) %></p>
<span class="star-review"><i class="fa fa-star"></i>
<%= gig.average_rating %> <span class="star-review">(<%= gig.reviews.count %>)</span>
</span>
</div>
<footer class="card-footer">
<p class="deletegig">
<%= link_to destroy_gig_path(gig), method: :delete, data: { confirm: "are you sure"} do %>
<span class="icon has-text-danger">
<i class="far fa-trash-alt"></i>
</span>
<% end %>
</p>
<% basic_price = gig.pricings.find{ |p| p.pricing_type == 'basic' }%>
<a class="has-text-danger is-block card-footer-item has-text-right">
<% if !basic_price.nil? %>
<span class="small-title">Points</span> <i class="fab fa-bitcoin"></i>
<strong><%= basic_price.price %></strong>
<% else %>
<strong>
<span class="small-title has-text-dark">Pas de point</span>
</strong>
<% end %>
</a>
</footer>
</div>
</div>
<% end %>
</div>
</div>
</div>
<div class="card">
<div class="card-header-title is-centered">
<%= paginate #user_gigs_pager %>
</div>
</div>
Kaminari.paginate_array(user_gigs).page(params[:page]).per(4)
expects page number as argument of page and number of records per page as argument of per.
Your params must contain page number (i.e. 1 or 2 or 3 ...) in :page key.
The solution was to apply the pagination on the ActiveRecord association instead of the array.
So in my controller it should be
#user_gigs_pager = current_user.gigs.page(params[:page]).per(4)
then in the view
<% #user_gigs_pager.each do |gig| %>
....
<%= paginate #user_gigs_pager %>

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

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 %>

Can I update a user's attributes with a form in rails?

is there a way i can use a form to update a user's points in rails with a simple form that takes in the name and the points I want to append?
Heres the link to the app i made : enter link description here
my view for the index is :
<div class="container">
<h1 class="text-center">Listing Students</h1>
<div class ="jumbotron">
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Points</th>
</tr>
</thead>
<% #users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= user.points %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Delete', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
<br>
<%= link_to 'New Student', new_user_path, class:'btn btn-primary' %>
</div>
I tried using the code in my edit page :
<div class="container">
<div class=" text-center">
<div class="col-md-6 col-md-offset-3">
<div class= "well well-lg">
<%= render 'form' %>
<%= link_to 'Back', users_path, class:"back" %>
</div>
</div>
</div>
</div>
to render the form in the index but it gives me an error of #user can not be nill
I simply need to update the users points in the index page , it would be great if i can greate a modal to appear and then type in the name and edit it. Ive been working on this for hours and seem to update it .
Sure, you could use simple_form or form_for. Or you could do inplace editing. Your question is not very precise as to what exactly you need.
UPDATE 1:
Assuming that you have added simple_form gem to the gemfile, and that you have something like this in the routes.rb : resources :users, then edit view of the UsersController could look something like this:
#in controller
def edit
#user = User.find(params['id'])
end
And the view:
<%= simple_form_for #user do |f| %>
<%= f.input :name %>
<%= f.input :points %>
<%= f.button :submit %>
<% end %>
Please try it and let me know if it works for you (the edit view; in order to persist, you will need and update action as well).
Add a div on index page to open modal popup:
<div class='modal_popup>
</div>
For updating name and points of user on index page, you have to change edit link like this:
<%= link_to 'Edit', edit_user_path(user), remote: true %>
Controller changes:
def edit
#user = User.find(params[:id])
end
_modal.html.erb
<div class="modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">Modal title</h4>
</div>
<%= form_for #user, remote: true do |f| %>
<div class="modal-body">
<%= f.text_field :name %>
<%= f.text_field :points %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<%= f.submit 'Update', class: "btn btn-primary" %>
</div>
<% end %>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
edit.js.erb
$('.modal_popup').html("<%= j(render partial: '/users/modal') %>");
$('.modal').show();
After updating user in update.js.erb add below lines of code:
$('.modal').hide();
window.location.reload();
Hope this may help..

Rails: How should I adjust the 'each' method under a nest structure?

Before putting pinunder the nest structure of group,
One of the view looked like this:
<div class="transitions-enabled" id="pins">
<% #pins.each do |pin| %>
<div class="box panel panel-default">
<%= link_to (image_tag pin.image.url), pin %>
<div class="panel-body">
<h2><%= link_to pin.title, pin %></h2>
</div>
<div class="footer">
<div class="row footer-all">
<div class="col-md-6">
<p class="user">Submitted by <%= pin.user.username %></p>
</div>
<div class="col-md-6">
<div class="btn-group like_btn">
<% if user_signed_in? %>
<% if current_user.voted_up_on?(pin) %>
<%= link_to unlike_pin_path(pin), method: :put, class: "btn btn-default" do %>
<span class='glyphicon glyphicon-heart'></span>
<%= pin.get_upvotes.size %>
<%end%>
<% else %>
<%= link_to like_pin_path(pin), method: :put, class: "btn btn-default" do %>
<span class='glyphicon glyphicon-heart'></span>
<%= pin.get_upvotes.size %>
<%end%>
<% end %>
<% else %>
<div class="like_btn">
<span class='glyphicon glyphicon-heart'></span>
<%= pin.get_upvotes.size %>
</div>
<% end %>
</div>
</div>
</div>
</div>
</div>
<%end%>
How should I adjust it after I put it under group (I'll mark the code which I think needed to change with'* *'):
Group has_many pins
Pin belongs_to group
<div class="transitions-enabled" id="pins">
<% #pins.each do |pin| %>
<div class="box panel panel-default">
<%= link_to (image_tag pin.image.url), *pin* %>
<div class="panel-body">
<h2><%= link_to pin.title, *pin* %></h2>
</div>
<div class="footer">
<div class="row footer-all">
<div class="col-md-6">
<p class="user">Submitted by <%= pin.user.username %></p>
</div>
<div class="col-md-6">
<div class="btn-group like_btn">
<% if user_signed_in? %>
<% if current_user.voted_up_on?(*pin*) %>
<%= link_to unlike_group_pin_path(*pin*), method: :put, class: "btn btn-default" do %>
<span class='glyphicon glyphicon-heart'></span>
<%= pin.get_upvotes.size %>
<%end%>
<% else %>
<%= link_to like_group_pin_path(*pin*), method: :put, class: "btn btn-default" do %>
<span class='glyphicon glyphicon-heart'></span>
<%= pin.get_upvotes.size %>
<%end%>
<% end %>
<% else %>
<div class="like_btn">
<span class='glyphicon glyphicon-heart'></span>
<%= pin.get_upvotes.size %>
</div>
<% end %>
</div>
</div>
</div>
</div>
</div>
<%end%>
After stating that your objective is to use this view file to filter the pins depending on its group, then I can think of two approaches for this.
Use nested resources. (RailsCast)
This is a little trickier than 2. but it is much more organised, and RESTful
You could check the RailsCast if you are interested. Otherwise, I will just go explaining 2. as it's simpler.
Use params[:group_id] to filter the pins.
In the PinsController, add the following at the very end of the method where this view is rendered.
#group = Group.where(id: params[:group_id]).first
#pins = #pins.where(group: #group) if #group
Then in your view files, you'll just have to tweak your links to specify the group_id parameter. If this view file is associated to the #index method, then change
<%= link_to 'Link', pins_path %>
Into
<%= link_to 'Link', pins_path(group_id: 1) %>
Change 1 accordingly as you wish. If you don't specify the parameter group_id, the link will still work but you will notice that the page will show all pins, and not filtered by group.
Thanks for everyone's help, I think I find the problem:
The view should be changed into:
<div class="transitions-enabled" id="pins">
<% #pins.each do |pin| %>
<div class="box panel panel-default">
<%= link_to (image_tag pin.image.url), group_pin_path(#group, pin)
%>
<div class="panel-body">
<h2><%= link_to pin.title, group_pin_path(#group, pin) %></h2>
</div>
<div class="footer">
<div class="row footer-all">
<div class="col-md-6">
<p class="user">Submitted by <%= pin.user.username %></p>
</div>
<div class="col-md-6">
<div class="btn-group like_btn">
<% if user_signed_in? %>
<% if current_user.voted_up_on?(#group, pin) %>
<%= link_to unlike_group_pin_path(#group, pin), method: :put, class: "btn btn-default" do %>
<span class='glyphicon glyphicon-heart'></span>
<%= pin.get_upvotes.size %>
<%end%>
<% else %>
<%= link_to like_group_pin_path(#group, pin), method: :put, class: "btn btn-default" do %>
<span class='glyphicon glyphicon-heart'></span>
<%= pin.get_upvotes.size %>
<%end%>
<% end %>
<% else %>
<div class="like_btn">
<span class='glyphicon glyphicon-heart'></span>
<%= pin.get_upvotes.size %>
</div>
<% end %>
</div>
</div>
</div>
</div>
</div>
<%end%>
And remember to state #group = Group.find(params[:group_id]) in the PinController, this is very important.

How to put content under the first record rails 4

I am on Rails 4. I have two resources: subarticles and articles. Subarticles are nested in articles like so:
resources :articles do
resources :subarticles do
member do
put "like" => "subarticles#upvote"
put "dislike" => "subarticles#downvote"
end
end
end
On the articles show page, I display all of the subarticles. However, I would like to place some of the article attributes ( specifically pictures and videos) directly under the first subarticle.
I am having trouble finding any documentation on doing so.
Also note that I have subarticles ordered by number of votes. So if one gets voted higher than the other, it will go to the top. But I want to keep the same pictures and videos right under the first subarticle.
Here is a simplified version of my Article show page:
<div class="row">
<div class="col-md-9">
<div class="well" style="background:white; height:230px">
<%= #article.title.titleize %><br>
<%= social_share_button_tag %>
</div>
<% #subarticles.each do |subarticle| %>
<div class="well" style="background:white">
<%= subarticle.rating %><br>
<%= subarticle.whyrating %><br>
<div class="row" style="margin-top:40px;">
<div class="col-md-7 col-md-offset-1" style="margin-top:30px">
<%= link_to like_article_subarticle_path(#article, subarticle), class: "like", method: :put do %>
<button type="button" class="btn btn-success btn-lg" aria-label="Left Align" style="margin-right:5px">
<span class="glyphicon glyphicon-thumbs-up" aria-hidden="true"></span> Helpful
</button><span class="badge" style="margin-right:10px"><%= subarticle.get_upvotes.size %></span>
<% end %>
<%= link_to dislike_article_subarticle_path(#article, subarticle), class: "like", method: :put do %>
<button type="button" class="btn btn-danger btn-lg" aria-label="Left Align" style="margin-right:5px">
<span class="glyphicon glyphicon-thumbs-down" aria-hidden="true"></span> Unhelpful
</button><span class="badge"><%= subarticle.get_downvotes.size %></span>
<% end %>
</div>
</div>
</div>
<% end %>
<div class="well" style="background:white; text-align:center">
<h4>Pictures & Videos</h4><br>
<%= image_tag #article.image1(:medium) %><br>
<div class="embed-responsive embed-responsive-4by3">
<iframe class="embed-responsive-item" src="<%= #article.video1 %>"></iframe>
</div>
</div>
</div>
</div>
Because of the #subarticles.each do it will push pictures and videos all the way to the bottom. What is the best way to show just the first subarticle, then pictures & videos, then the rest of the subarticles?
Let me know if I need to show any other code.
<% #subarticles.each_with_index do |subarticle, i| %>
<div class="well" style="background:white">
....... // subarticle contents
</div>
<% if i==0 %>
// put articles content here
<% end %>
<% end %>
In that way after the first subarticle the if condition checks the loop index, as the loop index is currently 0, then it will first show the subarticle first content, then for index 0 it shows the article contents.
You can always use a flag for that:
<% first_one = false %>
<% #subarticles.each do |subarticle| %>
<div class="well" style="background:white">
...
</div>
<% unless first_one %>
// article contents here....
<% first_one = true %>
<% end %>
<% end %>

Resources