I get an error undefined method 'email' for nil:NilClass when I try to access a post with a comment from a user that has been deleted in the DB.
I wonder: how can I remove the comments that has been created by users who no longer exists "on the fly"?
I tried something like this
<%= div_for(comment) do %>
<% if comment.user.email.nil?%>
<% comment.destroy %>
<%else%>
<p><%= comment.body %></p>
<p class="comment-submitted-by"><%= time_ago_in_words(comment.created_at) %> ago by
<%= comment.user.email %></p>
<%end%>
but I still get the error.
You're still getting an error because you've referenced comment.user.email, and user is nil. You need to check comment.user.nil?, or you're also at risk for deleting a comment just because a user's email is missing (though maybe you disallow that):
<% if comment.user.nil? %>
<% comment.destroy %>
Cleaning up on the fly is going to be finicky and cumbersome. What it looks like you want is dependent: :destroy on your User#comments association.
class User
has_many :comments, dependent: :destroy
end
Then when your User is removed, all of their Comments will be too, and you don't have to worry about it at display time.
Since there are existing orphaned comments, you can clean them out with a simple SQL statement:
DELETE FROM comments WHERE user_id NOT IN (
SELECT id FROM users
)
Or your Rails console:
Comments.find_each { |c| c.destroy if c.user.nil? }
Removing some comments from a thread might make it hard to understand the remaining comments, because of missing context.
Therefore I would like to suggest another approach: Just display deleted user instead of the user's email when the user was deleted.
A simple implementation might look like this:
<%= div_for(comment) do %>
<p><%= comment.body %></p>
<p class="comment-submitted-by">
<%= time_ago_in_words(comment.created_at) %> ago by
<%= comment.user ? comment.user.email : 'deleted user' %>
</p>
<%end%>
Related
I have tried setting up a comment system on my application. I have made a migration for the comments so all the comments have a user_id and post_id referenced with them. I have added has_many :comments, through: :posts in my user model. I have also added has_many :comments in my posts controller. In my comments controller I have also added belongs_to :post and the same for belongs_to :user. The problem occurs though when I try to call anything from the user model through an html.erb. When I make a comment through the console everything goes through fine and I can see what user made the comment, but when I try to even display any comments everything go sideways. Here is the part which is causing the error:
<% #comments.each do |comment| %>
<h3><%= comment.user.username %></h3>
<h4><%= comment.body %></h4>
</div>
<% end %>
It throws me an error in the username part giving me: undefined method `username' for nil:NilClass. Also, this occurs one every post even if that post doesn't have any comments. The body does work though.
undefined method `username' for nil:NilClass
This is caused by the fact that username is not a property of nil
You need to account for the fact that for some of your records, probably legacy data before you wrote the code to handle the associations, there is no user associated with a comment.
Change your view code to check for nil
<% #comments.each do |comment| %>
<h3><%= comment.user.username unless comment.user.blank? || comment.user.username.blank?%></h3>
<h4><%= comment.body %></h4>
</div> <%# why a random closing div here, remove it or move it to a more appropriate location to match an opening div%>
<% end %>
Or perhaps a little nicer
<% #comments.each do |comment| %>
<h3>
<%if comment.user.blank?%>
No user associated with this comment
<%= else comment.user.username.blank?%>
</h3>
<h4><%= comment.body %></h4>
</div> <%# why a random closing div here, remove it or move it to a more appropriate location to match an opening div%>
<% end %>
Root, because when you created comment, you did not set comment.user (example comment.user = current_user) before save.
Check your code in CommentsController -> method create
I am building a basic bare bones social media app right now.
I have a user class and a status class.
For each status, there is a "creater" (a user object) and a "subject" (a user object that the status is about). I was able to create tags by using the acts_as_taggable_on gem. What ends up happening is when a user goes to create a post, he/she can select another user from a dropdown menu. The chosen user's id attribute is then stored.
Now I am trying to link to the chosen User's profile. This is my code for show statuses on a profile page.
<% if #statuses %>
<% #statuses.each do |status| %>
<div class="well">
<%= status.content %>
<br></br>
#link to user who's associated with the tagId
<%= link_to User.find(status.tag_list).profile_name, user_profile_path(User.find(status.tag_list).profile_name) %>
<hr />
<%= link_to time_ago_in_words(status.created_at), status_path(status) %> ago
</div>
<% end %>
<% end%>
this is the line where the above code breaks
<%= link_to User.find(status.tag_list).profile_name, user_profile_path(User.find(status.tag_list).profile_name) %>
Can anyone help me out with this?
Not surprised this line is failing:
<%= link_to User.find(status.tag_list).profile_name, user_profile_path(User.find(status.tag_list).profile_name) %>
A couple points:
It's a little cleaner to separate it onto multiple lines
I suspect your problem is because you're passing a profile_name to user_profile_path instead of an id, though I can't be certain without seeing your routes.
Try the following:
<% profile_user = User.find(status.tag_list) %>
<%= link_to profile_user.profile_name, user_profile_path(profile_user.id) %>
I am making an app in Rails 4.
I have an address model, which is polymorphic.
My associations are:
profile.rb
has_many :addresses, as: :addressable
address.rb
belongs_to :addressable, :polymorphic => true
In my address.rb, I have a method for:
def country_name
self.country = ISO3166::Country[country]
country.translations[I18n.locale.to_s] || country.name
end
In my profile views folder, I have a partial to display a user's country, as:
<span class="profilesideinfo">
<% if #addresses.country_name.present? %>
<%= #addresses.country_name.titlecase %>
<% else %>
<span class="profileeditlink">
<%= link_to "Add your location", new_address_path %>
</span>
<% end %>
</span>
I have also tried:
<% if #profile.addresses.country_name.present? %>
<%= #profile.addresses.country_name.titlecase %>
<% else %>
<span class="profileeditlink">
<%= link_to "Add your location", new_address_path %>
</span>
<% end %>
And I have also tried (changing country_name (which is the method in my model) to country (which is the attribute in my address table))
Im getting stuck, because I can successfully create an address, but then that country name should show in the profile show partial. It doesn't. Instead, I get an error that says:
undefined method `country_name' for nil:NilClass
Is there something else that needs to happen for a reference to a polymorphic instance to show in the parent.
Can anyone see what needs to happen to get this to work?
I have tried making a scope in my profile model as:
Profile.joins(:addresses).where("addresses.profile_id = ?", profile_id)
I'm not sure this is adding any value. I'm not sure how to use it or whether it works, given that the address model doesn't have a foreign key for profile_id.
When I save this and try to reload the page, I get this error:
undefined local variable or method `profile_id' for #<Class:0x007fbacaec2d18>
Taking SurreyMagpie's suggestion below, I change the partial to:
<% if #profile.addresses.country_name.any? %>
<%= #profile.address.country_name.first.titlecase %>
<% else %>
<span class="profileeditlink">
<%= link_to "Add your location", new_address_path %>
</span>
<% end %>
I am checking if there are any addresses and then displaying the first country name.
When I try this, I get this error:
undefined method `country_name' for #<ActiveRecord::Associations::CollectionProxy []>
The polymorphic nature of the association is not responsible for your difficulties here.
When you define country_name as a method in your Address class, that is known as an instance method. As such, you are able to call it on a single Address object. So, if in the rails console you run Address.first.country_name you should receive a result for that specific instance of Address.
However, when you query a has_many association, in your case #profile.addresses, you get an ActiveRecord::Associations::CollectionProxy returned, even if there is only a single Address record. It is not exactly an array but has very similar behaviour.
The point is: you cannot call your instance method on the whole set at once. You need to iterate through the collection and call the method on each instance. For example:
<% if #profile.addresses.any? %>
<% #profile.addresses.each do |address| %>
<span class="profilecountry">
<%= address.country_name.titlecase %>
</span>
<% end %>
<% else %>
<span class="profileeditlink">
<%= link_to "Add your location", new_address_path %>
</span>
<% end %>
may be what you need - though how you choose to display multiple countries is up to you.
I know this is a really simple question, but I've gone completely blank! I'm reading through the Rails guides and looking at the getting started section. The following code is displaying all comments that belong to the current Post:
<h2>Comments</h2>
<% #post.comments.each do |comment| %>
<p>
<b>Commenter:</b>
<%= comment.commenter %>
</p>
<p>
<b>Comment:</b>
<%= comment.body %>
</p>
<% end %>
What is the simplest way of linking to each individual comment? For reference the page I am looking at is http://guides.rubyonrails.org/getting_started.html
The models are as follows:
class Post < ActiveRecord::Base
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :post
end
Rails will try to create route helpers to assist you in this. You can get a full list by running rake routes, but there are good odds that the one you'll be looking for is named comment_path:
<% #post.comments.each do |comment| %>
<%= link_to 'Click to view comment', comment_path(comment) %>
<% end %>
For reference, check out the Rails Routing Guide.
You should take a look to your routes, and see what's the path to an individual comment.
It should be something like : comment_path(comment) or post_comment(#post, comment)
You will link it with <%= link_to "View comment", comment_path(comment) %>
Article HABTM authors
In Article model, i say:
validates_associated :authors
But, by creating of the new Article, this validation does't happen, because i don't see the errors.
Another errors are displayed properly, but this.
I render errors so:
<div class="errors">
<%= article_form.error_messages %>
</div>
What's wrong here ?
Validates_associated should work with any kind of association.
Try to display your errors either with:
<%= #article.errors.full_messages.to_sentence %>
or
<%- for author in #article.authors %>
<%= author.errors.full_messages.to_sentence %>
<%- end %>