RubyQL
A query language for ruby hashes
RubyQL is a query language designed for very flexible rest apis or plain ruby hashes.
RubyQL loves it when its used together with ActiveRecord 🤤
Example:
require 'rubyql'
class UserQuery < RubyQL
def query
result = User.find_by(query_params)
result.attributes unless result.nil?
end
end
The class we created overwrites the query method, to provide a custom mechanism which should return a hash. query_params
is
the hash which holds the provided parameter, like WHERE
in SQL.
IMPORTANT: .attributes
is necessary for ActiveRecord, only returning the actual hash, not the ActiveModel object.
Usage:
UserQuery.new({"firstname"=>"", "lastname"=>"", "email"=>"[email protected]"}).execute
=> {"firstname"=>"Niklas", "lastname"=>"Hanft", "email"=>"[email protected]"}
UserQuery.new({"lastname"=>"", "email"=>"[email protected]"}).execute
=> {"lastname"=>"Hanft", "email"=>"[email protected]"}
UserQuery.new({"lastname"=>"", "email"=>"", "id"=>1}).execute
=> {"lastname"=>"Hanft", "email"=>"[email protected]", "id"=>1}
As you can see we left the wanted attributes blank, so rubyql will fill them out, if they exist.
For a better understanding another plain ruby example:
require 'rubyql
class PlainQuery < RubyQL
def query
{"firstname"=>"Niklas", "lastname"=>"Hanft", "email"=>"[email protected]", "id"=>1337, "another_attribute"=>"Hello World"}
end
end
The method is only returning a simple hash. Now we can execute queries:
PlainQuery.new({"firstname"=>"", "lastname"=>"", "email"=>"[email protected]", "id"=>""}).execute
=> {"firstname"=>"Hanft", "lastname"=>"Niklas", "email"=>"[email protected]", "id"=>1337}
PlainQuery.new({"email"=>"[email protected]", "id"=>"", "another_attribute"=>""}).execute
=> {"email"=>"[email protected]", "id"=>1337, "another_attribute"=>"Hello World"}
As this is static, it doesn't really make sense, but for understanding it might be ok to use it this way. But mainly it should be used with a database orm or some dynamic functions which return hashes.
Advanced usage:
A typical API in Rails
module Api
module V1
class UserQueryController < ApiController
before_action :user_params
def execute
render json: UserQuery.new(user_params).execute.to_json
end
private
def user_params
params.permit(:username, :firstname, :email, :id, :lastname, :posts, :created_at).to_h
end
end
end
end
The Query class
require 'rubyql'
class UserQuery < RubyQL
def query
result = User.find_by(query_params)
result.attributes unless result.nil?
end
end
Routing:
namespace :api, defaults: { format: :json } do
namespace :v1 do
post '/user-query', to: 'user_query#execute'
end
end
A request:
POST /api/v1/user-query
{
"email": "[email protected]",
"firstname":"",
"id":"",
"created_at":"",
"lastname":""
}
The response:
{
"id": 1,
"firstname": "Niklas",
"lastname": "Hanft",
"created_at": "2017-11-21T07:10:46.953Z",
"email": "[email protected]"
}
A second request:
POST /api/v1/user-query
{
"email": "[email protected]",
"firstname":""
}
The response:
{
"email": "[email protected]",
"firstname": "Niklas"
}