Make the post's comments toggleable in Rails using Jquery - ruby-on-rails

Scenarioļ¼šA post has many comments. In the index page of posts, when user clicks the show link( link_to post), its comments will show below the post.
Here I use the append() to add the comments:
$('#edit_post_<%= #post.id %>').append('<%= j render "comments/comments" %>')So when user click the show link, comments would be load and show up.
But how can I hide these comments again (i.e to make comments toggeable) ?
posts/index
<h1>Posts</h1>
<% #posts.each do |post| %>
<%= form_for post, remote: true do |f| %>
<%= post.content %>
<div id="post_<%= post.id %>">
<%= link_to "show", post, remote: true %>
</div>
<% end %>
<% end %>
posts/show.js.erb
$('#edit_post_<%= #post.id %>').append('<%= j render "comments/comments" %>')
comments/_comments.html.erb
<% #comments.each do |comment| %>
<%= comment.content %>
<% end %>

I suppose you dont have the event bindings for new comments.
you should use something like
$('.container-of-your-comments').on('click', '.the-toggle-button', function (e) {
// toggle
});
so toggling works for all (also future) elements.
EDIT:
given the changes in the question: if toggle means just hiding the whole comment list,
you have to do it manually.
i suggest you have separate show / hide buttons (you can show and hide the buttons upon changing state as well), because if not, it gets more complex.
so for example, in posts/index:
<h1>Posts</h1>
<% #posts.each do |post| %>
<%= form_for post, remote: true do |f| %>
<%= post.content %>
<div id="post_<%= post.id %>">
<%= link_to "show", post, remote: true %>
</div>
<div class="post-comments" id="post_comments_<%= post.id %>">
</div>
<% end %>
<% end %>
in comments/_comments.html.erb
<% #comments.each do |comment| %>
<%= comment.content %>
<% end %>
<%= link_to "hide", '#', class: "hide-comments" %>
and in posts/show.js.erb
$('#post_comments<%= #post.id %>').html('<%= j render "comments/comments" %>')
and in assets/javascripts/posts.js (be sure you include this in your application.js)
$(document).ready(function() {
$('.hide-comments').click(function(e) {
e.preventDefault();
$(this).parent().hide();
});
});
backbone.js is a great tool, if you'll be doing a lot of things with those comments, like CRUD etc. and you need to stay on one page - use backbone.js. if not, stick to jQuery.

Related

Rails: how to create a list with conditional links

I am working on a RAILS application where I create a view which lists all available resources of a given model species.rb.
The view partial is:
<% i= #s
for species in #species %>
<%= species.name %>, <%= species.author.surname %> <%= species.author.initial_name %>
<% i -= 1
end %>
Some of the resources species have an related article, others have only the name. I would like to loop through the partial and add a link only to the entries which have an associated article.
Something like: add link if species.article is present else just put species.name without link + loop through it for all entries.
How can I do this?
UPDATE:
Thanks to #jvillian and #fool-dev I was able to progress. In my case I wanted to add a link if the resource has a description in a description row of its table.
<% #species.each do |species| %>
<div class="entry">
<p><i><%= link_to_if(species.txtlandscape.present?, "#{species.name}, #{species.author.surname}, #{species.author.initial_name}. 2014", :controller => 'projects', :action => 'show', :id => species) %></i></p>
</div>
<% end %>
Now that a link is added I was wondering if it can be used to load a partial to a target such as in, where ArticleRequest is a JS function I have:
<% # species.each do | species | %>
<div id="species-<%= species.id %>" class="species-entry">
<a onClick="ArticleRequest('/species/show/<%= species.id %>', 'species-<%= species.id %>');">
<p><%= species.name %></p>
</a>
</div>
<% end %>
Until I find a way to do this with link_to_if, I will use something like:
<% for species in #species %>
<% if species.txtlandscape.present? %>
<a onClick="ArticleRequest('/species/show/<%= species.id %>', 'species-<%= species.id %>');">
<p><%= species.name %>, <%= species.author.surname %> <%= species.author.initial_name %></p>
</a>
<% else %>
<p><%= species.name %>, <%= species.author.surname %> <%= species.author.initial_name %></p>
<% end %>
<% end %>
According to the docs, it seems you should be able to do:
<% #species.each do |specie| %>
<%= link_to_if(specie.article, specie.name, specie_article_path(specie.article)) %>
<% end %>
I made the path name up, you'll have to make that match your actual routes.
BTW, this:
for species in #species
Is super non-idiomatic.
You can do this, see the below
<% for species in #species %>
<% if species.article.present? %> #=> I thin it will be articles because table name is articles, anyway, you know better
<%= link_to species.name, link_path(species.article) %>, #=> on the link_path it will be your proper link just replace this
<% else %>
<%= species.name %>,
<% end %>
<%= species.author.surname %> <%= species.author.initial_name %>
<% end %>
You can do this with Rails each method like below
<% #species.each do |species| %>
<% if species.article.present? %> #=> I thin it will be articles because table name is articles, anyway, you know better
<%= link_to species.name, link_path(species.article) %>, #=> on the link_path it will be your proper link just replace this
<% else %>
<%= species.name %>,
<% end %>
<%= species.author.surname %> <%= species.author.initial_name %>
<% end %>
Or you can use link_to_if it is also most easier to understand
<% #species.each do |species| %>
<%= link_to_if(species.article.present?, "#{species.name},", link_path(species.article)) %>
<%= species.author.surname %> <%= species.author.initial_name %>
<% end %>
Hope it will help.

Is It Possible To Truncate (or limit the amount of words displayed) On A Rendered Post in Ruby on Rails?

I'm having trouble with my bloglike application I'm building.
Essentially I have posts which are displayed using a _post partial. I use this two different ways: as part of a feed (displaying all posts) and when the specific post is clicked on.
When the post is part of the overall feed I want to limit the amount of characters that are displayed to keep things tidy. This is how posts are displayed in the feed:
<% #posts_by_month.each do |monthname, posts| %>
<div style="clear:left"><h2><%= monthname %></h2></div>
<% for post in posts %>
<div style="float:left;width:33%">
<ol class="posts">
<% if post.status == 'new' %>
<div class="new-post">
<%= link_to edit_post_path(post) do %>
<%= render post.first(80) %>
<% end %>
</div>
<% else %>
<div class="edited-post">
<%= link_to post_path(post) do %>
<%= render post %>
<% end %>
</div>
<% end %>
</ol>
</div>
<% end %>
When I change the line <%= render post %> to <%= render post.first(80) %> to limit it to the first 80 characters I get the error: "undefined method `first' for #< Post:0xc5785e0 >". The same happens with truncate.
I can't put the truncate in the _post partial because then it will truncate it when the specific post is clicked on, which is not what I want. How do I make it so for this feed of posts the posts are limited to a certain number of characters?
Edited to add
My post partial:
<div id="post-<%= post.id %>">
<span class="timestamp">
<%= post.created_at.strftime('%A, %b %d')%>
<span class="content"><%= post.content %></span>
</span>
</div>
I can't put the truncate in the _post partial because then it will truncate it when the specific post is clicked on, which is not what I want.
Naturally. This then calls for one of two solutions.
Truncate text of post objects prior to rendering, or otherwise make the post partial see shortened text (for example, use a Presenter pattern)
<% for post in posts %>
<% post.title = truncate(post.title) %> // truncate
<%= render post %> // then render
Use another partial for rendering posts on the index page, the one with truncate inside.
Try:
<%= render partial: 'post', :locals => {:post => post, :length => 80} %>
and in your partial,
<div id="post-<%= post.id %>">
<span class="timestamp">
<%= post.created_at.strftime('%A, %b %d')%>
<span class="content"><%= length.present? ? post.content.first(length) : post.content %></span>
</span>
</div>

Ruby on Rails 5 - Duplicate "Delete" links

This is the picture of my problem ---> Duplicate Delete Links Picture
I have a comment with two delete links.
This is the order of how I'm rendering the comment form and the comments from partials:
<h2>Comments</h2>
<%= render 'comments/form' %>
<%= render #recipe.comments %>
This is the code for _form.html.erb
<%= form_for([#recipe, #recipe.comments.build]) do |f| %>
<p><%= f.label 'Comment' %> <br> <%= f.text_area :comment %></p>
<p><%= f.submit 'Post' %></p>
<% end %>
This is the code for _comment.html.erb
<div class="show-text-formatting">
<p><strong><%= comment.name %></strong></p>
<p><%= comment.comment %></p>
<%= link_to 'Delete', [comment.recipe, comment], method: :delete,
data: { confirm: 'Are you sure want to delete this comment?' } %>
</div>
The first delete link have the extension: /recipes/10/comments/1 (1 is the comment id #)
Also, when I hover over the second delete link has the extension: /recipes/10/comment
The difference between is that the second delete link's extension doesn't have a comment id
I know that by switching the order of
<h2>Comments</h2>
<%= render 'comments/form' %>
<%= render #recipe.comments %>
to
<h2>Comments</h2>
<%= render #recipe.comments %>
<%= render 'comments/form' %>
would solve my problem, but I want the form to come before the comments.
EDIT:
The second delete link isn't actually a "second" delete link. It's a delete link for a null object. I still don't know how to get rid of it though.
Try this. Set an order to your comments. Like this:
<h2>Comments</h2>
<%= render 'comments/form' %>
<%= render #recipe.comments.order(created_at: :DESC) %>
That should fix your problem. I've had the same issue and it worked for me.
If you know for sure it's nil object, why don't you add a trigger. I mean we can check the object whether it's nil or not before rendering.

Click count the link article in rails

I have view
<% #r.each do |g| %>
<%= link_to g.title %>
<% end %>
When I click the link i won't to display the count how many people's click this link.
Like this:
<%= link_to g.title %> Click:<%= countclick %>
Title Click:45
Article should have countclicks:integer database column.
Than in article show method (I think you use this method to show article):
def show
#article = Article.find(params[:id])
count=#article.countclicks+1
#article.update_attributes(:countclicks=> count)
#other code
end
And than in index view:
<% #articles.each do |article| %>
<%= link_to "#{article.name}", show_article_path(article)%>
<%=article.countclick %>
<% end %>
Or alternatively you can do this via model callbacks.
If you want to use link_to like this, you have to give it a block:
<% link_to g.title do %>
Click <%= countclick %>
<% end %>

Firing Ajax call when click submit button

In my Rails 3.1 application I have a Jquery dialog that pops up when clicked, and inside that you have a submit button. I have made somewhat an attempt at making this 'submit' button ajax. So that when it is clicked it updates the appointment time and date. I have the following code:
<% if #booking.id and current_user.is_booking_manager? %>
<button id="confirm_appointment">
test confirmation
</button>
<div style="display:none;">
<div id="confirm_appointment_dialog" title="Test Confirm Booking">
<%= form_for #booking, :url => booking_confirmation_path(#booking), :remote => true do |f| %>
<%= f.hidden_field :id %>
<%= f.datetime_select :confirmed_appointment %>
<br />
<b>Clear provisional appointment:</b><%= check_box_tag "make_unexpected" %>
<br />
<%= f.submit :class => 'submit_me' %>
<% end %>
</div>
</div>
<% end %>
Application.js
$('.submit_me').bind('change',
function() {
$(this).parents('form:first').submit();
});
Is there something I am missing
You don't update your View, after the JS request is processed. First you need to add an id to the HTML-Element you want to update.
Your Pastie had this Code:
<tr>
<td><%= f.label :confirmed_appointment %></td>
<td> <% f.hidden_field :confirmed_appointment %>
<% if #booking.confirmed_appointment %>
<%= l #booking.confirmed_appointment %>
<% else %> <em>unconfirmed</em> <% end %> </td>
</tr>
In order to make it easy to reference the part you want to update in JavaScript, let's add an id to that td.
<td id="booking-confirmation"> <% f.hidden_field :confirmed_appointment %>
After that you need to create an update.js.erb in your views/ folder. Now you can put the line
$("#booking-confirmation").html("<%= l #booking.confirmed_appointment %>");
In there, which will look for a field with the id "booking-confirmation" in your HTML and update it.
Lastly, be sure to include
respond_to do |format|
format.html
format.js
end
In your action, to make the action respond to JS calls.
Change bind('change') -> bind('click')
Ok, you doing this slightly wrong, http://wowkhmer.com/2011/09/19/unobtrusive-ajax-with-rails-31/ try to use this guide

Resources