norman/friendly_id-globalize

Best way to update slug?

Opened this issue · 2 comments

Hi, I use your gem with friendly-id and globalize (last versions) in a Rails 4.2.5 application. I need to update slug every time a user modify the attribute name.

Model :

class Project < ActiveRecord::Base
  # Translations
  TRANSLATED_FIELDS = [:name, :description, :full_description, :slug, :meta_desc, :meta_keys].freeze
  translates *TRANSLATED_FIELDS, :fallbacks_for_empty_translations => true

  # Friendly URL generation
  extend FriendlyId
  friendly_id :name, use: :globalize

  validates_presence_of     :name

end

When I use update action in my controller slug is not regenerated because slug is not nil in translations. I check the code and I realize that the method used to update slug is :

    def should_generate_new_friendly_id?
      translation_for(::Globalize.locale).send(friendly_id_config.slug_column).nil?
    end

How can I manage to set slug attributes to nil?
I try :

  • to do in the form but it's a string i can't pass a nil value
  • to do in the controller in merging attributes with ( { slug: nil} )
  • to use a before validation method in model :
  before_validation :set_slug_nil_if_blank

  def set_slug_nil_if_blank
    self.slug = nil if slug.blank?
  end

I go further and discover that the object instance in should_generate_new_friendly_id? seems to be the old one not the one which is updated.

Is there a classic way to do this?

the solution I find is to override should_generate_new_friendly_id? in config/initializers :

# Hack to override method should_generate_new_friendly_id 
module FriendlyId
  module Globalize

    def should_generate_new_friendly_id?
      regenerated_keys = %w( name title login)
      slug.blank? || (self.changes.keys & regenerated_keys).present?
    end

  end
end

Good catch @ldonnet . Just a note: The general solution would be translation_for(::Globalize.locale).send(friendly_id_config.slug_column).blank? instead of slug.blank? .