Given these 4 Rails models:
class Apple < ActiveRecord::Base
has_one: ?
end
class Banana < ActiveRecord::Base
has_one: ?
end
class FruitMapping < ActiveRecord::Base
belongs_to :fruit, polymorphic: true
has_one :cart
end
class Cart < ActiveRecord::Base
end
How can I connect the has_one of the Apple/Banana to Cart, so that when I write apple.cart I will get the relevant Cart (through the mappings table)?
class Apple < ActiveRecord::Base
has_one :fruit_mapping, as: :fruit
end
class Cart < ActiveRecord::Base
has_many :fruit_mappigns
has_many :apples, through: :fruit_mappings, source: :fruit, source_type: 'Apple'
has_many :bananas, through: :fruit_mappings, source: :fruit, source_type: 'Banana'
end
Using the source and source_type options, you can define the polymorphic relationships. If using source and source_type are depricated in the Rails version you're using you can try
has_many :apples, through: :fruit_mappings, class_name: 'Apple', foreign_key: :fruit_id
Related
Hi I'm trying to set up a many to many relationship in my app. I have two models Count.rb
class Count < ApplicationRecord
has_many :users, through: :counts_users
end
users.rb:
class User < ApplicationRecord
has_many :counts, through: :counts_users
end
and counts_users.rb:
class CountsUser < ApplicationRecord
belongs_to :user
belongs_to :count
end
Now I can create a count
Count.new(message: 'hello')
but if I then do
Count.last.users << User.last
I get the error ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :counts_users in model ErrorCount
I assume I've done something wrong setting up the association, but I'm not sure what?
Your models' associations should be set up like this:
# count.rb
class Count < ApplicationRecord
has_many :counts_users
has_many :users, through: :counts_users
end
# user.rb
class User < ApplicationRecord
has_many :counts_users
has_many :counts, through: :counts_users
end
# counts_user.rb
class CountsUser < ApplicationRecord
belongs_to :user
belongs_to :count
end
See: the Rails Guides on has_many :through Association
I have an application with a business logic concerning products with multiple variants:
class Task < ApplicationRecord
belongs_to :variant
end
class Variant < ApplicationRecord
belongs_to :product
has_many :variant_option_values
has_many :option_values, through: :variant_option_values
has_many :prices
end
class Product < ApplicationRecord
has_many :product_option_types
has_many :option_types, through: :product_option_types
has_many :variants
end
class OptionValue < ApplicationRecord
belongs_to :option_type
end
class OptionType < ApplicationRecord
has_many :product_option_types
has_many :products, through: :product_option_types
has_many :option_values
end
class ProductOptionType < ApplicationRecord
belongs_to :product
belongs_to :option_type
end
class VariantOptionValue < ApplicationRecord
belongs_to :variant
belongs_to :option_value
end
The ERD looks like this:
Having a product product_1 how can I find its variants that have OptionValue instances option_value_1, option_value_2 and option_value_3? Note that the variant has to have all three option values at the same time and can have more than those three (but not necessarily).
option_values = [option_value_1, option_value_2, option_value_3]
Variant.include(product: [option_types: :option_values])
.where("option_values.id IN (?)", option_values.map(&:id))
.group("products.id")
.having("count(*) >= ?", option_values.size)
In my database there are 4 models
class MasterPayment < ActiveRecord::Base
has_many :payments
end
class Payment < ActiveRecord::Base
belongs_to :master_payment
belongs_to :payable, polymorphic: :true
end
class TreatmentPlan < ActiveRecord::Base
has_many :payments, as: :payable
end
class ArbitraryBillableItem < ActiveRecord::Base
has_many :payments, as: :payable
end
What i would like to do is set up an association in MasterPayment that will associate payables to master payments.
Currently, the closest i could find was setting up the master payment model as follows
class MasterPayment < ActiveRecord::Base
has_many :payments
has_many :treatment_plans, through: :payments, source: :payable, source_type: "TreatmentPlan"
has_many :arbitrary_billable_items, through: :payments, source: :payable, source_type: "ArbitraryBillableItem"
def payables
self.treatment_plans + self.arbitrary_billable_items
end
end
The only problem i have with this is that it doesn't feel like the "correct" way to do it.
The only reason i can see for rails not having a solution to this is because you would presumably have to union the tables to return it in one sql statement.
Is there an alternative way to accomplish this that will make more use of the active record associations?
This seems too simple but would it work?
def payables
self.payments.joins(:treatment_plans, :arbitrary_billable_items).distinct
end
class Card < ApplicationRecord
has_one :card_rating
has_one :rating, through: :card_rating
end
class Rating < ApplicationRecord
has_many :card_ratings
has_many :cards, through: :card_ratings
end
class CardRating < ApplicationRecord
belongs_to :card
belongs_to :rating
end
I want to do something along the lines of the following:
c = card.card_rating.new
c << rating
But there doesn't seem to be any association going on at all, because already at the first statement I receive the following error:
undefined method `new' for nil:NilClass
You do not need a join table for a one to many relation:
class Card
belongs_to :rating
end
class Rating
has_many :cards
end
Rather you would use has_one :through in case the domain dictates that the relation is indirect.
class Student
belongs_to :school
has_one :headmaster, through: :school
end
class School
has_many :students
end
class Headmaster
belongs_to :school
has_many :students, through: :school
end
I've a problem with an active record relation. I have a Content class and a Product Class defined in this way:
Class Content < ActiveRecord::Base
has_many :product_relations, as: :productable
has_many :products, through: :product_relations
end
Class Product < ActiveRecord::Base
end
Content.first.products return me the products associated to the contents, but I cannot create an association to build a query like Product.first.contents that return me all the contents associated to a product.
Update
I have also this class:
class ProductRelation < ActiveRecord::Base
belongs_to :product
belongs_to :productable, polymorphic: true
end
Solved
has_many :contents, through: :product_relations, source_type: "Content", source: :productable