ruby-on-rails - 根据关联重置 PK 数

标签 ruby-on-rails ruby sequel

我有一个帖子评论表。

Post 有很多评论,Comment 属于一个帖子。

当我为 Post 创建评论时,我希望主键从 1 开始,这样我就可以以 REST 方式访问评论,例如:

/posts/1/comments/1
/posts/1/comments/2
/posts/2/comments/1
/posts/2/comments/2

如何使用 Rails 3 实现这一目标? 我使用 MySQL 作为数据库。

奖励:我正在使用 Sequel ORM;一种与 Sequel 兼容的方法,而不仅仅是与 ActiveRecord 兼容,那就太棒了。

最佳答案

嗯,你不能使用 id 来实现这一点,因为 id 是这里的主键。您可以做的是向数据库表中添加一个额外的字段,例如 comment_number 并使其在帖子范围内唯一:

#migration
def change
  add_column :comments, :comment_number, :integer, null: false
  add_index :comments, [:post_id, :comment_number], unique: true
end

#Class
class Comment < ActiveRecord::Base
  belongs_to :post

  validates :post_id, presence: true
  validates :comment_number, uniqueness: { scope: :post_id } 
end

现在,您需要确保填充此列:

class Comment < ActiveRecord::Base
  #...

  before_create :assign_comment_number

  private

  def assign_comment_number
    self.comment_number = (self.class.max(:comment_number) || 0) + 1
  end 
end

最后一步是告诉 Rails 使用此列而不是 id。为此,您需要重写 to_param 方法:

class Comment < ActiveRecord::Base
  #...
  def to_param
    comment_number
  end
end

更新:

还有一件事,将此字段设置为只读非常有用:

class Comment < ActiveRecord::Base
  attr_readonly :comment_id
end

此外,在重新考虑对 comment_number 进行唯一性验证之后,在运行验证后对其进行分配几乎没有意义。最有可能的是,您应该摆脱它并依赖数据库索引。

即使进行了此验证,仍然可能存在条件竞争。我可能会重写 save 方法来处理约束验证异常,并重试几次,以确保这不会破坏应用程序流程。但这是另一个问题的主题。

关于ruby-on-rails - 根据关联重置 PK 数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23942163/

相关文章:

ruby - 如何使用后续声明 postgresql json/jsonb 字段?

ruby-on-rails - Routes.rb 未反射(reflect)在 _path 和 _url 中

ruby-on-rails - 第一次尝试 RSepc 但没有成功

ruby-on-rails - 如何将 force_ssl 与 302 一起使用

ruby-on-rails - 将 bool 列类型更改为 int

ruby - 如何避免查询结果中出现重复的字段名

ruby - 续集 gem 增量

ruby-on-rails - 使用敏感信息(如密码)rails 保护数据库列

javascript - 脚本导致链接调用服务器两次

ruby-on-rails - Ruby/Rails - 在不建模的情况下访问 "lookup"表?