簡體   English   中英

添加對Rails Friendly_id虛榮URL的隨機唯一引用

[英]Add random unique reference to Rails Friendly_id vanity URL

我有一個產品型號,其中包含產品名稱和在產品創建之前隨機生成的唯一引用。 我想使用它們來生成frindly_id URL。 這是我的嘗試:

# == Schema Information
#
# Table name: products
#
#  name        :string           not null
#  slug        :string
#  reference   :string
#
class Product < ActiveRecord::Base
  extend FriendlyId

  before_create :generate_unique_reference
  friendly_id :friendly_id_syntax, use: :slugged

  def generate_unique_reference
    self.reference = SecureRandom.hex(3).upcase
  end

  def friendly_id_syntax
    [
      [:name, :reference]
    ]
  end
end

這會生成僅包含產品名稱的虛榮URL(不包含產品參考)。 似乎在引用屬性仍為零時完成了slug生成。 當我把friendly_id :friendly_id_syntax, use: :sluggedbefore_create之前friendly_id :friendly_id_syntax, use: :slugged before_create時,我有相同的結果。

有什么想法嗎?

這里的文檔:

FriendlyId使用before_validation回調來生成和設置slug ...

before_validationbefore_create之前before_create 所以要修復它,將before_create更改為before_validation

class Product < ActiveRecord::Base
  extend FriendlyId

  before_validation :generate_unique_reference, on: :create
  friendly_id :friendly_id_syntax, use: :slugged

  def generate_unique_reference
    self.reference = SecureRandom.hex(3).upcase
  end

  def friendly_id_syntax
    [
      [:name, :reference]
    ]
  end
end

另一種方法是使用slug_candidates (雖然我不認為它會提供你想要的確切功能):

#app/models/product.rb
class Product < ActiveRecord::Base
   extend FriendlyID
   friendly_id :slug_candidates, use: :slugged

   def reference
      SecureRandom.hex(3).upcase
   end

   private

   def slug_candidates
      [
        [:name, :reference]
      ]
   end
end

好吧,我剛剛意識到這正是你已經完成的事情。 如果有人想看到對問題的另一種解釋,我仍會發布答案; 如有必要,我會刪除。


可能希望考慮的其他事情是在數據庫中實現uuid

通用唯一標識符(UUID)是軟件構造中使用的標識符標准。 UUID只是一個128位的值。 每個位的含義由幾個變體中的任何一個定義。

大多數人都會因為暗示這一點而將我分開; 你必須用以下字符串替換你的id主鍵: de305d54-75b4-431b-adb2-eb6b9e546014

我們用一些東西來做:

在此輸入圖像描述

這有幾個好處,包括您可以引用單個對象,無論它們存儲在何處,並且 - 正如您所發現的那樣 - 能夠在諸如slug之類的東西中使用uuid

你可以隨意拿走; 我實現了一個uuid ,然后在after_create之后進行friendly_id更新:

#app/models/product.rb
class Product < ActiveRecord::Base
   extend FriendlyID
   friendly_id :slug_candidates, use: :slugged

   after_create :set_new_friendly_id

   private

   def slug_candidates
      [
        [:name, :uuid]
      ]
   end

   def set_new_friendly_id
      self.save #-> I know a double SQL call, but only way to get UUID
   end

   def should_generate_new_friendly_id?
      uuid.present? #-> only updates if uuid is present
   end
end

要使uuid工作,你必須使用MYSQL中的uuid()函數或PGSQL中的uuid_generate_v4函數:

# db/schama.rb
create_table "nodes", force: :cascade, id: false do |t|
    t.string   "uuid",        limit: 255, default: (Rails.env.staging? ? "uuid_generate_v4();" : 0), null: false
    t.string   "type",        limit: 255
    t.string   "slug",        limit: 255
    t.string   "title",       limit: 255
    t.text     "value",       limit: 65535
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
end

  execute "ALTER TABLE nodes ADD PRIMARY KEY (uuid);"
  if Rails.env.staging? #-> Heroku PGSQL
    execute("CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\"")
  else
    execute("DROP TRIGGER IF EXISTS before_insert_nodes;") #http://stackoverflow.com/a/5945220/1143732
    execute("CREATE TRIGGER before_insert_nodes BEFORE INSERT ON nodes FOR EACH ROW SET new.uuid = uuid();")
  end

雖然這會將UUID生成從應用程序邏輯中移除,但這意味着您只能在創建記錄使用UUID。 這就是為什么使用friendly_id可能會很粗略; 但最終可能會為您提供您想要的功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM