2016-02-05 2 views
3

Я хочу иметь URLs, как это:Дружественные ID пробкового не содержит идентификатор

http://domain.com/products/454-table-lamp 

Поэтому я использую friendly_id так:

extend FriendlyId 

friendly_id :slug_candidates, use: :history 

def slug_candidates 
    [ 
     [:id, :title] 
    ] 
end 

Теперь, так как дружественный идентификатор генерирует слизняка до объект сохраняется я в конечном итоге с URL, как так (Пожалуйста, обратите внимание на недостающую идентификатор в URL):

http://domain.com/products/table-lamp 

Сейчас пока это не слишком плохой как таковой. Как только я сохраняю другой продукт под названием «Настольная лампа», я получить URL, как это:

http://domain.com/products/table-lamp-ebaf4bf5-a6fb-4824-9a07-bdda34f56973 

Так что мой вопрос, как я могу убедиться, дружелюбный ID создает слизняк, содержащий идентификатор, а также.

ответ

4

Просто добавьте обратный вызов after_commit к вашей модели. В этом обратном вызове установите slug на ноль и сохраните:

after_commit :update_slug, on: :create 

    def update_slug 
    unless slug.include? self.id.to_s 
     self.slug = nil 
     self.save 
    end 
    end 
+0

Я взял на себя смелость, чтобы отредактировать ваш ответ, потому что я столкнулся с переполнением стека, поэтому я должен проверить, что идентификатор еще нет. – Besi

+0

Спасибо Besi :). Я думаю, 'after_commit: update_slug, on:: create' делает трюк для этого. Обязательно ли проверять идентификатор? –

+0

Да, когда я не проверяю идентификатор при каждом сохранении, метод 'update_slug' будет вызван снова. – Besi

2

Ну, короткий ответ - вы не можете. FrienlydId генерирует slug в before_validation callback здесь: https://git.io/vgn89. Проблема в том, что вам нужно создать slug перед сохранением, чтобы избежать конфликтов, но вы хотите использовать информацию, доступную только после фактического сохранения, когда запись уже находится в db.

Посмотрите на этот answer for details.

Конечно, вы можете сделать что-то вроде, если вы действительно хотите:

def slug_candidates 
    [ title, Model.maximum(:id) + 1 ] 
end 

Но этот код не поточно и может привести к некоторым очевидным проблемам. Другой способ - изменить slug после сохранения, например, в обратном вызове after_create. Вы можете установить его на nil и снова позвонить set_slug.

Но спросите себя - вам это действительно нужно? Может быть, лучше использовать временную метку из created_at, например, как часть кандидатов в пули?

+0

Спасибо за разъяснение. Я мог бы сделать это с помощью Терри и обратного вызова 'after_commit'. См. Его ответ. – Besi

+0

Добро пожаловать =) Да, это сработает. Но в этом случае у вас есть двойное сохранение при создании, и вы не увидите никаких ошибок проверки, если что-то происходит во время сохранения after_commit. – kimrgrey

Смежные вопросы