Ruby - ActiveRecord belongs_to and nil association - ruby-on-rails

Imagine the following situation:
I have a user model and a user_group model, so:
Class User < ActiveRecord::Base
belongs_to :user_group
end
Class UserGroup < ActiveRecord::Base
has_many :users
end
Now, let say some of the user does not have group. Which mean, when I call:
<% #u.each do |item| %>
<tr>
<td><%= item.id %></td>
<td><%= item.username %></td>
<td><%= item.name %></td>
<td><%= item.user_group.name %></td>
</tr>
<% end %>
It will throw nil. Is there any way nil will be displayed as empty string (somewhat like LEFT JOIN, or DataMapper include_related in CodeIgniter) instead of showing error page?
Right now I am using
<%= item.user_group.name unless item.user_group.nil? %>
to check before calling, but doing that for all view file is somewhat not a good approach.
Thanks in advance!

use try..
class Manufacturer < ActiveRecord::Base
has_many :products
def contact
"Manufacturer has been contacted."
end
end
Product.first.try(:manufacturer).try(:contact)
#=> nil
Product.last.try(:manufacturer).try(:contact)
#=> "Manufacturer has been contacted."

You can use an helper too:
def group_name_for(item)
item.user_group.name unless item.user_group.nil?
end
And call that helper in your views:
<%= group_name_for(item) %>

Related

Rails - error while showing field from class

i want to bring all the resources and then show the 'nombre' field that is from 'curso'. One curso has many resources.( I have all the has_many and belongs_to well configured.)
For that i do the following:
resources_controller:
def index
#resources = Resource.all
end
index.html:
<% #resources.each do |resource| %>
<tr>
<td><%= resource.title %></td>
**<td><%= resource.curso.nombre %></td>**
<td><%= resource.cantidad %></td>
<td><%= link_to 'Show ', resource %></td>
<% else %>
<% end %>
but when i test it, it gives me the following error: "undefined method `nombre' for nil:NilClass"
do you know what can it be?
thanks!
It means that this particular resource is not associated with any of your curso.
If you want to mandate that each resource should be associated with any of your curso while it's creation, you should have this in your Resource model:
class Resource < ActiveRecord::Base
belongs_to :curso
# Validate the presence of curso in every resource.
validates :curso, presence: true
end
class Curso < ActiveRecord::Base
# When any curso is destroyed, all it's associated resources should be gone.
has_many :resources, dependent: :destroy
end
Only in above case, you can ensure that resource always have a curso during it's creation.
Additionally, you can have DB level not null constraint on curso_id field of resources table.
Seems like some resources dont have acurso`.
Just check if the curso exists before calling nombre on it:
<%= resource.curso.nombre if resource.curso %>
or
<%= resource.curso && resource.curso.nombre %>
or
<%= resource.curso.try(:nombre) %>

undefined method operators on legal Postgresql database

I'm beginner, so sorry if i ask for something trivial.
Two tables imed_patient and imed_operator are legal Postgresql tables with relation between them (many patients to one operator by r_opr_code field in imed_patient), described by definitions:
class ImedOperator < ActiveRecord::Base
self.table_name = "imed_operator"
self.primary_key = "code"
belongs_to :ImedPatient
end
class ImedPatient < ActiveRecord::Base
self.table_name = "imed_patient"
self.primary_key = "code"
has_one :ImedOperator, :foreign_key => "r_opr_code"
end
I want to view all patients with data (ex. name, surname) from imed_operator (details of patients), so I produced pacjenci_controller.rb
class PacjenciController < ApplicationController
def index
#patients = ImedPatient.all
#operator = #patients.operators
end
def show
#patient = ImedPatient.find(params[:id])
end
end
In web broweser I receive error :
NoMethodError in PacjenciController#index
undefined method `operators' for #<ImedPatient::ActiveRecord_Relation:0x007fbb269ffe00>
Extracted source (around line #5): #operator = #patient.operators
UPDATE:
my index.html.erb
<h1>Pacjenci w Optimed</h1>
<table>
<tr>
<th>Nazwisko</th>
<th>ImiÄ™</th>
<th>Pesel</th>
<th>Code_operator</th>
<th>Wizyty</th>
<th></th>
<th></th>
</tr>
<% #patients.each do |patient| %>
<tr>
<td><%= link_to #operator.surname, controller: "pacjenci", action: "show", id: patient.r_opr_code %></td>
<td><%= #operator.first_name %></td>
<td><%= #operator.pesel %></td>
<td><%= patient.r_opr_code %></td>
<td><%= link_to 'Wizyty', url_for(action: 'wizytypacjenta', controller: 'wizyty', id: patient.code) %></td>
</tr>
<% end %>
</table>
<br>
<p><%= link_to 'Start', url_for(action: 'index', controller: 'pacjenci') %></p>
<p><%= link_to 'Wstecz', url_for(:back) %></p>
And I stucked :(
ImedPatient has_one ImedOperator, so you need to change
#operator = #patient.operators
to
#operator = #patient.imed_operator
However, I'm not sure you are doing what you want to do. In the index action you are calling ImedPatient.all, so you will get all the records. That's why the variable should be called #patients, not #patient. Then, if you want to get all operators for all the patients, you should use
#operator = #patients.map(&:imed_operator)
If you made a mistake and you actually wanted the #operator in show action it should be:
#operator = #patient.imed_operator
Update: another problem is the has_one declaration. I think it should be:
has_one :imed_operator, :foreign_key => "r_opr_code"
Update 2:
After what you have written in comments it seems that you have confused the association and it should be the other way:
class ImedOperator < ActiveRecord::Base
has_one :imed_patient, foreign_key: 'r_opr_code'
end
class ImedPatient < ActiveRecord::Base
belongs_to :imed_operator , foreign_key: 'r_opr_code'
end
Have a look at: http://guides.rubyonrails.org/association_basics.html#choosing-between-belongs-to-and-has-one

How to save data in database using HABTM in rails 4

I have included
class User < ActiveRecord::Base
has_and_belongs_to_many :subjects
end
class Subjects < ActiveRecord::Base
has_and_belongs_to_many :users
end
I have created one table i.e subjects_users having subject_id and user_id
<% Subject.all.each do |subject| %>
<tr>
<td><%= subject.name %></td>
<td><%= link_to 'Select Subject', final_subject_subject_path(subject) %></td>
</tr>
<% end %>
It goes in controller method:
def final_subject
# now please guide me what I have to write in this so that when select subject is clicked than it will both current_user.id and subject.id in associated table
end
Please help me out in solving this. Thanks in advance
To create subjects for a particular user, you can do it as:
def final_subject
#subject = Subject.find(params[:id)
current_user.subjects << #subject
end

How do I get the table column data from one model into the view of another?

I want the customer name to appear in the customer name column on one of my model view pages, but I can't seem to figure out how to do this.
Here are my associations:
Customer Model is -
class Customer < ActiveRecord::Base
has_many :appointments, :dependent => :destroy, :as => :customer
has_many :birds, :dependent => :destroy, :as => :customer
end
Bird Model is -
class Bird < ActiveRecord::Base
belongs_to :customer
has_one :appointment
end
I've also added this to the Bird model index view -
<tbody>
<% #birds.each do |bird| %>
<tr data-link="<%= bird_path(bird) %>">
<td><%= bird.customer_id %></td>
<td><%= bird.name %></td>
<td><%= bird.breed %></td>
<td><%= bird.color %></td>
<td><%= bird.age %></td>
</tr>
<% end %>
The customer parameter I'd like to pass into the customer name column on the birds index view page is customer.name, or :name. If I try that, I get an undefined methods error on my /birds page.
Thanks!
I would expect that this should work:
<%= bird.customer.name %>
Or - if you have birds without an customer - you might want avoid exceptions like this:
<%= bird.customer.try(:name) %>
Or - less error prone - add the following to your bird model:
delegate :name, to: :customer, allow_nil: true, prefix: true
And use it in your views like this:
<%= bird.customer_name %>
You need to use in your view like this :
<%= bird.customer.name %>
In your controller, for the bird index page:
when you query for Bird.all, do Bird.all.includes(:customer)
then you will have access to <%= bird.customer.name %> in the view

Rails table joins

I'm trying to figure out how to do a table join in one of my models.
There are points, questions, and users.
point.rb
class Point < ActiveRecord::Base
belongs_to :user
belongs_to :question
end
question.rb
class Question < ActiveRecord::Base
has_many :points
end
user.rb
class User < ActiveRecord::Base
In my Points controller I am doing this:
def index
#points = Point.all
#user_points = Point.where('user_id' => current_user)
end
And in my points/index view:
<% #user_points.each do |user_point| %>
<tr>
<td><%= current_user.name %></td>
<td><%= user_point.question_id %></td>
<td><%= user_point.correct_answer %></td>
<td><%= user_point.user_answer %></td>
</tr>
<% end %>
I need to access the name of each question in the questions table (I have the question id available in my view. I'm a n00b to rails, and can't figure out how to this with the documentation.
If you read my previous answer ignore it. I misread your question. This should work.
In your view:
<% user_points.questions.each do |question| %>
...Do whatever...
<% end %>
Take a look at the Rails Guides, especially these two:
http://guides.rubyonrails.org/association_basics.html
http://guides.rubyonrails.org/active_record_querying.html
I think you should be able to set this in your model:
class User < ActiveRecord::Base
has_many :points, :through => :questions
end
in your controller say #user_points = current_user.points
in your view. This should already work with your current code!
<% #user_points.each do |user_point| %>
<td><%= user_point.question.name %></td>
<% end %>

Resources