Thierry
Thierry

Reputation: 121

Rails 5.2 Service objects with non current user

I am trying to forward an action to another controller through the service object methodology in rails 5.2.

The create action should pass the user id for the create action but I am failing at passing that param appropriately.

Business logic is the following: a user rents out an asset, the potential renter makes a request, when the asset owner agrees to a visit, the rent user is created as a client in another controller to organise a visit.

I am trying to address the create action in the client controller as follows:

In the rent controller :

private

 def visit(room, rent)
   @newclient = NewclientService.create(params)
   if @newclient.save
   rent.Approved!
   ...
  else
  rent.Declined!
  ...
end

and then in the app/service/newclient_service.rb

module NewclientService
  class << self
    def create(params)
      @rent = Rent.find_by(id: params[:id])
      user = @rent.user_id
      name = @rent.user.fullname
      email = @rent.user.email
      Client.create(user_id: user, name: name, email: email)
    end
  end
end

This code does the job. The db is filled up, validations and strong params seem to work and it seems to me robust/secure enough.

Question: is the service object (my way ?) route the most preferred way for forwarding that action ?

Thanks for your help,

Upvotes: 0

Views: 300

Answers (1)

Tyrone Wilson
Tyrone Wilson

Reputation: 4618

I like the pattern in principle and it has really cleaned up the apps which I produce. There are a couple of nice gems that I typically use to get the job done and keep the controllers clean.

I use the mutations gem and simple_command. These two together give you a nice (almost completely) consistent API. The mutations gem in particular is what I use for digesting and resolving JSON input data from params which can then handle processes for me.

This is a good pattern in the sense that it encapsulates the logic of discrete functionality very well. For example, if you have a RegisterUser mutation, you can use that in a controller or you can use it to digest a whole list of objects etc. You can even use the builder option for attributes to process deeply nested json.

I would recommend checking it out.

https://github.com/cypriss/mutations

For those times where I am not processing JSON from an API and want to create discrete encapsulated functionality I generally use simple_command https://github.com/nebulab/simple_command. This approach is also great because it allows you to use the same components from any context. For example, a command called GetLatestTweets.call() could be used equally well from a controller as it could from the REPL.

Both of these libraries provide you with a result object which you can then process as appropriate

def create
  outcome = NewClientMutation.run(params.require(:resource).permit!)
  if outcome.success?
     render json: outcome.result, status: :created
  else
     render json: {resource: outcome.result, errors: outcome.errors}, status: :unprocessable_entity 
  end
end

In my particular case I use 'permit!' since the mutations library ignores any parameters that aren't explicitly specified which means that strong parameters aren't necessary if you use this library as it filters parameters as well.

Upvotes: 0

Related Questions