contracts.ruby icon indicating copy to clipboard operation
contracts.ruby copied to clipboard

Can't use Contracts with define_method in a module

Open actsasbuffoon opened this issue 10 years ago • 5 comments

I love the fact that Contracts works with define_method and define_singleton_method. It makes my life a lot easier. The problem is that the same pattern doesn't seem to work in modules.

require 'contracts'

# This works:
class ExampleClass
  include Contracts

  def self.define_typed_method(method_name)
    # This works, and the contract is applied to the metaprogrammed method
    Contract None => Fixnum
    define_method(method_name) { 42 }
  end

  define_typed_method :foo
end

ExampleClass.new.foo
# => 42

# This is where things go wrong:
module ExampleModule
  include Contracts

  def define_typed_method(method_name)
    Contract None => Fixnum
    # ~> (eval):7:in `Contract': undefined method `Contract' for Class:Class (NoMethodError)
    # ~>    from -:22:in `define_typed_method'
    # ~>    from -:34:in `<class:HypotheticalClass>'
    # ~>    from -:31:in `<main>'
    define_method(method_name) { 42 }
  end
end

class HypotheticalClass
  extend ExampleModule

  # This is how I'd use it, if things were working correctly
  define_typed_method :foo
end

actsasbuffoon avatar Oct 14 '15 21:10 actsasbuffoon

This works for me after I add include Contracts in the HypotheticalClass class, though it should work without that too.

egonSchiele avatar Oct 15 '15 13:10 egonSchiele

@actsasbuffoon read this comment: https://github.com/egonSchiele/contracts.ruby/issues/229#issuecomment-193544001

I bet this is what is happening here too. Unfortunately the fix won't fix your issue ... Ruby is trying to resolve Contract as a constant, and it doesn't work.

egonSchiele avatar Mar 09 '16 00:03 egonSchiele

@egonSchiele Maybe we could provide an alias with lowercase? Like def_contract(...) ?

waterlink avatar Mar 09 '16 00:03 waterlink

@waterlink I'm wondering if we should start moving away from Contract and towards contract. This conflict (constant vs function name resolution) will always be there.

egonSchiele avatar Mar 11 '16 21:03 egonSchiele

@egonSchiele We can totally do that, I don't mind contract at all. It is not so pretty, but what can you do about it :)

waterlink avatar Mar 11 '16 23:03 waterlink