# define a command class
class AuthenticateUser
prepend SimpleCommand
# optional, initialize the command with some arguments
def initialize(email, password)
@email = email
@password = password
end
# mandatory: define a #call method. its return value will be available
# through #result
def call
if user = User.find_by(email: @email)&.authenticate(@password)
...
end
So you can invoke it like this
AuthenticateUser.call(session_params[:email], session_params[:password])
And I wondered how the SimpleCommand module might be structured. Additionally, I considered how it could support keyword arguments in the form of:
def my_method(value:, second_value:)
puts "value #{value}, second_value #{second_value}"
end
my_method(value: 'value one', second_value: 'value two')
In fact, it is quite simple. Let’s define it in two different ways without using any additional dependencies:
Using class_eval and self for defining a class method
module SimpleCommand
def self.included(klass)
klass.class_eval do
def self.call(*args, **kwargs)
puts "args #{args}"
new(*args, **kwargs).call
end
end
end
end
or
Using extend to define the methods as class methods
module SimpleCommand
def self.included(klass)
klass.extend(ClassMethods)
end
module ClassMethods
def call(*args, **kwargs)
new(*args, **kwargs).call
end
end
end
And here is how you can use it after that
class NamedArguments
include SimpleCommand
def initialize(value: , second:)
@value = value
@second = second
end
def call
puts "the method in myClass @value: #{@value}, @second #{@second}"
end
end
NamedArguments.call(value: 'the value', second: 'from second')
Or using positional arguments
class SimpleArguments
include SimpleCommand
def initialize(valueOne, valueTwo)
@valueOne = valueOne
@valueTwo = valueTwo
end
def call
puts "the method in myClass @value: #{@valueOne}, @second #{@valueTwo}"
end
end
SimpleArguments.call('arg one', 'arg two')
There you have it!