I have a ruby on rails application and i have two models posts and category. Category has_many :posts and Post belongs_to :category. Now how can i display the last post item of each category. i.e retrieving the last post in each category.
In your view something like:
<% #categories.each do |category| %>
<p><%= category.posts.last %></p>
<% end %>
the example above will order the records by id but you might want to order the result by "created_at" field (in case you have it):
<%= category.posts.order('created_at desc').last %>
Related
I am trying to show only post from a particular category id
I have a category section and i have my relationship between categories and post working i just want to show post a specific category id instead of calling all post.
I have tried this but it's not working.
<% #posts.each do |post| %>
<h5><td><%=link_to post.category(1).title, post %></td></h5>
<% end %>
if you want to show a post of a category id, this should help
<% Post.where(category_id: 1).each do |post| %>
where that 1 would be the category id
In your code:
<% #posts.each do |post| %>
<h5><td><%=link_to post.category(1).title, post %></td></h5>
<% end %>
...this part looks suspicious: category(1). If post belongs_to category, try this:
post.category.title
If a post has_many (or has_and_belongs_to_many) categories, try this:
post.categories.first.title
One of those two should give you what you want.
Beyond that, I'm not sure you're trying to link. You're linking to a post, but the linktext is the category title. So, if you have three posts in the category, "Recipes," all three links will say "Recipes." Are you trying to link to the post or the category? Either way, the linktext should relate to the url.
I have two models here, Groups and Posts. Posts belong to group and groups have many posts. Here is my issue. I have an index page of groups. I'm trying to have a sidebar display a list of latest posts. I am unable to link to the posts because of the nested routes (I can't get the correct parameter for the group because this is all appearing on the group index page). Here is how I first tried to do it:
<% #latest_posts.each do |post| %>
<li><%= link_to post.title, group_post_path(#group, post) %></li>
<li><%= post.group.title %></li>
<% end %>
I've already looped through the list of groups on this same view, though:
<% #groups.each do |group| %>
<div class="table-cell">
<%= link_to group.title, group %>
</div>
<div class="table-cell">
<%= group.description.truncate(70) %>
</div>
<% end %>
So in my groups controller, I can't just make a #group instance variable to place into the group_post_path params. Here's my controller:
def index
#latest_posts = Post.order('created_at DESC').limit(20)
#groups = Group.order('created_at DESC').page(params[:page]).per(25)
end
So I have two problems. My main one is that I can't link to the post. I thought this would work, but no to that one also (I have friendly id set up, so I need to link to the group name instead of the id here.)
<%= link_to post.title, group_post_path(post.group_id, post) %>
But any attribute from the parent isn't available.
<%= post.group.title %>
produces
undefined method `title' for nil:NilClass
The same goes for trying it in the params.
<%= link_to post.title, group_post_path(post.group.title, post) %>
My models:
class Post < ApplicationRecord
belongs_to :group
class Group < ApplicationRecord
has_many :posts
How can I get at least access to the parent attributes?
to-many association between 2 modles. It works perfectly in the console but in the view just I get object-references appears like this:
#<Author:0x0000000434bf80>
#<Author:0x000000043485b0>
This appears in my view which has this code:
<h1 class="page-title">Articles</h1>
<hr>
<div class="category-container">
<ul class="category-titles">
<% #cat.each do |c| %>
<li><%= link_to c.catName, category_path(c) %></li>
<% end %>
</ul>
</div>
<br><br><br><hr>
<% #art.each do |t| %>
<p class="articles-list-page"><%= link_to t.artTitle, article_path(t) %></p>
<p><%= t.author %></p>
<% end %>
Here is my association in Author Model
class Author < ActiveRecord::Base
has_many :articles
end
and Here is my association in Article Model
class Article < ActiveRecord::Base
belongs_to :category
belongs_to :author
end
I could not understand why it is working well in the console but not in the view
It works fine in the view.
This line:
<p><%= t.author %></p>
outputs the author model. What you probably want to do is output the author name - something like
<p><%= t.author.name %></p>
You're attempting to output an ActiveRecord relation to the view. There's probably no situation ever where you'd want to display an entire ActiveRecord object in a view. Instead, you'd want to display particular attributes of the object.
Such as:
t.author.created_at
t.author.name
t.author.whatever
However, if there was some strange reason you wanted to output the entire object to the view, you could use inspect like so:
t.author.inspect
UPDATE:
To answer the other issue you're running into, you'll need to make sure that you actually have a related Author for each of the Articles before trying to output an Author attribute to the view. You can accomplish that like so:
<% if t.author.present? %>
<p><%= t.author.authName %></p>
<% else %>
<p>No author available</p>
<% end %>
Or like so, if you want to use a terniary operator to keep things on one line:
<p><%= t.author.present? ? t.author.authName : 'No author available' %></p>
Or if you don't care about returning a default value such as "No author available" if an author isn't available, then you could just do something like this:
<p><%= t.author.try(:authName) %></p>
You should delegate that author attributes to Article model
class Article < ActiveRecord::Base
belongs_to :category
belongs_to :author
delegates :authName, allow_nil: true
end
Also in your controller use following code
class ArticleController < ApplicationController
def index
#art = Article.includes(:author).all
end
end
And in your view use like bellow
<% #art.each do |t| %>
<p class="articles-list-page"><%= link_to t.artTitle, article_path(t) %></p>
<p><%= t.authName %></p>
<% end %>
I'm wondering if theres a best practice for what I'm trying to accomplish...
First we have the model categories, categories, has_many posts.
Now lets say, users add posts.
Now, I have a page, that I want to display only the current user's posts by category.
Lets say we have the following categories: A, B, and C
User 1, has posted in Categories A and B.
In my view I have something like:
#categories.each do |category|
category.name
#posts.each do |post|
if post.category_id==category.id
post content here
end
end
end
The problem with this, is I'm going to show the empty category, as well as the categories that do have content.
Is there a more efficient way of going about this? As I don't want to show the empty categories.
Best,
Elliot
UPDATE:
So I've been trying to use this code:
0}.each do |category| %>
For the most part its almost there. The issue is, it will still show an empty category if any posts have been entered in it at all (even if the current user has not input posts into that category.
So the question boils down to:
How do I make the following loop only count posts in the category from the current user?
0}.each do |category| %>
<% #categories.select {|cat| cat.posts.count > 0}.each do |category| %>
<%= category.name %><br/>
<% category.posts.select {|post| post.user == current_user}.each do |post| %>
<%= post.content %><br/>
<% end %>
<% end %>
This renders each category with any posts, then the content for each post within the category belonging to the current user. You'd probably want to do the initial selection in the controller though, to keep the view clean.
Adding to zetetic's answer, perhaps the lookup of the posts of a user in a given category would be done the opposite way. Instead of querying "All the posts for the category where the author is the current user", ask for "all the posts for the user where it is in given category"
<% #categories.select {|cat| cat.posts.count > 0}.each do |category| %>
<%= category.name %><br/>
<% current_user.posts_in_category(category).each do |post| %>
<%= post.content %><br/>
<% end %>
<% end %>
And throw a scoped search User#posts_in_category
EDIT: Probably you should also set the #categories variable already filtered from your controller, if you're not showing them somewhere else in your view. Also, if the category has no posts, it will not enter the cycle, so maybe the select is not needed.
#categories.select do |category|
category.posts.any? {|post| post.user == current_user }
end
Will filter out the categories to have only categories with posts by the current_user. I guess it would be more efficient doing this in the db, use this if you're fetching the #categories anyway.
As per my concern you need to have an intermediate table for users who publish posts for a given category that table might have following fields
user_id,post_id, category_id by this way you will be having a table which has category id's and for each category there is a post.
then you can do the following
get the distinct categories (from above table)
loop through the categories
get posts for those categories
** then you will not get any categories without posts
cheers,
sameera
I have an index of users where I display the user name, location of user and a field called categories, which can range from zero to many items. I'm having trouble getting the categories to display properly. Here are my details:
User
has_many :user_categories
has_many :categories, :through => :user_categories
Categories
has_many :user_categories
has_many :users, :through => :user_categories
User_categories
belongs_to :user
belongs_to :category
In my user_categories table, there are three columns: id, user_id, category_id.
In my categories table, there are two columns: id and name.
In my user/index view, I have the following:
<% #users.each do |user| %>
<%= link_to user.name, user %>
<%=h user.state %>
<%=h user.categories %> ## This line is the problem
<% end %>
Where I've indicated the problem with my comment directly above, I've tried multiple variations, but somehow I'm missing it. Here are the variations that I've tried, and the results that they produce. Note that for testing, user #2 is the only one with a category that should display.
<%=h user.categories %>
displays: #<Category:0x3f40634>
Log shows:
UserCategory Load (0.4ms) SELECT * FROM "user_categories" WHERE ("user_categories".user_id = 2)
Category Load (0.4ms) SELECT "categories".* FROM "categories" INNER JOIN "user_categories" ON "categories".id = "user_categories".category_id WHERE (("user_categories".user_id = 2))
<%=h user.categories.name %> <-- Here I added .name at the end of the call
displays: category
log shows: App does not do a category load.
<%=h user.user_categories %>
displays: #<UserCategory:0x3e4d1a0>
log shows: UserCategory Load (0.4ms) SELECT * FROM "user_categories" WHERE ("user_categories"."user_id" = 2) AND ("user_categories".user_id = 2) LIMIT 1
Does not do a category load.
<%=h user.user_categories.find_by_user_id(user.id) %>
produces same results as above.
Based on this, I think that <%=h user.categories %> is the one that makes the most sense, but I've tried every variation that I can think of and they all throw exceptions.
The model definitions look correct. You may want to check your database to ensure you've used proper conventions for your ids. I was a concerned that you tried to display all categories in the "problem line". Try looping over them:
<% #users.each do |user| %>
<%= link_to user.name, user %>
<%=h user.state %>
<%=user.categories.each do |c| %>
<%h c.name%>
<%end%>
<% end %>
The problem you were having is that in all three cases, you were attempting to display or operate on a collection of ActiveRecord objects. <%= h user.categories %> and <%= h user.user_categories %> will display the results of calling to_s on the collection, which gives the output (#<Category:0x3f40634> or #<UserCategory:0x3e4d1a0>) you noted. <%= h user.categories.name %> will display the result of calling name on the categories association.
jrhicks' answer works because he iterated over the categories and printed out the name of each one. See http://guides.rubyonrails.org/getting_started.html#hooking-comments-to-posts for a similar example - in that case, they iterate over a post's comments.