Proper Rails Association for this setup - ruby-on-rails

Just starting out with rails and I have a question. My grasp on associations is weak.
Lets say I have a model Cars
some cars will be rentals and some will not. So I created a table and a model called Rentals
which just has the car_id in it, designating that at car_id is a rental.
Right now I have a belong_to :cars line in my Rental model. And I'm not sure that's right. I am attempting to get a list of all the rentals easily. So grabbing the car_ids from the rental table and getting all the car information from the cars table the most efficient way.
Can someone help out?

The following:
Car.joins(:rentals).all # try with :rental if not working
Will output all the cars that have a rental object associated with ;)

It depends on what you will exactly need to do with it.
For simplicity, this is how I would do it.
class CarType #better than Rentals and more meaningful [:type => [rental, lease, own]]
belongs_to :car
end
class Car
has_one :car_type
end
So, now for the cars table, it will have a car_type_id pointing to the type in car_types table.

Related

Is many-to-many association still apply here?

When an entity isn't associated with many other entity at the same time, should I still use many-to-many association?
For example, I understand that Author-Book relationship is a many to many, An author can write many books, a book can be written by many authors. This holds for all time.
Consider this situation. A Batch has many students at one particular time. If a student fails, he should move to the next junior batch. In other word, A student cannot belong to more than one batch at the same time. In this case, is this a many to many association?
Alternative Solution I thought:
I was thinking about putting two columns in students table. initial_batch and current_batch. I can get the student's Batch history, by checking the gaps between current and initial batch, because of the rule A student must drop to the next immediate batch. Also, batch.students exists with a has_many association in rails. So, I think that would not be a big deal.
By Batch, I mean batch of students get admitted in the same year.
I think you'd still want to use an association table (many-to-many association) because you might want to keep a history of which classes the student has taken.
If you want it to be a many-to-one and have a student belong to one class at a time, you'd have to add a class_id field to your student table. This allows you to call student.class to find their current class, but you wouldn't be able to do class.students because that relation doesn't exist. For this reason, I think it should be a many-to-many.
is this a many to many association
Yep.
An ActiveRecord association is simply a way for you to create two connected objects (ActiveRecord is an ORM -- Object Relationship Mapper).
Remember, as Ruby is object orientated, each "Model" (class) is counted as an object, invoked every time you want to populate it with data. Each ActiveRecord association for each object is accessed through a method in the object...
#app/models/student.rb
class Student < ActiveRecord::Base
has_many :subjects #-> AR appends the "subjects" method to your Student object
end
Simply, this means that even if you have the functionality for a number of different objects, you don't need to have the method populated with data.
If you have the following...
#app/models/student.rb
class Student < ActiveRecord::Base
has_and_belongs_to_many :subjects
end
#app/models/subject.rb # "class" is a reserved word
class Subject < ActiveRecord::Base
has_and_belongs_to_many :students
end
This simply provides the functionality / capacity for #students.subjects etc.
What's contained inside this method is up to you to determine:
<% if #students.subjects.any? %>
<% #students.subjects.each do |subject| %>
...
<% end %>
<% end %>

User Model with Listings Rails - How to reach?

I have a Boat Model and its Models such as Brand, Model and Year. I have also User model and I would like to connect them by adding migrations to User model of boat_id and I added belongs_to :boat and has_many :boats to User model. But I can not reach User.first.boat.name from the console even though I am able to reach Boat.first.brand.name.
When I try User.first.boat.name. Console gives an error saying;
NoMethodError: undefined method `boat' for #<User:0x0000000665dc30>
Btw: Boat Model includes model_id brand_id and year_id.
EDIT1:
Or should i remove Boat model and add model_id brand_id and year_id to User model directly.
EDIT2:
I would like to be able to reach User.first.boat.brand.name or User.first.boat.year.nameor User.first.boat.model.name
EDIT3:
Every boat has one brand, year and model. But user can have many boats
EDIT4:
What i will do is;
User can sign up and login
Then User press the link list my boat.
He/she saves the boat then the page renders to User Profile
In the User profile I do not know how to get current user boat name year etc. That is why I am confused. Sorry for the misunderstanding
I think you're confused about how Rails associations work in conjunction with how they are stored in the database. If a User can have many boats, then the foreign key needs to be on the boats table. Currently you have boat_id in the users table, this should be removed and a user_id column needs to be added to the boats table as per Matt's answer.
Reference
To achieve what you're trying to do, you'll need to setup your models in the following manner:
class User
has_many :boats
...
end
class Boat
belongs_to :user # table has a user_id column
...
end
Then you can access a boat's brand using user.boats.first.brand.name
Run rails generate migration, then fill in the change method as follows:
def change
add_column :boats, :user_id, :integer
end
Then run rake db:migrate.
You user model has_many boats, so you need the boats table to refer to users. It's probably worth reading the Rails guide for ActiveRecord associations to get a better feel for how this works: http://guides.rubyonrails.org/association_basics.html#the-has-many-association

Count only datasets that are associated through HABTM

I have two models with a HABTM associaton called LegacyDatum and Category Now I want to count how many Objects of LegacyDatum are associated with one or more categories. When I call LegacyDatum.joins(:categories) that works but it also returns the datasets with no category. How can I only get the datasets that have at least one category associated?
The Model is really simple, no unconventional associations...
LegacyDatum:
class LegacyDatum < ActiveRecord::Base
has_and_belongs_to_many :categories
.....
....
...
end
I believe it's because all is loading everything before the joins method is called. What do you get if you drop the all portion, or tack it on the end instead?

Newbie: access attributes of model object

I have two model classes: Cars and Customers,
Model Cars:
class car < ActiveRecord::Base
#car has attribute :town_code
has_many :customers
end
Model Customers:
class customer < ActiveRecord::Base
# customer has attribute :first_name, :last_name
belongs_to :car
end
In my controller, I have the following code:
my_customer = Customer.find_all_by_first_name('John')
p my_customer.last_name
p my_customer.car_id
But I got no attribute 'car_id' error, I also got no attribute 'last_name' error.
---Question 1:---
I checked my database, I do have 'car_id' and 'last_name' columns on my customer table. Why I can not access them in the way how my controller code does?
---Question 2:---
but the code : my_customer.map(&:car_id) is working for accessing car_id, however, I do not quite understand the code .map(&:car_id), what does it do? Can anyone explains to me?
The reason you aren't able to do my_customer.last_name is that my_customer is not a Customer here but an array of Customers, since you did find_all. That's also why my_customer.map(&:car_id) works. What that bit of code means is: For each object in the array my_customer, call the method car_id and insert the results into a new array -- and return that new array.
If customer belongs to car, you need a car_id in the customer table (which corresponds to an id column in the car table). Also, you shouldn't have last_name in the car table, but rather in the customer table.
It sounds like you may need to step back and gain a better understanding of ActiveRecord associations. It's not clear to me why a customer would belong_to a car, anyway.

Structure movie lists

I'm trying to set up a proper database-design, but I'm stuck.
Here is what I'm trying to save.
Every user can define a vote history list from imdb looking like this.
Two users can define the same list.
First I want to be able to save each list as an imdb_vote_history_list - list.
class ImdbVoteHistoryList < ActiveRecord::Base
has_and_belongs_to_many :vote_history_list
has_and_belongs_to_many :movies
# Fields
# id (Integer) - defined by the user
end
Each list should be unique and is being defined by it's ID (given in the link).
Each list has and belongs to many movies, as in the code above.
Each user should be able to pick a name for every list.
So instead of saying
Each imdb_vote_history_list belongs_to user
I create a new relation called vote_history_list.
class VoteHistoryList < ActiveRecord::Base
has_and_belongs_to_many :imdb_vote_history_lists
belongs_to :user
# Fields
# name (String)
end
Here the user can pick any name for the list, without interference with other user's names.
Is this a good way to store the data?
From the theoretical database design view this is the right approach.
For example the entity relationship model describes it this way. You can have relationships between entities and attributes at those relationships. If you map those to a relational model (database tables) you get a table for the relationship containing references to both entites and all additional information.
This is what theory can tell us about it :)

Resources