场景
我有媒体比可以有许多音频轨道,我想存储的轨道在媒体中的顺序,但对于特定的媒体,序列必须是独特的。例如,一个Media对象可能有10个音轨,每个音轨的序列为1,2,。10
class Medium < ActiveRecord::Base
has_many :tracks, inverse_of: :medium, dependent: :destroy
end
class Track < ActiveRecord::Base
belongs_to :medium
validates_uniqueness_of :sequence, scope: :medium, message: 'sequence is not unique for the medium'
end然而,用户可以更改轨道序列,例如,他们将第二轨道移动到第8位置--这将导致轨道序列3-8减少1(分别变为2-7),而序列2变为轨道8。
问题
问题是,我不能简单地更改值并保存跟踪,因为当然验证失败了。
我唯一能想到的解决办法是:
然而,这似乎是非常低效的,而且只适合这一种情况。例如,我可以把轨道从第8位置移到第2位置。
理想情况下,我希望允许用户更改轨道上的序列,并修改其他数据,并且只有一次愉快地提交,这将导致调用将调用media.save的操作。
Rails中是否有更好的实践来处理此场景,或者它是否像看起来那样复杂。更好的做法是将此作为特例处理,并以原子方式处理每个更改--即一旦用户更改跟踪序列(调用父保存正在处理的其他跟踪属性更改,即.media.save)
发布于 2016-11-28 23:41:54
您可以使用充当列表宝石来解决排序和重新排序问题。
Gemfile
gem 'acts_as_list'medium.rb
class Medium < ActiveRecord::Base
has_many :tracks,
-> { order(sequence: :asc) },
inverse_of: :medium,
dependent: :destroy
endtrack.rb
class Track < ActiveRecord::Base
belongs_to :medium
acts_as_list column: :sequence, scope: :medium
end发布于 2016-11-28 22:03:01
您可以在父媒体记录上使用事务并执行所有更改,包括在一个块中重新编号序列。
https://stackoverflow.com/questions/40852962
复制相似问题