Rails Relationship Help - ruby-on-rails

I have simplified my design to make this question more clear. (Design of models below)
What I am trying to do is from a CourseEnrollment get all the PatientCourseSteps for that enrollment only (An enrollment consists of a patient and a course).
Here is what I have tried:
#Gives me ALL the patient course steps regardless of the course
course_enrollment.patient.patient_course_steps
#Gives me ALL the patient course steps regardless of the patient
course_enrollment.course.patient_course_steps
Below is the models that are necessary
class CourseEnrollment < ActiveRecord::Base
belongs_to :patient
belongs_to :course
end
class Course < ActiveRecord::Base
has_many :course_steps, :dependent => :destroy
has_many :steps, :through => :course_steps
has_many :course_enrollments, :dependent => :destroy
has_many :patients, :through =>:course_enrollments
has_many :patient_course_steps, :dependent => :destroy
end
class Patient < ActiveRecord::Base
belongs_to :user, :dependent => :destroy
has_many :enrollments, :dependent => :destroy
has_many :clients, :through => :enrollments
has_many :course_enrollments, :dependent => :destroy
has_many :courses, :through => :course_enrollments
has_many :patient_course_steps, :dependent => :destroy
end
class Step < ActiveRecord::Base
belongs_to :step_type
belongs_to :client
has_one :step_quiz, :dependent => :destroy
has_one :step_survey, :dependent => :destroy
has_one :step_text, :dependent => :destroy
has_one :step_download, :dependent => :destroy
has_one :step_video, :dependent => :destroy
has_one :step_presentation, :dependent => :destroy
has_many :course_steps, :dependent => :destroy
has_many :courses, :through => :course_steps
has_many :patient_course_steps, :dependent => :destroy
end
class PatientCourseStep < ActiveRecord::Base
belongs_to :patient
belongs_to :course
belongs_to :step
end

What I ended up doing was adding a method to CourseEnrollment named patient_course_steps which queries for what I need.
def patient_course_steps
PatientCourseStep.where(:patient_id => self.patient_id, :course_id => self.course_id)
end

Related

Rails dependent destroy not working

I have User and Organization model. User has_many :organizations and Organization has_many :users.
When I want to destroy user from db using #user.destroy I get error Key (id)=(3) is still referenced from table "organizations".
Here is my User and Organization models:
Organization.rb
class Organization < ApplicationRecord
extend FriendlyId
friendly_id :name, :use => :slugged
has_many :members, :dependent => :destroy
has_many :users, :through => :members, :dependent => :destroy
has_many :moderators, -> { where :members => { :role => 1 } }, :through => :members, :source => :user
has_many :admins, -> { where :members => { :role => 2 } }, :through => :members, :source => :user
has_many :campains, :dependent => :destroy
has_many :statuses, :as => :statusable
has_many :activities
has_many :world_members
has_many :teams
accepts_nested_attributes_for :members, :users
User.rb
class User < ApplicationRecord
extend FriendlyId
friendly_id :full_name, :use => :slugged
acts_as_voter
enum role: [:user, :moderator, :organization, :admin]
has_many :members, :class_name => "Member", :foreign_key => "user_id", :dependent => :destroy
has_many :organizations, :through => :members, :dependent => :destroy
has_many :conversations, :foreign_key => :sender_id
has_many :admin_organizations, ->{ where(members: {role: 2}) }, :through => :members, source: :organization
has_many :moderate_organizations, ->{ where(members: {role: 1}) }, :through => :members, source: :organization
has_many :member_organizations, ->{ where(members: {role: 0}) }, :through => :members, source: :organization
accepts_nested_attributes_for :members, :organizations
Member.rb
class Member < ApplicationRecord
enum role: [:member, :moderator, :admin]
belongs_to :user
belongs_to :organization
You should not have dependent_destroy for :organizations or :users, just for :members.
You do not have direct relation from organization to user, nor from user to organization.
class User < ActiveRecord::Base
has_many :members, dependent: :destroy
has_many :organizations, through: :members
end
class Organization < ActiveRecord::Base
has_many :members, dependent: :destroy
has_many :users, through: :members
end
class Member < ActiveRecord::Base
belongs_to :user
belongs_to :organization
end
As you do not want to delete all users for example from an organization, just there reference to the organization and vice verse if you delete user, you do not want to delete all organizations on which user was connected to, just the reference

Rails find and calculate using has_many through releationship

I have following models:
Product:
class Product < ActiveRecord::Base
has_many :product_recommendations, :dependent => :destroy
has_many :recommendations, :through => :product_recommendations
end
ProductRecommendation:
class ProductRecommendation < ActiveRecord::Base
belongs_to :recommendation
belongs_to :product
end
Recommendation:
class Recommendation < ActiveRecord::Base
has_many :product_recommendations, :dependent => :destroy
has_many :products, :through => :product_recommendations
has_many :recommendation_ratings, :dependent => :destroy
has_many :ratings, :through => :recommendation_ratings
end
Rating:
class Rating < ActiveRecord::Base
has_many :recommendation_ratings, :dependent => :destroy
has_many :recommendations, :through => :recommendation_ratings
end
RecommendationRating:
class RecommendationRating < ActiveRecord::Base
belongs_to :recommendation
belongs_to :rating
end
How would I be able to calculate the average rating for a given recommendation? My ratings table contains just 4 records, (Ratings 1-4), and I have an action in my recommendation controller which updates the RecommendationsRatings join table to associate a rating with a recommendation. Thanks!
have you tried:
class Product < ActiveRecord::Base
has_many :product_recommendations, :dependent => :destroy
has_many :recommendations, :through => :product_recommendations
has_many :ratings, :through => :recommendations
end
and then
p = Product.find 1
p.ratings.average(:rating)
this is assuming the Ratings model has an int / float called rating which stores the rating

has_one :through polymorphic - is it possible?

I have models in my app:
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
class Project < ActiveRecord::Base
has_many :discussions, :dependent => :destroy
has_many :tickets, :dependent => :destroy
end
class Discussion < ActiveRecord::Base
has_many :comments, :as => :commentable, :dependent => :destroy
end
class Ticket < ActiveRecord::Base
has_many :comments, :as => :commentable, :dependent => :destroy
end
Everything works fine, but sometimes it's not very convinient to get project from comment through commentable, i.e. comment.commentable.project.
Is there any way to make has_one project in Comment model?
I would add the following method to your class Comment:
def project
self.commentable ? self.commentable.project : nil
end
This will give you the same result without all the magic of ActivRecord.

:has_many relationship with :through on another relationship with :through

My setup is as follows:
class User < ActiveRecord::Base
has_many :owners, :dependent => :destroy
has_many :properties, :through => :owners
end
class Owner < ActiveRecord::Base
belongs_to :user
belongs_to :property
end
class Property < ActiveRecord::Base
has_many :owners, :dependent => :destroy
has_many :users, :through => :owners
has_many :datafiles, :dependent => :destroy
end
class Datafile < ActiveRecord::Base
belongs_to :property
end
Now I'd like to be able to do #user.datafiles.
I tried has_many :datafiles, :through => :properties, :source => :datafiles but there appears to be a problem with a :through on something that's already went to a :through. So how would I go about to try and manage what I'm trying to do here?
Thank you in advance.
2 approaches;
1>
class User < AR
has_many :owners, :dependent => :destroy
has_many :properties, :through => :owners
has_many datafiles
end
class Datafile < AR
belongs_to :user
belongs_to :property
end
Your requirement of user.datafiles should be fulfilled with this.
If you want a nested has_many through, you'll need to use a plugin which is the 2nd approach.
2>
You can find it here.
The plugin works out of the box and does the job.
How about something like:
#user.rb
def datafiles
Property.find(:all, :joins => :owners, :conditions => ['owners.user_id = self.id'], :include => :datafile).collect(&:datafile)

Rails relation select

I have the following models:
class User < ActiveRecord::Base
has_many :results, :dependent => :destroy
has_many :participants, :dependent => :destroy
has_many :courses, :through => :participants
end
class Course < ActiveRecord::Base
has_many :tests, :dependent => :destroy
has_many :participants, :dependent => :destroy
has_many :users, :through => :participants
end
class Result < ActiveRecord::Base
belongs_to :test
belongs_to :user
end
class Test < ActiveRecord::Base
belongs_to :course
has_many :results, :dependent => :destroy
end
The Idea is that a user has_and_belongs_to_many courses, the course has_many tests, and every test has_and_belongs_to_many users (results).
So what is the best query to select every Result from a single Course (not test), and also the query to select every Result from a single Course, but from one user.
Thanks!
To get the results from a specific course - given that the only bridge between the two is the test model you will need to include the test in the query.
Result.find(:all, :conditions => ["tests.course_id = ?",#course.id], :include => :test)
For the second query:
Result.find(:all, :conditions => ["user_id = ? AND tests.course_id = ?",#user.id, #course.id], :include => :test)

Resources