Accessing fields_for object in Rails undefined method - ruby-on-rails

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

Related

ActiveRecord_Associations_CollectionProxy:0x0000000e490b98 in RoR

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|

ActionView::Template::Error (undefined method `city' for nil:NilClass):

I'm having belongs_to / has_many relationship between Trainer and Sportists. I'm trying to loop through their values in view like this:
<% #sportists.each do |s| %>
<%= s.name %> <%= s.surname %>
<%= s.trainer.city %>
<% end %>
and the Sportist related information works fine, but the trainers - doesn't. I get the error given in the title. If I try to do this in rails console everything works, so relationships should be set fine.
Things I've tried:
<% s.trainers.each do |t| %>
<%= t.city %>
<% end %>
that gives me undefined method 'trainers' error, and if I try s.trainer I get
#<TRAINER:0X00000004CE7CB0>
So what could be the fix?
EDIT
My models:
Trainer
has_many :sportists
belongs_to :team
accepts_nested_attributes_for :sportists, :reject_if => :all_blank, :allow_destroy => true
Sportist
belongs_to :trainer
Controller
#sportists = Sportist.all
You are getting undefined method 'city' for nil:NilClass in below code:
<% #sportists.each do |s| %>
<%= s.name %> <%= s.surname %>
<%= s.trainer.city %>
<% end %>
which means that there is a sportists record which doesn't have trainer associated to it.
So, for that particular sportlist record s.trainer is nil and you cannot call city on nil object.
To identify the sportist record for which you don't have an associated trainer, just update the view code as below:
<% #sportists.each do |s| %>
<%= s.name %> <%= s.surname %>
<%= s.trainer.try(:city) %>
<% end %>
This way even if you don't have an associated trainer record, error would not be raised.
In the rendered view, just look for sportlist record which doesn't show any city, that would be the sportlist record without an associated trainer.
As for the second error undefined method 'trainers' that you received on
<% s.trainers.each do |t| %>
<%= t.city %>
<% end %>
sportlist belongs_to trainer, you only have dynamic method trainer (NOTE singular) available and NOT trainers (NOTE plural). Also, s.trainer would return a single trainer record so you cannot iterate over it with each method as it is not a collection BUT a single record.
UPDATE
Ideally, you should not have allowed creation of sportist records without a trainer.
You should have added an index on the foreign key trainer_id created on sportlists table. With this you don't even have to use try method and your current code would work as it is.
You can make use of delegate and avoid use of try, if and terniary operator.
Sportist
belongs_to :trainer
delegate :city, to: :trainer, :allow_nil => true
You need to make small change to your existing code and it will work smoothly :)
<% #sportists.each do |s| %>
<%= s.name %> <%= s.surname %>
<%= s.city %>
<% end %>
Seems like you have a sportists that doesn't have a trainer. To avoid this make an if condition like this.
<% #sportists.each do |s| %>
<%= s.name %> <%= s.surname %>
<%= s.trainer.city if s.trianer.present?%>
<% end %>
And also setting the validation in the Sportist model should resolve the empty trainer_id values
Class Sportist < ActiveRecord::Base
belongs_to :trainer
validates :trainer_id, presence: true
end
You can update your code
<% #sportists.each do |s| %>
<%= s.name %> <%= s.surname %>
<%= s.trainer.city %>
<% end %>
with
<% #sportists.each do |s| %>
<%= s.name %> <%= s.surname %>
<%= s.trainer.present? ? s.trainer.city : "No City Found" %>
<% end %>
This will stop the code to throw nil errors

undefined method `keys' for nil:NilClass

Why when you iterate through a serialized JSON hash but spits out that the class is nil?
View
<% #test.yo.keys.each do |key| %>
<%= key %>
<% end %>
Model
class Test < ActiveRecord::Base
belongs_to :city
serialize :yo, JSON
end
it's saying that yo is nil for #test. you need to check yo for nil before you call a method against it :
<% if !#test.yo.nil? %>
<% #test.yo.keys.each do |key| %>
<%= key %>
<% end %>
<% end %>
you can probably find a better place to put your check, but this gives you an idea of how to fix it

undefined method `fields_for' for #<MyModel:0xc2f8da0>

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.

rails - displaying nested find hash

I am trying to display the output of this find -
#test = User.joins(:plans => [:categories => [:project => :presentations]]).where(current_user.id)
Here is my output loop
<% #test.each do |p| %>
<%= p.plans %>
<% p.plans.each do |d| %>
<%= debug(d) %>
<% d.categories.each do |e| %>
<% e.project.each do |r| %>
<%= debug(r) %>
<% end %>
<% end %>
<% end %>
<% end %>
The loop works until it gets to project when it throws this error
undefined method `each' for "#<Project:0x000001033d91c8>":Project
If I change it to projects in the loop it gives this error
undefined method `projects' for #<Plan:0x000001033da320>
The debug at categories level shows this
--- !ruby/object:Category
attributes:
id: 2
name: test
short_name: tst
created_at:
updated_at:
category_id: 2
plan_id: 5
My relationships look like this
User
has_many :user_plans
Plan
has_many :user_plans
has_and_belongs_to_many :categories
Category
has_one :project
has_and_belongs_to_many :plans
Project
has_many :presentations, :dependent => :delete_all
Presentation
belongs_to :project
Do I need to changed my find ?
Thanks, Alex
Category has_one :project
so it is single object not collection thus no each method.
According to your relationship definitions, Category only has_one project, so why do you want to iterate over e.project? If you just want to show debugging output, replace
<% e.project.each do |r| %>
<%= debug(r) %>
<% end %>
with
<%= debug(e.project) %>
But if you want to go deeper, into presentations, do:
<%= debug(e.project) %>
<% e.project.presentations.each do |presentation| %>
<%= debug(presentation) %>
<% end %>
Your problem is that you are calling the array method .each on a single object.
category.project will give you a single Project object right? That's not an array, so you can't call each on it.
Replace this:
<% e.project.each do |r| %>
<%= debug(r) %>
<% end %>
with
debug(e.project)
While you're at it, here's some other advice: use descriptive variable names. Why does 'p' represent a test, 'd' represent a plan, 'e' represent a category, etc? Variable names should tell you what the object is. Similarly, i'd expect the variable #test to hold a Test object. In your code it seems to be an array. Use plural variable names for a variable that holds a collection of that type of object - eg #plans would be an array of Plan objects.
eg
<% #tests.each do |test| %>
<% test.plans.each do |plan| %>
<%= debug(plan) %>
<% plan.categories.each do |category| %>
<%= debug(category.project) %>
<% end %>
<% end %>
<% end %>
Isn't that more readable?

Resources