Joining one table two times - ruby-on-rails

My db schema:
tournaments(id, ...)
teams(tournament_id, id, ...)
matches(tournament_id, id, team_id_home, team_id_away, ...)
Models:
class Tournament < ActiveRecord::Base
has_many :teams, dependent: :destroy
has_many :matches, dependent: :destroy
...
end
class Team < ActiveRecord::Base
belongs_to :tournament
...
end
class Match < ActiveRecord::Base
belongs_to :tournament
has_many :teams
...
end
I would like to have the following data in my view:
match_id team_id_home team_id_away team_id_home_name team_id_away_name
So, I'm asking for help with the following query (I'm trying to get team's names, but having problem with joining):
#matches = #tournament.matches.where(:tournament => #tournament).joins(:teams).paginate(page: params[:page])

I'm fairly new to rails, but you should be able to setup your associations like this: (going from memory)
class Match < ActiveRecord::Base
belongs_to :tournament
has_one :home_team, :class_name => "Team", :foreign_key => "team_id_home"
has_one :away_team, :class_name => "Team", :foreign_key => "team_id_away"
end
#####
m = Match.first
m.away_team.team_name
m.home_tam.team_name
Or in your case:
#matches = #tournament.matches.paginate(page: params[:page])
I don't think you need the where function: the has_many association tells rails to only pull matching matches.

It is belongs_to, not has_one in Match model.
class Match < ActiveRecord::Base
belongs_to :tournament
belongs_to :home_team, :class_name => "Team", :foreign_key => "team_id_home"
belongs_to :away_team, :class_name => "Team", :foreign_key => "team_id_away"
end
class Team < ActiveRecord::Base
belongs_to :tournament
has_many :matches
end
Now I can use tournament.home_team.name in my view

Related

Multi-level nested count in ActiveRecord (Rails)

I feel a little out of my depth here. I've got the following relationships:
class User < ActiveRecord::Base
has_many :flights
end
class Flight < ActiveRecord::Base
has_many :flight_legs
belongs_to :user
end
class FlightLeg < ActiveRecord::Base
belongs_to :departure_airport, :class_name => "Airport"
belongs_to :arrival_airport, :class_name => "Airport"
end
class Airport < ActiveRecord::Base
belongs_to :country
has_many :flight_legs_arriving_here, :class_name => "FlightLeg",
:foreign_key => "arrival_airport_id"
has_many :flight_legs_departing_here, :class_name => "FlightLeg",
:foreign_key => "departure_airport_id"
end
class Country < ActiveRecord::Base
attr_accessible :name
has_many :airports
end
I want to get a list of users by the number of countries that they have visited, and a separate query which will return the number of countries a user has visited. Does anyone have any idea how to do this? I am sort of lost with the details of the documentation on this one.

Named many to many relations in Rails

How should I create following model in Rails 3.2? Project can have 1+ owners and 1+ users. Both of them are instances of class Person. I've thought about has_and_belongs_to_many but I don't know how to handle two separate collections of Persons for each Project.
You'll need a join model to represent each has-and-belongs-to-many relationship, and you would access using has-many-through as described here:
class ProjectOwnerLink < ActiveRecord::Base
belongs_to :project
belongs_to :owner, class_name: 'Person'
end
class ProjectUserLink < ActiveRecord::Base
belongs_to :project
belongs_to :user, class_name: 'Person'
end
class Project < ActiveRecord::Base
has_many :project_owner_links
has_many :owners, :through => :project_owner_links
has_many :project_user_links
has_many :users, :through => :project_user_links
end
class Person < ActiveRecord::Base
has_many :project_owner_links
has_many :owned_projects, :through => :project_owner_links, :source => :project
has_many :project_user_links
has_many :used_projects, :through => :project_user_links, :source => :project
end
You could define another model Participation that holds the type of the relationship, i.e. the role of the user. (Untested) code:
class Project < ActiveRecord::Base
has_many :participations
has_many :users, :through => :participations
def with_role(role)
includes(:participations).where('participation.role = ?', role)
end
def owners
users.with_role('owner')
end
def participants
users.with_role('participant')
end
end
 
class User < ActiveRecord::Base
has_many :participations
has_many :projects, :through => :participations
def with_role(role)
includes(:participations).where('participation.role = ?', role)
end
def projects_owned
projects.with_role('owner')
end
def projects_participating_in
projects.with_role('participant')
end
end
 
class Participation < ActiveRecord::Base
# has an attribute 'role'
belongs_to :project
belongs_to :user
end
Below is the demo application.
https://github.com/diatmpravin/habtm-demo.git
Please have a look, Let me know if you have any question?

ActionRecord modeling: Employee with many managers

This should be easy. I think I must be getting caught up on naming.
Both a 'manager' and a 'subordinate' (employee) are of class "Person".
Here's what I have:
class Person < ActiveRecord::Base
has_many :person_manager_assignments
has_many :managers, :through => :person_manager_assignments
has_many :subordinates, :through => :person_manager_assignments
end
class PersonManagerAssignment < ActiveRecord::Base
has_one :subordinate, :class_name => "Person", :foreign_key => "id", :primary_key => 'person_id'
has_one :manager, :class_name => "Person", :foreign_key => "id", :primary_key => 'manager_id'
end
Which works great for checking and assigning managers.
I'm caught on the part about subordinates. It returns the Person's self, instead of their subordinates:
p.subordinates
Person Load (0.5ms) SELECT "people".* FROM "people" INNER JOIN "person_manager_assignments" ON "people"."id" = "person_manager_assignments"."person_id" WHERE "person_manager_assignments"."person_id" = 15973
See the bit where in the WHERE clause where it's matching "person_id"? I need that to be "manager_id", but messing with the PersonManagerAssignment associations foreign_key and primary_key values doesn't seem to help.
Any ideas?
Answer is essentially here: http://railscasts.com/episodes/163-self-referential-association
So I think you need this:
class Person < ActiveRecord::Base
has_many :person_manager_assignments
has_many :managers, :through => :person_manager_assignments
has_many :subordinate_relationships, :class_name=>"PersonManagerAssignment", :foreign_key=>"manager_id"
has_many :subordinates, :through => :subordinate_relationships, :source=>:person
end
and
class PersonManagerAssignment < ActiveRecord::Base
belongs_to :person
belongs_to :manager, :class_name=>"Person"
end
Rock on.
I'm going to guess that your PersonManagerAssignment table has a person_id and a manager_id and associations in the model like has_one :person and has_one :manager. If that's the case, I'll recommend changing this association
has_one :person
to this
has_one :subordinate, :class_name => "Person", :foreign_key => "person_id"
and then your has_many :subordinates should work as expected.
class Person < ActiveRecord::Base
has_many :subordinates :through => :person_manager_assignments
has_many :managers, :through => :person_manager_assignments
end
class PersonManagerAssignment < ActiveRecord::Base
belongs_to :subordinate, :class_name => 'Person'
belongs_to :manager, :class_name => 'Person'
end

has_many associations

So, my question is: how to make possible that calls:
Clan.win #to get all won rounds
Clan.blue #to get all rounds when clan was in blue team
or even this:
Clan.matches_win #need to calculate which team won match by counting rounds
Clan.matches_lost
Round model:
class Round < ActiveRecord::Base
belongs_to :match
has_and_belongs_to_many :banned_champions, :class_name => "Champion", :join_table => "banned_champions_rounds"
belongs_to :clan_blue, :class_name => "Clan", :foreign_key => "clan_blue_id"
belongs_to :clan_purple, :class_name => "Clan", :foreign_key => "clan_purple_id"
belongs_to :winner, :class_name => "Clan", :foreign_key => "winner_id"
end
Clan model:
class Clan < ActiveRecord::Base
has_many :players
has_many :rounds
end
Match model:
class Match < ActiveRecord::Base
has_many :rounds
end
In your Clan class:
def win
rounds.where("winner_id = ?", self.id)
end
The others are more or less the same.

Combining Polymorphic Associations with Rich Many-to-Many Associations

Right now I have a rich many-to-many association with VideoVote as the independent record.
class VideoVote < ActiveRecord::Base
belongs_to :user
belongs_to :video
end
class User < ActiveRecord::Base
has_many :video_votes
has_many :voted_videos,
:through => :video_votes,
:source => :video
end
class Video < ActiveRecord::Base
has_many :video_votes
has_many :voted_users,
:through => :video_votes,
:source => :user
end
However, I want to trasform this into a polymorphic association where comments can also have many VideoVotes (I realize this is confusing, so I should probably change it to Votes). (also, a video will have many comments.) How should I do this?
You first want to add voteable_id:integer and voteable_type:string to your video_votes table.
Then your models will look like:
class VideoVote < ActiveRecord::Base
belongs_to :voteable, :polymorphic => true
end
class Comment < ActiveRecord::Base
has_many :video_votes, :as => :voteable
#code
end
class Video < ActiveRecord::Base
has_many :video_votes, :as => :voteable
#code
end
Then you can access them just like any other has_many:
#video.video_votes
#comment.video_votes
#etc.

Resources