Hi,
I’m having trouble to factor some simple code. Since, I have been stuck for several days now I ask the question here.
Beginning of code
module DefWithName
def integer(name, options = {})
store_result name, MyInteger.new(options)
end
def id(name)
integer(name, an_options: true)
end
end
module DefWithoutName
def integer(options = {})
store_result MyInteger.new(options)
end
def id
integer(an_options: true)
end
end
class A; include DefWithName; end
class AA; include DefWithName; end
class B; include DefWithoutName; end
class BB; include DefWithoutName; end
End of code
Constraints:
Any ideas?
Regards,
-Nico
Could you give some examples of what you're trying to do or problems you've run into? You've posted some code but haven't described how you'll be using it and in what way it isn't adequate.In fewer words: I don't see what your question is.
Fred
Thanks for replying.
Yes sorry. I realize that some context is missing.
I am writing an API where the users are allowed to write something like that:
FooContextWithName.new.eval do |o|
o.integer “id”, an_option: true # [1]
o.integer “foo”, an_option: true # [2]
o.bar “a_name” do |o|
o.integer an_option: true # [3]
end
end
I would like that users are able to factor [1] and [2] by writing a small plugin like this:
module MyHelpers
def id(name = “id”)
integer name, an_option: true
end
end
MyLib.add_helpers(MyHelpers) # add_helpers would be defined appropriately
To factor [3] users should be able to write something like that:
module MyHelpers
def id
integer an_option: true
end
end
To implement this API I have something like this
module DefWithName
def integer(name, options = {})
store_result name, MyInteger.new(options)
end
end
module DefWithoutName
def integer(options = {})
store_result MyInteger.new(options)
end
end
class FooWithName < BasicObject
include DefWithName
def store_result(name, object)
@props[name] = object
end
end
class BarWithoutName < BasicObject
include DefWithoutName
def store_result(object)
@items << object
end
end
I finally found a good way to factor this.
Instead of having two modules DefWithoutName and DefWithName I have only one:
module BasicDef
def integer(name, options = {})
store_result name, MyInteger.new(options)
end
end
Then I use a proxy for evaluation that will
-
in the case of “with name” will call directly the target method and pass it all the arguments
-
in the case of “without name” will call the target method by passing “nil” as first arguments and then the rest of the arguments.
The proxy checks when the target method requires a name as first argument using the Method#parameters method.