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 %>
Related
First, the example I read in the docs shows to declare the associated model as singular, :address, but if I do I get the error Association named 'address' was not found on User; If I change it to plural :addresses, then the next problem I have is the association doesn't work in views undefined method `country' for ...
Why am I declaring the association as plural and how can I make the association available in the view
User.rb:
class User < ActiveRecord::Base
searchkick word_middle: ['full_name', 'description', 'interests']
has_many :addresses
scope :search_import, -> { includes(:addresses) }
search.html.erb:
<% #users.each do |u| %>
<li>
<%= link_to "#{u.first_name} #{u.middle_name} #{u.last_name}", page_path(name: u.name) %>
<% #ua=u.addresses.where("current=?", true) %>
<% if #ua.country=="US" %>
<%= #ua.city %>, <%= #ua.state %> <%= ISO3166::Country.find_country_by_alpha2(#ua.country) %>
<% else %>
<%= #ua.city %>, <%= ISO3166::Country.find_country_by_alpha2(#ua.country) %>
<% end %>
</li>
<% end %>
</ul>
In controller, do this: #user = User.includes(:addresses).where(your_query) to make the association readily available in view.
And yes has_many associations are bound to be plural: "User has_one
:life" and "User has_many :passions"; does it make sense?
And finally your error: where returns an array because you queried: "bring me all records which fulfill this condition". find, on the other hand, will bring back 1 specific record as it expects a unique attribute or brings back first record that matches that attribute.
What you need to do:
You should either do this (if you are dead-sure that you will get 1
such record or you need only one of that type):
<% #ua=u.addresses.where("current=?", true).first %>
OR
If you need to go through all the resultant array then:
<% #ua=u.addresses.where("current=?", true) %>
<% #ua.each do |ua| %>
# Your code for each ua instead of #ua.
<% end %>
Happy Learning :)
I'm creating a application using ruby on rails, but currently i'm suffering a problem like db relation, below my code:
Company
has_many :posts, :foreign_key => :company_id
Post
belongs_to :companies, :foreign_key => :company_id
controller
#post = current_user.companies.all
view
<% #post.each do |p| %>
<%= p.posts.post_title %>
<% end %>
Showing error above code.
If I debug like use <%= debug p.posts %> then showing all posts, which is under my companies but when I use <%= debug p.posts.post_title %> then showing ActiveRecord_Associations_CollectionProxy:0x0000000e490b98
Thanks
I think the problem here is that you are trying to call the method :post_title on p.posts, which is an ActiveRecord::Associations::CollectionProxy object.
In your example, p is a Company object, which has a method posts, which returns to you a CollectionProxy object that acts a lot like a list of posts. That list will not have a method post_title, but each element of that list will have a method post_title
So, instead of
<% #post.each do |p| %>
<%= p.posts.post_title %>
<% end %>
You will want something like:
<% #post.each do |company| %>
<% company.posts.each do |post| %>
<%= post.post_title %>
<% end %>
<% end %>
Two additional things to note:
1) The variable #post is inaccurately named. Inaccurate variable names will lead to confusion when trying to understand what is happening. current_user.companies.all returns a list of companies, and therefore, it should read:
#companies = current_user.companies.all
not
#post = current_user.companies.all
2) The actual error that is being shown to you likely says something like
Undefined Method 'post_title' for ActiveRecord_Associations_CollectionProxy:0x0000000e490b98
Not just
ActiveRecord_Associations_CollectionProxy:0x0000000e490b98
When debugging and asking for help, it's very important to note the entire message of the exception being raised.
Because companiy has_many :posts........ posts are objects you need a loop to show all posts e.g
p.posts.each do |post|
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%>
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 %>
Hey all, I have been away from rails for a while and have been catching up to rails 3, I think my problem might stem from me using an unsupported syntax from rails 2 that didnt make it to rails 3. Anyways, my problem might be to broad but while I have been able to fix all the other problems with this app, this one still puzzles me.
On the home page of the site there is this code:
<%- unless #requested_contacts.empty? -%>
<h2>Contact Requests</h2>
<ul class="list requests small">
<%- #requested_contacts.each do |contact| -%>
<%- conn = Connection.conn(current_user, contact) -%>
<li>
<p><%= person_link contact %></p>
<p class="meta published">
<%= time_ago_in_words(conn.created_at) %>
ago
</p>
<p>
<%= link_to "Respond", edit_connection_path(conn) %> |
<%= link_to "View profile", contact %>
</p>
</li>
<%- end -%>
</ul>
<%- end -%>
When I click respond instead of getting to the Connection edit page, I get an error:
undefined method `contact' for nil:NilClass
app/controllers/connections_controller.rb:15:in `edit'
{"id"=>"4"}
The controller code is:
def edit
#contact = #connection.contact
end
The relavent models are, Person.rb:
has_many :connections
has_many :contacts, :through => :connections, :order => 'people.created_at DESC'
has_many :requested_contacts, :through => :connections, :source => :contact
Connection.rb:
belongs_to :person
belongs_to :contact, :class_name => "Person", :foreign_key => "contact_id"
def conn(person, contact)
find_by_person_id_and_contact_id(person, contact)
end
The edit page I am trying to get to is:
<h2>Contact request</h2>
<p>You have a contact request from <%= #contact.name %></p>
<% form_for(#connection) do |f| %>
<p>
<%= f.submit "Accept", :class => "button" %>
<%= f.submit "Decline", :id => nil, :class => "button" %>
</p>
<% end %>
I think that is all the relevant code to this issue. If there is anything else you might need to see please let me know, I am very grateful for any an all help. Sorry if it is glare lying obvious, I am learning ruby and rails as a hobby (and loving it so far!).
When you see this error:
undefined method `contact' for nil:NilClass
It usually means you're trying to call a method on an unassigned variable. Since the error points to the controller, and the code you've shown us is:
def edit
#contact = #connection.contact
end
I'm going to guess that #connection is unassigned. Normally you would expect to have a finder method to retrieve the value before using it, like:
#connection = Connection.find(params[:id])
Sometimes this code is placed in a before_filter, to reduce duplication. If you do have such a filter, perhaps it is not being reached. It's hard to know without seeing the rest of the controller code.
The problem is that you seem to have mixed things up. In your controller's edit method, you reference #connection which hasn't been instantiated as far as we know, like zetetic said, so it's nil, then you try to call a method on it. It seems we need even more information.
I believe your def conn(person, contact) should be a class method: def self.conn(person, contact), based on the way you are calling it (not from an object but directly from the class).
Basically, the problem is that conn is coming up as nil, I believe it's for the reason I mentioned above, but if not, then figuring out why will find you your answer.
EDIT: If you are still getting the same error, then I recommend you try this out in the rails console.
Connection.find_by_person_id_and_contact_id(person, contact)
Try and use the same information you are using in the form which is generating the error. Most likely the problem is that there is no connection between the person and the contact. If you are sure there is but the above method says otherwise, then there is most likely an issue with how you set up your associations. Remember that not only do you have to specify the association in the class but you also have to modify the tables accordingly to reflect the association.
Assuming your associations are OK, and person references a connection.
Replace this line <%- conn = Connection.conn(current_user, contact) -%> with <%- conn = #person.conn(current_user, contact) -%>