Review model - shared across two different other models - ruby-on-rails

I am making an application that lets people list food items that they want to sell. They list Dishes (Dish model) and when people buy it, an Order record is created.
I want people to be able to submit reviews on Dishes if they have purchased it, and also review the Order (the order involves meeting the person).
I was wondering if I could create an Review model as follows:
class Review < ActiveRecord::Base
belongs_to :dish
belongs_to :order
end
I feel like this isn't right. The reviews on Dishes and the reviews on Orders will have different fields and potentially a completely different kind of logic, but at the same point in time its the same "idea" so I thought it would be better to create only one model for it.
Is the above correct?
Thanks

This is the use case that single table inheritance (STI) was designed for. When most of the values are shared between two models, STI can let you inherit both of them from another model. E.g.:
class Review < ActiveRecord::Base; end
class DishReview < Review
belongs_to :dish
end
class OrderReview < Review
belongs_to :order
end
You then store the review type in a new type column, and ActiveRecord handles storing them both in the same reviews table. The reviews table will need foreign keys for both a dish and an order.
If these review types may diverge much ... say you want to add spicyness and sweetness, etc. to dish reviews, and speed and friendliness, etc., to the order reviews ... then it makes more sense to start with separate tables, one for DishReview and another for OrderReview. You can then use modules, services, concerns, etc., to share logic between them. You can also store common data in the Review table and have DishReview and OrderReview link one-to-one with that.

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

Cannot understand has_one relation

I have some problems understanding the has_one relation.
I have two models Planning and Sport. A Planning is concerned by one Sport and a Sport can be found in many Plannings. So I defined my Planning this way:
class Planning
...
has_one :sport
...
end
And I didn't add anything in Sport regarding the Planning.
In my mind, this would allow me to access planning.sport but I don't mind if I can't find sport.plannings (which makes no sense).
The problem is that when I try to create a new Planning using my ActiveAdmin interface, I have the following error as soon as I try to access the plannings/new page:
undefined method `planning_id' for #<Planning:0x30d8570>
What I understand is that it checks in Sport that a planning_id exists, but my understanding was that there was just a sport_id in the Planning, not the opposite...
What did I do wrong? Do I need to use an intermediary model? Is this jsut linked to ActiveAdmin?
Thanks!
What you need is
class Planning
...
belongs_to :sport
...
end
class Sport
has_many: plannings
end
You can think of it like, whoever has the foreign key is like the child. So here planning has the foreign key of sport. So it is a child of Sport and it belongs to sport.

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

Rails active record model relationship - one model belonging to three models

I have situation where a single model needs to have three foreign ids. This table has the information which belongs to three models.
e.g. -
Three models - Keyboard, Mouse, Monitor
Now i have fourth model details - which has information about what will happen for any combination like keyboard1, mouse1 and monitor1.
So what should be good design pattern for this ?
Right now what i use is Detail.find_by_keyboard_id_and_mouse_id_and_monitor_id(keyboard1id, mouse1id, monitor1id) #=> Detail1
Which of course is not a best way to go...
I don't think what you have is a bad design. There probably aren't too many options for how this should be implemented, but you should think about how you want to use it. Personally, I wouldn't call the model Detail since it doesn't tell you anything about what the model really is. Something like HardwareConfiguration is more explicit. Maybe too lengthy, but you could shorten it to HardwareConfig or Configuration, depending on your taste.
This model should have an id and the three foreign keys. You should add database indexes to each foreign key field as well.
class Detail < ActiveRecord::Base
belongs_to :keyboard
belongs_to :mouse
belongs_to :monitor
end
Then each hardware model would have_many :details like:
class Keyboard < ActiveRecord::Base
has_many :details
end
You could look up the detail combo by its ID, or any combination of foreign keys.
Detail.find(id)
Detail.find_all_by_keyboard_id(keyboard_id)

Rails: Relationship between two loosely related models

I am working on a Ruby on Rails 3 web application and am not sure how to relate two of the models.
In our organization sales reps go out on appointments. If the appointment is successful, it will result in creating an order (which then has the items ordered related to it, but that's for another day.) If this appointment is not successful, it will be marked as no sale and as you might have guessed, no order is created.
On the other hand, sometimes sales happen without an appointment. For example, a customer may call into the store and order something. In this case, an order can exist without an appointment.
It would be simple if there were no relationship between orders and appointments, but there has to be for ease of use for the end user. For example, if an appointment generates an order, but later the buyer cancels, they will mark the appointment as sale cancelled and then the system should automatically set the order as cancelled. Likewise,they may choose to cancel the order, then the appointment would have to be cancelled automatically by the system.
How does a developer handle something like this? Does the appointment :have_many => orders? does the order :belong_to => appointments? I don't know what to do!
Please help me with this, I am a pretty new rails developer and I feel in over my head! Thank you!
As you already said, the following will work fine:
class Appointment < ActiveRecord::Base
has_many :orders
end
class Order < ActiveRecord::Base
belongs_to :appointment
end
belongs_to requires the field appointment_id to be present in the orders table. But, if the order is not associated with an order then appointment_id does not need to be set. You can have multiple belongs_to associations for a given class.

Resources