Get values from a has_many through relation - ruby-on-rails

My setup:
class ServiceUser < ActiveRecord::Base
belongs_to :user
belongs_to :service
enum status: [ :unavailable, :available ]
end
class Service < ActiveRecord::Base
has_many :service_users
has_many :users, :through => :service_users
end
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :service_users
has_many :services, :through => :service_users
end
From the ServiceUser model i can call the status field, in my case available and unavailable.
In my app i'm listing all the users for a specific service with:
#service.users
But now i want to show the status for each user from the ServiceUser model. What is the best way to do is?
Also i want to make a form for the ServiceUser model to make a new relation between the service and the current user:
ServiceUser.new(service_id: #service.id, user_id: current_user.id, status: 1)
What do i need to specify in the form for?

Construct a hash with user_id as the key and value as the status
user_status = Hash[*#service.service_users.map{|su|[su.user_id, su.status] }.flatten]
Now you can get the status for each user by
#service.users.each do |user|
p user_status[user.id]
end

Related

Rails associations within same model depending on attribute

I am building a rails app with devise and cancancan and I am trying to create associations within the same model. I have a User model, a role model and an appointments model. The user can have the role of Doctor or Patient. I want to create an association so a Patient can create appointments with the Doctor. I managed to create the associations but I do not know how to make the patient only create appointments with a doctor and only in that way.
My models are like this:
User model
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
belongs_to :role, optional: true
validates :name, :DOB, presence: true
has_many :doctor_user_appointments, class_name: 'Appointment', foreign_key: 'doctor_user_id', dependent: :destroy
has_many :patient_user_appointments, class_name: 'Appointment', foreign_key: 'patient_user_id', dependent: :destroy
before_save :assign_role
scope :doctor_user, -> {where("role_id = ?", 1)
scope :patient_user, -> {where("role_id = ?", 2)
def admin?
role.name == 'Admin'
end
def doctor?
role.name == 'Doctor'
end
def patient?
role.name == 'Patient'
end
def assign_role
self.role = Role.find_by name: 'Patient' if role.nil?
end
end
Role model
class Role < ApplicationRecord
has_many :users, dependent: :restrict_with_exception
end
Appointment model
class Appointment < ApplicationRecord
belongs_to :doctor_user, class_name: 'User'
belongs_to :patient_user, class_name: 'User'
end
With these models, I can create appointments between doctor_user and patient_user, both users, but the associations do not distinguish who has the role "doctor" and who has the role "patient". I have tried with scopes but it is not working.
What I basically want is that doctor_user could only be a user with role "doctor" or user with role_id=1 and a patient_user only could be a user with role_id=2 or role "patient"
Any help would be welcome since I am quite stuck
Thanks in advance
Simply updating with the following lines to your Appointment controller will do the job:
belongs_to :doctor_user, -> { doctor_user }, class_name: 'User'
belongs_to :patient_user, -> { patient_user }, class_name: 'User'
I have fixed the issue by adding these lines to the Appointment model
belongs_to :doctor_user, -> {where("role_id = ?", 1)}, class_name: 'User'
belongs_to :patient_user, -> {where("role_id = ?", 2)}, class_name: 'User'

Access value of foreign-key

I'm working on my own Web-app but I'm facing a problem.
Here is my models :
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :player_seasons
has_many :forecasts, through: :player_seasons
end
class PlayerSeason < ApplicationRecord
belongs_to :user
belongs_to :season
belongs_to :championship
has_many :forecasts
has_many :matches, through: :forecasts
end
class Championship < ApplicationRecord
belongs_to :season
has_many :player_seasons
has_many :users, through: :player_seasons
end
#playerseasons = PlayerSeason.all
I am iterating on: #playerseasons
I would like to compare all the PlayerSeason (#playerseasons) as following :
#playerseasons.each do |playerseason|
if playerseason.championship_id == #playerseason.championship
else
end
end
The idea is comparing all the playerseasons, if a playerseason has the same championship as the current_user, something will appears otherwise something else (basic condition).
But I'm stuck and can't access the exact championship of the current user, on the other side I can access the championship of the playerseasons.
Thank you by advance :)
I did not look critically at database design model which potentially could be done differently. Also I'm taking this as a non-production app as you mention in your question therefore database load optimization is a second priority.
With what you have now I would do something like just to get it to work
user_championships = current_user.player_seasons.map(&:championship).uniq
#playerseasons.each do |playerseason|
if user_championships.include?(playerseason.championship)
else
end
end

Querying for values from several models

I have a Course and Lesson models. Course has several lessons. I want to find all the lessons for currently logged in student to generate kind of timetable.
I have a method that returns all the courses that this student is studying. Now I want to get all lessons from all those courses in #courses into #lessons, something like:
def index
#courses = current_student.find_courses
#lessons = #courses.lessons
end
Is it possible to do it somehow simple on one line?
The find_courses method is implemented as following:
def find_courses
Course.where("id IN (?)", StudentAssignment.select("course_id").where('student_id == (?)', self.id))
end
The Models:
class Student < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :student_assignments
has_many :courses, :through => :student_assignments
....
class Lesson < ApplicationRecord
belongs_to :room
belongs_to :teacher
belongs_to :course
....
class Course < ApplicationRecord
has_many :lessons, dependent: :destroy
has_many :teacher_assignments
has_many :teachers, :through => :teacher_assignments
has_many :student_assignments
has_many :students, :through => :student_assignments
...
class Student < ApplicationRecord
has_many :courses
def active_lessions
Lession.joins(course: :students).where(students: {id: self.id})
end
end
In this way you can directly get all active lesssions for current_user
current_student.active_lessions
Try:
#lessons = #courses.flat_map(&:lessons)
It takes each course in #courses list and gets the list of lessons for that course.

Audited-activerecord gem not working properly for polymorphic associations

I want to make audits for nested associations like I have
User has_many addresses i.e either
HomeAddress or OfficeAddress
Now if I have just one table Address and I have used type and id for differentiating them.In this case if I use associated_audits for User then it will make just one audit record and whenever I update the record again ,its just replacing the previous audit with the last one.
Here is the models association:
class Patient < ActiveRecord::Base
devise :database_authenticatable, :registerable, :recoverable, :rememberable,
:trackable, :validatable, :confirmable, request_keys: [:subdomain]
has_one :home_address,-> { where(addr_type: 'home') },class_name: 'Address'
has_one :office_address,-> { where(addr_type: 'office') }, class_name: 'Address'
has_associated_audits
accepts_nested_attributes_for :home_address, allow_destroy: true
accepts_nested_attributes_for :office_address, allow_destroy: true
end
class Address < ActiveRecord::Base
belongs_to :patient
audited
end
class Address < ActiveRecord::Base
belongs_to :patient
audited associated_with: :patient
end
class Patient < ActiveRecord::Base
has_many :addresses
has_associated_audits
end

Rails 3: calling database on a has_many association

Hi I have a many to many association where 'posts' have many 'feeling', I'd like to figure out how to find all the posts with a specific feeling by the user. My Feeling model has a 'name' attribute.
class User < ActiveRecord::Base
has_many :posts, :dependent => :destroy
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
class Post < ActiveRecord::Base
has_many :feelingships
has_many :feelings, :through => :feelingships
belongs_to :user
end
class Feeling < ActiveRecord::Base
has_many :feelingships
has_many :posts, :through => :feelingships
end
class Feelingship < ActiveRecord::Base
belongs_to :post
belongs_to :feeling
attr_accessible :post_id, :feeling_id
end
I tried this but it says I have the wrong association: "ActiveRecord::ConfigurationError: Association named 'feeling' was not found; perhaps you misspelled it?"
def feeling
#user = User.find(params[:id])
#feed_items= #user.posts.includes(:feeling).where(
['`feelings`.name = ?', params[:feeling]])
#feed_items = #feed_items.paginate(:per_page => "10", :page => params[:page])
render 'shared/_feed', :layout => 'head_layout'
end
The includes argument should be :feelings - notice the plural, which is what your association is named.
So it should be:
#user.posts.includes(:feelings)

Resources