How to find a comments' count ... or even articles' count - ruby-on-rails

Ok, relying on guide's blog tutorial:http://edgeguides.rubyonrails.org/getting_started.html
Trying to learn how to write a method myself.
The guide did both article and comments ie, belongs_to & has_many relationship.
So, thought why not try to find out the totality of comments.
This is the method I wrote for Comments controller:
def total_number_of_comments
#article = Article.all
#comments_total = #article.comments.count
end
Then I put this in article's view index.html.erb
<p>Total number of comments:</p>
<%= #comments_total %>
On the index page, it doesn't show anything.
So, what am I doing wrong?
And, I don't want just a "correct" answer. I'd like to understand what I'm missing here.
But what I'm befuddled here is how to think this out.
I hesitate to do this because it would prolong the post, but I thought why not try to do count of articles too.
So, here's what I did:
In Article model
def self.total_number_of_articles
Article.all.count
end
In Article controller
def total_number_of_articles
#articles_total = Article.total_number_of_articles
end
Then in index.html.erb of Article View again, I put this:
<p>Total number of articles:</p>
<%= #total_number_of_articles %>
Again, nothing shows up in terms of count in either comment or article.
So .... clearly I'm missing something here.
EDIT
The comment (total_number_of_comments) method was sorta based on this: (from railsguide)
def create
#article = Article.find(params[:article_id])
#comment = #article.comments.create(comment_params)
redirect_to article_path(#article)
end

There are many things you missed, I would happy to explain you.
Here
def total_number_of_comments
#article = Article.all
#comments_total = #article.comments.count
end
You have to do this
def total_number_of_comments
#comments_total = Comment.all.count // simple solution
end
Next is , you didn't used proper instance variable.
def total_number_of_articles
#articles_total = Article.total_number_of_articles
end
See yourself
Total number of articles:
<%= #total_number_of_articles %> // this is wrong
You assigned #articles_total but used #total_number_of_articles. if you use #articles_total it will work fine.

You should define a function index in your controller.
calling a GET on /articles/index calls the controller function index, you should set #articles_total = Article.total_number_of_articles in your index function in controller. You have it in a function in your controller that is not getting called.

Related

Refactoring the following code?

I have two models blog and comment. Blog contains multiple comments, comment can only belong to 1 blog.
For showing the API like
blog/2/comment/1
I have to use the following code inside the comment controller
def show
#blog = Blog.find(params[:blog_id])
#comments = #blog.comments
#comment = #comments[params[:id].to_i - 1]
end
I feel this code is quite akward, especially the last one #comments[params[:id].to_i - 1]. I have to convert parameter id to integer, then change to 0 based array index. Any refactoring can happen here
Do you mean make it look more "Rails"? Like this?
def show
#blog = Blog.find(params[:blog_id])
#comment = #blog.comments.find params[:id]
end
As per OP's comment. Your transformation is necessary. However, you can avoid loading the entire set of comments and only take the one you need.
#comment = #blog.comments.offset(params[:id].to_i - 1).limit(1)

Post with latest comment on top of index page - Ruby On Rails

I need to display post with the latest made comment in it, on top of page. And every Post has many comments and many Comments belong to one post.
Here is my index method from Posts controller
def index
#posts = Post.all.order("posts.created_at desc")
def new
#post = Post.new
end
end
I looked through Rails docs and found .order and .where methods, and I think those two methods are the solution to my problem but I am not sure how to use it
try this:
#posts = Post.joins(:comments).order("comments.created_at DESC")
def index
#posts = Post.all.order("created_at DESC")
#latest_post = #posts.first
end
update
I interpreted word comments as posts.
update 2
First you need to find the latest comment:
#latest_comment = Comment.all.order('created_at DESC').first
Having that, you can extract the ID of the Post to which this comment belong:
post_id = latest_comment.post_id
Now you have the latest comment and the respective post's id. I would modify index page like this:
def index
#posts = Post.all.order("created_at DESC")
#latest_comment = Comment.all.order('created_at DESC').first
#post_of_latest_comment = Post.find(#latest_comment.post_id)
end
I am not sure what do you mean by displaying it on top, but I am pretty sure with this code you can do it in your view.
update 3
In your view, you hsould have something like this:
<h1>Top comment</h1>
<%= #latest_comment.text %>
By .textI mean some attribute of model Comment wich contains the content of the comment, plain text. If you need more help with this, show what atributes your Post and Coment model have.
I tried a modified line from Pitabas Prathal:
Post.joins(:comments).order("comments.created_at DESC").group('post_id')
where post_id is the foreign key in the Comment model from the Post model. It worked fine for me :)

Undefined method in controller - rails

I have a controller called blogger:
class BloggerController < ApplicationController
def home
end
def favoritePosts
#blogger = current_blogger
#favorites = #blogger.favorite_posts
end
def suggestedPosts
posts = Post.all
#suggestedPosts = posts.similar_posts
end
end
And in the Blogger model i have a method:
def similar_posts
title_keywords = Post.body.split(' ')
Post.all.sort do |post1, post2|
post1_title_intersection = post2.body.split(' ') & title_keywords
post2_title_intersection = post2.body.split(' ') & title_keywords
post2_title_intersection.length <=> post1_title_intersection.length
end
end
When i run the server its gives me an error:
undefined method `similar_posts' for #<Post::ActiveRecord_Relation:0x007fa365029760>
After searching on stackoverflow i tried def self.similar_postsbut it still gives the same error message. I also tried new in the controller like this #suggestedPosts = posts.new.similar_posts which still gives me the same error.
Any suggestions on how to overcome this?
You have 2 issues happening at the same time. The first is that you're using posts in your call, when you should be using something more like post.blogger. The specific object depends on what your intent actually is.
The second issue is that you're making the call to similar_posts on the association, not on an individual record. This can be resolved with a call to each on the association.
So, putting those together and looking at what you might have meant, I think that you might have intended this as your suggestedPosts method:
def suggestedPosts
posts = Post.all
#suggestedPosts = posts.map {|post| post.blogger.similar_posts }
end
I also changed the name of #suggestedDevelopers to #suggestedPosts, because I don't think that you meant 'developers' in this case. This should give you something closer to what it appear you were trying for.

Getting all comments

I have two models: posts and comments. Each comment belongs to a post. I would like to have a page of all comments not just the comments for a post. I can't seem to get this seemingly simple thing to work.
Here is my controller:
def top
#topcomments = #comments.order("created_at desc")
end
I am getting an 'undefined method order' error.
If you want to access comments directly, and not through a relationship with another model, you need to access the model itself, Comment:
def top
#topcomments = Comment.order('created_at desc')
end
how would you get the post for each comment
Assuming you have a relationship set up correctly between comments and posts, you would just access .post for each comment. You can use includes(:post) to avoid the n+1 problem.
def top
#topcomments = Comment.order('created_at desc').includes(:post)
#topcomments.each |comment|
comment.post # here is the post
end
end
def top
#topcomments = Comment.order("created_at desc")
end

Including a list of recent records in show method

I'm trying to include a few other recent articles when someone views a particular article in my Rails app.
I have the following method in my controller:
def show
#article = Article.find(params[:id])
#recents = Article.where(!#article).order("created_at DESC").limit(4).offset(1)
end
As the expert eye might see, #recents isn't correct. It's my best guess. :)
How do I show some recent articles but not repeat the one they are currently viewing?
You should use a scope in the model, for it has a lot of advanteges. Learn about scopes here. Your case should be something like this:
In the model:
class Article < ActiveRecord::Base
scope :recent, ->(article_id) { where.not(id: article_id).order(created_at: :desc).limit(4) }
end
and in the controller:
def show
#article = Article.find(params[:id])
#recent = Article.recent(#article.id)
end
This way the recent scope will always get the four last articles leaving out the article you pass in as an argument. And scopes are chainable so you could do something like this as well:
def some_action
#user = User.find(params[:user_id])
#user_recent_articles = #user.articles.recent(0)
end
You are getting the user recent articles. I pass a zero because the scope asks for an argument. You could create a different scope if you want to do it the cleanest way.
This, assuming a user has_many articles.
Well, hope it helps!
try with #recents = Article.where.not(id: #article.id).order("created_at DESC").limit(4)
click here - section 2.4 :).
I think there is a way of only making one call instead of 2 the way you have it now.

Resources