Active record association works only in one way - ruby-on-rails

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

Related

Rails has_one association through mapping table

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

Joining an attribute from a has_many through Table in Rails

I have the following 2 models:
Parent Model:
class Babysitter < ApplicationRecord
has_many :jobs
has_many :babysitters, through: :jobs
Babysitter Model:
class Babysitter < ApplicationRecord
has_many :jobs
has_many :parents, through: :jobs
They have a has_many through relationship from the Job model:
Model Job:
class Job < ApplicationRecord
belongs_to :Babysitter, :touch => true
belongs_to :Parent
end
I now want to call babysitter.parents but have each parent also include the attribute salary (an attribute from the Jobs table).
Is this possible?
I tried:
babysitter.parents.includes(:jobs.salary)
Additionally is it possible to include the result in a fastJsonApi?
parents_including_salary = babysitter.parents.includes(:jobs.salary)
options = {
include: [:babysitter, :'parents_including_salary']}
json = Api::CampaignReportSerializer.new(otherData, options).serialized_json
I think you can use delegate to call the salary?
belongs_to :Parent
delegate :salary, to: :parent
you can try this
in your API can call parent.salary

Rails has_many association through a belongs_to polymorphic association

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

Dynamic has_many class_name using polymorphic reference

I am trying to associate a polymorphic model (in this case Product) to a dynamic class name (either StoreOnePurchase or StoreTwoPurchase) based on the store_type polymorphic reference column on the products table.
class Product < ActiveRecord::Base
belongs_to :store, polymorphic: true
has_many :purchases, class_name: (StoreOnePurchase|StoreTwoPurchase)
end
class StoreOne < ActiveRecord::Base
has_many :products, as: :store
has_many :purchases, through: :products
end
class StoreOnePurchase < ActiveRecord::Base
belongs_to :product
end
class StoreTwo < ActiveRecord::Base
has_many :products, as: :store
has_many :purchases, through: :products
end
class StoreTwoPurchase < ActiveRecord::Base
belongs_to :product
end
StoreOnePurchase and StoreTwoPurchase have to be separate models because they contain very different table structure, as does StoreOne and StoreTwo.
I am aware that introducing a HABTM relationship could solve this like this:
class ProductPurchase < ActiveRecord::Base
belongs_to :product
belongs_to :purchase, polymorphic: true
end
class Product < ActiveRecord::Base
belongs_to :store, polymorphic: true
has_many :product_purchases
end
class StoreOnePurchase < ActiveRecord::Base
has_one :product_purchase, as: :purchase
delegate :product, to: :product_purchase
end
However I am interested to see if it is possible without an extra table?
Very interesting question. But, unfortunately, it is impossible without an extra table, because there is no polymorphic has_many association. Rails won't be able to determine type of the Product.purchases (has_many) dynamically the same way it does it for Product.store (belongs_to). Because there's no purchases_type column in Product and no support of any dynamically-resolved association types in has_many. You can do some trick like the following:
class Product < ActiveRecord::Base
class DynamicStoreClass
def to_s
#return 'StoreOnePurchase' or 'StoreTwoPurchase'
end
end
belongs_to :store, polymorphic: true
has_many :purchases, class_name: DynamicStoreClass
end
It will not throw an error, but it is useless, since it will call DynamicStoreClass.to_s only once, before instantiating the products.
You can also override ActiveRecord::Associations::association to support polymorphic types in your class, but it is reinventing the Rails.
I would rather change the database schema.

Selecting objects direction from Favorite model

We have these models setup for users, categories and favorites:
class Favorite < ActiveRecord::Base
belongs_to :favoritable, polymorphic: true
belongs_to :user, inverse_of: :favorites
end
class User < ActiveRecord::Base
has_many :favorites, inverse_of: :user
end
class Category < ActiveRecord::Base
has_many :favorites, as: :favoritable
end
There are also some other objects that can be favorited (SubCategories, etc), and I would like to be able to grab the Category objects directly instead of a list of favorites:
#categories = #user.favorites.where(favoritable_type: "Category")
Is there way to grab a list of the actual Category objects through this #user object?
Have you tried just setting up a realtionship in user?
class User < ActiveRecord::Base
has_many :favorites, inverse_of: :user
has_many :categories, through: :favorites
end

Resources