Rails 3 Model Relationships - ruby-on-rails

I'm kinda stumped on how to relate some models I have. Was hoping for some pointers or ideas!
Let's say I have 3 models, named "MinorTeam", "MajorTeam", and "Game". Each game references two teams; but how do I designate whether it could be either a major or minor team?
has_one :team_1, :class_name => "MajorTeam"
# or
has_one :team_1, :class_name => "MinorTeam"
The two team models are substantially different, so I couldn't simply add a major/minor flag to a Team model. Any ideas?

Polymorphic associations should work. You might have to tweak things a bit to get it right, but by using them, the team classes don't have to be anything alike, apart from having games.
module Team
extend ActiveSupport::Concern
included do
has_many :home_games, :class_name => "Game", :as => :team_1
has_many :away_games, :class_name => "Game", :as => :team_2
end
end
class MajorTeam < ActiveRecord::Base
include Team
end
class MinorTeam < ActiveRecord::Base
include Team
end
class Game < ActiveRecord::Base
belongs_to :team_1, :polymorphic => true
belongs_to :team_2, :polymorphic => true
end
I'm assuming you meant for your has_one to be belongs_to, as has_one would mean that each team belongs to only one game, which seems like it might be incorrect. If I'm mistaken, let me know.

Related

Rails many to many relationship confusion

So im working on a rails app for users to create events (and attend other created events). You can read about the assignment here (for the Odin Project): https://www.theodinproject.com/courses/ruby-on-rails/lessons/associations
Anyways I thought I had understood many to many relationships in rails, but the way i've seen other people write the models is confusing to me.
To me it seems like it should be something like:
class User < ApplicationRecord
has_many :attendances
has_many :events, through: :attendances
end
class Attendance < ApplicationRecord
belongs_to :user
belongs_to :event
end
class Event < ApplicationRecord
has_many :users
has_many :users, through: :attendances
end
This makes sense to me because a User can create many events, and an event can have many users attending. (Although attendances is probably the wrong word, maybe invites or something).
But i've seen some weird examples (You can see others source code below on the project) and it seems like they are adding much more to the models and also renaming the source/foreign_key/class_name.
Am I missing something? This still allows a user to "own" an event right? Maybe im mis-understanding how many-to-many works. But this fits at least in my mind of how it should be.
For reference some other models I was seeing was similar to this:
class Event < ActiveRecord::Base
belongs_to :creator, :class_name => "User"
has_many :event_attendees, :foreign_key => :attended_event_id
has_many :attendees, :through => :event_attendees
end
class EventAttendee < ActiveRecord::Base
belongs_to :attendee, :class_name => "User"
belongs_to :attended_event, :class_name => "Event"
end
class User < ActiveRecord::Base
has_many :created_events, :foreign_key => :creator_id, :class_name => "Event"
has_many :event_attendees, :foreign_key => :attendee_id
has_many :attended_events, :through => :event_attendees, :foreign_key => :attendee_id'
end
Basically similar things to the above. Im not really sure what this is doing? Or why all the extra is necessary.
In your example everything according to conventions. Maybe except many-to-many table naming.
attendances table has 'user_id' and 'event_id' fields. But in case it could conflict with other fields, or not descriptive enough you could use different keys.
belongs_to :creator, :class_name => "User"
belongs_to :creator by default would look for Creator model, so it is needed to specify class name explicitly, like in the provided example.
has_many :event_attendees, :foreign_key => :attended_event_id
By default foreign key would be event_id, so here it is specified explicitly too.
has_many :created_events, :foreign_key => :creator_id, :class_name => "Event"
By default, rails would look for user_id foreign key and CreatedEvent model. And these attributes specified explicitly.
You just need to understand what attributes rails provides by default, to change if it is required.
ActiveRecord associations default to a class and foreign key with the same name as the association. The code here is specifically specifying these because they are not the default.

Rails Polymorphic Associations

Total newbie to Rails and programming in general, so please forgive me if the answer to my question seems glaringly obvious. I've been doing a lot of reading including the ROR guides but can't seem to find a scenario specific to the following situation:
I have three models scaffolded under one User model, and am trying to link them like so:
class User < ActiveRecord::Base
has_many :malls, :dependent => :destroy
end
class Mall < ActiveRecord::Base
belongs_to :user
has_many :stores, :dependent => :destroy
has_many :cakes, :as => :cake_poly, :dependent => :destroy
end
class Store < ActiveRecord::Base
belongs_to :mall
has_many :cakes, :as => :cake_poly, :dependent => :destroy
end
class Cakes < ActiveRecord::Base
belongs_to :cake_poly, :polymorphic => true
end
Will this work? If it does, is there a better way to implement this? If not, how else can I implement the associations?
The idea is that each User may have many malls, each Mall may have many stores, and both malls and stores may have many cakes.
A key question for your design is the intent - what do you want to achieve?
You should not use the polymorphic relationship if you simply like to aggregate cakes available in the mall's shops for the mall model. You can use the following relationship to achieve such a design:
class Mall < ActiveRecord::Base
has_many :stores
has_many :cakes, :through => :stores
end
The polymorphic approach is a perfect choice if the two sets (cakes in the mall, cakes in the mall's stores) don't correlate.

generic categories for my rails models

I am working in a rails app which main points are articles and products.
Someone has implemented categories for articles.
class ArticleCategory < MainSchemaBase
belongs_to :user
has_many :articles, :through => :article_category_articles, :conditions => 'articles.deleted_at IS NULL'
has_many :article_category_articles, :conditions => 'article_category_articles.deleted_at IS NULL'
And I have been asked to do basically the same thing for products.
Of course I want to DRY but products belongs to brand instead of user, and I have many products instead of many articles
The model is almost empty (some named scopes), controller and views also very dependent of the context (article)
Can this be DRY? Or should I just copy the implemntation ?
Make it polymorphic: The best way, i think, is to set up a polymorphic many-to-many relationship using has_many_polymorphs (https://github.com/Nielsomat/has_many_polymorphs) so that a single category could be applied to a product and an article.
class Category
#doesn't have any association fields
has_many_polymorphs :categorizables, :from => [:products, :articles], :through => :categorizations, :dependent => :destroy
end
class Categorization < ActiveRecord::Base
#has fields categorizable_id, categorizable_type, :category_id
belongs_to :categorizable, :polymorphic => true
belongs_to :category
end
class Product < ActiveRecord::Base
#doesn't need anything to set up the association
end
class Article < ActiveRecord::Base
#doesn't need anything to set up the association
end
"Categorizable" is a bit of a mouthful but you won't actually be using it. You'll be saying #product.categories or #category.articles etc.

ActiveRecord has two association

What is the best way to achieve a has two association with activerecord?
I have a Team and Game models. Each Team will have_many games #team.games. A Game will have two teams #game.hosting_team and #game.opposing_team.
I started out with two belongs_to/has_one associations but then #team.games would only return their home games.
The other option I can think of is using a HABTM and use a validator to ensure there are only records. The only thing missing is keeping track of the home team. It seems like I need a has many through association but I'm not exactly sure...
Thanks for your help.
This is an example of how the two has_many associations look. The problem here is I would have to call team.games and team.opponents to get a full list of their games
class Team < ActiveRecord::Base
has_many :games
has_many :opponents, :class_name => "Team"#, :foreign_key => ""
end
class Game < ActiveRecord::Base
belongs_to :team, :class_name => "Team" #, :foreign_key => "team_id"
belongs_to :opponent, :class_name => "Team" #, :foreign_key => "opponent_id"
end
I'd like something like this but this obviously isn't how belongs_to works.
class Team < ActiveRecord::Base
has_many :games
end
class Game < ActiveRecord::Base
belongs_to :hosting_team
belongs_to :opposing_team
end
My desired api would look like this.
#team.games # return all games home or away
#game.hosting_team # Team
#game.opposing_team # Team
You can probably still model it with the bt/ho associations, and set up games as an accessor method on the team instead of as an association:
class Team < ActiveRecord::Base
def games
Game.find(:conditions => ["home_team_id = ? OR away_team_id = ?", id, id])
end
end

Going from 2 to many in Rails

I have a Rails application that I'm in the process of designing. I have a separate model that needs to link to only 2 of one model. Specifically, my "evaluation"s have 2 "member"s, an evaluator, and an evaluatee. They also have a few other pieces of information, too but they should not be relevant to this.
What is the best way to represent this? Would 2 foreign keys in the evaluation be best, or a many-many relationship between the evaluations and the members? Would there be some other option that would work even better?
I would initially think many to many, but since there is a defined number on one side of the relationship I question the applicability here. To my knowledge, many-to-many generally implies that the number on each side of the relation is variable.
You probably want two different associations, possibly with the same class:
class Member < ActiveRecord::Base
has_many :evaluations_out, :class_name => 'evaluation', :as => :evaluator
has_many :evaluations_in, :class_name => 'evaluation', :as => :evaluatee
end
class Evaluation < ActiveRecord::Base
belongs_to :evaluator, :class_name => 'member'
belongs_to :evaluatee, :class_name => 'member'
end
I haven't tested it myself and it might sound a little adventurous, but I think that could work:
Evaluation Model
class Evaluation < ActiveRecord::Base
belongs_to :evaluator, :class_name => "Member", :foreign_key => "evaluator_id"
belongs_to :evaluatee, :class_name => "Member", :foreign_key => "evaluatee_id"
end
Member Model
class Member < ActiveRecord::Base
has_many :evaluators, :class_name => "Evaluation", :foreign_key => "evaluator_id"
has_many :evaluatees, :class_name => "Evaluation", :foreign_key => "evaluatee_id"
end

Resources