RoR how to find a record backwards - ruby-on-rails

I have a 3 table - users, employees, contacts.
The employees and contacts have a foreign key pointing the the associated user.
Employee belongs_to :user
Contact belongs_to :user
User has many employees, contacts
But, I would like to list the employee name or contact name in the user index view.
Do I need to use a find_by_sql statement?
Thanks,
Dave

You have the belongs_to associations set up already, so you can add the has_one association in your User class for employee and contact, then you can do #user.employee.name or #user.contact.name.
You definitely don't need find_by_sql for this.

In your index view,
<table>
<% #users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= user.employees.map{ |empl| empl.name }.join(", ") %></td>
<td><%= user.contacts.map{ |contact| contact.name }.join(", ") %></td>
</tr>
<% end %>
</table>
The only down side is it will do a query for all the user's employees and all the user's contacts in the loop for user. If the page loads reasonably fast, code it as above, because that's clearer code.

Related

Display results of a query in a table in rails application

I have 3 models as below.
Model for Item
class Item < ApplicationRecord
belongs_to :item_type, :class_name=>ItemType, :foreign_key=>"item_type_id"
end
and Model for Ingredients
class Ingredient < ApplicationRecord
validates_presence_of :ingredient, :message=>"name cannot be blank!"
end
and model for recipe_ingredients
class RecipeIngredient < ApplicationRecord
belongs_to :item, :class_name=>Item, :foreign_key=>"item_id"
belongs_to :ingredient, :class_name=>Ingredient, :foreign_key=>"ingredient_id"
validates_numericality_of :quantity
end
The table for ingredients has following columns
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"ingredient" varchar,
"inventory_unit" varchar,
"recipe_unit" varchar,
"created_at" datetime NOT NULL,
"updated_at" datetime NOT NULL
The view for index of recipe ingredients is as below. The ingredients are appearing in the view. I want to pull recipe unit from ingredients table for the selected ingredient and display it in the table. I have tried it doing a query. The code is as below.
<p id="notice"><%= notice %></p>
<h1>Recipe Ingredients</h1>
<table>
<thead>
<tr>
<th>Item</th>
<th>Ingredient</th>
<th>Quantity</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #recipe_ingredients.each do |recipe_ingredient| %>
<tr>
<td><%= recipe_ingredient.item %></td>
<td><%= recipe_ingredient.ingredient.ingredient %></td>
<td><%= recipe_ingredient.quantity %></td>
<td><%= Ingredient.select('recipe_unit').where(:id => #ingredient_id) %></td>
<td><%= link_to 'Show', recipe_ingredient %></td>
<td><%= link_to 'Edit', edit_recipe_ingredient_path(recipe_ingredient) %></td>
<td><%= link_to 'Destroy', recipe_ingredient, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Recipe Ingredient', new_recipe_ingredient_path %>
But the output I am getting is as shown in image given below.
You can simply type the following:
recipe_ingredient.ingredient.recipe_unit
Why is this possible?
Since a RecipeIngredient belongs_to an Ingredient, you can access the Ingredient of a RecipeIngredient as if it was any other field like this:
recipe_ingredient.ingredient
Once you have the ingredient, you can pull the recipe_unit directly by typing:
recipe_ingredient.ingredient.recipe_unit
Side note:
You can omit the :class_name and :foreign_key hashes from your associativity rules in your model classes. For example, take this class:
class Student < ActiveRecord::Base
belongs_to Course
end
By convention, rails will associate the Student class with the Course class. Rails will look for a column in the "students" database table labeled "course_id", and if "course_id" exists as a column in the table, Rails will automatically use that field as the foreign key for Student. You can use the :foreign_key => 'some_key' notation when you want to override the default conventions in rails (which isn't recommended unless its strictly necessary).
For more reading on the subject of active record migrations and foreign key associations, you can check out the rails docs.
Ok, it's displaying as it is because you are displaying the whole class, not an actual detail of the instance.
In this case below, you are selecting a whole set of Ingredients (the set contains only one ingredient, but it will always return a set):
Ingredient.select('recipe_unit').where(:id => #ingredient_id)
What you probably want is something like this:
Ingredient.find(#ingredient_id).recipe_unit
The differences:
where always returns a set of items (even if there's just one item in the set) What is returned is not an ingredient, but an Active Relation. To just return one ingredient, you need to use find or first (or a similar such method).
select just tells Rails what to pull out of the db... it doesn't tell the template what to display in the template. It says "only fetch the recipe_unit column from the db" it doesn't say and then output therecipe_unitcolumn - for that you need to actually call the recipe_unit method on the ingredient (as in the example I gave).
Note that you have the same problem with recipe_ingredient.item
What column from an item do you want to display? does it have a name or a description if so - you need to actually call that eg:
<%= recipe_ingredient.item.name %>
First of all, you may omit :class_name and :foreign_key from your models because of convention over configuration - your models are named exactly like classes and foreign keys you list.
As for your question, you need to use yak shaving for that:
recipe_ingredient.ingredient.recipe_unit

Get specific item from object

I'm attempting to return the specific hospital name associated to a patient but keep getting errors.
Models:
Hospital
has_many :patients
Patients
belong_to :hospital
When rendering my page I call the controller:
def list_patients
#patients = Patient.all
end
In my view I print out each patient and their information:
<% #patients.each do |patient| %>
<table>
<tr>
<td><%= patient.first_name + "," + patient.last_name %></td>
<td><%= patient.ssn %></td>
<td><%= patient.dob %></td>
<td><%= patient.hospital.name%></td>
</tr>
</table>
The above returns an "undefined method for name". If I remove name I can see that a object (<Hospital:0x007fa1d9530138>)
is returned, but I'm unable to then access the specific attributes within the object.
I can return the specific hospital ID, if I do something like:
patient.hospital_id
but am then stuck on how to get to the hospital name.
Is your code equal to the pasted one?
If so, is belongs_to and not belong_to
If you also can't do Hospital.first.patients in the console, make sure you have a hospital_id in you patient model

Rails printing the value of a database column

I'm new to rails and I have been experimenting. I have to tables companies and contacts and i have set up the associations and relationship. what I would like to do is this.
Currently, in the contacts table it brings back a number for the value of the company name. What I would like instead is the the value of the company name instead of the number. I have tried changing it from the company_id to company_name - but I then get an error about no method being found. Can anyone help on how I do this.
You can delegate to the company
class Contact < ActiveRecord::Base
delegate :name, to: :company, prefix: true
end
<%= #contact.company_name %>
I assume a contact will always belong to a company, if not add, allow_nil: true
If you're looping through them like this:
<% #contacts.each do |contact| %>
<tr>
<td><%= #contact.company_name %></td>
</tr>
<% end %>
I doubt you've defined #contact as you're looping through #contacts calling them contact you want
<% #contacts.each do |contact| %>
<tr>
<td><%= contact.company_name %></td>
</tr>
<% end %>
I.e. without the # - you're using a local variable not an instance variable.

Rails view and pulling data within a loop

<% #blog.blog_comment_types.each do |blog_comment_type| %>
<tr>
<td><%= blog_comment_type.comment_type_id %></td>
<td>Comment name goes here</td>
</tr>
<% end %>
I want to be able to output the comment name based off the comment_type_id.
I an looping through the blog_comment_type table, I want to use the "comment_type_id" column so I can pull from the following table: comment_type which has the name field I want to output. The comment_type table has an id which is the referenced comment_type_id being looped through.
Is there a best practice in Rails to do so within a view?
Tbl: comment_type
fields:
id
name
tbl: blog_comment_type
fields:
id
comment_type_id (this is the matching id in the comment_type table).
Thanks!
In Rails and beyond, the best practice is not to do this in a view. Instead, if you setup your Blog object so it knows about the comment types associated with it, then the problem becomes pretty simple:
class Blog
has_many :blog_comment_types
....
end
then in your view:
<% #blog.blog_comment_types.each do |blog_comment_type| %>
<tr>
<td><%= blog_comment_type.id %></td>
<td><%= blog_comment_type.name %></td>
</tr>
<% end %>

Show name instead of ID in has_many view table

I have tried a couple other similar posts but am still getting an error.
In the Posts model I have a category_id field. I have the following models:
#Posts model
belongs_to :categories
#Category model
has_many :posts
In the Posts index controller I have:
#categories = #posts.Category.find(:all, :order => 'categoryname')
In the View I have:
<% #posts.each do |post| %>
<tr>
<td><%= post.category_id %></td>
<td><%= #categories.categoryname %></td>
<td><%= link_to 'View', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
</tr>
<% end %>
In the 2nd column I am trying to show the category name ("categoryname") from the Category table instead of the category_id from the posts table. I am getting an error:
undefined method `Category' for #ActiveRecord::Relation:0x3e1a9b0>
I have also tried:
<td><%= post.categories.categoryname %></td>
But get the same error.
As well as:
<td><%= post.category.categoryname %></td>
Any suggestions would be greatly appreciated.
In your model
belongs_to :category
In your view
<td><%= post.category.categoryname %></td>
You can get rid of the #categories = line in your controller
Also, categoryname is probably not the best attribute name for your Category model. Why not just name it name. post.category.name seems a lot better than post.category.categoryname, don't you think?
Okay, a couple things
belongs_to :categories
belongs_to is a singular relationship. You should be putting
belongs_to :category
In this case you need category_id in the posts table. You would get the category by
#post.category.categoryname
Unless a post can have many categories, in which case you'd want
#Post
has_and_belongs_to_many :categories
#Category
has_and_belongs_to_many :posts
In this case you need a join table called categories_posts with two fields category_id and post_id and you would get it by calling
#post.categories.each do |cat|
cat.categoryname
end
There are some other problems with you code, like
#categories = #posts.Category.find(:all, :order => 'categoryname')
Category is a model, not your named relationship, which is probably why you are getting the exception in your application.
You will get the following error
undefined method `categoryname' for nil:NilClass on the line: <%= post.category.categoryname %>
if there are records in your table without a category specified.
In other words, make sure all of your records have a category associated with them
i Noticed that #category in your controller starts with a small letter c, but in your view, it starts with a Capital letter !
In your case, if there is a chance that you can have an empty category_id in posts table (as you mentioned in your comment), you can add
if post.category_id?
so your cell will look like this:
<td><%= post.category.categoryname if post.category_id? %></td>
If post.category_id is null it will just show an empty cell.

Resources