Reputation: 2210
I have the following class
class EvaluateService
def initialize
end
def get_url
end
def self.evaluate_service
@instance ||= new
end
end
class CheckController < ApplicationController
def index
get_url = EvaluateService.get_url
end
end
The problem here is that i know that i can do evaluate_service = EvaluateService.new
and use the object evaluate_service.get_url
and it will work fine but i also know that some frown upon the idea of initializing the service object this way and rather there is a way of initializing it via a call, send method in the service class.
Just wondering how do i do this?
Upvotes: 2
Views: 3442
Reputation: 8777
I think what you're looking for is something like:
class Evaluate
def initialize(foo)
@foo = foo
end
def self.call(foo)
new(foo).call
end
def call
url
end
private
def url
# Implement me
end
end
Now you can do this in your controller:
class CheckController < ApplicationController
def index
@url = Evaluate.call(params)
end
end
The reason some prefer #call
as the entry point is that it's polymorphic with lambdas. That is, anywhere you could use a lambda, you can substitute it for an instance of Evaluate
, and vice versa.
Upvotes: 4
Reputation: 114138
There are various ways to approach this.
If the methods in EvaluateService
don't need state, you could just use class methods, e.g.:
class EvaluateService
def self.get_url
# ...
end
end
class CheckController < ApplicationController
def index
@url = EvaluateService.get_url
end
end
In this scenario, EvaluateService
should probably be a module.
If you want a single global EvaluateService
instance, there's Singleton
:
class EvaluateService
include Singleton
def get_url
# ...
end
end
class CheckController < ApplicationController
def index
@url = EvaluateService.instance.get_url
end
end
But global objects can be tricky.
Or you could use a helper method in your controller that creates a service instance (as needed) and memoizes it:
class EvaluateService
def get_url
# ...
end
end
class CheckController < ApplicationController
def index
@url = evaluate_service.get_url
end
private
def evaluate_service
@evaluate_service ||= EvaluateService.new
end
end
Maybe even move it up to your ApplicationController
.
Upvotes: 2