Search code examples
ruby-on-railsactiverecordfriendly-idactivesupport-concern

Rails 5.0.1 - Friendly_id gem - included active concern module before_create or before_save


I have created this module:

app/models/concerns/sluggable.rb

module Sluggable
  extend ActiveSupport::Concern

  included do
    before_create :set_slug
  end


  def set_slug
    if self.slug.nil?
      puts 'adding slug'
      self.slug = SecureRandom.urlsafe_base64(5)
    end
  end

end

and I include it in a model, like so:

app/models/plan.rb

class Plan < ApplicationRecord
  extend FriendlyId
  friendly_id :id, :use => :slugged
  include Sluggable
end

but the before_create does not fire. The slug column is a not_null column so I get a database error.

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

If put the set_slug code directly in the model, it works. So what am I missing here about Concerns in Rails 5?

I wonder if its something related to using FriendlyId (which is why I added slugs in the first place!)


Solution

  • This helped me solve this. Friendly_Id sets the slug in a before_validation callback if it is nil.

    So my module needs to 'jump' in ahead of that. So the solution to make a module that doesn't conflict with Friendly_id is as below.

    Notice I need to change the method name for my hook (as set_slug is a method used by Friendly_Id) AND I have to use prepend: true. Together this causes my code to set the slug before Friendly_Id fires its check to try and set it.

    module Sluggable
      extend ActiveSupport::Concern
    
      included do
        before_validation :set_a_slug, prepend: true
      end
    
    
      def set_a_slug
        if self.slug.nil?
          self.slug = SecureRandom.urlsafe_base64(5)
        end
      end
    
    end