Ruby on rails NoMethodError active record - ruby-on-rails

I have these models
class Auto < ApplicationRecord
belongs_to :marca
belongs_to :modelo
belongs_to :cliente
end
class Cliente < ApplicationRecord
has_many :autos
end
class Marca < ApplicationRecord
has_many :modelos
has_many :autos
end
class Modelo < ApplicationRecord
belongs_to :marca
has_many :autos
end
and this index view
<table class="table table-striped" id="autos">
<tr>
<th>Id</th>
<th>Cliente</th>
<th>Marca</th>
<th>Modelo</th>
<th>Placas</th>
</tr>
<% #auto.each do |auto| %>
<tr>
<td><%= auto.id %></td>
<td><%= auto.cliente.nombre %></td>
<td><%= auto.marca.nombre%></td>
<td><%= auto.modelo.nombre %></td>
<td><%= auto.placas %></td>
</tr>
<% end %>
</table>
and this in my autos controller
def show
#auto = Auto.find(params[:id])
end
def index
#auto = Auto.all
end
the problem is that show me this error:
undefined method `nombre' for nil:NilClass in this line:
<td><%= auto.cliente.nombre %></td>
rarely at show view where I call
#auto.cliente.nombre
works fine, can you help me? thanks

It seems like <td><%= auto.cliente.nombre %></td> doesn't work because auto.cliente is nil, and you cannot call that method nombre on nil. Perhaps one of your auto objects doesn't have an associated client?
To see how this happens, try running nil.hello in Ruby and you should see a NoMethodError with the error message undefined method 'hello' for nil:NilClass.

auto.cliente.try(:nombre) will save you from error if you by chance allow auto without cliente.

Related

Rails How to access different DB table in a view

I am new to Ruby and RubyOnRails. I have been following a basic Rails tutorial thus far and have created several views and controllers to be able to perform basic CRUD on my MySQL DB, each one is specific to tables in the DB.
I started a new view, and I want to be able to display info from two separate tables. I want to be able to grab the Customers Name for their contract. I feel like this is an easy and common fix, What the heck am I overlooking?
Contract View
<table>
<tr>
<th>Contract ID</th>
<th>Customer ID</th>
<th>Discount</th>
<th>Start Date</th>
<th>End Date</th>
<th>Payment Terms</th>
<th>Delivery Day Of Week</th>
<th>Employee ID</th>
<th>Note</th>
<th>Commission</th>
<th>Active</th>
</tr>
<% #contracts.each do |contract| %>
<tr>
<td><%= contract.ContractID %></td>
<td><%= contract.CustomerID %></td>
<td><%= contract.fields_for :customer do |w| %>
<%= w.text_field :CustomerName %>
<% end %>
</td>
<td><%= contract.Discount %></td>
<td><%= contract.StartDate %></td>
<td><%= contract.EndDate %></td>
<td><%= contract.PaymentTerms %></td>
<td><%= contract.DeliveryDayOfWeek %></td>
<td><%= contract.EmployeeID %></td>
<td><%= contract.Note %></td>
<td><%= contract.Commission %></td>
<td><%= contract.Active %></td>
</tr>
<% end %>
</table>
Contract Model
> class Contract < ApplicationRecord belongs_to :customer
>
> accepts_nested_attributes_for :customer
> #Validation
>
>
> #Mapping this object to the Database tables self.table_name = "contract" self.primary_key = "ContractID" end
Customer Model
> class Customer < ApplicationRecord
>
> has_many :contracts
>
> #Validation validates :CustomerID, :CustomerTypeID, presence: true
>
> validates :CustomerID, uniqueness: true
>
> #Mapping this object to the Database tables self.table_name = "customer" self.primary_key = "CustomerID"
>
> end
Contracts Controller
class ContractsController < ApplicationController
def index
#contracts = Contract.all
#customers = Customer.all
end
end
Since you've already defined that a Customer may have many contracts then you need now to define that that Contract belongs to a customer, so, modifying your models they should look like:
class Contract < ApplicationRecord
belongs_to :customer
...
end
class Customer < ApplicationRecord
has_many :contracts
...
end
Now you're able to access the customer name attribute from a certain contract, like:
<% #contracts.each do |contract| %>
<%= contract.customer.name %>
<% end %>
This should work on getting the customer name, but for improving that query, you might add an includes on the index action:
def index
#contracts = Contract.includes(:customer).all
...
end

Rails association loop display same primary key in row

I have a loop using associations. I'm looking to group by treatment and display in a row.
Each loop has three records for each treatment. The code below this is what i'm producing.
VIEW
<table>
<tr>
<td>Treatment</td>
<td>Date</td>
<td>Count</td>
</tr>
<% #trial.establishmentMethods.order(:treatment_selection_id).each do |data| %>
<tr>
<td><%= data.treatmentSelection.treatment.name %></td> This is reference by treatment_selection_id.
<td><%= data.date %></td>
<td><%= data.count %></td>
</tr>
<% end %>
</table>
This is what i'm hoping to produce. Display the treatment once, then loop the related treatment_selection_id's on the same row.
Here are my models and associations.
class Trial < ApplicationRecord
has_many :assessments, primary_key: 'trial_id'
has_many :establishmentMethods, through: :assessments
end
class EstablishmentMethod < ApplicationRecord
belongs_to :treatmentSelection, primary_key: 'treatment_selection_id', foreign_key: 'treatment_selection_id'
has_many :treatments, through: :treatmentSelection
end
class TreatmentSelection < ApplicationRecord
belongs_to :treatment, primary_key: 'treatment_id'
end
It seems like TreatmentSelection has_many establishmentMethods, so you should add that to the TreatmentSelection model. Then you can do something like:
<% treatment_selections.each do |treatment_selection| %>
<tr>
<td><%= treatment_selection.treatment.name %></td>
<% treatment_selection.establishmentMethods.each do |em| %>
<td><%= em.date %></td>
<td><%= em.count %></td>
<% end %>
</tr>
<% end %>
By the way, it's convention to use snake_case in ruby and it will make using associations easier.

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

Implement order pages with rails

I wanna implement a order page, but it's so hard...
The system is in portugues, for others reasons, sorry about this.
My view:
conta/pedidos/index.html.erb
<h3>Meus pedidos</h3>
<table>
<thead>
<th>#</th>
<th>Data do pedido</th>
</thead>
<tbody>
<% #pedidos.each do |pedido| %>
<tr>
<td><%= link_to pedido.id, pedido_path(pedido.token) %></td>
<td><%= pedido.create_at.to_s(:long) %></td>
</tr>
<% end %>
</tbody>
</table>
My controller:
conta/pedidos_controller.rb
class Conta::PedidosController < ApplicationController
before_action :authenticate_usuario!
def index
#pedidos = current_usuario.pedidos.order("id DESC")
end
end
My model:
pedido.rb
class Pedido < ActiveRecord::Base
belongs_to :pessoa
has_many :itens, class_name: "ItemPedido" , dependent: :destroy
accepts_nested_attributes_for :enderecos
before_create :gerar_token
def gerar_token
self.token = SecureRandom.uuid
end
end
And the error:
ArgumentError in Conta::PedidosController#index
No association found for name `enderecos'. Has it been defined yet?
Please, what I make?
I'm not sure why do you have accepts_nested_attributes_for :enderecos in pedido.rb. It's not mentioned anywhere in the provided code. Can you simple comment/remove it?
If it's need, then you need to set association for it: may be has_many :enderecos

Ruby - ActiveRecord belongs_to and nil association

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) %>

Resources