【问题标题】:NoMethodError: undefined method for String with custom module in HanamiNoMethodError:Hanami 中带有自定义模块的字符串的未定义方法
【发布时间】:2016-09-29 19:16:49
【问题描述】:

我正在使用 Hanami,并在 /lib/supports/utils.rb 中创建了一个自定义模块。我要求所有位于 /lib/myapp 中的 /lib/supports 文件如下所示:

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

/lib/supports/utils.rb 中,我有:

# 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

我尝试在存储库中包含 MyModule::Utils::Slug,但它总是返回 NoMethodError: undefined method `slug_it' for "string":String。一个例子:

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

只有在 /lib/supports/utils.rb 的底部添加才有效:

class String
  include MyModule::Utils::Slug
end

我希望始终在 EventRepository 中包含像 include Hanami::Repository 这样的模块。

我做错了什么?

【问题讨论】:

    标签: ruby hanami


    【解决方案1】:

    当您将MyModule::Utils::Slug 包含到EventRepository 中时,包含的模块中定义的方法可用于EventRepository 的实例而不是String。如果您想按原样使用该模块,则需要将其包含在 String 中。如果您不想将其包含在全局类中,您可以这样做

    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
    

    然后修改slug创建将你想要的字符串传递给slugify

    unless found.slug.include? slug_it(attrs[:name])
      attrs[:slug] = slug_it(attrs[:name], true)
    end
    

    【讨论】:

    • 谢谢你,@LukasEklund!你的回答真的帮助了我。我还需要更改 Dir["#{dir}/myapp/**/*.rb"].each 和 Dir["#{dir}/supports/**/*.rb"].each 并在 EventRepository 类中扩展 MyModule。
    【解决方案2】:

    你也可以试试类似的:

    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
    

    【讨论】:

      【解决方案3】:

      另一种方法是:

      require 'slugify'
      
      module MyModule
        module Utils
          module Slug
            def self.slug_it(string, random = false) # Please note `self` and `string`
              # ...
            end
          end
        end
      end
      

      那么你可以这样使用它:

      MyModule::Utils::Slug.slug_it(attrs[:name], true)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-29
        • 1970-01-01
        • 2020-07-01
        • 2014-06-01
        • 2013-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多