rails rich join model controller example - ruby-on-rails

I have been reading up on some rails stuff and one thing I never came across is an example of what the controller or the view pages of a rich join model looks like.
Is it general practice not to have a controller/view pages off of those models?
Does anyone have any code example of the controller/view for a rich join?
edit: defining rich join.
Model A
has_many :model_c
has_many :model_b, :through => model_c
Model B
has_many :model_c
has_many :model_a, :through => model_c
Model C
belongs_to :model_a
belongs_to :model_b
I am curious to see how the controller of model C looks like given it's a join model between model A and B. For example, when you need to create a new Model C page, how do you retrieve and store the values for model_a.id and model_b.id so that it's all connected.

Ok, so I can give you my personal opinion of this and that is "it depends". :)
I've seen projects where there is a full scaffold for the join-model, and I've seen projects where there's none. Generally the difference is in how important the join-model is. if there's only, like, one or two extra columns on it - and they're generally only displayed on, say, the user's profile page, then don't bother. But if the join-model really is richly decorated... well it's really a whole model in its own right - and deserves a full scaffolding to cover that.
Sometimes there's a full scaffolding but only from certain perspectives.
A good example of the latter might be where you have models A&B be "user" and "service" and model C as "subscriptions".
In some situations, users can only see a list of services, and a list of their own subscriptions to them... and a service could only see a list of subscribed users... and admins could see all of them.
so... it depends :)

Related

Model which belongs_to can be several models?

This is the situation that I have now:
Adword has_many pages
page belongs_to Adword
Right now I want to place another Ad provider, and that will also generate pages. So, ideally I want somehow to say something like (this is where I am lost):
AdProvider has_many pages
page belongs_to AdProvider
Where AdProvider could be Adwords, X, Y - What is the correct way to approach this kind of situations in Rails? RIght now I just have a adword_id attribute in Page, but there will be pages which are not associated to Adword but to another Ad provider.
Use Polymorphic association.
From the doc:
With polymorphic associations, a model can belong to more than one
other model, on a single association. For example, you might have a
picture model that belongs to either an employee model or a product
model.
I use Single Table Inheritance (STI) when I want to accomplish this.
"STI should be considered when dealing with model classes that share much of the same functionality and data fields, but you as the developer may want more granular control over extending or adding to each class individually. Rather than duplicate the code over and over for multiple tables (and not being DRY) or forego the flexibility of adding idiosyncratic functionality or methods, STI permits you to use keep your data in a single table while writing specialized functionality."
You can read more about it here.
As suggested by #emaillenin you could use polimorphic associations to deal with this.
You can see more about that here
But you should have in mind that classes sharing this type of association should follow a pattern, or else you could end up with tons of if statements in order to avoid their differences.
However by your description of the relation between AdProvider and Adword, I'm guessing that you are using a STI (Single Table Inheritance) system, so those similarities are already implied.
This article will help you to choose between Polymorphism and STI approach: STI
Below you can find a quote from the article:
"
3. Do the objects have similar data but different behavior?
How many database columns are shared by every model? If there are going to be many model-specific columns, you should consider Polymorphic Associations. On the other hand, if a Car, Truck, and Motorcycle all have the same attributes, eg:
color
engine_size
price
but different method implementations, eg:
drivetrain_weight # sums different components
value_after_depreciation(years) # uses different depreciation rates
drivers_license_certifications # references different certifications
then Single Table Inheritance is probably a good design choice. If there are only minor differences in a few methods, you may want to “cheat” and go with a Single Class."

How best to model reservation/appointments database in Rails

I'm looking to write some sort of Rails app to help users book time slots at a restaurant. How can this be modeled in such a way so that it can be reservations can be displayed and booked through the browser? I have two models:
class Restaurant < ActiveRecord::Base
has_many :reservations
class Reservation < ActiveRecord::Base
belongs_to :restaurant
attr_accessible :name, :date, :time
At first I toyed with a using a hash within the Restaurant model to store availability, using dates as keys. But then I realized that Rails databases must serialize hashes, and I'd like to make sure there isn't a better way to go about this before I dive into that stuff.
I'm using Postgres (if that's relevant). Any help would be much appreciated!
Your basic model structure is fine. Note that attr_accessible is not current best practices, as of Rails 4. (It has been replaced by strong parameters)
Doesn't matter too much about what database you are using (even though PG is a solid choice) but the general engineering that is truly important.
I won't give you a copy paste answer but hopefully give you some direction.
So a Restaurant can have many Reservations throughout the day. I assume each restaurant can only hold so many people and thus have some type of "reservation limit" and Reservations cannot overlap.
Because of the constraints I imagine your 2 model method will work. You just need to figure out exactly how they must interact to work as you plan.
Restaurants should be able to keep track of open times/vacancies (or whatever important details). While Reservations will keep track of the number of people in the party, time, etc.
Your initial relationship looks to be well defined. But the other answer does correctly point out the new Rails 4 preferred method.

How to design/model a has many relationship that has a meaningful join table?

I wasn't able to put well into words (in Question title) what I'm trying to do, so in honor of the saying that an image is worth a thousand words; In a nutshell what I'm trying to do is..
Basically, what I have is A Teacher has many Appointments and A Student has many Appointments which roughly translates to:
I'm trying to stay away from using the has_and_belongs_to_many macro, because my appointments model has some meaning(operations), for instance it has a Boolean field: confirmed.
So, I was thinking about using the has_many :through macro, and perhaps using an "Appointable" join table model? What do you guys think?
The Scenario I'm trying to code is simple;
A Student requests an Appointment with a Teacher at certain Date/Time
If Teacher is available (and wants to give lesson at that Date/Time), She confirms the Appointment.
I hope you can tell me how would you approach this problem? Is my assumption of using the has_many :through macro correct?
Thank you!
Both teachers and students could inherit from a single class e.g. Person. Then create an association between Person and Appointments. This way you keep the architecture open so that if in the future you want to add 'Parents' then they could easily be integrated and may participate in appointments.
It may not be completely straightforward how you do the joins with the children classes (Students, Parents, Teachers). It may involve polymorphic relationships which I don't particularly like. You should though get away with a single join table.
In any case, you want to design so that your system can be extended. Some extra work early on will save you a lot of work later.

Objects and Relations in Ruby on Rails

I'm attempting to create a simple web application for some personal development, but I've run into an obstacle, which I'm hoping others will find trivial. I have working classes created, but I'm not sure how define their relationships, or whether their models are even appropriate.
For the sake of argument, I have the following classes already in existence: User, Team, and Athlete
The functionality I'm striving for is for a user to create a team by adding one athlete to the team object. Other users can either add players to the team, or they can add alternatives to an existing athlete on the team roster. Essentially, I want to create some sort of class to wrap an array of athlete objects, we'll call it AthleteArray.
If my understanding is correct, these are the relationships that would be appropriate:
So a Team would have-many AthleteArrays
An AthleteArray would have-many Athletes and would belong-to a Team
Athletes would belong-to a User, and would belong-to a AthleteArray.
Users would have-many athletes, but that would be the extent of their involvement.
Since the AthleteArray class wouldn't have any attributes, is it wise to create it as an ActiveRecord object(would it merely have an ID)? Is there another way to implement this idea(can you define the team class, to have an array of arrays of athlete objects)? I have very little knowledge of RoR, but I thought it would be a good place to start with web development. Any help would be appreciated. Thanks in advance!
Edit: The names of Athletes, Teams, and AthleteArrays are unimportant. Assume that an Athlete is basically a comment, validated against a list of athletes. Duplication is acceptable. If I'm understanding the answers posted, I should basically create an intermediate class which takes the IDs of their parents?
Is response to Omar:
Eventually, I'd like to add a voting system. So after basic team is created, users can individual suggest replacements for a given player, and users can vote up the best choices. For instance, If I have a team of chess_players created:
Bobby Fischer
Garry Kasparov
Vladimir Kramnik
someone might click on Kasparov, and decide that a better athlete would be Deep Blue, so this option would appear nested under Kasparov until it received more votes. This same process would occur for every character, but unlike a comment system, you wouldn't be able to respond to "Deep Blue" and substitute another player, you would simply respond to the position number 2, and suggest another player.
Right, so if I understand the question properly, there will be many possible combinations of athletes for a team, which may or may not use the same athletes?
Something sounds off here, possibly in the naming of your models. Don't quite like the smell of AthleteArrays.
has_many_through might be what you need to access the athletes from your team e.g.
has_many :athletes, :through => :team_permuations # your AthleteArray model
Josh Susser has an old roundup of many to many associations which i guess is what you need, since according to your specification, theoretically it can be possible for an athlete to belong to any number of teams. I suppose the best thing is that you can have automagically populated audit columns (created/updated_at/on) on your many to many associations, which is a nice thing to have.
http://blog.hasmanythrough.com/2006/4/20/many-to-many-dance-off
Please comment if you think I have understood the question wrong.
If I understand your need, this is something that can be solved through has_many :through.
basically you can represent this in the database like
athletes:
id
other_fields
teams:
id
other_fields
roster_items:
id
team_id
athlete_id
position
is_active #is currently on the team or just a suggestion
adding_user_id #the user who added this roster item
class Athlete < ActiveRecord::Base
has_many :roster_items
end
class Team < ActiveRecord::Base
has_many :roster_items
has_many :athletes, :through => :roster_items
end
class RosterItem < ActiveRecord::Base
belongs_to :team
belongs_to :athlete
belongs_to :adding_user, :class_name => 'User'
end

ActiveRecord has_n association

I was wondering what the best way to model a relationship where an object is associated with exactly n objects of another class. I want to extend the has_one relationship to a specific value of n.
For example, a TopFiveMoviesList would belong to user and have exactly five movies. I would imagine that the underlying sql table would have fields like movie_id_1, movie_id_2, ... movie_id_5.
I know I could do a has_many relationship and limit the number of children at the model level, but I'd rather not have an intermediary table.
I think implementing this model through a join model is going to be you're best bet here. It allows the List model to worry about List logic and the Movie model to worry about Movie logic. You can create a Nomination (name isn't the greatest, but you know what I mean) model to handle the relationship between movies and lists, and when there's a limit of 5, you could just limit the number of nominations you pull back.
There are a few reasons I think this approach is better.
First, assuming you want to be able to traverse the relationships both ways (movie.lists and list.movies), the 5 column approach is going to be much messier.
While it'd be so much better for ActiveRecord to support has n relationships, it doesn't, and so you'll be fighting the framework on that one. Also, the has n relationship seems a bit brittle to me in this situation. I haven't seen that kind of implementation pulled off in ActiveRecord, though I'd be really interested in seeing it happen. :)
My first instinct would be to use a join table, but if that's not desirable User.movie[1-5]_id columns would fit the bill. (I think movie1_id fits better with Rails convention than movie_id_1.)
Since you tagged this Rails and ActiveRecord, I'll add some completely untested and probably somewhat wrong model code to my answer. :)
class User < ActiveRecord::Base
TOP_N_MOVIES = 5
(1..TOP_N_MOVIES).each { |n| belongs_to "movie#{n}".to_sym, :class_name => Movie }
end
You could wrap that line in a macro-style method, but unless if that's a common pattern for your application, doing that will probably just make your code that harder to read with little DRY benefit.
You might also want to add validations to ensure that there are no duplicate movies on a user's list.
Associating your movie class back to your users is similar.
class Movie < ActiveRecord::Base
(1..User::TOP_N_MOVIES).each do |n|
has_many "users_list_as_top_#{n}".to_sym, :class_name => User, :foreign_key => "movie#{n}_id"
end
def users_list_as_top_anything
ary = []
(1..User::TOP_N_MOVIES).each {|n| ary += self.send("users_list_as_top_#{n}") }
return ary
end
end
(Of course that users_list_as_top_anything would probably be better written out as explicit SQL. I'm lazy today.)
I assume you mean "implement" rather than "model"? The modeling's pretty easy in UML, say, where you have a Person entity that is made up of 5 Movie entities.
But the difficulty comes when you say has_one, going to has_5. If it's a simple scalar value, has_one is perhaps a property on the parent entity. Has_5 is probably 2 entities related to one another through an "is made up of" relationship in UML.
The main question to answer is probably, "Can you guarantee that it will always be 'Top 5'?" If yes, model it with columns, as you mentioned. If no, model it with another entity.
Another question is perhaps, "How easy will it be to refactor?" If it's simple, heck, start with 5 columns and refactor to separate entities if it ever changes.
As usual, "best" is dependent on the business and technical environment.

Resources