I am running a rake task to copy over some live data for demo purposes. Before each re-copy, I want to delete the old records. But when I try to Host.where(organization_id: target_org_id, customer_slug: target_customer_slug).destroy_all, I get the following err:
ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: update or delete on table "hosts" violates foreign key constraint "fk_rails_f66d1a8a7f" on table "event_attendees"
Models look something like this:
class Host
has_many :event_attendees, inverse_of: :host, dependent: :destroy
has_many :events, -> { distinct }, through: :event_attendees
end
class Attendee
has_many :event_attendees, inverse_of: :attendee, dependent: :destroy
has_many :events, through: :event_attendees
end
class Event
has_many :event_attendees, inverse_of: :event, dependent: :destroy
has_many :attendees, through: :event_attendees
end
class EventAttendee
belongs_to :event, inverse_of: :event_attendees
belongs_to :attendee, inverse_of: :event_attendees
belongs_to :host, inverse_of: :event_attendees
end
I thought dependent: :destroy should remove the associations?
Related
I have a self join table on my product model using a model called matches as the join table. What I would like to do is when deleting a product to have the associated product removed but not deleted. Right now I am trying dependent: :destroy which doesn't work, but I know its not what I want because I don't want to delete the self associated product.
product.rb
class Product < ApplicationRecord
...
has_many :variations, -> { order(:order) }, dependent: :destroy
has_and_belongs_to_many :categories
has_and_belongs_to_many :tags
has_many :matches
has_many :matched_products, through: :matches, dependent: :destroy
...
end
match.rb
class Match < ActiveRecord::Base
belongs_to :product
belongs_to :matched_product, class_name: 'Product', dependent: :destroy
has_many :variations, :through => :matched_product
end
I suggest you update your models as follows:
product.rb
class Product < ApplicationRecord
...
has_many :variations, -> { order(:order) }, dependent: :destroy
has_and_belongs_to_many :categories
has_and_belongs_to_many :tags
has_many :matches, dependent: :destroy
has_many :product_matches, class_name: 'Match', foreign_key: :matched_product_id, dependent: :destroy
has_many :matched_products, through: :matches
...
end
This will ensure that all matches records are deleted when deleting a product whether the product is a product or matched_product in the match record. Removing dependent: :destroy from has_many :matched_products will prevent deletion of the, well, matched_products.
match.rb
class Match < ActiveRecord::Base
belongs_to :product
belongs_to :matched_product, class_name: 'Product'
has_many :variations, :through => :matched_product
end
Similar to above, removing dependent: :destroy from belongs_to :matched_product, class_name: 'Product' will prevent deletion of the matched_product.
I have been experiencing problems when trying to destroy_all my users in my database. When I run User.destroy_all I get:
ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection: Cannot modify association 'Account#hotel_partnerships' because the source reflection class 'Partnership' is associated to 'Hotel' via :has_many.
I suspect that the main problem is that in my schema I have an accountmodel that belongs_to a user(the owner of the account) and at the same time the account has_many users through its offices and hotels.
Here's how my associations look like :
- Account.rb
class Account < ActiveRecord::Base
# associations
has_many :hotel_partnerships, through: :hotels, source: :partnerships, dependent: :destroy
has_many :office_partnerships, through: :offices, source: :partnerships, dependent: :destroy
has_many :hotel_users, through: :hotels,source: :users, dependent: :destroy
has_many :office_users, through: :offices, source: :users, dependent: :destroy
has_many :hotels, dependent: :destroy
has_many :offices, dependent: :destroy
has_many :rooms, through: :hotels, dependent: :destroy
has_many :tasks, through: :hotels, dependent: :destroy
belongs_to :admin, class_name: "User", foreign_key: "admin_user_id", dependent: :destroy
- User.rb
class User < ActiveRecord::Base
## this line adds auth token to all user on creation
acts_as_token_authenticatable
# associations
belongs_to :account, dependent: :destroy
has_and_belongs_to_many :hotels
has_and_belongs_to_many :offices
has_many :tasks, dependent: :destroy
has_many :bookings, dependent: :destroy
has_one :created_account, class_name: "Account", foreign_key: "admin_user_id", inverse_of: :admin, dependent: :destroy
- Partnership.rb
class Partnership < ActiveRecord::Base
belongs_to :hotel
belongs_to :office
- Hotel.rb
class Hotel < ActiveRecord::Base
geocoded_by :full_address
after_validation :geocode
has_many :partnerships
belongs_to :account
has_and_belongs_to_many :users
has_many :tasks, dependent: :destroy
has_many :rooms, dependent: :destroy
has_many :beds, through: :rooms, dependent: :destroy
has_many :photos, dependent: :destroy
accepts_nested_attributes_for :photos
accepts_nested_attributes_for :rooms
Is it possible to fix this circular association problem ?
I have the association setup like the below, but I'm getting errors/exceptions thrown from Rails telling me that I don't have the associations set up properly.
Here's what I have:
class Case
has_many :case_accesses, as: :policy, inverse_of: :case, dependent: :destroy
has_many :agents, through: :case_accesses, source: :ownable, source_type: 'Agent'
end
class CaseAccess
belongs_to :policy, polymorphic: true
belongs_to :ownable, polymorphic: true
end
class Agent
has_many :case_accesses, as: :ownable, dependent: :destroy
has_many :cases, through: :case_accesses
end
The error from Rails:
Could not find the source association(s) "case" or :cases in model CaseAccess. Try 'has_many :cases, :through => :case_accesses, :source => '. Is it one of policy, connection, or ownable?
I tried setting the source to ownable and it's causing problems in my query. How should I be setting up this association? It's a traditional has many through, except on one side the policy can be either of type Case or Ppae, and the ownable can be of type Agent or User.
Columns for tables:
Case
-id
CaseAccess
-id
-policy_id
-policy_type
-ownable_id
-ownable_type
Agent
-id
A Case has many case_accesses as policy. Is the CaseAccess the policy, or is the Case the policy for the CaseAccess?
I believe you need to change
has_many :case_accesses, as: :policy, inverse_of: :case, dependent: :destroy
to
has_many :case_accesses, inverse_of: :policy, dependent: :destroy
This is what did it:
class Case
has_many :case_accesses, as: :policy, inverse_of: :policy, dependent: :destroy
has_many :agents, through: :case_accesses, source: :ownable, source_type: 'Agent'
has_many :users, through: :case_accesses, source: :ownable, source_type: 'User'
end
class CaseAccess
belongs_to :policy, polymorphic: true
belongs_to :ownable, polymorphic: true
end
class Agent
has_many :case_accesses, as: :ownable, dependent: :destroy
has_many :cases, through: :case_accesses, source: :policy, source_type: 'Case'
end
I'd like to set up multiple has_many :through relationships in parallel. Here are my 2 standard and 2 join models:
User.rb
has_many :ownerships, dependent: :destroy
has_many :devices, through: :ownerships
has_many :bookings, dependent: :destroy
has_many :devices, through: :bookings
Ownership.rb
belongs_to :user, touch: true, counter_cache: :devices_count
belongs_to :device, touch: true
Booking.rb
belongs_to :user, touch: true, counter_cache: :bookings_count
belongs_to :device, touch: true, counter_cache: :bookings_count
Device.rb
has_many :ownerships, dependent: :destroy
has_many :users, through: :ownerships
has_many :bookings, dependent: :destroy
has_many :users, through: :bookings
This current setup is NOT working as expected, there seems to be crosstalk between the join models. I want the join models to be independent and in parallel (i.e. Users can have relationships - Ownerships - with devices independently of being able to book them). I am not looking for a nested has_many :through relation here.
When I change the User Ownerships of a Device that seems to alter the number of Bookings and vice versa... any ideas on how should I be setting this up correctly?
I think the first error you've got is you're calling two associations by the same name (users / devices)
To help any further respondents, the real question is --> how do you set up an association to pull from multiple join models?
Quick Fix
Rails associations are named primarily by their class, but because of conflicts, you should refrain from setting them twice. This is why you're seeing the current issue. A simple resolution will be to call the associations by different names:
User.rb
has_many :ownerships, dependent: :destroy
has_many :owner_devices, through: :ownerships, class_name: "Device", foreign_key: "ownership_id"
has_many :bookings, dependent: :destroy
has_many :booking_devices, through: :ownerships, class_name: "Device", foreign_key: "booking_id"
I am still looking for information on how you could set an association to use two models
This appears be a working solution following Rich Peck's suggestions:
User.rb
has_many :ownerships, dependent: :destroy
has_many :device_ownerships, through: :ownerships, class_name: "Device", foreign_key: "device_id", source: :device
has_many :bookings, dependent: :destroy
has_many :device_bookings, through: :bookings, class_name: "Device", foreign_key: "device_id", source: :device
Booking.rb (Join model)
belongs_to :user, touch: true, counter_cache: :bookings_count
belongs_to :device, touch: true, counter_cache: :bookings_count
Ownership.rb (Join model)
belongs_to :user, touch: true, counter_cache: :devices_count
belongs_to :device, touch: true, counter_cache: :users_count
Device.rb
has_many :ownerships, dependent: :destroy
has_many :user_ownerships, through: :ownerships, class_name: "User", foreign_key: "user_id", source: :user
has_many :bookings, dependent: :destroy
has_many :user_bookings, through: :bookings, class_name: "User", foreign_key: "user_id", source: :user
To be honest, I'm a bit confused over why the foreign_key's need(?) to be set up as they are, so I'll have to do a bit more reading about it. Otherwise it appears to be functional, I don't see crosstalk between these join models anymore.
I'm not sure what has changed getting this error when trying to login:
ERROR: relation "tags" does not exist
LINE 1: SELECT DISTINCT "tags".* FROM "tags" INNER JOIN "taggings" O...
The tag model:
class Tag < ActiveRecord::Base
attr_accessor :unread_count, :user_feeds
has_many :taggings
has_many :feeds, through: :taggings
end
The tagging model:
class Tagging < ActiveRecord::Base
belongs_to :tag
belongs_to :feed
belongs_to :user
end
And the user relationships:
class User < ActiveRecord::Base
has_one :coupon
has_many :subscriptions, dependent: :delete_all
has_many :feeds, through: :subscriptions
has_many :entries, through: :feeds
has_many :imports, dependent: :destroy
has_many :billing_events, as: :billable, dependent: :delete_all
has_many :taggings, dependent: :delete_all
has_many :tags, through: :taggings
has_many :sharing_services, dependent: :delete_all
has_many :unread_entries, dependent: :delete_all
has_many :starred_entries, dependent: :delete_all
has_many :saved_searches, dependent: :delete_all
has_many :actions, dependent: :destroy
belongs_to :plan
end
This error is new and came right after I tried to install the intercom.io gem. I removed the gem, did a gem cleanup, reset the db and still the same error.
Not sure what happened, if anyone has any suggestions I would appreciate it.
Checked missing tables, and that was the problem.