【问题标题】:Generating a slug after Active Record object creation in rails在 Rails 中创建 Active Record 对象后生成 slug
【发布时间】:2016-07-23 01:47:09
【问题描述】:

在使用 after_commit 回调创建对象后,我正在尝试为该对象生成一个唯一的 slug。

after_commit :create_slug, on: :create

def create_slug
    self.slug = generate_slug
    self.save
end

当我尝试保存对象时,出现“堆栈级别太深”错误。我假设是因为我正在保存对象并且它被一次又一次地调用 after_commit 回调。

在这种情况下生成和保存独特 slug 的最佳方法是什么?

【问题讨论】:

    标签: ruby-on-rails activerecord slug


    【解决方案1】:

    我建议在创建时使用 after_validation 回调而不是 after_commit。您将调用多个事务,这不是此回调的意图。我会这样做:

    after_validation(on: :create) do
      self.slug = generate_slug
    end
    

    还要确保 generate_slug 中没有保存操作。该方法应该只是返回一个值以插入到 slug 属性中。

    【讨论】:

    • 我认为这种方法和@lei_liu 都有效。有什么想法更好用吗?
    • 取决于您是否需要在创建 slug 之前将数据保存在磁盘中。当我阅读您的代码时,我假设正在发生一些事情,需要在生成 slug 之前创建数据,例如数据库交互在某处创建静态路由,或者如果数据不持久,则发送无效的电子邮件在生成蛞蝓之前。如果您没有在生成依赖于数据库中数据的 slug 中做某事,那么仅针对数据库进行单个事务(我的建议)的性能会更好。
    • bkoski/slug 在创建 slug 时使用 before_validation 回调。 FriendlyId/friendly_id 使用 before_validation 设置 slug 和 after_validation 为 unset_if_invalid。
    • 所以使用 before_validation 会生成 slug 并将所有数据保存在一个事务中?我不需要在生成 slug 之前创建数据。我有一个用户创建了一个带有一些参数的邀请,然后我需要在用户提交它时同时为该邀请生成一个唯一的 URL。
    • 这些 gem 使用 before_validation 回调的原因是 gem 的消费者可以基于 slug 创建验证。我建议将其移至 after_validation,这样就不会花费额外的处理来为无效记录生成 slug。
    【解决方案2】:

    使用不会触发回调的方法,例如:update_column

    def create_slug
        update_column('slug ', generate_slug)
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多