RailsServices Gem Reaches 2.0.0
Since early-2014, I began to move away from the strict MVC approach with our Rails application. As I refactored some of our fatter models and not-so-skinny controllers, I wrote quite a few service classes. As a typical, developer, this was just too “hard” :). Naturally, I needed a generator to create these classes - and their attendant test scripts. So, I created my first gem, Rails Services.
The 1.x.x Family
In the first iterations of my gem, running the generator resulted in the following service class:
app/services/parent_model_or_controllers/sub_folder/service_class_name.rb
This approach - wherein all service classes and their methods were accessed as a Class, versus an instance of said call - worked fine, for the most part. However, two things bothered me about it. First, and there is no logical reason for this, writing self.
before methods felt “wrong” more often than not. Second, setting an instance variable in a few classes resulted in some odd race-condition-like behaviors. It was one of those things where I knew I needed to change my various service classes, but, I wasn’t sure the best way forward.
The 2.x.x Family
About a month ago, I was reading through some Ruby blogs and found one about services that I really liked - and I must apologize because, for the life of me, I cannot find “the post” that altered my trajectory with service classes. If the dude or dudette that wrote the post is reading this, sorry (let me know your post/URL and I will GLADLY link to it!).
Anyway, this “newfound” approach uses a BaseService
class, included in all services, to properly instantiate an instance of the class and then proceed on to do the required work.
Now, when you run the generate command in the terminal, you get the following output (a BaseService
class will be created for you in app/services
should it not already exist):
app/services/parent_model_or_controllers/sub_folder/service_class_name_test.rb
Did Anything Break?
Nope. You can switch mix and match the service styles all you want. In fact, if you prefer the original approach, you can still have the gem produce that style for your services. Just pass in the newly added, and optional, variable when generating a new service.
Terminal
Passing in --instance no
tells the gem to produce the older/original style of service class where BaseService
is not included and all methods are prefixed with self.
, etc. Note: --instance yes
is the default in the 2.x.x line, meaning the gem will produce the new style of service classes unless you tell it otherwise.