1

I know there are some gems out there that give you slugs out of the box. However, I think doing something similar is a good way of learning.

Since I'm using slugs in several models, I decided to create a module and include it via ActiveSupport::Concern.

This is my module sluggable.rb:

module Sluggable
    extend ActiveSupport::Concern

    module ClassMethods
        def slug(*atts_to_slug)
            after_validation set_slug(atts_to_slug)
        end

        def set_slug(atts)
            slug_string = atts.map{|f| f.parameterize}.join("-")
            # Then I would think I can do something like:
            # model_instance.send("slug", slug_string)
        end
    end
end

Then I'd like to do something like this in the model:

class Classification < ApplicationRecord
    include Sluggable

    slug :name, :street
end

The problem I'm finding is:

How do I set the model's attribute slug from the module?

1 Answer 1

1

after_validation is a callback that expects a method name, block or a callable object (proc/lambda).

The way you're currently using it. It will call set_slug once when slug is first called and not after that.

slug should set the required attributes into some (class-level) variable. after_validation should call the set_slug method that should be an instance method. Then in the set_slug instance method you have access to all the attributes.

module Sluggable
  extend ActiveSupport::Concern

  module ClassMethods
    def slug(*atts_to_slug)
      @atts_to_slug = atts_to_slug
    end

    def atts_to_slug
      @atts_to_slug
    end
  end

  included do # instance scope
    after_validation :set_slug

    def set_slug
      slug_string = self.class.atts_to_slug.map do |f|
        # send since we're in the instance and I want to just call `name`
        public_send(f).parameterize
      end.join("-")
      self.slug = slug_string
    end
  end
end
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.