1

Perhaps a duplicate but I searched both SO and Google and couldn't find an answer even though it should be something trivial..

A Ruby method requires multiple args..

def initialize(options = {}) requires!(options, :arg1, :arg2, ...) super end 

How should one call such method with a variable number of parameters without knowing in advance these required parameters?

I know already Ruby 1.9.2 and later we can use the parameters method on a method to get the list of parameters for that method, and from there I can imagine we can reuse that to call the method since we knew its parameters. Correct?

If not correct, what is the best way to interact with such methods that take variable number of required parameters?

8
  • 1
  • what do you mean by "interact with such method"? Need to look at required arguments? Commented Jul 16, 2018 at 1:36
  • to interact as to "call it" without knowing its parameters requirements. Commented Jul 16, 2018 at 2:32
  • 1
    How and why would you call a method unless you know what it does? This is what documentation is for, and why it is so important. In order to use a library, or even a language, you first must learn what methods are available to you, what they do, how they work, etc, etc. This is primarily done by reviewing documentation for it, hence the reason documentation is distributed with things, and nobody uses those that don't.. Commented Jul 16, 2018 at 3:42
  • I feel like adding a reference to an older question remained unanswered.. stackoverflow.com/questions/48220723/… In this problem, it is required to initialize an instance of the gateway method without at first knowing what mandatory parameters the gateway method requires. Commented Jul 16, 2018 at 5:28

3 Answers 3

0

As far as I've understood, you do not want to provide a hash as an argument, but rather an array of values, skipping key names.

If you are using a third party library, and that method is defined there - it is not possible because that method was designed to receive an argument in a specified form (in your example hash must have some specific keys), and Ruby does not provide any capability to know what user had in mind (If you want to go extreme you can write of course a source file parser that would extract an arguments that come from that hash).

If you are designing method by your own, you can just:

def initialize(arguments = {}) case arguments when Hash @foo = arguments[:foo] @bar = arguments[:bar] when Array @foo = arguments[0] @foo = arguments[1] else raise ArgumentError.new("argument of type Hash or Array expected") end end 
Sign up to request clarification or add additional context in comments.

Comments

0

Your question basically equates to "how do I know about something that I don't know about".

The answer to this, to put bluntly, is go learn about it. In the context of programming and how to call a method, the same logic applies, and this is the sole purpose of documentation, and the same way that you learned to write Ruby code. I am sure you have like all of us here spent plenty of time looking through documentation on how to write code, what methods are available to us, what they are used for, how to invoke them, and so on.

If you come across the existence of a function, and all you can originally tell about it is that it takes a variable number of arguments, then you need to figure it out. This typically means looking up the documentation for it, or if you have access to the source, to examine the method body and see if you can determine how it is used.

This is why good documentation is essential, even more so for compiled languages where one cannot actually see body of a method and/or its signature. If no documentation exists, then IMHO, it is crap and you shouldn't be using it. It's like writing a book with your own made-up vocabulary and expecting people to have to try and decipher every word to even read it. You can write the most beautiful piece of code, and if you don't explain how to use it, what's the point of making it public?

To put simply, if you don't understand a method or what it does, you shouldn't be "interacting" with it, at least if you care about your code being robust. How are you supposed to debug code that you don't even understand? There is no explain_how_to_use_this(method) function to call, you're going to have to research it and do some old-fashioned learning.

3 Comments

Why do you think Ruby has introduced the parameters method? The method does solve my problem actually, but I am asking about the best way to do it other than this!
According to Ruby official documentation ruby-doc.org/core-2.2.2/Method.html#method-i-parameters I should be able to use the parameters method in order to initialize a gateway in active_merchant. Now require "active_merchant" ActiveMerchant::Billing::Base::gateway( :trust_commerce ).parameters should be giving me something like "login" (which solves my problem since I know now the "login" parameter and then able to ActiveMerchant::Billing::Base::gateway.(:trust_commerce).("login" => "value"). The funny this is when I do this it gives me a no method error!!
Technically your answer about "Reading the documentation" is the only valid answer so far since the official documentation about the method literally says this rubydoc.info/gems/activemerchant/ActiveMerchant/Billing/… But that raises another problem. Is the official Ruby documentation wrong about that parameters method? It gave me a no method error in my case when it simply should have given me the parameters of the method I want. Is there an explaination for this?
0

I don't think the method should be concerned with what arguments are passed in. All it should care about are the parameter necessary for it to do whatever it wants to do.

This way, you would have the initialize method taking the keys from the hash which concerns it and not really worrying about the others.

class Person def inititialize(opts: {}) @name = opts[:person_name] # could be nil end end class Car def initialize(opts: {}) @brand = opts[:car_brand] # could be nil end end opts = { person_name: "Ivan", car_brand: "Fiat", something_else: "ignored" } c = Car.new(opts) # is unaware of what is in 'opts' #<Car:0xd34db33f> p = Person.new(opts) # is unaware of what is in 'opts' #<Person:0x1337b347> 

I think encapsulation as a principle covers this. Methods should only know what they need to know to function. A scope should not legislate on the data coming in from its environment.

If you keep this in mind, you can pass anything into the method and allow the method do as it wishes.

2 Comments

I never mentioned that the method is concerned. I was asking about calling a method that takes variable parameters. In your example can I pass opt = {"Ivan", "Fiat"} without knowing the keys names in the hash? I think encapsulation indeed covers that so thanks for pointing me out to the right direction though.
can you take a look at this stackoverflow.com/questions/48220723/… and tell me how to initialize a gateway instance passing only the values of the parameters keys the gateway initialize method take?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.