In the ruby gem I am writing I have to take in as input certain known query parameters and massage them into a query string and then use that constructed (url) string as a rest endpoint to retrieve that data.
Now there are some weird inconsistencies in inputs coming in and I am forking my code to normalize inputs into a consistent output.
def build_query(params, endpoint)
limit = Hash[limit: params[:limit] || 0]
skip = Hash[skip: params[:skip] || 0]
asc = Hash[asc: params[:asc] || ""]
desc = Hash[desc: params[:desc] || ""]
query = [limit, skip, asc, desc].select { |hash| hash.values.none? { |val| val == '' || val == 0 } }
encoded = query.map{ |q| q.to_query }.join("&")
references = build_references(params[:include]) || ""
query_string = references.empty? ? "#{endpoint}#{encoded}" : "#{endpoint}#{references}&#{encoded}"
end
You will see above that the references
piece of the params
are not handled the same way as the rest of the parameters. There are more slightly inconsistent edge cases coming soon. And the only way I know how to deal with these is to keep forking my code inside this function. It's going to get messy soon!
So how should I now refactor this code? Where should I go from here to manage this complexity? Should I use collaborating objects (ParamsBuilder
or QueryManager
) and some kind of polymorphism strategy?
I would like to keep my code simple and functional as much as possible.
Basically, you have two types of parameters: those you are to pass through as is (like
:limit
,) and those, you are to transform (like:include
.)Former are just passed through, latter are transformed using the list of lambdas specified in the very beginning of this snippet.
Since you were using
to_query
in the original question, I suggest you userails
, hence you haveblank?
method on hand and there is no need to explicitly check for empty strings and/or zeroes.In the last step, we reject blanks and join everything with an ampersand.