添加随机唯一参考 Rails Friendly_id 虚荣心 URL
Add random unique reference to Rails Friendly_id vanity URL
我有一个 Product 模型,其中包含产品名称和产品创建前随机生成的唯一参考。我想同时使用两者来生成 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。当 reference 属性仍为 nil 时,似乎已完成 slug 生成。当我将 friendly_id :friendly_id_syntax, use: :slugged
放在 before_create
之前时,我得到了相同的结果。
有什么想法吗?
来自文档here:
FriendlyId uses a before_validation callback to generate and set the
slug...
before_validation
在 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
好的,我刚刚意识到这正是您已经完成的。我仍然 post 答案,以防有人想看到对问题的另一种解释;有需要我会删
您可能想考虑的其他事情是在您的数据库中实施uuid
:
A universally unique identifier (UUID) is an identifier standard used in software construction. A UUID is simply a 128-bit value. The meaning of each bit is defined by any of several variants.
大多数人会因为我提出这个建议而把我撕成碎片;您必须将 id
主键替换为如下字符串:de305d54-75b4-431b-adb2-eb6b9e546014
我们用我们的一些东西来做:
这样做有几个好处,包括您可以引用单个对象,而不管它们存储在何处,以及 - 正如您所发现的那样 - 可以在类似 slug 的东西中使用 uuid
。
这个你可以随便拿;我会实施 uuid
然后 friendly_id
更新 after_create
:
#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
正常工作,您必须使用 PGSQL 中的 uuid()
function in MYSQL, or the 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;") #
execute("CREATE TRIGGER before_insert_nodes BEFORE INSERT ON nodes FOR EACH ROW SET new.uuid = uuid();")
end
虽然这从应用程序逻辑中提取了 UUID
代,但这意味着您只能在 创建记录后使用 UUID 。这就是为什么将它与 friendly_id
一起使用可能会很粗略;但最终可能会为您提供您想要的功能。
我有一个 Product 模型,其中包含产品名称和产品创建前随机生成的唯一参考。我想同时使用两者来生成 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。当 reference 属性仍为 nil 时,似乎已完成 slug 生成。当我将 friendly_id :friendly_id_syntax, use: :slugged
放在 before_create
之前时,我得到了相同的结果。
有什么想法吗?
来自文档here:
FriendlyId uses a before_validation callback to generate and set the slug...
before_validation
在 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
好的,我刚刚意识到这正是您已经完成的。我仍然 post 答案,以防有人想看到对问题的另一种解释;有需要我会删
您可能想考虑的其他事情是在您的数据库中实施uuid
:
A universally unique identifier (UUID) is an identifier standard used in software construction. A UUID is simply a 128-bit value. The meaning of each bit is defined by any of several variants.
大多数人会因为我提出这个建议而把我撕成碎片;您必须将 id
主键替换为如下字符串:de305d54-75b4-431b-adb2-eb6b9e546014
我们用我们的一些东西来做:
这样做有几个好处,包括您可以引用单个对象,而不管它们存储在何处,以及 - 正如您所发现的那样 - 可以在类似 slug 的东西中使用 uuid
。
这个你可以随便拿;我会实施 uuid
然后 friendly_id
更新 after_create
:
#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
正常工作,您必须使用 PGSQL 中的 uuid()
function in MYSQL, or the 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;") #
execute("CREATE TRIGGER before_insert_nodes BEFORE INSERT ON nodes FOR EACH ROW SET new.uuid = uuid();")
end
虽然这从应用程序逻辑中提取了 UUID
代,但这意味着您只能在 创建记录后使用 UUID 。这就是为什么将它与 friendly_id
一起使用可能会很粗略;但最终可能会为您提供您想要的功能。