Active Model Serializer causes endless loop and SystemStackError - ruby-on-rails

I have a serializer for my Client model that causes an endless loop when I include has_many :referrers in the ClientSerializer.
class Client < ActiveRecord::Base
has_many :referrals, class_name: 'Referral', foreign_key: 'referrer_id'
has_many :referrals_as_referred, class_name: 'Referral', foreign_key: 'referred_id'
has_many :referred_clients, through: :referrals, source: :referred
has_many :referrers, through: :referrals_as_referred, source: :referrer
end
class Referral < ActiveRecord::Base
belongs_to :referrer, class_name: 'Client'
belongs_to :referred, class_name: 'Client'
end
In my serializer, the following works successfully:
class API::ClientSerializer < ActiveModel::Serializer
attributes :referrers
# has_many :referrers
has_many :referrals
def referrers
object.referrers
end
end
But this causes the infinite loop and stack error:
class API::ClientSerializer < ActiveModel::Serializer
has_many :referrers
has_many :referrals
end
Why is this occurring?

Related

ActiveRecord grab shared model from polymorphic association

I'm looking for a better way to query Users from 2 different Models used in a polymorphic association. Here is the setup
class Schedule < ApplicationRecord
belongs_to :announcement
has_many :targets, dependent: :destroy
has_many :lists, through: :targets, source: :target, source_type: 'List'
has_many :accounts, through: :targets, source: :target, source_type: 'Account'
end
class Target < ApplicationRecord
# belongs_to :announcement
belongs_to :schedule
belongs_to :target, polymorphic: true
delegate :announcement, to: :schedule
end
class List < ApplicationRecord
belongs_to :account
has_many :targets, as: :target, dependent: :destroy
has_many :lists_users
has_many :users, through: :lists_users
end
class Account < ApplicationRecord
has_many :announcements, dependent: :destroy
has_many :targets, as: :target, dependent: :destroy
has_many :users, dependent: :destroy
end
At the moment I'm solving this by creating a method inside the Schedule model that grabs Users this way:
def subscribers
targets.map(&:target).map(&:users).flatten.uniq
end
I looked at something similar with this question, but didn't seem to solve it.
I would do that like this:
class Schedule < ApplicationRecord
def subscribers
# fetch all associated user IDs
lists_user_ids = lists.joins(:lists_users).distinct.pluck("lists_users.user_id")
accounts_user_ids = accounts.joins(:users).distinct.pluck("users.id")
user_ids = (lists_user_ids + accounts_user_ids).uniq
# fetch users by IDs
User.where(id: user_ids)
end
end

ActiveRecord::HasManyThroughOrderError: Cannot have a has_many :through association

In my rails app I'm trying to create a system that will reward users with badges for various achievements
created a table 'user_badges'
migration:
class CreateUserBadges < ActiveRecord::Migration[5.1]
def change
create_table :user_badges do |t|
t.references :user, foreign_key: true
t.references :badge, foreign_key: true
t.timestamps
end
end
end
model UserBadge:
class UserBadge < ApplicationRecord
belongs_to :user
belongs_to :badge
end
модель Badge:
class Badge < ApplicationRecord
has_many :users, through: :user_badges
has_many :user_badges
end
model User:
class User < ApplicationRecord
...
has_many :badges, through: :user_badges
has_many :user_badges
...
end
when I try to add a badge to the user:
b = Badge.create(title: 'first')
User.last.badges << b
I get this error:
ActiveRecord::HasManyThroughOrderError: Cannot have a has_many
:through association 'User#badges' which goes through
'User#user_badges' before the through association is defined.
also when I simply call:
User.last.badges
same error:
ActiveRecord::HasManyThroughOrderError: Cannot have a has_many
:through association 'User#badges' which goes through
'User#user_badges' before the through association is defined.
Define has_many association first then add through: association
class UserBadge < ApplicationRecord
belongs_to :user
belongs_to :badge
end
class Badge < ApplicationRecord
has_many :user_badges # has_many association comes first
has_many :users, through: :user_badges #through association comes after
end
class User < ApplicationRecord
...
has_many :user_badges
has_many :badges, through: :user_badges
...
end
Note, in case you mistakenly wrote first has_many 2 times, then it can reproduce this error too. E.g.
class User < ApplicationRecord
...
has_many :user_badges
has_many :badges, through: :user_badges
...
has_many :user_badges
end
# => Leads to the error of ActiveRecord::HasManyThroughOrderError: Cannot have a has_many :through association 'User#badges' which goes through 'User#user_badges' before the through association is defined.
Active Record should alert has_many being used two times IMHO...

Pluralized many-to-many but still uninitialized constant

As per the below I think this setup is fine:
class Location < ActiveRecord::Base
has_many :traders
has_many :servicelocations
has_many :services, through: :servicelocations
end
class Service < ActiveRecord::Base
has_many :servicelocations
has_many :locations, through: :servicelocations
end
class ServiceLocation < ActiveRecord::Base
belongs_to :location
belongs_to :service
end
class Trader < ActiveRecord::Base
belongs_to :location
end
The problem is I am still getting an uninitialized constant error.
I have noticed that as I created the model ServiceLocation, funky rails magic created service_location.rb but I am unsure if a) this is the problem and b) how to fix it if it is.
I believe your error came from this
class Service < ActiveRecord::Base
has_many :servicelocations
has_many :locations, through: :servicelocations
end
These should be like this
class Service < ActiveRecord::Base
has_many :service_locations
has_many :locations, through: :service_locations # notice the underscore
end
Your model Class name is ServiceLocation and the rails convention name for this is service_location not servicelocation
And here also,you have to change
class Location < ActiveRecord::Base
has_many :traders
has_many :service_locations
has_many :services, through: :service_locations
end
I guess ruby understand servicelocations like one word, so you need to change model to Servicelocation or change association to service_locations. Second method i guess is better, it would be like:
class Location < ActiveRecord::Base
has_many :traders
has_many :service_locations
has_many :services, through: :service_locations
end
class Service < ActiveRecord::Base
has_many :service_locations
has_many :locations, through: :service_locations
end

has_one :through polymorphic association

I have these models and associations. I want to reach roleable trough privilege model doesnt matter what roleable_type is(Dj or Photographer)? Use join model because privilege model will have other attributes. It is possible something like this:
class User
has_one :privilege, dependent: :destroy
has_one :roleable, through: :privilege
end
class Dj < ActiveRecord::Base
has_one :privilege
has_one :user, through: :privilege, as: :roleable
end
class Photographer < ActiveRecord::Base
has_one :privilege
has_one :user, through: :privilege, as: :roleable
end
class Privilege < ActiveRecord::Base
belongs_to :user
belongs_to :roleable, polymorphic: true
end
If i add source_type: 'Dj' to has_many :through return only with roleable_type 'Dj'. I want to do this bellow:
u = User.first
u.roleable #return privilage roleable( doesnt matter Dj or Photograher)
I'd make those belongs_to, not that that changes anything.
class User < ActiveRecord::Base
has_one :privilege, dependent: :destroy
has_one :roleable, through: :privilege
end
class Dj < ActiveRecord::Base
has_one :privilege
belongs_to :user, through: :privilege, as: :roleable
end
class Photographer < ActiveRecord::Base
has_one :privilege
belongs_to :user, through: :privilege, as: :roleable
end
class Privilege < ActiveRecord::Base
belongs_to :user
belongs_to :roleable, polymorphic: true
end
Can you post, what u.roleable returns?

has_many through polymorphic with custom type

I have 2 applications one that serves as an API and has read only access and one that is the primary application. In the primary app, I have a has many through polymorphic relationship. The models in the main app look like so, and they work great:
class Category < ActiveRecord::Base
has_many :category_associations
has_many :posts, through: :category_associations
has_many :pages, through: :category_associations
end
class Post < ActiveRecord::Base
has_many :category_associations, as: :associated
has_many :categories, as: associated, through: :category_associations, source: :post
end
class Page < ActiveRecord::Base
has_many :category_associations, as: :associated
has_many :categories, as: associated, through: :category_associations, source: :post
end
class CategoryAssociation
belongs_to :category
belongs_to :associated, polymorphic: true
end
Now for the second app I will need to access the same tables but my class names will be different, this effects the type field that I cannot seem to override even with source_type.:
class Category < ActiveRecord::Base
has_many :category_associations
has_many :articles, through: :category_associations
has_many :static_contents, through: :category_associations
end
class Article < ActiveRecord::Base
self.table_name = 'posts'
has_many :category_associations, as: :associated
has_many :categories, as: associated, through: :category_associations, source: :article, source_type: 'Post'
end
class StaticContent < ActiveRecord::Base
self.table_name = 'pages'
has_many :category_associations, as: :associated
has_many :categories, as: associated, through: :category_associations, source: :static_content, source_type: 'Page'
end
class CategoryAssociation
belongs_to :category
belongs_to :associated, polymorphic: true
end
I get the following Error:
=> Posts.first.categories
# ActiveRecord::HasManyThroughAssociationPointlessSourceTypeError: Cannot have a has_many :through association 'Post#categories' with a :source_type option if the 'CategoryAssociation#category' is not polymorphic. Try removing :source_type on your association.
It also seems that when I grab the posts from the category
Have you tried putting polymorphic:true to the category belongs_to? It seems that's the direction pointed by the error message points, though I'm not sure
class CategoryAssociation
belongs_to :category, polymorphic: true
...
end

Resources