I have a Collaboration model with a polymorphic association with a Grade | School, and a one-to-many association with a User
belongs_to :owner, polymorphic: true
belongs_to :user, foreign_key: "teacher_id"
this is the way i manage the users who can access a school or a grade. Now, what i need is to do something like this
School.first.teachers
Grade.first.teachers
I think it would be something like this in the Grade/School model
has_many :teachers, through: :collaborations, foreign_key: "teacher_id"
but it doesn't seem to be the right solution. Any ideas?
has_many :collaborations, :as => :owner
has_many :teachers, :through => :collaborations, :source => :user
You need to establish the polymorphic association to collaborations. Try:
class School < ActiveRecord::Base
has_many :collaborations, :as => :owner
has_many :teachers, :through => :collaborations
end
Related
I have a User model:
class User < ActiveRecord::Base
has_many :tracks, dependent: :destroy
has_many :tracked_locations, through: :tracks, source: :tracking, source_type: 'Location'
and a Track model (think of it as 'following'):
class Track < ActiveRecord::Base
belongs_to :user
belongs_to :tracking, polymorphic: true
end
The idea here is I will have many models to track / follow so I am using polymorphism. For example I have a Location model:
class Location < ActiveRecord::Base
has_many :tracks, :as => :tracking, :dependent => :destroy
has_many :users, through: :tracks
Now in the console Location.first.users works fine along with User.first.tracked_locations.
Now I will be adding another polymorphic relationship along the lines of Flagged. The user can 'flag' another model with a note etc. So if I add has_many :users, through: :flagged to the Location model for example I need to differentiate between tracking users and flagged users.
I tried:
has_many :tracking_users, through: :tracks, source: :tracking, source_type: 'User'
but I get:
NoMethodError: undefined method `evaluators_for' for #<Location:0x007ff29e5409c8>
Can I even do this or am I missing something simple here?
UPDATE
Based on the answer below I figured it out:
has_many :tracking_users, through: :tracks, class_name: "User", foreign_key: "user_id", source: :user
I'm not 100% on this, but you could try:
has_many :tracking_users, through: :tracks, class_name: "User", foreign_key: "user_id", source: :user
Or you could also just create a class method and do it by hand.
def self.tracking_users
user_ids = tracks.collect(&:user_id)
User.where(id: user_ids)
end
edit: Had a brainfart, changed the "source" up there to :user. That tells what table to actually do the lookup in with the other attribute you've provided. of course it wouldn't be in :tracks
I'm a designer/HTML+CSS dev learning Rails, and I'm having trouble with multiple user roles. My main models are as follows:
Studio
has_many :locations, dependent: :destroy
has_many :events, through: :locations
has_many :teachers, through: :events
Location
belongs_to :studio, :class_name => Studio, :foreign_key => "studio_id"
has_many :events
has_many :teachers, through: :events
Event
belongs_to :location, :class_name => Location, :foreign_key => "location_id"
belongs_to :studio
has_many :teachers
Teacher
belongs_to :event, :class_name => Event, :foreign_key => "event_id"
belongs_to :location
belongs_to :studio
has_one :user, :as => :roleable
accepts_nested_attributes_for :user
User
belongs_to :roleable, :polymorphic => true
The Teacher/User relationship is the tricky bit; I'm not sure if it should be reversed.
Users have basic profile info, Teachers have many details. All users can follow teachers, but teachers can also invite new teachers, and list other teachers as influences. I had this set up as
Teacher
has_many :guests, class_name: "Teacher", foreign_key: "host_id"
belongs_to :host, class_name: "Teacher"
has_many :influences, class_name: "Teacher", foreign_key: "student_id"
belongs_to :student, class_name: "Teacher"
User
has_many :favorites, class_name: "User", foreign_key: "fan_id"
belongs_to :fan, class_name: "User"
Does this look right, or should I say that User has_one :teacher ? The latter seems more correct, but it made my views really difficult. Thanks in advance!
I have 3 tables:
User class
User has_many :project_assignments
User has_many :projects, through: :project_assignments
ProjectAssignment class
ProjectAssignment belongs_to :user
ProjectAssignment belongs_to :project_owner, class_name: 'User', foreign_key: 'user_creator_id'
ProjectAssignment belongs_to :project
Project
has_many :project_assignments
has_many :users, through: :project_assignments
ProjectAssignment has the columns:
project_id, user_id, creator_user_id
I want to get all the projects, for a user through creator_user_id
ex: current_user.created_projects
The query: ProjectAssignment.where(creator_user_id: current_user.id)
Can it be done when defining the relations in the models, the same as I did with projects but the foreign_key should be creator_user_id
I think you just need another couple of associations in User which leverage the creator_user_id field (as opposed to user.projects which will return the projects the user is a member of)
Try this -
#in User class
has_many :owned_project_assignments, :class_name => "ProjectAssignment", :as => :project_owner, :foreign_key => "user_creator_id"
has_many :owned_projects, :through => owned_project_assignments, :class_name => "Project", :source => :project, :as => :project_owner
the :source and :as options can be a bit tricksy, so this might not work, it's just off the top of my head...
In my case this was the correct solution:
has_many :owned_project_assignments, class_name: "ProjectAssignment", foreign_key: 'user_creator_id'
has_many :owned_projects, through: :owned_project_assignments, source: :project
Trying to get to total number of users for a given event and I'm thinking what I've got should work, but I get the following:
Could not find the source association(s) :squads_users in model Squad. Try 'has_many :users, :through => :squads, :source => '. Is it one of :team, :event, :event_division, :users, :point_adjustments, :checkpoint_squads, :division, or :checkpoints?
My ActiveRecord Kung Fu is weak :-/
Event
has_many :squads
has_many :users, :through => :squads
Team
has_many :squads
Squad
belongs_to :event
belongs_to :team
has_and_belongs_to_many :users
SquadsUsers
belongs_to :user
belongs_to :squad
User
has_and_belongs_to_many :squads
Is your join model really named SquadsUsers? That might be the problem. It should be SquadUser.
Also, I think you want a many-to-many relationship between Event and Team, not Event and Squad, correct? In which case you need this:
Event
has_many :event_teams
has_many :teams, :through => :event_teams
EventTeam
belongs_to :event
belongs_to :team
Team
has_many :squads
Squad
belongs_to :team
has_many :squad_users
has_many :users, :through => :squad_users
SquadUser
belongs_to :squad
belongs_to :user
User
has_many :squads
You should remove your SquadsUsers model and just have a table called squads_users. has_and_belongs_to_many will automatically use this table without needing the additional model.
I have a schema where:
Students
has_and_belongs_to_many :courses
has_many :grades, :dependent => :destroy
has_many :assignments, :through => :grades
Courses
has_many :assignments, :dependent => :destroy
has_and_belongs_to_many :students
Assignments
belongs_to :course
has_many :grades, :dependent => :destroy
has_many :students, :through => :grades
Grades
belongs_to :student
belongs_to :assignment
I would like to add functionality whereby if a grade is added and the student does not belong to the course that the grade's assignment belongs to, then this relationship is made. Any suggestions as to the best way to do this? The grades_courses table does not have it's own model, will this need to be made?
A friend has suggested using after_create, but I don't know how to pass the parameters to this.
How about an observer on grades? Something like this
class GradeObserver < ActiveRecord::Observer
def after_create(grade)
unless grade.assignment.course.students.include?(grade.student)
grade.assignment.course.students << grade.student
end
end
end