0

TLDR: A hash extension works flawlessly, returning the desired output, when included locally in my Mailer, but always returns nil when imported from a module in lib/, even though the class method is successfully loaded.

When I declare the extension in my mailer.rb file, before my class definition, as in:

class Hash
  def try_deep(*fields)
    ...
  end
end

class MyMailer < ApplicationMailer
  some_hash.try_deep(:some_key)
end

it works flawlessly, but this is bad practice. I thought it better to declare the extension in /lib/core_ext/hash/try_deep.rb and then require it in the Mailer, as in:

/lib/core_ext/hash/try_deep.rb:

module CoreExtensions
  module Hash
    module TryDeep
      def try_deep(*fields)
        ...
      end
    end
  end
end

/my_mailer.rb:

require 'core_ext/hash/try_deep'

class MyMailer < ApplicationMailer
  Hash.include CoreExtensions::Hash::TryDeep
  some_hash.try_deep(:some_key)
end
  • 1
    Side question: Are you implementing [Hash#dig](https://ruby-doc.org/core-2.5.3/Hash.html#method-i-dig)? – Marcin Kołodziej Nov 15 '18 at 03:01
  • @MarcinKołodziej Good question. The reason I'm implementing this is to be able to safely dig for attributes in a mixed-object-version environment. Older objects are missing certain newer attributes. Hash#dig, while it seems great at first, doesn't solve my problem because it throws an error rather than 'nil' when it digs for a key that doesn't exist. For my idiosyncratic use-case (sending an email), 'nil' is what I want when a key isn't found. – Reverse Engineered Nov 16 '18 at 04:30
  • It seems to return `nil` to me when a key does not exist: `{a: 1}.dig(:b) => nil` – Marcin Kołodziej Nov 16 '18 at 04:39

1 Answers1

2

You need to inject your custom method into Hash outside of your class:

my_mailer.rb:

require 'core_ext/hash/try_deep'

class Hash
  include CoreExtensions::Hash::TryDeep
end

class MyMailer < ApplicationMailer
  some_hash.try_deep(:some_key)
end
Ilya Konyukhov
  • 2,666
  • 1
  • 12
  • 21