Rails How to access different DB table in a view - ruby-on-rails

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

Related

Ruby on rails NoMethodError active record

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.

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.

How to use has_many fields in views, rails?

Frnds I am new to rails, here i created two tables caleed stocks and stock_availabilities.
in the stock model
class Stock < ActiveRecord::Base
belongs_to :projects_lkp
has_many :stock_availabilities
validates_presence_of :item
end
In the stock_availabilities model
class StockAvailability < ActiveRecord::Base
belongs_to :stock
validates_presence_of :qty,:add_or_issue,:price, :captured_at, :stock_id,:unit
end
Now my doubt is how to bring the field of stock_availabilties in the views of stock
<% #stock.each do |d| %>
<tr>
<td><%= d.item %></td>
"Here i need to print the values of qty and pricevwhich is in stock_availabilities class"?
</tr>
You are on the right track.
this is what you need:
<% #stock.each do |d| %>
<tr>
<td><%= d.item %></td>
<% d.stock_availabilities.each do |sAV| %>
<td> <%= sAV.qty %> </td>
... <-- You do the other ones here
<% end %>
</tr>

Rails children not rendering p

I have a model called Task Order that has_many Invoices. When I click "Show" for a Task Order, it is supposed to show all of the Invoices that belong to that Task Order. However, when I click "Show" it shows ALL of the invoices, even ones that do not belong to that task order. Note that I have the same relationship and views for my Contract/Task Order, but it is working correctly so I am not sure where I went wrong.
Here is my Task Order model:
class TaskOrder < ActiveRecord::Base
belongs_to :contract
has_many :invoices, :dependent => :destroy
validates_presence_of :id
validates_uniqueness_of :id
self.primary_key = :id
end
Here is my Invoice model
class Invoice < ActiveRecord::Base
belongs_to :task_order
validates_presence_of :task_order_id
end
Here is my views/task_orders/show code
Invoices:
<table>
<thead>
<tr>
<th>Invoice Date</th>
<th>Invoice #</th>
<th>PoP</th>
<th>Amount</th>
<th>Description</th>
<th>Invoice TO</th>
<th></th>
<th></th>
</tr>
</thead>
</tr>
<tbody>
<% #invoices.each do |invoice| %>
<tr>
<td><%= invoice.invoiceDate%></td>
<td><%= invoice.invoiceNumber %></td>
<td><%= invoice.PoP %></td>
<td><%= number_to_currency(invoice.amount) %></td>
<td><%= invoice.description %></td>
<td><%= invoice.task_order_id %></td>
<td><%= link_to 'Show', invoice %></td>
<td><%= link_to 'Edit', edit_invoice_path(invoice) %></td>
<td><%= link_to 'Destroy', invoice, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
And here is my Task Order controller:
def show
#invoices = Invoice.all
end
def index
#task_orders = TaskOrder.all
end
In your show method, you just want to get only the task order's invoices, rather than all invoices, which you are currently getting.
def show
#task_order = TaskOrder.find(params[:id])
#invoices = #task_order.invoices
end
This way, you don't need to change your show.html.erb file. In addition, you should take a look at the Rails Guides, which should aid you in your quest to learn Rails.

Rails 3: How to move code from view to controller (or model)?

I have this in the index view:
<% #submissions.each do |submission| %>
<tr>
<td><%= submission.id %></td>
<td><%= User.find_by_id(submission.user_id).name.to_s %></td>
</tr>
<% end %>
I know I am not supposed to use find_by in the view.
How can I move this to the controller (or model)?
I tried to insert this in the index method of my submission controller and using the username variable but it doesn't work.
def index
#submissions = Submission.all
#submissions.each do |submission|
username = User.find_by_id(submission.user_id).name.to_s
end
end
Model, add relation to user
class Submission
belongs_to :user
end
Controller, eager load users to avoid N+1 queries.
def index
#submissions = Submission.includes(:user).all
end
View, just project the user from each submission
<% #submissions.each do |submission| %>
<tr>
<td><%= submission.id %></td>
<td><%= submission.user.name.to_s %></td>
</tr>
<% end %>
#in controller
def index
#submissions = Submission.all
end
#in view
<% #submissions.each do |submission| %>
<tr>
<td><%= submission.id %></td>
<td><%= submission.user.name %></td>
</tr>
<% end %>
This code implies you have declared the following relations:
Submission belongs_to :user
User has_many :submissions (or has_one)
You can use eager loading (uses less queries to the DB) to improve the previous code:
#submissions = Submission.includes(:user).all
You can use an ActiveRecord association:
class Submission
belongs_to :user
# etc
end
Then in your view:
<td><%= submission.id %></td>
<td><%= submission.user.first_name</td> <!-- or whatever -->

Resources