I have 2 tables with a relation between them:
Users table: user_id,
Blogs table: user_id, blog_content,
Im working with a view that should show a users latest blog entry.. When I use
<%= #users.blogs.last %>
I get "#"
Can someone assist as to why its showing "#" and how to actually show the the last blog entry made by a #user?
Many thanks!!
I found out, I needed to define what part of the hash I needed to show
<%= #users.blogs.last[:blog_content] %>
I'd have thought you want to do:
<%= #users.blogs.last.blog_content %>
What you've done will try and display the Blog object itself with the to_s method, which returns something that looks like the following:
#<Blog:0x?????????>
Which on screen will just look like a hash.
Related
Assuming I have this association
User have_many posts
Post belongs_to user
User Post
----------------
id id
name title
user_id
How to list only post title and username with includes/joins ?
(list of posts [title - username])
#posts = Post.includes(:user).select('........')
don't offer this
#posts = Post.all.each {|p| p.user.username}
__________________UP_____________________
It worked for joining 2 tables.
What if I want to use it for more complex example?
check out my prev question optimize sql query rails
#Humza's answer partly worked.
it might be something like this
#posts = Post.joins(:user, :category).paginate(:page => params[:page]).order("created_at DESC")
but It doesn't display posts that don't have category
I also need to display gravatar but I think I can just use user.email as usr_email and use gravatar_for (post.usr_email) but I'll have to customize gravatar helper for this.
posts_controller.rb
def index
#posts = Post.includes(:user).includes(:comments).paginate(:page => params[:page]).order("created_at DESC")
end
index.html.erb
<%= render #posts %>
_post.html.erb
<%= gravatar_for post.user, size:20 %>
<%= link_to "#{post.title}", post_path(post) %>
<%= time_ago_in_words(post.created_at) %>
<%= post.comments.count %>
<%= post.category.name if post.category %>
Take a look at pluck.
Post.joins(:user).pluck(:title, :name)
Note that it works in this case because there's no ambiguity regarding the name column, you might want to specify the table explicitly (pluck(:title, "users.name")).
includes is used in case of eager-loading. You need joins in this case.
posts = Post.joins(:user).select("posts.title AS title, users.name AS username")
You can access the values then in the following way:
post = posts.first
post.title # will give the title of the post
post.username # will give the name of the user that this post belongs to
If you can pluck multiple columns, then the following might be more useful to you:
posts = Post.joins(:user).pluck("posts.title", "users.name")
The result will be a 2D array, with each element being an array of the form [post_title, post_username]
Post.joins(:user, :category)
but It doesn't display posts that don't have category
That's because joins uses INNER JOIN to join the tables together. If you want to everything from Post even though the particular record doesn't have its counterpart in the other table, you need to use LEFT JOIN. Unfortunately ActiveRecord doesn't have a nice way of generating it and you will need to do that manually:
Post.joins("LEFT OUTER JOIN categories ON categories.post_id = posts.id")...
See A Visual Explanation of SQL Joins for more information.
You can call array methods on a scope so:
Post.includes(:user).map { |p| [p.title, p.user.name] }
will get the posts with included user and map each post to a tuple of the post title and the user name.
That may not entirely answer your question as I think you might want to restrict the results of the query to just the required fields in which case, I think you can add a .select('title', 'users.name') to the query. (Not in a position to test at the moment)
I seem to be stuck with a problem that probably should be more obvious to me: How can I get certain attributes from a related model to show in a view.
In my application there are these 2 models:
products
product_images
I'm writing this while I'm on the go and don't have the exact code available. However I created the necessary associations, so that a product has_many product_images and a product_image belongs_to a product. The image model has an url, a default (boolean) flag and of course the product_id.
In the product index view I'd like to display the default image for that product. For the sake of simplicity though let's just assume I'm fine with showing the first picture - conditions should be easy to introduce once this works.
So in my products index view there's something like this (again, just from memory):
#products.each do |p|
<h3><%= p.name %></h3>
<%= image_tag p.product_images.first.url %>
<p><%= p.description %></p>
end
While the description and name of the product alone display just fine as soon as I include the image_tag my view breaks with a NoMethodError stating that url is an undefined method in Class Nil.
To keep it even simpler I got rid of the image_tag and just wanted to see the url printed in a paragraph - the problem remains of course.
If I just try to get p.product_images.first the view prints what I assume is some sort of ID for the object/model just fine, which tells me that the association itself is ok. So why does Rails think that the url attribute should be a method?
I also checked back with the rails console to see if this is the correct syntax to retrieve a related attribute. Like so (again, from memory - syntax errors possible):
p = Product.first
=> [successful - shows the first product]
p.product_images.first
=> [successful - shows the first image model]
p.product_images.first.url
=> [successful - shows me the single attribute, the url to the image]
As you can tell by now I'm very new to this and your help is very much appreciated. Of course I read the Rails documentation, however the Active Record Query Guide mostly focuses on getting data from the current model and I wasn't able to find what I'm obviously missing in my sample app.
Why does this work in the console but not in the view?
It is probably because one of your Product does not have any ProductImage.
You can correct this by adding a method in your ProductsHelper like so:
def product_image(product)
return if product.product_images.blank?
image_url = product.product_images.first.url
return if image_url.nil?
image_tag(image_url).html_safe
end
And then call it from your view like so:
#products.each do |p|
<h3><%= p.name %></h3>
<%= product_image(p) %>
<p><%= p.description %></p>
end
In my view, I'm using this to display the user
Made a comment on <%= link_to activity.trackable.micropost.user, activity.trackable.micropost.user %>
When I do this, it works, but the link shows up as something like #<User:0x5424a68>
I tried using activity.trackable.micropost.user.username, activity.trackable.micropost.user.name, and other variations but they didn't work.
What do I need to add after .user?
The activity.trackable is from the PublicActivity gem.
Open rails console and type:
User.instance_methods.grep(/name/)
It will give you a list of methods on User that contain the string 'name'. Chances are, that you will find the method you are looking for in the list (if there is any).
Try
<%= activity.trackable.micropost.user.inspect %>
or
<%= activity.trackable.micropost.user.to_s %>
This should give you a decent idea of what you need to add..
Building a form for users to submit data. I can't seem to understand or figure out how *collection_select* method works.
Essentially I'm trying to give my users the option to choose which sub_category their product belongs in when submitting the form. What should the collection_select syntax look like?
I ended up figuring it out based on comments, here is what I ended up with, in case it helps anyone else.
<%= f.collection_select(:sub_category_id , SubCategory.find(:all), :id , :name) %>
Edited
SubCategory.all
instead of
Sub_category.all
This is probably pretty basic, but I'm trying to figure out how to show how many comments a post has in rails, on the post index page of my app.
comments belongs_to post, and post has_many comments
Just not sure how to show on the index page, the amount of comments for each post.
Thanks in advance!
Elliot
Try this.
<%= post.comments.size %>
You might also be interested in the pluralize method.
<%= pluralize(post.comments.size, 'comment') %>
This will output "3 comments" or "1 comment", etc.
I may be wrong here, but you should use
<%= post.comments.count %> rather than size.
ActiveRecord knows that 'count' is a special method, and will turn it into a SELECT count(id) from comments where post_id = x (which is what you want).
size however, is not a special method, and ActiveRecord will load all the comments into an array in memory (SELECT * from comments where post_id = x, and then tell you how long this array is, which may be unneccessary - if you're going to loop through the array of comments further down the page, then you may want to use size to load them into memory, because it will need to happen later anyway.
You should also use some of ActiveRecord's built in functionality here. The counter_cache. Check it out here