Current_user && User profile - ruby-on-rails

So in my To-do app I have profiles for each user that displays a list of all the Items they have created like so :
<% if current_user %>
<h1>Hello, <%= current_user.username.capitalize%>, </h1>
<% else %>
<h1><%= #user.username.capitalize%> To - Do List. </h1>
<%end %>
<h4> List of Items </h4>
<%= render :partial => 'items/form', :locals =>{:item => Item.new} %>
<% #user.items.order('created_at DESC').each do |item| %>
<%= render :partial => 'items/item' , :locals => {:item => item } %>
<% end %>
My problem is that I want users to be able view other Users profile but with the Header changing according to who is viewing it.
<h1>Hello, <%= current_user.username.capitalize%>, Here is your To-do Items</h1>
if its the current_users own profile or:
<h1><%= #user.username.capitalize%> To - Do List. </h1>
if the user is viewing another users profile.
As you can see I tried a little something with an if statement but it doesn't seem to be working as i want it to .Can anyone help me out please?

Try current_user == #user in if condition.
If there is a possibility that current_user could be nil, then
Try current_user.present? && current_user == #user in if condition.

In your controller you may have:
#user = User.find(params[:id])
Then in your view something along the line of
<% if current_user == #user %>

use this code:
current_user == #user if condition.

Related

RoR Rnder a partial cant find method

I have a classes User and Company, I want to re-use the users partial as the to render company staff.
In my CompaniesController I have:
def staff
#company=Company.find(params[:id])
#users=#company.works_fors.paginate(page: params[:page], :per_page => 10)
#title=#company.name+" staff."
end
And in my staff.html.erb template I have:
<% if #users.any? %>
<ul class="users follow">
<%= render #users %>
</ul>
<%= will_paginate %>
<% end %>
This is the works_fors/_works_for partial:
<%= render :partial => 'user' %>
Which Renders
<li>
<%= gravatar_for user, size: 50 %>
<%= link_to user.name, user %>
<% if current_user.developer? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
</li>
However this throws an error on the user object as it cant find the method
undefined local variable or method `user' for~~
I think this is because Im calling the user object from within companies but there is a defined relationship, or do I need to redefine in companies ?
It's hard to tell, but it appears that what you call #users in your controller is in fact not a User collection, but a WorkFor collection.
#users = #company.works_fors...
What you mean is:
#works_fors = #company.works_fors...
This means that staff.html.erb is working with a works_for collection. So you should rename the variable in your template to avoid confusion.
# staff.html.erb
<% if #works_fors.any? %>
<ul class="users follow">
<%= render #works_fors %>
</ul>
<%= will_paginate #works_fors %>
<% end %>
Now we know we are rendering a works_for partial. So an instance of works_for is be available inside the partial. We need to ask it for its associated user instance, and pass it to the render method.
# works_fors/_works_for.html.erb
<%= render works_for.user %>
As a bonus, you can save yourself some queries by preloading the users.
#works_fors = #company.works_fors.includes(:user)...

Helper Method detect post - comment from user

I'm trying to create a helper method that will display {user.name} has no submitted posts." on the profile show view of user if they haven't yet submitted any posts and display the number posts they have . currently on my show view i have <%= render #user.posts %> which displays nothing when there are 0 posts submitted.
the partial for post is :
<div class="media">
<%= render partial: 'votes/voter', locals: { post: post } %>
<div class="media-body">
<h4 class="media-heading">
<%= link_to post.title, topic_post_path(post.topic, post) %>
<%= render partial: "labels/list", locals: { labels: post.labels } %>
</h4>
<small>
submitted <%= time_ago_in_words(post.created_at) %> ago by <%= post.user.name %> <br>
<%= post.comments.count %> Comments
</small>
</div>
</div>
ive tried :
def no_post_submitted?(user)
user.post.count(0)
"{user.name} has not submitted any posts yet."
end
on my user show view :
<%= if no_post_submitted?(#user) %>
<%= render #user.posts %>
which im more than sure is wrong but i have no idea how to implement this method .
Where you are using render #user.posts you can just add a simple conditional:
<% if #user.posts.empty? %>
<p><%= #user.name %> has no submitted posts</p>
<% else %>
<%= render #user.posts %>
<% end %>
There wouldn't be much point creating a helper for this unless you need to use it in multiple places.
Render collection returns nil if the collection is empty so you can use the || operator:
<%= render #user.posts || "{#user.name} has not submitted any posts yet." %>
Or if there is more code render another partial:
<%= render #user.posts || render 'no_posts' %>
In Ruby methods automatically return the last value so this method:
def no_post_submitted?(user)
user.post.count(0)
"{user.name} has not submitted any posts yet."
end
Will always return a string - if you use a string literal in a condition it will be evaluated as true with the warning warning: string literal in condition. Also that is not how you use count - passing 0 will cause it to query on column 0 or just error.
http://apidock.com/rails/ActiveRecord/Calculations/ClassMethods/count
So to fix the method you would do:
def no_post_submitted?(user)
user.posts.empty?
end
However that conditional is so simple that it does not really warrant a helper method. Instead you would just write:
<%= if user.post.any? %>
<%= render #user.posts %>
<% else %>
<%= "{user.name} has not submitted any posts yet." %>
<% end %>
There are a couple of problems with your solution. Remember, rails is more about convention over configuration.
Your method no_post_submitted? should actually return true/false since its a method ending with ?. Also it should be named no_posts_submitted? for clarity. It should look something like this:
def no_post_submitted?(user)
user.posts.count > 0
end
Then, there should be another helper method that will print your required message, Something like:
def no_posts_message(user)
"{user.name} has not submitted any posts yet."
end
And eventually you can all plug it in like this:
<% if no_posts_submitted?(user) %>
<%= no_posts_message(user) %>
<% else>
<%= render #user.posts %>
<% end %>
As per the docs:
In the event that the collection is empty, render will return nil, so it should be fairly simple to provide alternative content.
<h1>Products</h1>
<%= render(#products) || "There are no products available." %>
--
So...
<%= render(#user.posts) || "#{#user.name} has not submitted any posts yet." %>

List of users showing the same information

I am showing the subscription information for all users. The issue I have is that it is not displaying the correct information. It is showing the current_user subscription information for all the Users. When it should be displaying each users unique subscription information.
Admin views:
<% #users.each do |user| %>
<li>
<%= link_to user.username, user %>
|<%= #user.subscription.id %>|<%= #user.subscription.plan.name %>| <%= #user.subscription.created_at.strftime("%B %e, %Y") %>
</li>
<% end %>
Admin controller:
def index
#user = current_user
#users = #user.present? ? User.where('id != ?',#user.id) : User.all
render layout: 'new_application'
end
def show
#user = User.find_by(username: params[:id])
end
Error: NoMethodError: undefined method `id' for nil:NilClass
It seems like the template should refer to user, not #user.
Update:
As #rlecaro2 mentioned, it's possible you've got some users with any subscriptions. In the case, calling .subscription on the user variables returns nil and you crash while asking for its id.
<% #users.each do |user| %>
<li>
<%= link_to user.username, user %>
<% if user.subscription %>
|<%= user.subscription.id %>|<%= user.subscription.plan.name %>| <%= user.subscription.created_at.strftime("%B %e, %Y") %>
<% end %>
</li>
<% end %>
Also since you're asking every user for its subscription and later on for the subscription's plan, you should explicitly load these to avoid unnecessary queries. For Rails 4, the Admin controller should look like this:
def index
#users = User.includes(subscription: :plan)
#users = #users.where.not(id: current_user.id) if current_user
render layout: 'new_application'
end
Note that it's not necessary to carry the current_user via #user. You can refer to it in the template directly.

nested attribute pagination error (kaminari)

I'm pretty sure that this is a simple fix but I'm not seeing it. I have an app where I'd like to show a music_videos comments. Below are my controllers:
def show
#music_video = MusicVideo.find(params[:id])
#comment = Comment.new
#comments = #music_video.comments.page(params[:page]).per(3)
end
The above is my music video controller.
def create
#music_video = MusicVideo.find(params[:music_video_id])
#comment = #music_video.comments.build(comment_params)
if #comment.save
flash[:notice] = "Comment Submitted"
redirect_to music_video_path(#music_video)
else
render 'music_videos/show'
end
end
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
redirect_to root_path, notice: "Comment Deleted"
end
private
def comment_params
params.require(:comment).permit(:body)
end
Above is my comments controller
Finally my show page:
<div class="comments_row">
<% #music_video.comments.each do |comment| %>
<% if user_signed_in? && current_user.admin? %>
<p class="comment"><%= comment.body %></p>
<%= link_to 'Delete Comment', music_video_comment_path(#music_video,comment),
method: :delete %>
<% else %>
<p class="comment"><%= comment.body %></p>
<% end %>
<%end%>
</div>
<%= paginate #comments %>
I'm pretty sure something is wrong with my controllers, but I'm not sure exactly what it is. #comments is in the correct controller (MusicVideo) within the correct CRUD operation (show). Currently I have six comments in a particular show page and the pagination shows up just fine but the six comments are not paginated. Any thoughts?
EDIT-------------
I figured out one the problem but stumbled on a new one. I figured out that in my controller I am declaring #comments = pagination etc. etc. when in my views there is no #comments to paginate. The problem is now that when I use
<%= paginate #comment %>
the code will break.the problem now that I'm having is what variable to paginate. Trying this code will also break
<%= paginate #music_video.comments %>
Any recommendations?
I set up a test application using the kaminari gem for pagination. This is what my my music video controller's show action looks like:
def show
#music_video = MusicVideo.find(params[:id])
#comments = #music_video.comments.page(params[:page]).per(3)
end
And here is what my show view looks like:
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong> <%= #music_video.name %>
</p>
<% #comments.each do |comment| %>
<p>
Comment: <%= comment.text %>
</p>
<% end %>
<%= paginate #comments %>
<%= link_to 'Edit', edit_music_video_path(#music_video) %> |
<%= link_to 'Back', music_videos_path %>
It is working and the pagination is showing up for me.
I think one thing i see directly is that you should use <% #comments.each do |comment| %> instead of <% #music_video.comments.each do |comment| %> because the way you have it now it will display all comments for the video regardless of what page you are on. If you had 6 comments and wanted 3 per page you would see the pagination with the two pages because you're running your pagination based off of #comments and you would end up seeing all 6 comments on both pages because you're doing your .each with #music_videos.comments.each.
So, at least using #comments in both places would be a start. And make sure you're using <%= paginate #comments %> for the pagination. If you use this in your controller and view what do you get? Do you see any comments?
Also, Ryan Bates has a great screencast on Kaminari as well: http://railscasts.com/episodes/254-pagination-with-kaminari (that site is a great resource for rails questions)

Pulling records from one table (products) depending on a value in another (department)

I have a Products table and a Departments table.
In products model:
has_one :department
In departments model:
belongs_to :products
I also have a view in my products controller that lists all departments as so:
<% #departments.each do |department| %>
<div class="column_entry">
<%= link_to image_tag(department.image_attachment), products_of_a_given_main_cat_url %>
</div>
<% end %>
Those load up fine. When I click on one of the images I want products_of_a_given_main_category view to dynamically populate with products from the department whose image I clicked.
In my products controller:
def products_of_a_given_main_cat
#products = Product.all
#department = Department.where(:name == :department)
respond_to do |format|
format.html # index.html.erb
format.json { render json: #products }
end
end
and in the view:
<div class="the_grid_prod">
<% #products.each do |product| %>
<% if product.department == #department.name %>
<div class="column_entry">
<%= link_to image_tag(product.product_image.url(:normal_page_size)), products_content_url(product.id) %>
</div>
<% end %>
<% end %>
</div>
When I click on the image for a department that I'm certain has products the page loads but there are no products. I'm certain I'm doing something very wrong but I'm not really sure what it is.
in routes file:
get 'products/products_of_a_given_main_cat' => :products_of_a_given_main_cat, :as => :products_of_a_given_main_cat
The problem is this:
#department = Department.where(:name == :department)
The :department is a symbol, not a string, and not a variable. Basically it is a number deep down, definietly not a name. Also, this will evaluate to Departments which have a name false. Don't do evaluation in the where part, only a hash.
You need the params[:department] if you get it from the request.
#department = Department.where(:name => params[:department])
Update:
Please modify your request link:
<%= link_to image_tag(department.image_attachment), products_of_a_given_main_cat_url(:department => department.name) %>
This will introduce a new parameter to the request, and it will work for you with the condition written above.
So to solve this problem I changed my associations as #TomL suggested in his comment. I also changed the following:
In products controller I deleted
#department = Department.where(:name => params[:department])
and changed
#products = Product.all
to
#products = Product.where(:department => params[:department])
The products_of_a_give_main_category_view now looks like this:
<div class="the_grid_prod">
<% #products.each do |product| %>
<div class="column_entry">
<%= link_to image_tag(product.product_image.url(:normal_page_size)), products_content_url(product.id) %>
</div>
<% end %>
</div>
Thanks to both #Matzi and #TomL for their help. It's greatly appreciated.

Resources