我有一个帖子
和评论
表。
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/