Displaying microposts' comments for user - ruby-on-rails

Building upon Micropost's comments on users page (Ruby on Rails) , I was able to add new comments for each micropost. However, I'm having problem displaying back the comments for each post on the same page. The codes below didn't throw any error, so I'm thinking the each micropost's comments are not assigned correctly so it can't display.
Users > Microposts > Comments
users_controller.rb
def show
#user = Account.find(params[:id])
#microposts = #user.microposts
#micropost = Micropost.new
#comments = #micropost.comments
#comment = Comment.new
end
microposts/_micropost.html.erb
<li>
<span class="content"><%= micropost.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
</span>
<span class="comments">
<% if micropost.comments.any? %>
<ul class="comments">
<%= render #comments%>
</ul>
<% end %>
<%= render "shared/form_comment", micropost: micropost %>
</span>
</li>
comments/_comment.html.erb
<li>
<span class="content"><%= comment.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(comment.created_at) %> ago.
</span>
</li>

Change <%= render #comments%> to <%= render micropost.comments %> to loop through the specific post's comments instead of using generic comment loop.

<li>
<span class="content"><%= micropost.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
</span>
<span class="comments">
<ul class="comments">
<%= render micropost.comments %> # you can leave out the #any?
</ul>
</span>
</li>

Related

Notifications ruby on rails

Currently I have a notification system when a patients fills out a form they request a signature from a doctor. The doctor gets notified successfully. But what I am looking for is when the doctor gets the notification they can click on it (link_to) and be redirected automatically to the form.
<% if #notifications.count > 0 %>
<ul>
<% #notifications.each do |notification| %>
<li>
<span class="notification-title"><%= notification.title %></span>
<span class="notification-message"><%= notification.message %></span>
<span class="notification-time"><%= notification.created_at.strftime("%B %e at %l:%m%P") %></span>
</li>
<% end %>
</ul>
<div class="notifications-preview-footer">
<%= link_to "See All", notifications_path %>
</div>
<% else %>
<ul>
<li>No Notifications</li>
</ul>
<% end %>
I changed your title span with link_to sample, so if the title clicked then it will go to notification show page
<% if #notifications.count > 0 %>
<ul>
<% #notifications.each do |notification| %>
<li>
<%= link_to <span class="notification-title"><%= notification.title %></span>, notification_path(notification) %>
<span class="notification-message"><%= notification.message %></span>
<span class="notification-time"><%= notification.created_at.strftime("%B %e at %l:%m%P") %></span>
</li>
<% end %>
</ul>
<div class="notifications-preview-footer">
<%= link_to "See All", notifications_path %>
</div>
<% else %>
<ul>
<li>No Notifications</li>
</ul>
<% end %>
A lot of unknowns here, first you routes.rb file needs to have the routes defined to allow this say maybe
# config/routes.rb
resources: notifications
Then in you need to define the controller actions for a view maybe show/edit?
# notifications_controller.rb
class NotificationsController < ApplicationController
def show
#notification = Notification.find(params[:id])
end
end
Then you could modify you view like above to allow a link to each notification
<% #notifications.each do |notification| %>
<li>
<%= link_to <span class="notification-title"><%= notification.title %></span>, notification_path(notification) %>
<span class="notification-message"><%= notification.message %></span>
<span class="notification-time"><%= notification.created_at.strftime("%B %e at %l:%m%P") %></span>
</li>
<% end %>
This may get you what you're looking for.

How to avoid same instance variables for footer

I have a footer in my rails application that shows all recent posts and categories produced by two instances variables in the welcome_controller.rb
But then if i go to another section that has a different controller responsible i get an error as the #posts and #categories instance variables are not there to loop through and list the latest posts and categories.
welcome_controller.rb (code extract)
#categories = Category.all
#posts = Post.order("created_at DESC")
_footer.html
<div class="row footer-black">
<div class="large-3 columns text-left">
<h4>Categories</h4>
<ul>
<% #categories.each do |c| %>
<% unless c.header? %>
<% if c.restriction %>
<% if check_for_free_questions_in_restricted_category(c) %>
<li> <%= link_to c.title, category_random_free_question_path(c),'data-no-turbolink' => true %> </li>
<% else %>
<li> <%= link_to c.title, new_subscription_path,'data-no-turbolink' => true %> </li>
<% end %>
<% else %>
<li> <%= link_to c.title, category_random_question_path(c),'data-no-turbolink' => true %> </li>
<% end %>
<% end %>
<% end %>
</ul>
</div>
<div class="large-5 columns text-left">
<h4>Latest Posts</h4>
<ul>
<% #posts.each do |p| %>
<li> <%= link_to truncate(p.title, length:70), blog_post_path(p) %> </li>
<% end %>
</ul>
</div>
<div class="large-4 columns text-left social-links">
<h4>Social</h4>
<a href="#">
<i class="fa fa-facebook-square fa-2x"></i>
</a>
<a href="#">
<i class="fa fa-twitter-square fa-2x"></i>
</a>
<a href="#">
<i class="fa fa-google-plus-square fa-2x"></i>
</a>
</div>
</div>
is there a way to show categories and posts in footer without instantiating same variables over and over again?
The short answer is 'no'. Every variable must be instantiated (initialized) before it can be used (in this case, in your view).
Now, there are some more efficient ways of instantiating these variables than writing:
#categories = Category.all
#posts = Post.order("created_at DESC")
in multiple controllers. But, that's a different question. If you're interested in that, then ask a new question or refine this one.

Kaminari not limiting collection in Spree

For some reason Kaminari is not limiting child objects on the parent show view.
Can see the pagination links but the collection does not get limited.
What am I doing wrong?
View -
<% if #handbag.microposts.any? %>
<h3>Posts (<%= #handbag.microposts.count %>)</h3>
<div class="row">
<div class="col-md-8">
<ol class="microposts">
<% #handbag.microposts.each do |micropost| %>
<li id="micropost-<%= micropost.id %>">
<span class="user"><%= micropost.user.email %></span>
<span class="content"><%= micropost.content %></span>
<%= image_tag micropost.picture.url if micropost.picture? %>
<span class="timestamp">
Added <%= time_ago_in_words(micropost.created_at) %> ago.
</span>
</li>
<% end %>
</ol>
<%= paginate #microposts %>
Controller -
def show
#handbag = Spree::Handbag.find(params[:id])
#microposts = #handbag.microposts.page(params[:page] || 1).per(10)
end
Thanks for any help.
You're looping through #handbag.microposts, which is the entire collection, instead of #microposts, which is the paginated collection.
So just change #handbag.microposts.each to #microposts.each

adding labels/categories to looped micropost

I am following Hartl's screencast and we are iterating through microposts and showing them in the view:
<div class="span8">
<% if #user.microposts.any? %>
<h3>Microposts (<%= #user.microposts.count %>)</h3>
<ol class="microposts">
<%= render #microposts %>
</ol>
<%= will_paginate #microposts %>
<% end %>
</div>
</div>
However I want to label each micropost (Micropost 1, Micropost 2, etc...). How can I do that?
<%= render #microposts %> renders the partial app/views/microposts/_micropost.html.erb. So it should just be a case of editing that file.
In the tutorial, I believe the micropost.html.erb file looks like:
<tr>
<td class="micropost">
<span class="content"><%= micropost.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
</span>
</td>
</tr>
To add a label, you could do something like:
<tr>
<td class="micropost">
<span class="label"><%= "Micropost #{micropost.id}" %><span>
<span class="content"><%= micropost.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
</span>
</td>
</tr>
This will add the text 'Micropost 1', 'Micropost 2' ect above each of the microposts content
Edit
If you don't want to use ID and just want sequential numbering then you can change the code to iterate over each micropost and render them individually, passing in the count:
<% #microposts.all.each_with_index do |micropost, index| %>
<%= render micropost, locals: {index: index} %>
<% end %>
Then in your partial you can use the local variable index:
<tr>
<td class="micropost">
<span class="label"><%= "Micropost #{index}" %><span>
<span class="content"><%= micropost.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
</span>
</td>
</tr>

displaying two renders in staticpage home in rails 3

I have one feed in static_page home.html.erb that I'm trying to combine two renders
Here's what I mean:
First this is my controller
class StaticPagesController < ApplicationController
def home
if signed_in?
#micropost = current_user.microposts.build
#activities = PublicActivity::Activity.order("created_at desc").paginate(page: params[:page])
#feed_items = current_user.feed.paginate(page: params[:page])
else
redirect_to root_path
end
end
this is what I'm using inside the view
<%= render partial: 'shared/feed_item', collection: #feed_items %>
<%= will_paginate #feed_items %>
Here's the view shared/feed_item for #feed_items that is being rendered in
I want to join #activities into #feed_items so that they both display in the same list in descending order
<li id="<%= feed_item.id %>">
<br>
<%= link_to gravatar_for(feed_item.user), feed_item.user %>
<%= link_to feed_item.user.name, feed_item.user %>
<span class="textname">shared this</span><span class="timestamp"> <%= time_ago_in_words(feed_item.created_at) %> ago.
</span>
</li>
Can I use some form of if-else to integrate this view for #activities below into the above code to make them become a part of one list?
<li>
<% if activity.trackable_type == "Micropost" %>
<span class="user"><%= link_to activity.owner.name, activity.owner if activity.owner %></span><span class="textname"> posted this</span><span class="timestamp"> <%= time_ago_in_words(activity.created_at) %> ago.
</span>
<% else %>
<span class="user"><%= link_to activity.owner.name, activity.owner if activity.owner %></span><span class="textname"> made a comment</span><span class="timestamp"> <%= time_ago_in_words(activity.created_at) %> ago.
</span>
<% end %>
</li>
the full _item.html.erb that I created by joining _activity.html.erb and _feed_items.html.erb
<li>
<% if item.class == PublicActivity::Activity %>
<% if activity.trackable_type == "Post" %>
<%= link_to activity.owner.name, activity.owner if activity.owner %><span class="textname"> posted </span><span class="timestamp"> <%= time_ago_in_words(activity.created_at) %> ago.
</span>
<% else %>
<%= link_to activity.owner.name, activity.owner if activity.owner %><span class="textname"> made a comment</span><span class="timestamp"> <%= time_ago_in_words(activity.created_at) %> ago.
</span>
<% end %>
<% else %>
<br>
<span class="user">
<%= link_to feed_item.user.name, feed_item.user %>
</span>
<span class="textname">shared this</span><span class="timestamp"> <%= time_ago_in_words(feed_item.created_at) %> ago.
</span>
</li>
<% end %>
You can create an array containing both activities and feed.
In your controller:
...
#items = #activities + #feed_items
#items.sort_by{|item| item.class == Activity ? item.an_activity_field : item.a_feed_item_field}
...
and then in your view:
<%= render partial: 'shared/partial_name', collection: #items %>
<%= will_paginate #items %>
and in your partial:
<% if item.class == Activity %>
# activity display stuff
<% else %>
# feed display stuff
<% end %>
You will have to put more logic in your pagination if you follow this.

Resources