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
Related
In my application a user can say they have completed a piece of homework.
A field "completed_on" is populated with the date the homework was completed. If not completed the field is blank.
I would like to show a tick if the homework is completed or an x if the homework is not completed.
The column "completed_on" is located in a table called homework_students.
class Homework < ActiveRecord::Base
has_many :homework_students, :class_name => 'HomeworkStudent'
class HomeworkStudent < ActiveRecord::Base
belongs_to :homework, :class_name => 'Homework'
I have tried the following which does not work for me:
In my model:
def getCompletion
homework_students.where("completed_on is not null")
end
View:
<% if homework.getCompletion %><%= image_tag "fi-check.svg", class: "homework_student_complete" %><% else %><%= image_tag "fi-x.svg", class: "homework_student_complete" %><% end %>
I also tried this:
Model
def completed?
!homework.homework_student.completed_on.blank?
end
View
<% if homework.completed? %>
<%= image_tag "fi-check.svg", class: "homework_student_complete" %><% else %><%= image_tag "fi-x.svg", class: "homework_student_complete" %><% end %>
Appreciate any guidance.
UPDATE
This works:
def completed?
homework_students.where("completed_on is not null").length == 0
end
<% #homeworks.each do |homework| %>
...
<td height="1" class="text-center"><% if homework.completed? %>
<%= image_tag "fi-check.svg", class: "homework_student_complete" %>
<% else %>
<%= image_tag "fi-x.svg", class: "homework_student_complete" %>
<% end %></td>
...
<% end %>
The return type of your getCompletion method is an ActiveRecord::Relation. You are then asking if this relation exists by placing this inside a conditional. This will always be true, even if the relation contains an empty data set (e.g. []), because an empty Array is truthy.
You should be expecting getCompletion to return a collection of HomeworkStudent records. If you are wanting to show a tick, or an 'x' only if all students have completed the homework, then you need an aggregate method to check something about all of the records (if there are any, or none, etc). Try do something like:
# app/models/homework.rb
def completed?
homework_students.where("completed_on is null").none?
end
# in the view
<% if homework.completed? %>
<%= image_tag "fi-check.svg", class: "homework_student_complete" %>
<% else %>
<%= image_tag "fi-x.svg", class: "homework_student_complete" %>
<% end %>
More information on ActiveRecord::Relation methods at http://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-none-3F
The result of your query can be an ActiveRecord::Relation or an empty array and on both cases the if statement evaluates to true. Try changing your query to:
def completion
homework_students.where("completed_on is null").length == 0
end
your method get_completion is not returning anything. Try this
#homework_student = homework_students.where("completed_on is not null")
return #homework_student
may be it works. Also make sure that the completed_on is not null works correctly.
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
I have two models:
Perfiles
Modulos
And the relationship between them is: Many to Many, there is a table to map relation: modulos_perfiles
I need get all "modulos" that belongs to "perfil".. I have this:
<% #perfiles.each do |perfil| %>
<% #m = perfil.modulo.last %>
<%= #m.ruta %><br/>
<% end %>
but I get this error:
undefined method "ruta" for nil:NilClass
Where "ruta" is a column of "modulo" table.
I made this:
<% #perfiles.each do |perfil| %>
<% #m = perfil.modulo.last %>
<%= debug #m %><br/>
<% end %>
And I can see all attributes of #m object so:
ruby/object:Modulo
attributes:
id: 7
descripcion: Busquedas
ruta: /busquedas
created_at: 2012-11-25 02:23:51.984916000 Z
updated_at: 2012-11-25 02:23:51.984916000 Z
But I don't understand why I cannot get this attributes with:
<%= #m.ruta %>
Any idea?, thanks!
UPDATE
My model classes are:
class Perfil < ActiveRecord::Base
has_many :usuario
has_and_belongs_to_many :modulo
end
class Modulo < ActiveRecord::Base
has_and_belongs_to_many :perfiles
end
class ModulosPerfiles < ActiveRecord::Base
end
**
ANSWER
**
I don't have enough reputation to publish answer.
I've resolved:
I made this:
<% #perfiles.each do |perfil| %>
<% perfil.modulo.each do |modulo| %>
<%= modulo.ruta %><br/>
<% end %>
<% end %>
And so I can get any attribute of object "modulo".
Thanks.
<% #perfiles.each do |perfil| %>
<% perfil.modulo.each do |modulo| %>
<%= modulo.ruta %><br/>
<% end %>
<% end %>
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?
If I have...
class Bunny < ActiveRecord::Base
has_many :carrots
end
...how can I check in the View if #bunny has any carrots? I want to do something like this:
<% if #bunny.carrots? %>
<strong>Yay! Carrots!</strong>
<% for carrot in #bunny.carrots %>
You got a <%=h carrot.color %> carrot!<br />
<% end %>
<% end %>
I know #bunny.carrots? doesn't work -- what would?
<% if #bunny.carrots.any? %>
<strong>Yay! Carrots!</strong>
<% for carrot in #bunny.carrots %>
You got a <%=h carrot.color %> carrot!<br />
<% end %>
<% end %>
unless #bunny.carrots.empty?
would work as well
either:
if #bunny.carrots.length>0
or
unless #bunny.carrots.nil? || #bunny.carrots.length>0
or
if #bunny.carrots.any?
by the way, you will find more operations on collections if you use irb or script/console with require 'irb/completion'
#bunny.carrots is an array, so you can treat it as such by calling array methods on it, e.g. unless #bunny.carrots.empty?