gpt4 book ai didi

ruby-on-rails - 在 Rails has_many :through association 中保存关联记录的顺序

转载 作者:行者123 更新时间:2023-12-04 06:26:08 25 4
gpt4 key购买 nike

我正在开发一个 Rails 插件,其中包括一种修改 has_many 中关联记录顺序的方法:通过关联。假设我们有以下模型:

class Playlist < ActiveRecord::Base
has_many :playlists_songs, :dependent => :destroy
has_many :songs, :through => :playlists_songs
end

class Song < ActiveRecord::Base
has_many :playlists_songs, :dependent => :destroy
has_many :playlists, :through => :playlists_songs
end

class PlaylistsSong < ActiveRecord::Base
belongs_to :playlist
belongs_to :song
end

如果我们更改播放列表歌曲的顺序(例如 @playlist.songs.rotate! ),Rails 不会触及 playlists_songs 表中的记录(我使用的是 Rails 3.1),这是有道理的。不过,我想调用 Playlist 的歌曲 = 方法来保存歌曲的顺序,也许可以通过删除 playlists_songs 中的相关现有行并按正确顺序创建新行(以便 :order => "id" 可以在以下情况下使用)检索它们)或通过将 sort:integer 列添加到 playlists_songs 并相应地更新这些值。

我没有看到任何允许这样做的回调(例如 before_add)。在 ActiveRecord::Associations::CollectionAssociation ,相关方法好像是 writer , replace , 和 replace_records ,但我不知道下一步是什么。有没有办法扩展或安全地覆盖这些方法之一以允许我正在寻找的功能(最好仅用于特定关联),或者是否有不同的、更好的方法?

最佳答案

你看过acts_as_list ?它是最古老的 rails 插件之一,旨在处理此类问题。

而不是在 id 上排序,它按位置列排序。那就简单的更新仓位了,而不是换id的麻烦事或删除/替换记录。

在您的情况下,您只需添加 position整数列到 PlayListSong , 然后:

class PlayListSong
acts_as_list :scope => :play_list_id
end

正如您在评论中指出的, acts_as_list 中的方法主要处理列表中的单个项目,并且没有开箱即用的“重新排序”功能。我不建议篡改 replace_records去做这个。编写一个使用与插件相同的位置列的方法会更清晰、更明确。例如。
class PlayList
# It makes sense for these methods to be on the association. You might make it
# work for #songs instead (as in your question), but the join table is what's
# keeping the position.
has_many :play_list_songs, ... do

# I'm not sure what rotate! should do, so...

# This first method makes use of acts_as_list's functionality
#
# This should take the last song and move it to the first, incrementing
# the position of all other songs, effectively rotating the list forward
# by 1 song.
def rotate!
last.move_to_top unless empty?
end

# this, on the other hand, would reorder given an array of play_list_songs.
#
# Note: this is a rough (untested) idea and could/should be reworked for
# efficiency and safety.
def reorder!(reordered_songs)
position = 0
reordered_songs.each do |song|
position += 1

# Note: update_column is 3.1+, but I'm assuming you're using it, since
# that was the source you linked to in your question
find(song.id).update_column(:position, position)
end
end
end
end

关于ruby-on-rails - 在 Rails has_many :through association 中保存关联记录的顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7721163/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com