Reputation: 141
I am using Hanami and I created a custom module in /lib/supports/utils.rb. I'm requiring all the files located /lib/supports in /lib/myapp that it's like the following:
require 'hanami/model'
require 'hanami/mailer'
Dir["#{__dir__}/myapp/**/*.rb"].each { |file| require_relative file }
Dir["#{__dir__}/supports/**/*.rb"].each { |file| require_relative file }
Hanami::Model.configure do
# and so on
In /lib/supports/utils.rb, I have:
# using the gem 'slugify'
require 'slugify'
module MyModule
module Utils
module Slug
def slug_it(random = false)
if random
slugify + '-' + SecureRandom.hex(10).to_s
else
slugify
end
end
end
end
end
I tried to include MyModule::Utils::Slug in a repository but it always returns NoMethodError: undefined method `slug_it' for "string":String. An example:
class EventRepository
include Hanami::Repository
include MyModule::Utils::Slug
def self.create_or_update(attrs)
found = find(attrs.id)
attrs = event_attributes(attrs)
if found
unless found.slug.include? attrs[:name].slug_it
attrs[:slug] = attrs[:name].slug_it(true)
end
found.update(attrs)
update found
else
attrs[:slug] = attrs[:name].slug_it(true)
create Event.new(attrs)
end
end
end
It only works if I add at the bottom of /lib/supports/utils.rb:
class String
include MyModule::Utils::Slug
end
I would like to always include the module like include Hanami::Repository
in EventRepository.
What am I doing wrong?
Upvotes: 2
Views: 904
Reputation: 1211
another way to do that is:
require 'slugify'
module MyModule
module Utils
module Slug
def self.slug_it(string, random = false) # Please note `self` and `string`
# ...
end
end
end
end
Then you can use it like this:
MyModule::Utils::Slug.slug_it(attrs[:name], true)
Upvotes: 0
Reputation: 839
You could try somethong like it, also:
https://gist.github.com/rafaels88/5529b3863c699b1cd4d20265c32d4a21
# lib/your_app/ext/sluggable.rb
module Sluggable
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def sluggable(field)
@field = field
end
def field
@field
end
end
def slug
send(self.class.field).slugify
end
end
# USAGE
#
# class MyEntity
# include Hanami::Entity
# include Sluggable
# attributes :name, :slug, :other_field, :yet_another_field
# sluggable :name
# end
#
# Do not forget to create :slug field in database and mapping it to its entity
Upvotes: 0
Reputation: 6138
When you include MyModule::Utils::Slug
into EventRepository
, the methods defined in the included module are available on an instance of EventRepository
not on String
. If you want to use the module as-is, you need to include it on String
. If you don't want to include it on the global class you could do
module MyModule
module Utils
module Slug
def slug_it(string, random = false)
if random
string.slugify + '-' + SecureRandom.hex(10).to_s
else
string.slugify
end
end
end
end
end
and then modify the slug creation to pass the string you want to slugify
unless found.slug.include? slug_it(attrs[:name])
attrs[:slug] = slug_it(attrs[:name], true)
end
Upvotes: 3