Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

create a wrapper controller for all calls to web services in rails

I am working to creating a wrapper for my existing application controllers.

For example, i have two controllers accepting similar set of parameters and similar methods.

Code is as below

class EmployeeController < ApplicationController

  def list
  end

end


class DepartmentController < ApplicationController

  def list
  end

end

end point would be http://localhost:3000/employee/list & http://localhost:3000/department/list

What is the best way to create wrapper controller and invoke either of the controllers action.

is this way correct, where we check certain parameters and create objects accordingly or are there better ways to do it

class WrapperController < ApplicationController


  def list
    if params["which"].eql?("employee")
      data = EmployeeController.new(params).create
    else
      data = DepartmentController.new(params).label
    end

  end
end

end point would be http://localhost:3000/wrapper/list

Any help would be appreciated. Thanks in advance.

like image 737
opensource-developer Avatar asked Feb 21 '17 15:02

opensource-developer


1 Answers

This WrapperController sounds like a really bad idea. Especially instantiating another controller and calling a method on it. I don't recall seeing such pattern anywhere. Rails does a lot of magic around request/response cycle, so calling another controller will most likely break something later on. I am just guessing that cookies may not work, or rendering can be broken etc.

Anyway, what you probably want is better organise your business logic inside Rails application. As a starting point I strongly recommend reading this article. Based on limited information from your question it is hard to give a good answer for your particular case.

For example, you can implement a query object:

class EmployeesQuery
  def initialize(params)
    # initialize some internal variables
  end

  def list
    # write code for fetching employees based on passed params
  end
end

class DepartmentsQuery
  def initialize(params)
    # initialize some internal variables
  end

  def list
    # write code for fetching employees based on passed params
  end
end

class QueryFactory
  QUERIES = {
    "employee" => EmployeeQuery,
    "department" => DepartmentQuery
  }

  get self.get_query(resource)
    QUERIES[resource] || raise("Some exception")
  end
end

Now you can create a ListsController:

class ListsController < ApplicationController
  def index
    data = QueryFactory.get_query(params[:which]).list
    # render specific view based on requested resource
    # and rescue possible exception from get_query method
  end
end

And in config/routes.rb:

get "/:which/list" => "lists#index"

This can be later extended with more resources and having separate query objects for each will make it more maintainable. The only problematic thing is how to render generated results, but you can use similar pattern for selecting correct template to render.

If you want to have similar pattern for creating objects, you should look at service object pattern. It is described in linked article.

Also you can kind solve your problem with much simpler way, just by changing config/routes.rb a little bit.

get "/:controller/list", to: :list

It will route /employee/list to EmployeeController and /department/list to DepartmentController. And basically it will route to any valid controller, so maybe you want to tweak it a little bit and add some restrictions.

Hope that helps. Cheers.

like image 68
Michał Młoźniak Avatar answered Oct 28 '22 19:10

Michał Młoźniak