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

module ParentModelOrControllers
  module SubFolder
    class ServiceClassName
      def self.call

      end
    end
  end
end

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

module ParentModelOrControllers
  module SubFolder
    class ServiceClassName
      include BaseService

      def call
        some_stuff.do_it
        other_method
      end

      def other_method
      end
    end
  end
end

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

~/path/to/your_rails_app/ $ rails generate rails_services:create ServiceClassName ParentModelOrController SubFolder[optional] --instance no

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.