Skip to content

Instantly share code, notes, and snippets.

@saturnflyer
Created July 10, 2013 14:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saturnflyer/5966613 to your computer and use it in GitHub Desktop.
Save saturnflyer/5966613 to your computer and use it in GitHub Desktop.
Dynamically defining the initialize method and setting the arity.
class Something
def self.init(*init_args)
# this works but...
define_method(:initialize){|*args|
# arity is -1
}
class_eval %Q<
def initialize(#{*init_args})
# this doesn't work
end
>
end
end
# Here I want arity of :initialize to be 2
class Special < Something
init(:one, :two)
end
# And here I want arity of :initialize to be 3
class Other < Something
init(:one, :two, :three)
end
@mulder
Copy link

mulder commented Jul 10, 2013

You'r forgetting class_eval takes a string...

    class_eval %Q<
      def initialize(#{init_args.join(',')})
        # this doesn't work
      end
    >
[1] pry(main)> Other.new
ArgumentError: wrong number of arguments (0 for 3)
from (eval):2:in `initialize'
[2] pry(main)> Special.new
ArgumentError: wrong number of arguments (0 for 2)
from (eval):2:in `initialize'

@mattgreen
Copy link

class Something
  def self.init(*init_args)
    define_method(:initialize) do |*args|
      # TODO: check args, raise similar exception as Ruby
      init_args.zip(args) do |name, value|
        instance_variable_set("@#{name}", value)
      end
    end
  end
end

# And here I want arity of :initialize to be 3
class Other < Something
  init(:one, :two, :three)
end

o = Other.new("one", "two", "three")
puts o.inspect
# #<Other:0x007fbbc40592b8 @one="one", @two="two", @three="three">

@saturnflyer
Copy link
Author

thanks guys! @mulder's comment work. I wasn't joining the args

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment