使用friendly_id gem有条件地重置slug

时间:2017-10-11 04:05:22

标签: ruby ruby-on-rails-5 friendly-id

我的应用程序使用friendly_id gem以通常的方式分配slugs:

class Organization < ApplicationRecord
  extend FriendlyId
  friendly_id :name, use: :slugged
  strip_attributes
end

当用户更改organization.name时,默认情况下,slug不会更改。但我想让用户选择重置slug以匹配名称。

从控制台来看,这很简单:

>> organization.update(slug: nil)

Friendly_id使用before_validate挂钩跳转并生成一个新的slug。但是,如果我尝试使用OrganizationsController#update方法将slug设置为nil,那么它无效:

Started PATCH "/organizations/slo-mo-100?organization%5Bslug%5D=" for 127.0.0.1 at 2017-10-10 16:37:30 -0600
Processing by OrganizationsController#update as HTML
  Parameters: {"organization"=>{"slug"=>""}, "id"=>"slo-mo-100"}
  Organization Load (0.5ms)  SELECT  "organizations".* FROM "organizations" WHERE "organizations"."slug" = $1 ORDER BY "organizations"."id" ASC LIMIT $2  [["slug", "slo-mo-100"], ["LIMIT", 1]]
   (0.3ms)  BEGIN
  SQL (4.1ms)  UPDATE "organizations" SET "slug" = $1, "updated_at" = $2 WHERE "organizations"."id" = $3  [["slug", nil], ["updated_at", "2017-10-10 22:37:30.077956"], ["id", 1]]
   (0.2ms)  ROLLBACK
Completed 500 Internal Server Error in 24ms (ActiveRecord: 6.2ms)

PG::NotNullViolation - ERROR:  null value in column "slug" violates not-null constraint

我希望#update操作与控制台一样,即在传入值设置为nil时分配新的slug。

1 个答案:

答案 0 :(得分:0)

事实证明解决方案非常简单。问题是更新参数是通过将slug设置为空字符串({"slug"=>""})而不是nil来实现的。我使用strip_attributes gem将空字符串转换为nil,但在strip_attributes已经检查friendly_id字段后才slug被调用是nil

我通过在strip_attributes之前将回调的顺序切换为触发friendly_id来解决问题:

class Organization < ApplicationRecord
  extend FriendlyId
  strip_attributes
  friendly_id :name, use: :slugged
end