I have tables in db as following migration script:
class CreateAppointments < ActiveRecord::Migration
def change
create_table :physicians do |t|
t.string :name
t.timestamps null: false
end
create_table :patients do |t|
t.string :name
t.timestamps null: false
end
create_table :appointments do |t|
t.belongs_to :physician, index: true
t.belongs_to :patient, index: true
t.datetime :appointment_date
t.timestamps null: false
end
end
end
And the model class looks like:
class Physician < ActiveRecord::Base
has_many :appointments
has_many :patients, through: :appointments
end
class Appointment < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
end
class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, through: :appointments
end
I'm able to pick all patients data of specific physician using:
patients = Physician.find(123).patients
The problem is, I need appointment_date, which is stored in appointment table, along with patient details. Somehow I'm not able to figure out how to fetch it.
Relation looks completely right so querying should be quite easy or are you having some problems?
If you need appointment_date i would probably query Appointments of Physician instead:
Physician.find_by(id: 123).appointments.each do |x|
print "Date: #{x.appointment_date}\n"
print "Patient: #{x.patient.name}"
end
You can join Patient and Appointment models to get the required data easily:
Patient.joins(:appointments).where(. . . ).select('appointments.appointment_date')
You can put the required condition in the where clause and add more attributes from the patients and appointments tables in the select clause that you want to select.
See Active Record Query Interface for more information on this.
Update
I misunderstood your question initially. Th easiet way to get what you want is pointed by midN in his answer.
Related
I have a model named Letter and an other one named LetterTracking :
class Letter < ApplicationRecord
has_many :letter_trackings, as: :trackable
end
and:
class LetterTracking < ApplicationRecord
belongs_to :letter
has_many :letter_trackings, as: :trackable
end
this is my create table migration for Letter Tracking:
class CreateLetterTrackings < ActiveRecord::Migration[5.0]
def change
create_table :letter_trackings do |t|
t.integer :trackable_id, default: 0, null: false, unique: true
t.string :trackable_type
t.text :paraph
t.string :status
t.string :assignee
t.belongs_to :letter
t.timestamps
end
end
end
as you can see in below screen shots when I select a tracking record for the second tracking the relation is ok but when ever I add the third letter tracking the second one relation removes and the last one keeps the association.
What I want is to keep the letter tracking in each record not by the last one. I mean some thing like nested records in which I can keep the related records.
any Idea ?
Thank you
First of all as a second thought the polymorphic relation seems quite useless for keeping track in this case. The thing which fits best here is tree based relation I suppose.
this is my LetterTracking.rb
class LetterTracking < ApplicationRecord
belongs_to :letter
has_many :children, class_name: "LetterTracking", foreign_key: "parent_id"
belongs_to :parent, class_name: "LetterTracking"
end
and this is my letter.rb
class Letter < ApplicationRecord
has_many :letter_trackings
end
and finaly the LetterTrackings Migration:
class CreateLetterTrackings < ActiveRecord::Migration[5.0]
def change
create_table :letter_trackings do |t|
t.references :parent, index: true
t.text :paraph
t.string :status
t.string :assignee
t.belongs_to :letter, index: true
t.timestamps
end
end
end
Now I can have the records of the lettertrackings join together like a tree while keeping the letter id in every single record! Yep :)
I have probably one simple question. I have the following three tables:
create_table "appointments", force: true do |t|
t.integer "teacher_id"
t.integer "student_id"
t.datetime "start_date"
end
create_table "teachers", force: true do |t|
t.string "name"
end
create_table "students", force: true do |t|
t.string "email"
t.string "first_name"
t.string "last_name"
end
I have made the following models for these three type of data:
class Appointment < ActiveRecord::Base
belongs_to :teacher
belongs_to :student
end
class Teacher < ActiveRecord::Base
has_many :appointments
has_many :students, :through => :appointments
end
class Student < ActiveRecord::Base
has_many :appointments
has_many :teachers, :through => :appointments
end
So, every teacher can have many appointments with many different students and every student can have many appointments with different teachers. My question is how to delete an appointments which belong to some student if administrator deletes that student from database?
I thought I modeled this correctly but when I delete user like this, his appointments are still there:
def destroy
Student.find(params[:id]).destroy
end
Thank you!
class Student < ActiveRecord::Base
has_many :appointments, :dependent => :delete_all
has_many :teachers, :through => :appointments
end
delete_all will not call any destroy callbacks defined on appointment. but it is efficient because issues a single delete query
I'm really new to RoR so I apologize if I'm not thinking about this right. I have a Report where I need to be able to assign multiple users to that report. A user can be assigned to more than one report and a report can have multiple users. How do I create the database relationship where this would be allowed. I understand how to assign one user to one report but not many users to a single report.
I'd use a joining class to make this happen:
class Report
has_many :assignments
has_many :users :through => :assignments
end
class User
has_many :assignments
has_many :reports, :through => :assignments
end
class Assignment
belongs_to :report
belongs_to :user
end
The class Assignment has two fields: report_id and user_id to create the relationship.
Read the Ruby on Rails Guide to Active Record Associations: http://guides.rubyonrails.org/association_basics.html
I highly recommend you familiarize yourself with the Ruby on Rails guides. They will prove to be an invaluable asset!! For this task the site would be RailsGuides Active Record Associations.
As far as the code goes you want to create three database tables: reports, reports_users, and users, with reports_users being a join table.
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name, :null => false
t.timestamps
end
end
end
class CreateReports < ActiveRecord::Migration
def change
create_table :reports do |t|
t.string :name, :null => false
t.timestamps
end
end
end
class ReportsUsers < ActiveRecord::Migration
def change
create_table :reports_users, :id => false do |t|
t.references :user, :null => false
t.references :report, :null => false
end
end
end
Once you run this migration you need to set up the active record associations in your models.
class User < ActiveRecord::Base
has_and_belongs_to_many :reports
end
class Report < ActiveRecord::Base
has_and_belongs_to_many :user
end
This will set up the database and the many-to-many models connections. This will get you started. Now you have to go create some views
I'm trying to create a many to many relationship between two models in Rails 3.2.11.
A User can be associated with many Incidents and vice versa.
class User < ActiveRecord::Base
include ActiveModel::ForbiddenAttributesProtection
has_many :incident_participants, foreign_key: "participant_id"
has_many :participated_incidents, through: :incident_participants
end
class Incident < ActiveRecord::Base
include ActiveModel::ForbiddenAttributesProtection
has_many :incident_participants, foreign_key: "participated_incident_id"
has_many :participants, through: :incident_participants
end
The join table:
class IncidentParticipant < ActiveRecord::Base
include ActiveModel::ForbiddenAttributesProtection
t.belongs_to :participant, class_name: "User"
t.belongs_to :participated_incident, class_name: "Incident"
end
Table for IncidentParticipants
create_table "incident_participants", :force => true do |t|
t.integer "participant_id"
t.integer "participated_incident_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
So, why doesn't rails get this relationship? When I try to do #incident.participants in my view I get this error:
"Could not find the source association(s) :participant or
:participants in model IncidentParticipant. Try 'has_many
:participants, :through => :incident_participants, :source => '.
Is it one of ?"
Any ideas?
Try taking out the t.belongs_to and replace with belongs_to.
To create a many to many association you should consider creating an association table. That is to say you will have two 1-M relationships that point to a sort interim table. For instance:
In your first model:
class Example < ActiveRecord::Base
has_and_belongs_to_many :example2
end
In your second model:
class Example2 < ActiveRecord::Base
has_and_belongs_to_many :example
end
Then you need to write a migration to link the two tables together:
class CreateTableExamplesExamples2 < ActiveRecord::Migration
create_table :examples_examples2 do |t|
t.integer :example_id
t.integer :example2_id
end
end
Then just let rails magic work. Check out the guides for more information.
I am trying to get my relationships worked out but I am having trouble using the associations.
So I have three models Workout, Exercise and WorkoutExercise. A workout should have many exercises and a exercise should have different workouts therefore I wrote:
class Workout < ActiveRecord::Base
has_many :workout_exercises
has_many :exercises, :through => :workout_exercises
end
class Exercise < ActiveRecord::Base
has_many :workout_exercises
has_many :workouts, :through => :workout_exercises
end
class WorkoutExercise < ActiveRecord::Base
belongs_to :exercise
belongs_to :workout
end
I am running some tests but the tests aren't passing once I create a workout, exercise and then join them in the workout_exercise class. It won't let me access the exercises in the workout like this:
Workout.create
Exercise.create
WorkoutExercise.create(:workout => Workout.first, :exercise => Exercise.first)
work = Workout.first
work.exercises.count #This line causes the error: undefined method exercises
My database tables look like this:
class CreateWorkouts < ActiveRecord::Migration
def change
create_table :workouts do |t|
t.string :title
t.text :description
t.float :score
t.timestamps
end
end
end
class CreateExercises < ActiveRecord::Migration
def change
create_table :exercises do |t|
t.string :title
t.text :description
t.float :value
t.timestamps
end
end
end
class CreateWorkoutExercises < ActiveRecord::Migration
def change
create_table :workout_exercises do |t|
t.timestamps
end
end
end
When I run this tests it says exercises is undefined. Does anyone have any ideas?
Ok, so your WorkoutExercises table can't be empty. This is how it should look:
class CreateWorkoutExercises < ActiveRecord::Migration
def change
create_table :WorkoutExercises do |t|
t.integer :exercise_id, :null => false
t.integer :workout_id, :null => false
t.timestamps
end
# I only added theses indexes so theoretically your database queries are faster.
# If you don't plan on having many records, you can leave these 2 lines out.
add_index :WorkoutExercises, :exercise_id
add_index :WorkoutExercises, :workout_id
end
end
Also, you can name this table whatever you'd like, it doesn't have to be WorkoutExercises.
However, if you were using a has_and_belongs_to_many relationship, your table would have to mandatorily be named ExercisesWorkout. Notice how Exercises comes before Workout. The names have to be alphabetically ordered. Don't ask me why, it's just a Rails convention.
So, in this case, you'll do fine with your table being named WorkoutExercises. But if I were you, I'd change it to ExercisesWorkout, just in case, so that you never get it wrong.
Your code looks OK. Bug maybe has_and_belongs_to_many is a better choice. See Choosing Between has_many :through and has_and_belongs_to_many