rendering two partials into one (rails 3), am I doing this right? - ruby-on-rails

I am using the Public_Activity gem to display the list of actions being performed on the website. I already have a main feed on the homepage but I would also like to include all of the activities that are being tracked using that gem.
Here's what I am trying to do inside the controller
class StaticPagesController < ApplicationController
def home
if signed_in?
#micropost = current_user.microposts.build
#feed_activities = PublicActivity::Activity.order("created_at desc")
#feed_posts = current_user.feed.without_review.paginate(page: params[:page])
#feed_items = #feed_posts + #feed_activities
end
end
Then in my view, this is how I'm trying to call it
<% if #feed_items.any? %>
<ol class="microposts">
<%= render partial: 'shared/feed_item', collection: #feed_items %>
</ol>
<%= will_paginate #feed_items %>
<% end %>
the _feed_item.html being called above is
<li id="<%= feed_item.id %>">
<br>
<% if #feed_activities? %>
<%= link_to activity.owner.name, activity.owner if activity.owner %> has posted
<% else %>
<div class ="gravatarhome"><%= link_to gravatar_for(feed_item.user), feed_item.user %></div>
<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>
<div class="FeedContent"><%= truncate(feed_item.content, :length=>150, :omission=>' ...(continued)') %>
<% if current_user?(feed_item.user) %>
<%= link_to "delete", feed_item, method: :delete,
confirm: "You sure?",
title: feed_item.content %>
<% end %><br>
<% end %>
</li>
However, I'm getting this error
NameError in Static_pages#home
Showing C:/app/views/shared/_feed_item.html.erb where line #5 raised:
undefined local variable or method `activity' for #<#<Class:0x6ef3b98>:0x60d50d8>
anyone know if there's a better way to do this and where the activity variable needs to be defined to get this to work?
Update: here's my application_controller that uses the gem
class ApplicationController < ActionController::Base
include PublicActivity::StoreController

The error have stated the problem, rails does not know which activity refer to.
Neither you have activity loaded in the controller, or it is associated to feed_item
Or not rails does not know which activity refer to

activity is a variable that is not defined in this partial, so it will give error.
If you want to loop all activities via collection, then you have to pass variable as collection while rendering the partial and calling using partial name like this:
<%= link_to feed_item.owner.name, feed_item.owner if feed_item.owner %> has posted
Replace activity by feed_item in your partial. It will solve your problem.

Related

Rails - NoMethodError in Events#show undefined method `>' for nil:NilClass

I'm building an Events app in Rails and getting this error which seems a little odd.
It relates to the comments section at the foot of the show page. I'm simply attempting to move my comments form to the top of the section and have all recent comments below the form. This is my view code for the show page which results in the error code above -
<div id="comments">
<h3>Add a comment:</h3>
<%= render "comments/form" %>
<h2><%= #event.comments.count %></h2>
<%= render #event.comments %>
</div>
The reason I say its odd is that when I present the code like this (so the comments all show above the comment form) -
<div id="comments">
<h2><%= #event.comments.count %></h2>
<%= render #event.comments %>
<h3>Add a comment:</h3>
<%= render "comments/form" %>
</div>
I don't get the error code. Why would this be?
This is the code in my comments.html -
<div class="comment clearfix">
<div class="comment_content">
<p class="comment_name"><strong><%= comment.name %></strong></p>
<p class="comment_body"><%= comment.body %></p>
<p class="comment_time"><%= time_ago_in_words(comment.created_at) %> Ago</p>
</div>
<% if user_signed_in? %>
<p><%= link_to 'Delete', [comment.event, comment],
method: :delete,
class: "button",
data: { confirm: 'Are you sure?' } %></p>
<% end %>
The error refers to my events show action - I don't have any methods in my show action.
First make sure you have a nested route to create comments and an un-nested route to destroy them:
resources :events do
resources :comments, shallow: true, only: [:create, :destroy]
end
This is called shallow nesting and is desirable since it lets you route directly to resource for the member actions (show, edit, update, destroy) where a resource can be directly accessed through its unique id.
Then setup the form partial:
# comments/_form.html.erb
<%= form_for([commentable, Comment.new ]) do |f| %>
# ...
<% end %>
You then want to fix your events/show controller and view:
def show
#event = Event.eager_load(:comments).find(params[:id])
end
Note that we are not building a comment instance in the controller. We will do it later in the form when needed.
<div id="comments">
<% if #event.comments.any? %>
<h2><%= #event.comments.size %></h2>
<%= render #event.comments %>
<% else %>
<h2>There are no comments yet</h2>
<% end %>
<%= render 'comments/form', commentable: #event %>
</div>
Another big problem is that any signed in user can delete any comment. You can fix that by setting up an association:
class Comment < ApplicationRecord
belongs_to :user
end
class User < ApplicationRecord
has_many :comments
end
You then want to check that the user owns the comment:
<div class="comment clearfix">
<div class="comment_content">
<p class="comment_name"><strong><%= comment.name %></strong></p>
<p class="comment_body"><%= comment.body %></p>
<p class="comment_time"><%= time_ago_in_words(comment.created_at) %> Ago</p>
</div>
<% if user_signed_in? && comment.user == current_user %>
<% button_to 'Delete', comment,
method: :delete,
class: "button",
data: { confirm: 'Are you sure?' }
%>
<% end %>
</div>
Since we de-nested the destroy route you don't need to pass the event id as a param. Normally you want to use a library like Pundit or CanCanCan rather than spreading the authorization logic all over your application like this.
Added
For the delete button to work you need to associate the user with the comment:
def create
#event = Event.find(params[:event_id])
#comment = #event.comments.new(event_params) do |c|
c.user = current_user
end
# ...
end

How to put url from DB onto the view

I have a Job model where I save a bunch of attributes, one of which is a link attribute as a string which contains a url to an external site. I want to put this link on my view but when I try to render it, it does not work.
Is there some reason that rails blocks urls from being shown? All my other attributes show up fine and when I try on rails console I can see the .link attribute showing up as a string.
Here is my link_to tag
<%= link_to "Visit Website", job.link , class: "detail" %>
The problem is that job.link does not even evaluate on the view. But it works on rails console.
My full code is below
Model:
class Job < ActiveRecord::Base
def self.search(search)
where("position LIKE ?", "%#{search}%")
end
end
Controller:
class JobsController < ApplicationController
def index
#jobs = Job.paginate(:page => params[:page], :per_page => 10).search(params[:search])
end
end
Job partial
<% if #jobs.present? %>
<div id="integration-list">
<ul>
<% #jobs.each do |job| %>
<li>
<div>
<a class="expand">
<div>
<h2 class="position"><%= job.position %> </h2>
<span class="info"> <%= job.company %> <br> Due Date: <%= job.date %></span>
</div>
</a>
<%= link_to "Visit Website", job.link , class: "detail" %>
</div>
</li>
<% end %>
</ul>
<%= will_paginate #jobs, :class => 'jobsite_pagination' %>
</div>
There are no posts containing the term(s): .
Try below code, use job.link instead of #{job.link}
<%= link_to "Visit Website", job.link , class: "detail" %>

Multiple Loops on the same show page

I have a page that displays a users videos that he has posted and also on the same page a users videos that he has voted on.
here is my controller
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
#videos = #user.videos.order("created_at desc").page(params[:page]).per_page(12)
votes = #user.videos_with_votes("created_at desc").page(params[:page]).per_page(12)
end
end
Here is my view for my show page
<div id="videos">
<% #videos.each do |video| %>
<div class="box">
<%= image_tag video.image.url(:threeacross) %>
<%= video.title %>
<%= video.description %>
<%= video.user_id %>
<%= link_to 'Show', video %>
<%= link_to 'Edit', edit_video_path(video) %>
</div>
<% end %>
</div>
I am confused on how to display the videos that the user has voted on in the same way that i am looping the users video posted?
Use an instance variable, e.g.
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
#videos = #user.videos.order("created_at desc").page(params[:page]).per_page(12)
#voted_videos = #user.videos_with_votes("created_at desc").page(params[:page]).per_page(12)
end
end
<div id="voted_videos">
<% #voted_videos.each do |video| %>
<div class="box">
<%= image_tag video.image.url(:threeacross) %>
<%= video.title %>
<%= video.description %>
<%= video.user_id %>
<%= link_to 'Show', video %>
<%= link_to 'Edit', edit_video_path(video) %>
</div>
<% end %>
</div>
If the display of videos and voted videos is the same than you can look to make this code:
<div class="box">
<%= image_tag video.image.url(:threeacross) %>
<%= video.title %>
<%= video.description %>
<%= video.user_id %>
<%= link_to 'Show', video %>
<%= link_to 'Edit', edit_video_path(video) %>
</div>
a partial called _videos.html.erb that can be used for both #videos and #voted_videos.
Store this file (with the above code) in the same directory as the other view files
e.g.
<div id="voted_videos">
<% #videos.each do |video| %>
<% render "videos" %>
<% end %>
</div>
<div id="voted_videos">
<% #voted_videos.each do |video| %>
<% render "videos" %>
<% end %>
</div>
You need to use #votes instead of votes by itself. The # symbol shares the variable with the view layer so that you can do things with it (like loop over it).
there is a concept about instance variable and local variable in rails.
whenever you define a variable with # symbol that particular variable is an instance variable and is accessible across its views and partials.
for eg : #videos = #user.videos.order("created_at desc").page(params[:page]).per_page(12)
here #videos is an instance variable and persists its instance across its scope.
whereas local variables have its scope limited to its loop/boundry. Local variables are preferably used in loops where after the execution of the loop the variable is Garbage Collected and we can again use the same variable name for storing different value.
In your case votes is not accessible in your view as its a local variable, and hence to use this variable in your view you need to define this variable as instance variable (as #votes).

partial form not creating new value RoR

I am new to Ruby on Rails. My Question might sound weird, but i am stuck. i have a form Create that is on html page. i used render partial, but this form is not creating any value. here is my controller code.
Controller.rb
before_filter :signed_in_user, only: [:create, :destroy]
def create
#suppliers = current_user.suppliers.build(params[:supplier_name])
if #suppliers.save
flash[:success] = "Supplier Saved!"
redirect_to 'suppliers/home'
else
render 'suppliers/home'
end
end
def destroy
end
def home
if signed_in?
#supplier = current_user.suppliers.build
#feed_items = current_user.feed.paginate(page: params[:page])
end
end
my home.html.erb
<div class="row">
<aside class="span4">
<section>
<%= render 'suppliers/suppliers_form' %>
</section>
</aside>
<div class="span8">
<h3>Micropost Feed</h3>
<%= render 'suppliers/feed_supplier' %>
</div>
</div>
My _supplier_form.html.erb is
<%= form_for(#supplier) do |f| %>
<div>
<%= f.text_field :supplier_name, placeholder: "Add new Supplier" %>
</div>
<%= f.submit "Add", class: "btn btn-large btn-primary" %>
<% end %>
My _feed_supplier.html.erb is
<% if #feed_items.any? %>
<ol class="microposts">
<%= render partial: 'suppliers/feed_item', collection: #feed_items %>
</ol>
<%= will_paginate #feed_items %>
<% end %>
my _feed_item.html.erb is
<li id="<%= feed_item.id %>">
<span class="user">
<%= link_to feed_item.user.name, feed_item.user %>
</span>
<span class="content"><%= feed_item.supplier_name %></span>
</li>
please guide me to right direction, and if anything else is required then do ask. Thanks in advance
Note: all the mentioned files are in same folder i.e. suppliers. except the controller file
form_for #supplier
will create a parameter hash like
{ :supplier => { :supplier_name => '[some value you put in your form]' }}
so the create action should use
#suppliers = current_user.suppliers.build(params[:supplier])
There is no params[:supplier_name].
I think for the partials, you don't need to write suppliers/*, for example:
<%= render 'suppliers/suppliers_form' %>
could just be
<%= render 'suppliers_form' %>
not sure why that would be causing your app to do what it's doing, but worth a try!

rails rendering collection not working - undefined local variable or method

I am trying to create a feed that displays all comments for a model.
_comments.html.erb
<% if #comments.any? %>
<ol>
<%= render partial: 'shared/comment_feed', collection: #comments %>
</ol>
<%= will_paginate #comments %>
<% else %>
<h2>Be the first one to comment on this episode!</h2>
<% end %>
_comment_feed.html.erb
<li id="<%= comment.id %>">
<%= link_to gravatar_for(comment.user), comment.user %>
<span class="user">
<%= link_to comment.user.name, comment.user %>
</span>
<span class="content"><%= simple_format comment.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(comment.created_at) %> ago.
</span>
<% if current_user?(comment.user) %>
<%= link_to "delete", comment, method: :delete,
confirm: "Are you sure?",
title: comment.content %>
<% end %>
</li>
The above code gives me an undefined local variable or method `comment' error. Doesn't rails automatically generate comment when a partial is used to render comments collections? Any help would be greatly appreciated.
The name of the local variable corresponds to the name of the partial. In your case the local variable is going to be named comment_feed.

Resources