How to create this `through`` association? - ruby-on-rails

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

Related

Self-Referential Has Many Through with Custom Foreign Keys in 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

Associates the same model twice in mongoid

I have two class Intern::Question and Intern::Answer, and the standard association look like :
class Intern::Question
has_many :intern_answers, class_name: 'Intern::Answer'
end
class Intern::Answer
belongs_to :intern_question, class_name: 'Intern::Question'
end
And now I want to reference twice answer belongs_to question, answer can store parent question and next question, something like :
class Intern::Question
has_many :intern_answers, class_name: 'Intern::Answer'
has_many :node_for_answers, class_name: 'Intern::Answer'
end
class Intern::Answer
belongs_to :intern_question, foreign_key: :intern_question_id, class_name: 'Intern::Question'
belongs_to :next_question, foreign_key: :next_question_id, class_name: 'Intern::Question'
end
But I have try that and get this error :
Mongoid::Errors::AmbiguousRelationship
Found solution here, using inverse_of
class Intern::Question
has_many :intern_answers, class_name: 'Intern::Answer', inverse_of: :intern_question
has_many :node_for_answers, class_name: 'Intern::Answer', inverse_of: :next_question
end
class Intern::Answer
belongs_to :intern_question, foreign_key: :intern_question_id, class_name: 'Intern::Question', inverse_of: :intern_answers
belongs_to :next_question, foreign_key: :next_question_id, class_name: 'Intern::Question', inverse_of: :node_for_answers
end

How to use :inverse_of with multiple associations?

Does anyone know what I should put in the empty fields below to make this relationship work out of the box? I am very close to making this work as all associations work flawlessly. The only issue is that I cannot save a user with fruits attached to it as, currently, there is no :inverse_of.
I need the :inverse_of pointing in the right direction so that I can save a user with fruits instead of having to save the user first and then attach fruits to it later.
Thank you!
UPDATED AFTER COMMENTS:
The User model:
class User < ApplicationRecord
has_many :bought_fruits_users, -> { bought },
class_name: 'FruitsUser', inverse_of: :buyer
has_many :bought_fruits, through: :bought_fruits_users,
class_name: 'Fruit', source: :bought_fruit
has_many :sold_fruits_users, -> { sold },
class_name: 'FruitsUser', inverse_of: :seller
has_many :sold_fruits, through: :sold_fruits_users,
class_name: 'Fruit', source: :sold_fruit
end
The middle-table model:
class FruitsUser < ApplicationRecord
belongs_to :seller, foreign_key: :user_id,
class_name: 'User', inverse_of: :sold_fruits_users
belongs_to :buyer, foreign_key: :user_id,
class_name: 'User', inverse_of: :bought_fruits_users
belongs_to :bought_fruit, foreign_key: :fruit_id,
class_name: 'Fruit', inverse_of: :buying_fruits_users
belongs_to :sold_fruit, foreign_key: :fruit_id,
class_name: 'Fruit', inverse_of: :selling_fruits_users
scope :bought, -> { where(type_of: 'bought') }
scope :sold, -> { where(type_of: 'sold') }
end
The Fruit model:
class Fruit < ApplicationRecord
has_many :buying_fruits_users, -> { bought },
class_name: 'FruitsUser', inverse_of: :bought_fruit
has_many :buying_users, through: :bought_fruits_users,
class_name: 'User', source: :buyer
has_many :selling_fruits_users, -> { sold },
class_name: 'FruitsUser', inverse_of: :sold_fruit
has_many :selling_users, through: :sold_fruits_users,
class_name: 'User', source: :seller
end
Still can't save it:
u = User.new [OK]
u.needs << Fruit.sample [OK]
u.valid? [false]
u.errors [:bought_fruits_users=>["is invalid"]]

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.

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