Method parameters can be passed in different ways, allowing for flexible and readable code. Understanding the difference between positional arguments and keyword arguments is essential for writing clean and maintainable code.
To illustrate how these types of arguments can be used in practice, we’ll take a look at an example using an initialize
method. This example will help clarify the distinction between positional arguments and keyword arguments in the context of a class constructor. While this initializer serves as a concrete example, the concepts apply broadly across Ruby methods.
Let’s break down these two types of arguments using the following example of an initialize
method:
1
2
3
4
5
6
7
def initialize(plan, user, params = {}, current_country: nil)
@plan = plan
@user = user
@params = params
@current_country = current_country || user&.current_country
@plan_price_resolver = PlanPriceResolver.new(@plan, user, current_country: @current_country)
end
1. Positional Arguments
Positional arguments must be provided in a specific order when calling the method. In this example, plan
, user
, and params
are positional arguments.
plan: The first argument passed to the method. It is assigned directly to the instance variable @plan
.
user: The second argument passed and assigned to @user
.
params = {}: This is an optional argument with a default value. In this case, it defaults to an empty hash ({}
). The params
hash is a great way to pass multiple values through a single argument.
Example of a method call using positional arguments:
1
Membership::Plan::BasePresenter.new(plan, user, { location_id: 1, volunteer_position_id: 2 })
Here, params
will receive { location_id: 1, volunteer_position_id: 2 }
.
2. Keyword Arguments
Keyword arguments are named parameters that do not need to follow a strict order when passed to a method. They are introduced with a name followed by a colon (:
), and they can have default values, such as current_country: nil
.
current_country: nil: This is a keyword argument. If not provided, it will default to nil
. In the method, it is assigned as @current_country = current_country || user&.current_country
. This means that if current_country
is not passed, it will fall back to the country associated with the user
.
Example of a method call using keyword arguments:
1
Membership::Plan::BasePresenter.new(plan, user, { location_id: 1 }, current_country: "Brazil")
In this example, current_country
is explicitly passed as “Brazil”. This overwrites the default value of nil
.
The Difference Between Positional and Keyword Arguments
- Positional arguments must be passed in a specific order. If you switch their positions, you will likely encounter an error. For example, in the method
initialize(plan, user, params)
, theplan
must always be the first argument, followed byuser
, thenparams
. - Keyword arguments, on the other hand, offer flexibility. Since you explicitly define the name of the argument (
current_country: "Brazil"
), they can be passed in any order relative to other keyword arguments, and they can also have default values.
Practical Example
Imagine you have two users: one who has a country already set and another without. You want to initialize a presenter object for both users, optionally passing the current_country
value when it’s not present.
Case 1: User without a current_country
(you pass it explicitly):
1
presenter = Membership::Plan::BasePresenter.new(plan, user, { location_id: 1 }, current_country: "Brazil")
Here, you’re explicitly setting current_country
to “Brazil” when initializing the presenter.
Case 2: User with a current_country
(you don’t pass it explicitly):
1
presenter = Membership::Plan::BasePresenter.new(plan, user, { location_id: 1 })
In this case, since current_country
is not passed as an argument, the method will use the value from the user
object (user&.current_country
).
Why Use Keyword Arguments?
Keyword arguments offer several advantages:
- Clarity: When you see
current_country: "Brazil"
, it’s immediately clear what value you’re passing. This avoids confusion when a method has many parameters. - Default Values: You can set reasonable defaults, so the method is still functional even if certain arguments are not provided.
- Flexibility: Keyword arguments don’t have to follow a strict order, making them easier to manage, especially in methods that have several optional parameters.
Positional arguments are great when the order matters and you need a fixed structure. Keyword arguments, on the other hand, offer more flexibility and clarity, especially when there are many optional or default values involved.
Let me know if you need further adjustments!