Polymorphics in Rails ' uninitialized constant' error - ruby-on-rails

I wanted to make polymorphic association in my project so I followe rails guide to do it but I got: NameError: uninitialized constant DashboardAssignment::Assignable
error.
Models:
DashboardAssignment:
class DashboardAssignment < ActiveRecord::Base
belongs_to :dashboard
belongs_to :assignable, polymorphic: true
validates :dashboard, presence: true
validates :assignable, presence: true, uniqueness: { :scope => :dashboard }
end
User:
class User < ActiveRecord::Base
has_many :dashboard_assignments, as: :assignable
has_many :dashboards, through: :dashboard_assignments
end
Group:
class Group < ActiveRecord::Base
has_one :dashboard_assignment, as: :assignable
has_many :laboratories_assignments, as: :lab_assignable
end
Dashboard:
class Dashboard < ActiveRecord::Base
has_one :building
has_many :dashboard_assignments
has_many :users, through: :dashboard_assignments, as: :assignable
end
In DashboardAssignment Migration file I have:
t.references :assignable, null: false, polymorphic: true, index: true
When I try to create new DashboardAssignment by DashboardAssignment.create(assignable: u) where u = User.find(1)
it gives me error:
NameError: uninitialized constant DashboardAssignment::Assignable
from P:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/inheritance.rb:158:in `compute_type' ...
Am I doing something wrong?
My rails version is 4.2.6

You should be using source instead of as in a through association
class Dashboard < ActiveRecord::Base
has_one :building
has_many :dashboard_assignments
has_many :users, through: :dashboard_assignments, source: :assignable
end
I would caution though that this might give you assignables that are of class Group. The best way to go around this issue is by adding a condition to a has_many for dashboard_assignments that let's you filter only for dashboard_assignments that have assignable_type = 'User':
class Dashboard < ActiveRecord::Base
has_one :building
has_many :user_dashboard_assignments, -> { where(assignable_type: 'User') }, class_name: 'DashboardAssignment'
has_many :users, through: :user_dashboard_assignments, source: :assignable
end

Related

ActiveRecord::HasManyThroughAssociationNotFoundError cannot get the posts for each user for some reason Rails

In the rails console I am inputing User.first.posts and i am getting this error ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :likes in model User
from
USER MODEL
class User < ApplicationRecord
has_secure_password
has_many :posts
has_many :comments
has_many :posts, through: :likes
validates :name, presence: true, uniqueness: true
end
POSTS MODEL
class Post < ApplicationRecord
belongs_to :user
has_many :comments
has_many :likes
has_many :users, through: :likes
def number_of_comments
comments.length
end
def number_of_likes
likes.length
end
end
LIKES MODEL
class Like < ApplicationRecord
belongs_to :user
belongs_to :post
end
Im only showing you the likes model because its popping up in the error but i just want all the posts for each user so if i type User.first.posts all their posts will show up
You need to actually define the likes assocation that you're defining the indirect assocation through:
class User < ApplicationRecord
# ...
has_many :likes # this was missing
has_many :posts, through: :likes
end
But you also have two different assocations between users and posts that are sharing the same name - you actually need something more like:
class User < ApplicationRecord
has_many :posts # posts that this user has created
has_many :likes
has_many :liked_posts,
through: :likes,
source: :post
end
There's seems to be a typo in your User model. There are 2 associations for posts.
class User < ApplicationRecord
has_secure_password
has_many :posts
has_many :comments
# has_many :posts, through: :likes # <-- this i think is the culprit.
# it should be like this:
has_many :likes, through: :posts
validates :name, presence: true, uniqueness: true
end

Finding all Admins using Rails Associations

How do I find all admins using Rails 6 active record associations?
I have the following classes:
class Group < ApplicationRecord
has_many :relationships, dependent: :destroy
has_many :users, through: :relationships
end
class User < ApplicationRecord
has_many :posts, dependent: :destroy
has_many :relationships, dependent: :destroy
has_many :groups, through: :relationships
end
class Relationship < ApplicationRecord
belongs_to :user
belongs_to :group
validates :user_id, presence: true
validates :group_id, presence: true
validates :admin, inclusion: [true, false]
I'd like to add admins as a has_many relationship in Group.
Here's my first attempt at doing so:
has_many :admins, class_name: "User", through: :relationships
How would I filter those users whose relationship to the group has the admin attribute set to true?
Associations can be scoped using the normal query syntax.
class Group < ApplicationRecord
...
has_many :admins,
-> { where({ relationships: { admin: true} }) },
through: :relationships,
source: :user
end
source is necessary because otherwise it will try to do the has_many through Relationships.admins.
group.admins is equivalent to group.users.where({ relationships: { admin: true} }).
You could've modified your Group model to something like:
class Group < ApplicationRecord
scope :admins, -> { where(relationships: { admin: true }) }
has_many :relationships, dependent: :destroy
has_many :users, through: :relationships
end
From it you can use Group.joins(:users).admins to get groups with assoiciated admins.

Rails belongs_to/has_many with external Model

In my Rails 5.2 application I want to reference another Model. I have the following setup in the application:
class SomeModule::AnotherModule::User < ApplicationRecord
has_many :phones
end
class Phone < ApplicationRecord
belongs_to :user, optional: true, class_name: '::SomeModule::AnotherModule::User'
end
The migration was done like so:
add_reference :phones, :user, foreign_key: true, index: true
Now, when I try to call upon the user from a phone I get this:
Phone.first.user
#=> NameError: uninitialized constant User::Phone
from /home/testuser/.rvm/gems/ruby-2.5.1/gems/activerecord-5.2.0/lib/active_record/inheritance.rb:196:in `compute_type'
Removing the class_name: attribute does not change anything.
What am I doing wrong?
class SomeModule::AnotherModule::User < ApplicationRecord
has_many :phones, class_name: 'Phone', foreign_key: 'user_id'
end
class Phone < ApplicationRecord
belongs_to :user, optional: true, class_name: 'SomeModule::AnotherModule::User', foreign_key: 'user_id'
end

Gem `activity_notification` does not create a new record after getting triggered by an active record

The gem activity_notification is not creating/triggering after I've configured it according to the documentation. I've tried to create the notification in the event of a user creating a comment or replying to an existing comment, but the gem is not created/triggered. Please help me figure out why.
Here's my code
Model User
class User < ApplicationRecord
audited
with_options dependent: :destroy do |assoc|
assoc.has_many :forums, class_name: 'Communication::Forum'
assoc.has_many :favorited_forums, class_name: 'Communication::FavoritedForum'
assoc.has_many :comments
assoc.has_many :likes
end
acts_as_target
end
Model Forum
class Communication::Forum < ApplicationRecord
audited
belongs_to :user
acts_as_commentable
has_many :likes, as: :likeable
has_many :favorited_forums, class_name: "Communication::FavoritedForum"
end
Model Comment
class Comment < ActiveRecord::Base
audited
acts_as_nested_set scope: [:commentable_id, :commentable_type]
belongs_to :commentable, polymorphic: true
acts_as_notifiable :users,
targets: ->(comment, key) {
([comment.commentable.user] + [comment.user]).uniq
}
end

How do I properly alias a has_many through a join in Rails ActiveRecord?

Rails/ActiveRecord newbie here. Consider the following models for a Classroom, User and ClassroomEnrollments (join between the two)
class Classroom < ActiveRecord::Base
has_many :fulltime_enrollments, -> { where(duration: 'full-time') }, class_name: "ClassroomEnrollments"
has_many :fulltimers, :through => :fulltime_enrollments, class_name: "User"
has_many :parttime_enrollments, -> { where(duration: 'part-time') }, class_name: "ClassroomEnrollments"
has_many :parttimers, :through => :parttime_enrollments, class_name: "User"
end
class ClassroomEnrollment < ActiveRecord::Base
# columns: user_id, classroom_id, duration
belongs_to :user
belongs_to :classroom
end
class User < ActiveRecord::Base
has_many :classroom_enrollments
has_many :classrooms, :through => :classroom_enrollments
end
The following model for a classroom and classroom_enrollments does not work. Specifically the :fulltimers and :parttimers aliases throw undefined method 'to_sym' for nil:NilClass errors when I try to access them via my_classroom.fulltimers or my_classroom.parttimers.
If I remove the :parttimers alias and rename :fulltimers to :users it works fine (and displays only the full time students), so it seems to me that it has something to do with it figuring out that :fulltimers is of type User, even though I've specified the classname: "User" in the has_many condition.
What am I doing wrong?
Since the source association cannot be inferred automatically, you need specify it using the :source option:
class Classroom < ActiveRecord::Base
has_many(
:fulltime_enrollments,
-> { where(duration: 'full-time') },
class_name: "ClassroomEnrollments"
)
has_many :fulltimers, :through => :fulltime_enrollments, :source => :user
has_many(
:parttime_enrollments,
-> { where(duration: 'part-time') },
class_name: "ClassroomEnrollments"
)
has_many :parttimers, :through => :parttime_enrollments, :source => :user
end
http://guides.rubyonrails.org/association_basics.html#options-for-has-many-source
How about trying a cleaner, more readable approach? Something like this:
class Classroom < ActiveRecord::Base
has_many :classroom_enrollments
has_many :users, through: :classroom_enrollments
def full_timers
users_by_duration("full-time")
end
def part_timers
users_by_duration("part-time")
end
private
def users_by_duration(duration)
users.where(classroom_enrollments: { duration: duration })
end
end
Then:
my_classroom = Classroom.find(1)
my_classroom.full_timers
I stumbled on this while working on something similar. This is will generate the same sql and is a bit easier to look at.
class Classroom < ActiveRecord::Base
has_many :classroom_enrollments
has_many :users, through: :classroom_enrollments
def fulltimers
users.merge(ClassroomEnrollment.full_time)
end
def parttimers
users.merge(ClassroomEnrollment.part_time)
end
end
class ClassroomEnrollment < ActiveRecord::Base
belongs_to :user
belongs_to :classroom
scope :fulltime, ->{ where(duration: 'full-time') }
scope :parttime, ->{ where(duration: 'part-time') }
end
class User < ActiveRecord::Base
has_many :classroom_enrollments
has_many :classrooms, :through => :classroom_enrollments
end

Resources