Self-Referential Has Many Through with Custom Foreign Keys in Rails - ruby-on-rails

I have a User model and a relationship table called ParentsChildren.
I'm trying to create two relationships on the User model so that User#children returns all of a users children and User#parents returns all of a users parents.
I've managed to get this working before, but I'm doing something wrong right this time, and I'm not sure what it is exactly.
class ParentsChildren < ApplicationRecord
self.table_name = 'parents_children'
belongs_to :parent_user, class_name: 'User'
belongs_to :child_user, class_name: 'User'
end
class User
has_many :parent_relationships, class_name: 'ParentsChildren', foreign_key: :parent_user_id
has_many :child_relationships, class_name: 'ParentsChildren', foreign_key: :child_user_id
has_many :children, through: :parent_relationships, class_name: 'User', source: :child_user
has_many :parents, through: :child_relationships, class_name: 'User', source: :parent_user
end
# => uninitialized constant ParentsChildren::ChildUser

Figured it out. The key was to drop 'User' as the class name for has_many :parents and has_many :users. It's inferred through the given sources.
class User
has_many :parent_relationships, foreign_key: :child_user_id,
class_name: 'ParentsChildren'
has_many :children, through: :parent_relationships,
source: :parent_user
has_many :child_relationships, foreign_key: :parent_user_id,
class_name: 'ParentsChildren'
has_many :parents, through: :child_relationships,
source: :child_user
end

Related

How to create follower and followee in Rails?

I'm quite stuck in in Ruby on Rails relations and I really appreciate you help.
Have model User
class User < ActiveRecord::Base
has_many :followers, :through => :follows, foreign_key: "followee_id"
has_many :followees, :through => :follows, foreign_key: "follower_id"
end
and model Follow
class Follow < ActiveRecord::Base
belongs_to :followee, class_name: "User"
belongs_to :follower, class_name: "User"
end
but if want to create new follower like:
user.followers << User.first
the result is SystemStackError
Thank you for every help!
You have to try something like this:
class User < ActiveRecord::Base
has_many :follower_follows, foreign_key: :followee_id, class_name: "Follow"
has_many :followers, through: :follower_follows, source: :follower
has_many :followee_follows, foreign_key: :follower_id, class_name: "Follow"
has_many :followees, through: :followee_follows, source: :followee
end
Here follower_follows and followee_follows are join tables and source: :follower matches with the belong_to :follower identification in the Follow model and source: :followee matches with the belong_to :followee identification in the Follow model
I think this would work in your case

Association from promotion rule to product not working

I'm trying to access products through promotion but can't.
In the command line: Promotion.last.promotion_rules.first.products
Returns an error of an uninitialized constant.
Here are my associations:
class Product
has_many :product_promotion_rules, class_name: 'ProductPromotionRule'
has_many :promotion_rules, through: :product_promotion_rules
end
class ProductPromotionRule
belongs_to :product
belongs_to :promotion_rule
end
class PromotionRule
has_many :product_promotion_rules, class_name: 'ProductPromotionRule', join_table: 'products_promotion_rules', foreign_key: :promotion_rule_id
has_many :products, through: :product_promotion_rules
belongs_to :promotion
end
class Promotion
has_many :promotion_rules
end
Within the Product model try:
has_many :product_promotion_rules, class_name: 'ProductPromotionRule', foreign_key: :product_id
has_many :promotion_rules, through: :product_promotion_rules, source: :promotion_rule
And within the PromotionRule model:
has_many :products, through: :product_promotion_rules, source: :product
Update: saw this, which you may want to remove/fix:
join_table: products_promotion_rules
Either change to:
join_table: product_promotion_rules
Or try removing it.

How to create this `through`` association?

Organization and Link are associated through Node.
Organization:
has_many :nodes
has_many :links, through: :nodes, source: :where_first_links
Node:
belongs_to :organization
has_many :where_first_links, class_name: "Link",
foreign_key: "first_node_id"
has_many :where_second_links, class_name: "Link",
foreign_key: "second_node_id"
Link:
belongs_to :first_node, class_name: "Node"
belongs_to :second_node, class_name: "Node"
Question:: How can I associate Link back to Organization? I tried the line below but that does not seem to work (ArgumentError: Unknown key: :through.):
belongs_to :organization,
through: :first_node,
source: :where_first_links,
inverse_of: :links
belongs_to association not support through key
you should use has_one association
has_one :first_node_organization,
through: :first_node,
class_name: 'Organization',
source: :organization
Use has_one instead of belongs_to.
class Link < ActiveRecord::Base
belongs_to :first_node, class_name: "Node"
belongs_to :second_node, class_name: "Node"
has_one :organization, through: :first_node
end

Trying to 'alias' a polymorphic has_many relationship

I have a User model:
class User < ActiveRecord::Base
has_many :tracks, dependent: :destroy
has_many :tracked_locations, through: :tracks, source: :tracking, source_type: 'Location'
and a Track model (think of it as 'following'):
class Track < ActiveRecord::Base
belongs_to :user
belongs_to :tracking, polymorphic: true
end
The idea here is I will have many models to track / follow so I am using polymorphism. For example I have a Location model:
class Location < ActiveRecord::Base
has_many :tracks, :as => :tracking, :dependent => :destroy
has_many :users, through: :tracks
Now in the console Location.first.users works fine along with User.first.tracked_locations.
Now I will be adding another polymorphic relationship along the lines of Flagged. The user can 'flag' another model with a note etc. So if I add has_many :users, through: :flagged to the Location model for example I need to differentiate between tracking users and flagged users.
I tried:
has_many :tracking_users, through: :tracks, source: :tracking, source_type: 'User'
but I get:
NoMethodError: undefined method `evaluators_for' for #<Location:0x007ff29e5409c8>
Can I even do this or am I missing something simple here?
UPDATE
Based on the answer below I figured it out:
has_many :tracking_users, through: :tracks, class_name: "User", foreign_key: "user_id", source: :user
I'm not 100% on this, but you could try:
has_many :tracking_users, through: :tracks, class_name: "User", foreign_key: "user_id", source: :user
Or you could also just create a class method and do it by hand.
def self.tracking_users
user_ids = tracks.collect(&:user_id)
User.where(id: user_ids)
end
edit: Had a brainfart, changed the "source" up there to :user. That tells what table to actually do the lookup in with the other attribute you've provided. of course it wouldn't be in :tracks

Rails set role based relationship between belong_to and has_many for multiple primary keys

My belong_to Item -> User relationship works; however, how do I setup the corresponding relationship in my User model (has many User -> Item)?
#item.rb
belongs_to :update_user, foreign_key: :item_updated_at_user_id, class_name: "User"
belongs_to :delete_user, foreign_key: :item_deleted_at_user_id, class_name: "User"
#user.rb
has_many :update_items, class_name: "Items", inverse_of: :update_user
has_many :delete_items, class_name: "Items", inverse_of: :delete_user
The associations should look as below:
class Item < ActiveRecord::Base
belongs_to :update_user, foreign_key: :item_updated_at_user_id, class_name: "User", inverse_of: :update_items
belongs_to :delete_user, foreign_key: :item_deleted_at_user_id, class_name: "User", inverse_of: :delete_items
end
class User < ActiveRecord::Base
has_many :update_items, foreign_key: :item_updated_at_user_id, class_name: "Item", inverse_of: :update_user
has_many :delete_items, foreign_key: :item_deleted_at_user_id, class_name: "Item", inverse_of: :delete_user
end
class_name: "Items" should be class_name: "Item"(Note: Model names are Singular)
Specify foreign key option on both side of association.
Also, Its best to specify inverse_of option on both sides of association.

Resources