为一组关联记录定义订单

时间:2016-04-28 16:00:28

标签: ruby-on-rails ruby ruby-on-rails-4 database-design rails-activerecord

我有两个模型,任务和单位。任务has_many:单位。我想根据某种优先顺序订购单位。例如:有两个单元A和B.必须在B之前完成。用户可以在A和B之间添加另一个单元,例如C,然后也可以删除单元C - A和B的优先级将保持不变。什么是在Rails中实现这一点的最简单/直接的方式?

我考虑过的想法:

  1. 将一个优先整数列添加到units表中,该表在任何更改单位集合的操作上都会更新。

  2. 将自连接关联添加到指向下一个/上一个单元的单元模型,并在更改单元集合时修改关联。

2 个答案:

答案 0 :(得分:1)

对问题进行建模的正确方法取决于您的任务结构的复杂程度。

如果任务的单位总是可以按照倒数第一的顺序排列,那么为每个单位提供一个整数顺序,可以最简单地将单位置于该顺序中,在ActiveRecord中使用ordersort在记忆中。唯一的缺点是,当您添加或删除单位时,您可能需要保存其他单位以更新其订单。如果任务具有小的整数数量的单位,那可能不是一个很大的缺点。

如果任务可以有循环,则每个单元都需要对其前面的单元的引用。您甚至可能最终需要一个模型来表示单元与其后的单元之间的关系。因此,请仔细考虑您希望支持的用例,看看哪些适用。

答案 1 :(得分:0)

您可以使用acts_as_votable gem。 此迁移可以解决您的问题:

class AddCachedVotesToPosts < ActiveRecord::Migration
  def self.up
    add_column :posts, :cached_votes_total, :integer, :default => 0
    add_column :posts, :cached_votes_score, :integer, :default => 0
    add_column :posts, :cached_votes_up, :integer, :default => 0
    add_column :posts, :cached_votes_down, :integer, :default => 0
    add_column :posts, :cached_weighted_score, :integer, :default => 0
    add_column :posts, :cached_weighted_total, :integer, :default => 0
    add_column :posts, :cached_weighted_average, :float, :default => 0.0
    add_index  :posts, :cached_votes_total
    add_index  :posts, :cached_votes_score
    add_index  :posts, :cached_votes_up
    add_index  :posts, :cached_votes_down
    add_index  :posts, :cached_weighted_score
    add_index  :posts, :cached_weighted_total
    add_index  :posts, :cached_weighted_average

    # Uncomment this line to force caching of existing votes
    # Post.find_each(&:update_cached_votes)
  end

  def self.down
    remove_column :posts, :cached_votes_total
    remove_column :posts, :cached_votes_score
    remove_column :posts, :cached_votes_up
    remove_column :posts, :cached_votes_down
    remove_column :posts, :cached_weighted_score
    remove_column :posts, :cached_weighted_total
    remove_column :posts, :cached_weighted_average
  end
end

特别是此列add_column :posts, :cached_votes_up, :integer, :default => 0和此索引add_index :posts, :cached_votes_score