Rails Model Has_Many With Multiple Foreign_Keys

Rails has_many through multiple foreign keys

the default join in has_many :children in house.rb is between the children and parents table depending on the parent_id column that is not exist.

so you need to override it: so house.rb should look like below.

class House < ApplicationRecord
has_many :parents
has_many :children, -> { unscope(:joins).joins('INNER JOIN ON children.father_id = parents.id OR children.mother_id = parents.id') }, through: :parents
end

has_many through with multiple foreign keys on table

This is what jvillian commented, which is in fact an answer

class FeedPost < ApplicationRecord

has_many :flights
has_many :destinations, through: :flights, source: :destination
has_many :origins, through: :flights, source: :origin

def locations
(origins + destinations).uniq
end

Rails association with multiple foreign keys

TL;DR

class User < ActiveRecord::Base
def tasks
Task.where("owner_id = ? OR assigneed_id = ?", self.id, self.id)
end
end

Remove has_many :tasks in User class.


Using has_many :tasks doesn't make sense at all as we do not have any column named user_id in table tasks.

What I did to solve the issue in my case is:

class User < ActiveRecord::Base
has_many :owned_tasks, class_name: "Task", foreign_key: "owner_id"
has_many :assigned_tasks, class_name: "Task", foreign_key: "assignee_id"
end

class Task < ActiveRecord::Base
belongs_to :owner, class_name: "User"
belongs_to :assignee, class_name: "User"
# Mentioning `foreign_keys` is not necessary in this class, since
# we've already mentioned `belongs_to :owner`, and Rails will anticipate
# foreign_keys automatically. Thanks to @jeffdill2 for mentioning this thing
# in the comment.
end

This way, you can call User.first.assigned_tasks as well as User.first.owned_tasks.

Now, you can define a method called tasks that returns the combination of assigned_tasks and owned_tasks.

That could be a good solution as far the readability goes, but from performance point of view, it wouldn't be that much good as now, in order to get the tasks, two queries will be issued instead of once, and then, the result of those two queries need to be joined as well.

So in order to get the tasks that belong to a user, we would define a custom tasks method in User class in the following way:

def tasks
Task.where("owner_id = ? OR assigneed_id = ?", self.id, self.id)
end

This way, it will fetch all the results in one single query, and we wouldn't have to merge or combine any results.

has_many association with multiple foreign keys to the same table

You'll need something like:

class Team < ActiveRecord::Base
has_many :home_games, class_name: 'Game', foreign_key: 'home_team_id'
has_many :away_games, class_name: 'Game', foreign_key: 'away_team_id'

# This seems like a separate thing to me...
has_many :winning_games, class_name: 'Game', foreign_key: 'winning_team_id'

# Do not include winning games, since it would already be included
def games
self.home_games.to_a + self.away_games.to_a
end

end

Multiple Foreign Keys _ has_many

You can accomplish this without relying on the dependent command of an association. The best way I can think of is to 'clean out' the associations when the action is taken to disassociate the Profile from an Organization. You could have an inverse method in Organization.

class Profile < ActiveRecord:Base

def method_that_disassociates_from(inputted_organization)
self.organizations.delete(inputted_organization)
self.notifications.where(organization_id: inputted_organization.id).destroy_all
end

end

Rails Model has_many with multiple foreign_keys

Found a simple answer on IRC that seems to work (thanks to Radar):

class Person < ActiveRecord::Base
belongs_to :father, :class_name => 'Person'
belongs_to :mother, :class_name => 'Person'
has_many :children_of_father, :class_name => 'Person', :foreign_key => 'father_id'
has_many :children_of_mother, :class_name => 'Person', :foreign_key => 'mother_id'
def children
children_of_mother + children_of_father
end
end

Rails multiple foreign keys in the same table

Does table procedures need to have both the fields owner_id and
assignee_id, or just a field user_id

You should have both owner_id and assignee_id in procedures table instead of user_id so that you can call

@user.owned_procedures
@user.assigned_procedures

to get owned_procedures and assigned_procedures of a @user which is an instance of User. And to get a owner and assignee of a procedure, call

@procedure.owner
@procedure.assignee

Has_many, belongs_to with multiple foreign keys

You could define foreign keys

class Club < ActiveRecord::Base
has_many :home_matches, class_name: 'Match', foreign_key: 'home_team_id'
has_many :away_matches, class_name: 'Match', foreign_key: 'away_team_id'
end

But I suspect this will cause more problems as you'd presumably want to get all matches and order by date, which you could do by doing two queries and adding the results and sorting but that is frankly messy.

My initial thought it that you ought to be looking at a has many through relationship it you want to be able to do @club.matches

class Club < ActiveRecord::Base
has_many :club_matches
has_many :matches, through: :club_matches
end

class ClubMatch < ActiveRecord::Base
belongs_to :club
belongs_to :match
#will have an attribute on it to determine if home or away team
end

class Match < ActiveRecord::Base
has_many :club_matches
has_many :clubs, through: :club_matches
end

Then you'd be able to do @club.matches

Just my initial thought and someone may well come up with a better solution

Presumably though you could just do a query without the association which might be better and less refactoring for you. For example

class WhateverController < ApplicationController

def matches
@club = Club.find(params[:club_id)
@matches = Match.where("home_team_id = :club_id OR away_team_id = :club_id", {club_id: @club.id}).order(:date)
end


Related Topics



Leave a reply



Submit