I have 3 level hierarchy in my models for e.g
Publisher [have many] -> Author [have many] -> Book
In My form,
I have the following structure
<%= form_for(#publisher) do |p| %>
...
<%= p.fields_for #publisher.authors.build, :authors do |a| %>
...
<%= a.fields_for a.books.build, :books do |b| %>
...
<% end %>
<% end %>
<% end %>
It throws the following error
undefined method `fields_for' for #<Author:0xc2f8da0>
Any help would be much appreciated.
The problem is simply that you're trying to call fields_for on an instance of the Author class (which is a model). The method isn't defined on the model, it's a helper method that's part of ActionView.
Try simply removing a. and do:
<%= fields_for a.books.build, :books do |b| %>
...
<% end %>
There are more examples in the documentation. This may not be the full answer to your situation, but anytime you'te getting undefined method errors, the problem is very straight forward - you're calling a method that doesn't exist either in the scope, or the object upon which you're calling it. Usually this happens because you think you're dealing with an object of class x, but really you've got class y and you didn't realize it.
Related
I'm trying to access my fields_for object in order to access its properties with no luck:
<%= f.fields_for :items do |item| %>
<%= item.object.id %>
<% end %>
Output:
undefined local variable or method `item' for #<#<Class:0x0000000106aa5eb8>:0x000000012d4d6038>
Any ideas?
Feels like you are missing the instance here?
[...]
<%= f.fields_for :items, #some_instance.items do |item| %>
[...]
at least thats what a glance at the docs might suggest
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 have a loop to getting values in my database, but when I'm trying to get a value from a relationship, I get an error:
undefined method `first_name' for nil:NilClass
This is the loop:
<%= #sample.each do |s| %>
<%= s.relation.first_name %>
<% end %>
when I tried
<%= s.relation.to_json %>
with .to_json, I get this:
{"first_name":"testingtwo","last_name":"fdsaf","updated_at":"2013-11-21T07:47:05Z","user_id":null}
Shouldn't s.relation.first_name work?
Thanks
it's possible that there is a relation in the loop that doesn't have a value, and is getting hung up there - try this:
<%= #sample.each do |s| %>
<%= s.relation.first_name if s.relation %>
<% end %>
this only outputs s.relation.first_name if it isn't nil. You could also try this:
<%= #sample.each do |s| %>
<%= s.relation.first_name || "No name given" %>
<% end %>
which puts the first name if it exists, or "No name given" if it doesn't
One important thing you may want to consider too is whether or not having nil values within your database for that particular relationship is valid to begin with.
The || solution proposed is definitely a good one and a great Ruby pattern, but it may be worth adding in an ActiveRecord validation to ensure your relation(ships) are never nil.
ActiveRecord Validations are definitely the way to go in that particular case.
I have a very concrete dilemma right now.
Given the following models:
class Message < ActiveRecord::Base
attr_accessible :body, :sent_at
belongs_to :subject
end
class Subject < ActiveRecord::Base
attr_accessible :title
has_many :messages
belongs_to :last_message, :class_name => 'Message', :foreign_key => 'last_message_id'
end
In a view I want to iterate over a list of subjects and display:
- Subject title
- sent_at for the subject's last message
like this:
<% #subjects.each do |subject| %>
<%= subject.title %>
<%= subject.last_message.sent_at %>
<% end %>
The thing is: subject.last_message may some times be nil. In which case, the above code will throw an exception.
So: What is the best solution to this? I can see 3 possibilities, but honestly don't know which are considered good or bad.
1) Let the view rescue it
<%= subject.last_message.sent_at rescue '' %>
2) Make a helper
def last_message_sent_at(subject)
return '' if subject.last_message.blank?
subject.last_message.sent_at
end
<%= last_message_sent_at(subject) %>
3) Make a sort of "proxy" on the Subject model
class Subject < ...
...
def last_message_sent_at
return '' if last_message.blank?
last_message.sent_at
end
end
<%= subject.last_message_sent_at %>
Which would you choose, and why? Or is there perhaps another way, which I haven't thought about?
/ Carsten
Use try :
<%= subject.last_message.try(:sent_at) %>
So, if subject.last_message is nil, you will get no output; else if it is not nil, it will call the method sent_at on subject.last_message.
It is like a convenient form for your #2 idea
Documentation
As additional thought, helper is a bad choice. You ideally always want a "receiver" (in some_class.perform(), some_class is the "receiver" i.e. it "receives" the message "perform"). I avoid Helpers unless I need to generate HTML. So, your #3 does have a receiver, but since Rails provides try, you do not need to roll your own.
The easiest thing, in this case, may be to simply check for the null value...
<% #subjects.each do |subject| %>
<%= subject.title %>
<%= subject.last_message.sent_at if subject.last_message %>
<% end %>
or
<% #subjects.each do |subject| %>
<%= subject.title %>
<%= subject.last_message && subject.last_message.sent_at %>
<% end %>
If you had any logic or action to perform, best practice would be to move it out of your views (into helpers, presenters).
Since your question is about "how to call a method on possibly nil instance?", then try is probably the best way to go in this case. Because, it's already there and you don't need any extra gems.
On the other note, you can improve your code by just putting render #subjects and moving your block content into the _subject parcial. Rails will do the looping for you.
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) -%>