Rails activerecord associations - mysql

I apologize for a beginner question, but I'm trying to wrap my head around ActiveRecord associations for the project I'm trying to start.
I'm beginning to expand my knowledge in Rails and I'm a bit confused with the available ActiveRecord associations, that is which one should I pick and how to structure the models.
This is the general concept:
You would first define a Company - that is the first part of the tree
Secondly, you need to define the Departments. They should belong to the Company in question, and have a simple name and description.
And finally - Employees - each employee can be in one Department and fall under one Company.
What I'm looking is the best way to create the models for Company, Departments and Employees, so I can assign Employees to the correct Company and Department.
If you could point me to the right direction, book or tutorial/article to ease up these database table joins in my head and pick the right route for the project!
Any help is appreciated!

Seems straight forward.
Your Company model should show the following:
has_many :departments
has_many :employees
One could argue you could change the employees to a "has_many :employees, through: :departments". I don't suspect it matters too greatly.
Your Department model should have:
belongs_to :company
has_many :employees
Your Employee model should have:
belongs_to :company
belongs_to :department
You don't technically need the company line if you use the through departments for that relationship. But if you do this you can then run things like:
Employee.first.company
Employee.first.department
Department.first.business
Department.first.employees.first (notice this is plural as it's has_many)
Company.first.employees.first (will work if you have a through or if you assign it directly)
Company.first.departments.first
A "belongs_to" relationship means the model declaring it holds a foreign key for the model it belongs to. So, Department belongs_to Company. Thus, :company_id is created inside Department when you type, say, rails generate model Department company:references....etc.
In the example above, your Employee will have a :department_id and a :company_id, though, again, you may skip the company one and just declare it as a through and you will look up your employees through the departments they are in.
You could, in theory, also use a has_one instead of a belongs_to for employee. But I find those harder to work with.

Related

How to order by relationship when the related table has an alias

We have a table called Client and client belongs to a user in two ways, a client can have an updater and has a creator. It also belongs to a company.
belongs_to :creator, class_name: 'User'
belongs_to :updater, class_name: 'User'
I am trying to grab all clients for the current parent object company they belong to and then order them alphabetically by the name of their creator
Here is what I currently have tried
current_company.clients.includes(:creator).order("creator.name #{sort_dir}")
If I put :user in the includes it throws an error that user is not on the table.
Association named 'user' was not found on Client;
This was the closest I was able to get with what I found online.
The easiest way to see how the query looks like is to call .to_sql.
You will see that when the join is performed it uses the table name, users, instead of the relation name, creator.
This should work:
current_company.clients.includes(:creator).order("users.name #{sort_dir}")

Optional relation between two model objects in rails

I have two objects A and B in my Rails model which have an optional one-to-one relationship. Say, A can have 0 or 1 B. In most cases A has 0 Bs.
Also, other such relationships can be introduced between A and other objects X, Y, Z later.
Given that these are one-to-one relations, a has-a relationship between A and B makes sense. But given that it is an optional and infrequent relationship, and also that other such relationships can be introduced later with A, adding a new column for each new relationship seems questionable.
How can I model this relationship better? Should using a correlation table between A and B make better sense in this particular case?
You would add the id of Model A to all the other models, and Model A would has_one for each of them.
Each other would belong_to Model A
I would go with the presented solution, that is adding a new column b_id to A.
Else you could create a third model C which holds both a_id and b_id and then have A access B through C.
# Pluralization is off here. Remember to pluralize has_many
class A < ActiveRecord::Base
has_many :c
has_many :b, through: :c
end
class B < ActiveRecord::Base
has_many :c
has_many :a, through: :c
end
class C < ActiveRecord::Base
belongs_to :a
belongs_to :b
end
This would prevent any null values in the database. This is the solution I use most often when I will build something around the relation, since now you have a place to store more information about the relation.
You could also make C polymorphic so that it can store any model (not only A). http://guides.rubyonrails.org/association_basics.html#polymorphic-associations

Relationship with many to many

I am trying to get a basic rails application running that helps capture the nutritional information of each food item from a list of food items. The nutritional information is stored per ingredient and calculated as the sum of individual ingredients.
Here is what I have so far:
Have two models Food and Ingredient. Each Food has many Ingredients and each Ingredient is used in many Food. The way I want to fix this is to break up the many-to-many with a table in between say Recipe which has the pk of Food and pk Ingredient. But my problem is that a Recipe can have many ingredients and an ingredient has many recipes. How do i split these two tables the best way so I can capture a food item and its list of ingredients? Or is there a better way to do the whole thing?
Say for the purposes of example Food has name, description and Ingredient has name, calories, nutrients.
You need has_many_through association.
You will organize like:
class Food < ActiveRecord::Base
has_many :recipes
has_many :ingredients,
through: :recipes
end
class Ingredient < ActiveRecord::Base
has_many :recipes
has_many :foods,
through: :recipes
end
class Recipe < ActiveRecord::Base
belongs_to :food
belongs_to :ingredient
end
This way, you can store additional info inside Recipe

Modeling my Database

this is my first post on here. My question is pertaining to model relationships.
I'm new to rails and a bit confused as to what type of associations I need. I checked rails associations but this confused me more. I've tried quite a few things and can't figure out exactly what I need.
I have three models/tables:
Students
Teachers
Groups (as in classes)
I have it setup as:
teacher -> belongs_to :group
student -> belongs_to :group
group -> has_many :students & has_many :teachers
This setup works okay because it allows me to make calls like:
g.students.all
s.group.name
However I would like to be able to make a view page that generates all of the Groups(classes) that a teacher has. Such as: t.groups.all or t.groups.count
One thing that makes my table unique is that a group(class) can have different teachers. I don't know if I need a has_and_belongs_to_many relationship or a has_many :through relationship.
What is the ideal setup for my 3 tables, what table id's and associations are required?

How to create a model with multiple tables in Rails?

In my Rails application I am linking into a MySQL database from the legacy PHP application. The naming conventions are incorrect, so am making use of self.table_name to connect models to their respective tables.
I have a requirement to show information from multiple tables into one resource. All these tables have the same column structure. Can I create a model that pulls information from each of these tables? How do I do that? I have been playing around with find_by_sql but am yet to have any success
EDIT: This is all to be read only, no updating is required.
From your question I believe you are planning to load a other models from one particular model. My suggest is to use a polymorphic relationship.
class MainModel
has_many :sub_model, polymorphic: true
end
class Item1
belong_to :main_model, as: :sub_model
end
class Item2
belong_to :main_model, as: :sub_model
end
Now in the view you will have to write your data as follows.
#main_model.sub_model.name | #main_model.sub_model.value
Since all the other models/tables has the same structure you won't have to change the attribute.
And when updating it, you just accept the values of the sub_models as a nested attribute and they will update the corresponding model.
For more details on how to setup a polymorphic relationship visit Setting up a polymorphic association