ActiveRecord::InvalidForeignKey violation with dependent destroy - ruby-on-rails

I have this models:
User model
has_many :photos, inverse_of: :user, dependent: :destroy
Photo model
belongs_to :user, inverse_of: :photos
And in my controller I want to do something like this:
User.where(...).destroy_all
I get this error:
ActiveRecord::InvalidForeignKey
PG::ForeignKeyViolation: ERROR: update or delete on table "users" violates foreign key
constraint "fk_rails_d873b4f337" on table "photos"
DETAIL: Key (id)=(491234) is still referenced from table "photos".
: DELETE FROM "users" WHERE "users"."id" = $1
Why do I get this error if I have dependent: :destroy?

Related

Dependant destroy generates wrong sql query

I have m:n association with counter cache. I want delete user and remove appropriate records from the users_items association. The sql query which should remove records from users_items association is wrong.
class User < ApplicationRecord
has_many :users_items, class_name: 'UsersItem', dependent: :destroy
has_many :items, through: :users_items
end
class Item < ApplicationRecord
has_many :users_items, class_name: 'UsersItem', dependent: :destroy
has_many :users, through: :users_items
end
class UsersItem < ApplicationRecord
belongs_to :user, counter_cache: true
belongs_to :item, counter_cache: true
end
u = User.last
u.destroy
(0.3ms) BEGIN
UsersItem Load (0.4ms) SELECT "users_items".* FROM "users_items" WHERE "users_items"."user_id" = $1 [["user_id", 41]]
UsersItem Destroy (1.9ms) DELETE FROM "users_items" WHERE "users_items"."" IS NULL
(0.3ms) ROLLBACK
ActiveRecord::StatementInvalid (PG::SyntaxError: ERROR: zero-length delimited identifier at or near """")
LINE 1: DELETE FROM "users_items" WHERE "users_items"."" IS NULL
The problem was with the users_items table. The table was created without primary key. It started working when I added the primary id.
Myth

rails 5 has_many through order on through table

I want to order a has_many through relationship on a column in the through table
class DoctorProfile
has_many :doctor_specialties
has_many :specialties, through: :doctor_specialties
class Specialty
has_many :doctor_specialties
has_many :doctor_profiles, through: :doctor_specialties
class DoctorSpecialty
belongs_to :doctor_profile
belongs_to :specialty
I'd like the doctor specialties to be ordered by the column ordinal on DoctorSpecialty. Specifically this error happens when using includes
DoctorProfile.includes(:specialties).all
I've tried
has_many :specialties, -> { order 'doctor_specialties.ordinal' }, through: :doctor_specialties
DoctorProfile Load (0.6ms) SELECT "doctor_profiles".* FROM "doctor_profiles" ORDER BY "doctor_profiles"."id" ASC LIMIT $1 [["LIMIT", 1]]
DoctorSpecialty Load (0.8ms) SELECT "doctor_specialties".* FROM "doctor_specialties" WHERE "doctor_specialties"."doctor_profile_id" = 1
Specialty Load (0.4ms) SELECT "specialties".* FROM "specialties" WHERE "specialties"."id" = 69 ORDER BY doctor_specialties.ordinal
and receieve a missing FROM -clause error PG::UndefinedTable: ERROR: missing FROM-clause entry for table "doctor_specialties"
How can I define the order on the through table so specialties are returning in ascending order?
Note:
I was able to get this working by adding a default_scope to DoctorSpecialty
default_scope { order('ordinal ASC') }
However, I'm still wondering if there is a way to do it on the has_many through
I was able to get it working using
class DoctorProfile
has_many :specialties, -> { order 'doctor_specialties.ordinal' }, through: :doctor_specialties
end
class DoctorSpecialty < ApplicationRecord
belongs_to :doctor_profile
belongs_to :specialty
default_scope { order('ordinal ASC') }
end
Not sure if this is what's causing your error but you haven't completed the has many through relationship on the Specialty side. Should be has_many :doctor_profiles, through: :doctor_specialties
Also for this line in DoctorProfiles has_many :specialties, through: doctor_specialties, doctor_specialties needs to be a symbol
As for the ordering I think you need to do a joins instead of an includes
like DoctorProfile.joins(:doctor_specialties).order("doctor_specialties.ordinal ASC")

Rails 4 dependant destroy through nested relationships

I am trying to run a script to delete a whole bunch of students from our system, I am relying on the rails dependent: :destroy convention to make sure I clean up all data that's is related to those students.
I am pretty new to this system but this is how they structured the has_many relationships within the student_application model which belongs to a student.
student.rb student model
has_many :applications, class_name: "StudentApplication", dependent: :destroy
has_many :season_classes, through: :applications
has_many :payments, foreign_key: "student_id", dependent: :destroy
student_application.rb student_application model
belongs_to :student, touch: true
has_many :user_application_statuses, -> { order(id: :asc) }, dependent: :destroy
has_many :user_application_tasks, through: :user_application_statuses
has_many :file_upload_tasks, through: :user_application_statuses, class_name: "Tasks::FileUploadTask", source: :user_application_tasks
has_many :payment_tasks, through: :user_application_statuses, class_name: "Tasks::PaymentTask", source: :user_application_tasks
has_many :payments, through: :payment_tasks
user_application_status.rb user_applicaton_status model
belongs_to :application_status
# Student links
belongs_to :student_application
has_one :student, through: :student_application
payment.rb payment model
belongs_to :student
has_one :payment_task, class_name: "Tasks::PaymentTask"
has_many :transactions
When I delete a user I am getting this error
PG::ForeignKeyViolation: ERROR: update or delete on table "student_applications" violates foreign key constraint "payments_student_application_id_fkey" on table "payments"
DETAIL: Key (id)=(24747) is still referenced from table "payments".
: DELETE FROM "student_applications" WHERE "student_applications"."id" = $1
(0.3ms) ROLLBACK
ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: update or delete on table "student_applications" violates foreign key constraint "payments_student_application_id_fkey" on table "payments"
DETAIL: Key (id)=(24747) is still referenced from table "payments".
: DELETE FROM "student_applications" WHERE "student_applications"."id" = $1
At first I thought that there was an object at a deeper relationship level that was being left out. But as far as I can tell from looking at the tables and the source code there is no payments_student_application_id_fkey reference anywhere in the code, but i have found this in the structure.sql file
--
-- Name: payments_student_application_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY payments
ADD CONSTRAINT payments_student_application_id_fkey FOREIGN KEY (student_application_id) REFERENCES student_applications(id);
We are using Rails 4.1.14.1 and Ruby 2.1.6 and Postgres for the db. Any ideas as to what could be causing this issue?
From What I can see...
# in pseudocodes
user has_one or has_many student_application dependent destroy
student_application belongs to a user
student_application has_many payments
Therefore deleting a user causes the associated student_application to get deleted as well... but the student_application's id is being referenced from the payments table, therefore causing the error.
Two ready solutions I can see:
1) Set a dependent: :destroy on the student_application model for payments ( or payment_tasks ) as well. This will ensure that the payments also gets deleted as well.
However, if you don't want this to be the case... then option 2:
2) Set a dependent: :nullify on the student_application model for payments. This will ensure that the ``student_application_idcolumn on the associatedpaymentsobject to the deletedstudent_application` is set to null, preventing the above error.
:dependent Controls what happens to the associated objects when the associated parent is destroyed. More options for dependent can be found here.

setting up association for a has_one that is self-referential

I have a User and a Reviewer table.
Reviewer tracks user_id and reviewer_id
now my association is setup like this:
# reviewer
has_one :reviewer
accepts_nested_attributes_for :reviewer
has_many :active_managements, class_name: 'Reviewer',
foreign_key: 'reviewer_id',
dependent: :destroy
has_one :my_reviewer, through: :reviewer, source: :user
what I'm trying to set up is that a User can have one reviewer, but can review many.
Now I'm trying to make it so that I can do
current_user.my_reviewer.first_name
f.ex and get the first name of the reviewer of the current user. However currently the
has_one :my_reviewer, through: :reviewer, source: :user
just goes to yourself. Which I think has to do with the source. If I try to change it to :reviewer I get this error:
Could not find the source association(s) :reviewer in model Reviewer. Try 'has_many :my_reviewer, :through => :reviewer, :source => <name>'. Is it one of user or reviewer_user?
and if I change it to reviewer_user
I get this error:
PG::UndefinedColumn: ERROR: column reviewers.reviewer_user_id does not exist
LINE 1: ... "users" INNER JOIN "reviewers" ON "users"."id" = "reviewers...
^
: SELECT "users".* FROM "users" INNER JOIN "reviewers" ON "users"."id" = "reviewers"."reviewer_user_id" WHERE "reviewers"."user_id" = $1 LIMIT 1
Reviewers are Users, right? So why not just get rid of the reviewer table and do this:
# user
has_many :reviewees, class_name: "User", foreign_key: "my_reviewer_id"
belongs_to :my_reviewer, class_name: "User"

Join table on one-to-many cannot update

Ok, check this weirdness out. I have two types of users, leaders and followers (who each have their own subclasses for reasons that please for the love of god I don't want to go into and moreover are not germaine to this discussion).
class Admin < Account
has_many :leader_follower_relationships, foreign_key: :leader_id, dependent: :destroy
has_many :followers, through: :leader_follower_relationships
end
class Follower < Account
has_one :follower_leader_relationship, class_name: "LeaderfollwerRelationship",
dependent: :destroy
has_one :leader, through: :follower_leader_relationship
end
class LeaderFollowerRelationship < ActiveRecord::Base
belongs_to :follower, class_name: "Follower", foreign_key: :artist_id
belongs_to :leader, class_name: "Admin", foreign_key: :leader_id
end
Anyway, I can establish the relationship using a has_one, but I can't update it:
follower1.leader = leader1
(0.3ms) BEGIN
Account Exists (1.1ms) SELECT 1 AS one FROM "accounts" WHERE "accounts"."auth_token" IS NULL LIMIT 1
Account Exists (0.4ms) SELECT 1 AS one FROM "accounts" WHERE "accounts"."email_address" = 'leader1#example.com' LIMIT 1
SQL (0.6ms) ...
(0.5ms) COMMIT
follower1.leader = leader2
(0.3ms) BEGIN
(1.8ms) UPDATE "leader_follower_relationships" SET "leader_id" = 3 WHERE "leader_follower_relationships"."" IS NULL
(0.2ms) ROLLBACK
ActiveRecord::StatementInvalid: PGError: ERROR: zero-length delimited identifier at or near """"
LINE 1: ...ader_id" = 3 WHERE "leader_follower_relationships"."" IS NULL
If my follower can have many leaders (using has_many), I can both create and update:
class Follower < Account
has_many :follower_leader_relationships, class_name: "LeaderfollwerRelationship",
dependent: :destroy
has_many :leaders, through: :follower_leader_relationships
end
These commands work in succession:
follower1.leaders = [leader1]
follower1.leaders = [leader2]
The ActiveRecord error makes me think that the table for your LeaderFollowerRelationship model does not have an id column. If that's not it, can you post the related bits of schema.rb?

Resources