Serialize nested attributes in Rails? - ruby-on-rails

So I have models like this:
folder, up_file has 1 chat_room
chat_room belongs to crmable with polymorphic: true (so 1 chat_room may belongs to folder or 1 up_file)
chat_room has many comments
comment belongs to chat_room and user (who posted the comment)
I've defined all relationship like this:
class Folder < ApplicationRecord
has_one :chat_room, as: :crmable, dependent: :destroy
end
class UpFile < ApplicationRecord
has_one :chat_room, as: :crmable, dependent: :destroy
end
class ChatRoom < ApplicationRecord
belongs_to :crmable, polymorphic: true
has_many :comments, dependent: :destroy
has_many :users, through: :comments
end
class Comment < ApplicationRecord
belongs_to :chat_room
belongs_to :user
end
This setup worked fine with my web app. However, I'm writing API for this app, and I can't get that nested associations serialized with this gem
https://github.com/rails-api/active_model_serializers
I've follow their tutorial here but my associations not rendered.
class FolderSerializer < ActiveModel::Serializer
attributes :id, :name, :ancestry, :creator_name #... my other attributes
has_one :chat_room, include: [ :id, comments: :user ]
# ^ I tried to serialize folder's chat_room with all it comments, along with these comments' users.
end
All I got is this - chat_room association not serialized?

Related

Ruby on Rails: Polymorphic Association Confusion

I am contributing one of the ruby on rails application over GitHub where I faced the following scenario:
I am having following models which I want to convert to make polymorphic:
class Comment < ActiveRecord::Base
belongs_to :team
belongs_to :user
belongs_to :application
belongs_to :project
end
class Team < ActiveRecord::Base
has_many :comments
end
class Project < ActiveRecord::Base
has_many :comments, -> { order('created_at DESC') }, dependent: :destroy
end
class User < ActiveRecord::Base
end
class Application < Rails::Application
end
I made following changes to make it polymorphic:
Perform database change to removed team_id, project_id, application_id and user_id and added commentable_id and commentable_type to comments table.
Modifications in models as described within rails guides.:
class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
end
class Team < ActiveRecord::Base
has_many :comments, as: :commentable
end
class Project < ActiveRecord::Base
has_many :comments, as: :commentable, -> { order('created_at DESC') }, dependent: :destroy
end
While I use it with default scope, It doesn't allow me to use with default scope and gives error with below line:
has_many :comments, as: :commentable, -> { order('created_at DESC') }, dependent: :destroy
I am confused to change in following models:
class User < ActiveRecord::Base
end
class Application < ActiveRecord::Base
end
Should I need following changes in User and Application model?
class User < ActiveRecord::Base
has_many :comments, as: :commentable
end
class Application < ActiveRecord::Base
has_many :comments, as: :commentable
end
Thanks in Advance!
if your user/application object needs comments then add
class User < ActiveRecord::Base
has_many :comments, as: :commentable
end
class Application < ActiveRecord::Base
has_many :comments, as: :commentable
end
else create belongs_to/has_many relationship not polymorphic
Eg.
class User < ActiveRecord::Base
has_many :comments
end
class Application < ActiveRecord::Base
has_many :comments
end

Active Record association has_many with multiple foreign keys

I'm trying to set up a referral model. A referral contains a user who is referred, a user who does the referring, and a doctor
class User < ActiveRecord::Base
has_many :referrals
belongs_to :profile, polymorphic: true
end
class Referral < ActiveRecord::Base
belongs_to :user
belongs_to :referrer, :class_name => "User"
belongs_to :doctor, :class_name => "User"
end
I'm able to create the generic has_many :referrals to see doctors that have been referred to the user however I'd also like to see the doctors that you've referred to others (using the referrer column).
I've tried has_many :doctors_referred, primary_key: "referrer_id" and has_many :doctors_referred, through: :referrals ,source: "referrer" with no luck. How can I see which doctors a user has referred?
# mostly irrelevant
class PatientProfile < ActiveRecord::Base
has_one :user, as: :profile
end
class DoctorProfile < ActiveRecord::Base
has_one :user, as: :profile
end
My first attempt would be this:
class User < ActiveRecord::Base
has_many :referrals_as_referrer, source: :referred
has_many :referrals_as_referree, source: :user
has_many :doctors_as_referrer, through: :referrals_as_referrer
has_many :doctors_as_referree, through: :referrals_as_referree
end
The issue here is that saying has_many :referrals isn't enough because you can have a referral where you were the referrer or one where you were the referree. With this you can type user.referrals_as_referrer which will give a list of referrals where user is the referrer. You can also write user.doctors_as_referrer which will go through the previous association and retrieve a list of users that represent doctors which were referred by a referral in the user.referrals_as_referrer list.
I haven't tested this and I might be wrong, but let's iterate once you try it out.

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.

Retrieve polymorphic associations in Rails from one model

class User < ActiveRecord::Base
has_many :posts
has_many :images, as: :imageable
end
class Post < ActiveRecord::Base
belongs_to :user
has_many :images, as: :imageable
end
class Image < ActiveRecord::Base
belongs_to :imageable, polymorphic: true
end
Is there a specific way where I can do User.images and get both the user's images and the post's images that belong to that user?
For some reason I can't wrap my head around how to do this best.
In that case you can avoid polymorphic relationship, simple has_many and belongs_to will suffice. where :
class User ActiveRecord::Base
has_many :posts
has_many :images
end
class Post ActiveRecord::Base
belongs_to :user
has_many :images
end
class Image < ActiveRecord::Base
belongs_to :post
belongs_to :user
end
But then again I think you wanted to ask about User.last.images and not User.images
the same can be done through has_many through associations as well

How to query for attachments for a specific project

I have a Project model, which has many posts and tasks. Both posts and tasks have many attachments. Attachment is polymorphic. How can I query all the attachments for a single project?
Obviously this doesn't work because we don't have an attachable table; we have posts and tasks. It also produces a can't eager load polymorphic association 'attachable'.
# project.rb
def attachments
Attachment.joins(:attachable).where('attachable.project_id = ?', id)
end
Rest of code:
class Project < ActiveRecord::Base
has_many :posts
has_many :tasks
end
class Post < ActiveRecord::Base
belongs_to :project
has_many :attachments, as: :attachable
end
class Task < ActiveRecord::Base
belongs_to :project
has_many :attachments, as: :attachable
end
class Attachment < ActiveRecord::Base
belongs_to :attachable, polymorphic: true
end

Resources