Closed cloudy9101 closed 7 years ago
You can use dependent :destroy
on your relationship model.
e.g.
class User < ActiveRecord::Base
has_many :user_projects, dependent: :destroy
has_many :projects, through: :user_projecs
end
class Project < ActiveRecord::Base
has_many :user_projects, dependent: :destroy
has_many :users, through: :user_projecs
end
class UserProject < ActiveRecord::Base
belongs_to :user
belongs_to :project
end
This way, when you delete project, user
remains, but their association is destroyed.
Haha! You're quick off the mark today @swanandp! :)
Oh the power ( or peril ) of notifications!
I know, but when there are 1000 user_projects, we will execute the 'update position - 1' sql for 1000 times. I think it's too slow. Is that right? 😞
@cloudy9101, are you using the latest version of acts_as_list
? We try to detect a destroy via a parent relationship and skip those updates given all the children in the scope get deleted anyway. You need to use dependent: :destroy
though.
@swanandp @brendon Thanks for the response. I saw the code. But because the item is belongs_to two models, and destroy the model which is not the list, I think this will make the list's position discontinuous like [0, 1, 3, 4, 5], and when use insert_at, it will make some mistake, because the param use with insert_at is come from frontend, I'm not sure that you could understand what I am saying. If you can't understand, I could show some use case.
Thanks @cloudy9101, some code would be good. Show us a simplified set of models and the methods you're trying to execute against them.
Just like the example @swanandp shows, I make some changes.
class User < ActiveRecord::Base
has_many :user_projects, dependent: :destroy
has_many :projects, through: :user_projecs
end
class Project < ActiveRecord::Base
has_many :user_projects, dependent: :destroy
has_many :users, through: :user_projecs
end
class UserProject < ActiveRecord::Base
acts_as_list scope: :user
belongs_to :user
belongs_to :project
end
# project has_many users
# this code will execute remove_from_list many times(according to the project.users.count)
project.destroy
Sometimes the project.users.count is very large, it will be very slow. Is the use case too odd? 🤣
Unfortunately I think it's the only way if you want the positions to remain consistent (without gaps). Perhaps you could offload it to a delayed_job
or something like that?
OK, I will consider it. Thanks a lot. I will close the issues.
Thanks @cloudy9101, sorry I couldn't be of more help.
In my case, a many to many relationship between user and project through access table, and user can custom order his projects. So I use acts_as_list in the middle table access. But when a project is destroy, I want destroy all the accesses in the project. Because access use acts_as_list, I need invoke remove_from_list with each access. When a project has a lot accesses, it's very slow. Is there any solution for this? Thanks a lot.