toys icon indicating copy to clipboard operation
toys copied to clipboard

Availability of tool's private methods in `accept` (`acceptor`)

Open AlexWayfer opened this issue 5 years ago • 1 comments

Hello.

I want to define option with a processing in specific cases, like:

required_arg :new_version, accept: (lambda do |value|
  case value
  when 'major'
    "#{Integer(current_version.split('.').first) + 1}.0.0"
  else value
  end
end)

And current_version is a private method inside tool. And I can't access it, sadly.

How to better handle this case?

Also, I figured out that handler is unavailable for arguments.

Also I've tried to add attr_writer :new_version, but new_version getter is not regular, so it's not synchronized (sadly, again).

AlexWayfer avatar Nov 11 '20 14:11 AlexWayfer

Regarding current_version

You can't access methods of your tool from an accept function because it is called while command line arguments are being parsed, and the tool hasn't been constructed yet at that point. However, you should be able to call a class method of the tool, because, just like any class definition, self is pointing at the class.

tool "my-tool" do
  def self.current_version
    "1.2.3"
  end

  required_arg :new_version, accept: (lambda do |value|
    case value
    when 'major'
      "#{Integer(current_version.split('.').first) + 1}.0.0"
    else value
    end
  end)
end

Regarding handler for arguments

We could add a handler for arguments, but I didn't think there was a use case for it. It's generally useful if something could be set more than once (e.g. you have a flag that is given multiple times, and you use a handler to combine the values). But an argument can never be given more than once. Can you describe why you would use handler for an argument?

Regarding attr_writer

That I agree could be confusing, if you assume that the field is an attr_reader and uses an instance variable for its value. As you noted, that's not true. Fields are intentionally separate from instance variables. That was a design decision because I needed to support fields whose names are arbitrary objects (for special fields, so they don't have a chance of colliding with user-defined fields) and it would be even more confusing for some fields to be backed by instance variables while others are not.

dazuma avatar Jan 03 '21 06:01 dazuma